1 // Copyright (c) 2017 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <algorithm>
16 #include <memory>
17 
18 #include "gtest/gtest.h"
19 #include "source/opt/build_module.h"
20 #include "source/opt/ir_context.h"
21 
22 namespace spvtools {
23 namespace opt {
24 namespace {
25 
26 using FeatureManagerTest = ::testing::Test;
27 
TEST_F(FeatureManagerTest,MissingExtension)28 TEST_F(FeatureManagerTest, MissingExtension) {
29   const std::string text = R"(
30 OpCapability Shader
31 OpMemoryModel Logical GLSL450
32   )";
33 
34   std::unique_ptr<IRContext> context =
35       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
36   ASSERT_NE(context, nullptr);
37 
38   EXPECT_FALSE(context->get_feature_mgr()->HasExtension(
39       Extension::kSPV_KHR_variable_pointers));
40 }
41 
TEST_F(FeatureManagerTest,OneExtension)42 TEST_F(FeatureManagerTest, OneExtension) {
43   const std::string text = R"(
44 OpCapability Shader
45 OpMemoryModel Logical GLSL450
46 OpExtension "SPV_KHR_variable_pointers"
47   )";
48 
49   std::unique_ptr<IRContext> context =
50       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
51   ASSERT_NE(context, nullptr);
52 
53   EXPECT_TRUE(context->get_feature_mgr()->HasExtension(
54       Extension::kSPV_KHR_variable_pointers));
55 }
56 
TEST_F(FeatureManagerTest,NotADifferentExtension)57 TEST_F(FeatureManagerTest, NotADifferentExtension) {
58   const std::string text = R"(
59 OpCapability Shader
60 OpMemoryModel Logical GLSL450
61 OpExtension "SPV_KHR_variable_pointers"
62   )";
63 
64   std::unique_ptr<IRContext> context =
65       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
66   ASSERT_NE(context, nullptr);
67 
68   EXPECT_FALSE(context->get_feature_mgr()->HasExtension(
69       Extension::kSPV_KHR_storage_buffer_storage_class));
70 }
71 
TEST_F(FeatureManagerTest,TwoExtensions)72 TEST_F(FeatureManagerTest, TwoExtensions) {
73   const std::string text = R"(
74 OpCapability Shader
75 OpMemoryModel Logical GLSL450
76 OpExtension "SPV_KHR_variable_pointers"
77 OpExtension "SPV_KHR_storage_buffer_storage_class"
78   )";
79 
80   std::unique_ptr<IRContext> context =
81       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
82   ASSERT_NE(context, nullptr);
83 
84   EXPECT_TRUE(context->get_feature_mgr()->HasExtension(
85       Extension::kSPV_KHR_variable_pointers));
86   EXPECT_TRUE(context->get_feature_mgr()->HasExtension(
87       Extension::kSPV_KHR_storage_buffer_storage_class));
88 }
89 
TEST_F(FeatureManagerTest,GetExtensionsReturnsExtensions)90 TEST_F(FeatureManagerTest, GetExtensionsReturnsExtensions) {
91   const std::string text = R"(
92 OpCapability Shader
93 OpMemoryModel Logical GLSL450
94 OpExtension "SPV_KHR_variable_pointers"
95 OpExtension "SPV_KHR_storage_buffer_storage_class"
96   )";
97 
98   std::unique_ptr<IRContext> context =
99       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
100   ASSERT_NE(context, nullptr);
101 
102   const auto& extensions = context->get_feature_mgr()->GetExtensions();
103   EXPECT_EQ(extensions.size(), 2);
104   EXPECT_TRUE(extensions.contains(Extension::kSPV_KHR_variable_pointers));
105   EXPECT_TRUE(
106       extensions.contains(Extension::kSPV_KHR_storage_buffer_storage_class));
107 }
108 
109 // Test capability checks.
TEST_F(FeatureManagerTest,ExplicitlyPresent1)110 TEST_F(FeatureManagerTest, ExplicitlyPresent1) {
111   const std::string text = R"(
112 OpCapability Shader
113 OpMemoryModel Logical GLSL450
114   )";
115 
116   std::unique_ptr<IRContext> context =
117       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
118   ASSERT_NE(context, nullptr);
119 
120   EXPECT_TRUE(
121       context->get_feature_mgr()->HasCapability(spv::Capability::Shader));
122   EXPECT_FALSE(
123       context->get_feature_mgr()->HasCapability(spv::Capability::Kernel));
124 }
125 
TEST_F(FeatureManagerTest,ExplicitlyPresent2)126 TEST_F(FeatureManagerTest, ExplicitlyPresent2) {
127   const std::string text = R"(
128 OpCapability Kernel
129 OpMemoryModel Logical GLSL450
130   )";
131 
132   std::unique_ptr<IRContext> context =
133       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
134   ASSERT_NE(context, nullptr);
135 
136   EXPECT_FALSE(
137       context->get_feature_mgr()->HasCapability(spv::Capability::Shader));
138   EXPECT_TRUE(
139       context->get_feature_mgr()->HasCapability(spv::Capability::Kernel));
140 }
141 
TEST_F(FeatureManagerTest,ImplicitlyPresent)142 TEST_F(FeatureManagerTest, ImplicitlyPresent) {
143   const std::string text = R"(
144 OpCapability Tessellation
145 OpMemoryModel Logical GLSL450
146   )";
147 
148   std::unique_ptr<IRContext> context =
149       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
150   ASSERT_NE(context, nullptr);
151 
152   // Check multiple levels of indirection.  Tessellation implies Shader, which
153   // implies Matrix.
154   EXPECT_TRUE(
155       context->get_feature_mgr()->HasCapability(spv::Capability::Tessellation));
156   EXPECT_TRUE(
157       context->get_feature_mgr()->HasCapability(spv::Capability::Shader));
158   EXPECT_TRUE(
159       context->get_feature_mgr()->HasCapability(spv::Capability::Matrix));
160   EXPECT_FALSE(
161       context->get_feature_mgr()->HasCapability(spv::Capability::Kernel));
162 }
163 
TEST_F(FeatureManagerTest,GetCapabilitiesReturnsImplicitCapabilities)164 TEST_F(FeatureManagerTest, GetCapabilitiesReturnsImplicitCapabilities) {
165   const std::string text = R"(
166 OpCapability Tessellation
167 OpMemoryModel Logical GLSL450
168   )";
169 
170   std::unique_ptr<IRContext> context =
171       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
172   ASSERT_NE(context, nullptr);
173 
174   const auto& capabilities = context->get_feature_mgr()->GetCapabilities();
175   // Tesselation implies Shader, which implies Matrix.
176   EXPECT_EQ(capabilities.size(), 3);
177   EXPECT_TRUE(capabilities.contains(spv::Capability::Tessellation));
178   EXPECT_TRUE(capabilities.contains(spv::Capability::Shader));
179   EXPECT_TRUE(capabilities.contains(spv::Capability::Matrix));
180 }
181 
182 }  // namespace
183 }  // namespace opt
184 }  // namespace spvtools
185