• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2022 The Khronos Group 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 <string>
16 #include <vector>
17 
18 #include "gmock/gmock.h"
19 #include "test/val/val_fixtures.h"
20 
21 namespace spvtools {
22 namespace val {
23 namespace {
24 
25 using ::testing::HasSubstr;
26 using ::testing::Values;
27 using ::testing::ValuesIn;
28 
29 struct Case {
30   std::vector<std::string> caps;
31   bool shader;
32   std::string result_type;
33   std::string scope;
34   std::string delta;
35   std::string cluster_size;
36   std::string expected_error;  // empty for no error.
37 };
38 
operator <<(std::ostream & out,Case c)39 inline std::ostream& operator<<(std::ostream& out, Case c) {
40   out << "\nSPV_KHR_subgroup_rotate Case{{";
41   for (auto& cap : c.caps) {
42     out << cap;
43   }
44   out << "} ";
45   out << (c.shader ? "shader " : "kernel ");
46   out << c.result_type + " ";
47   out << c.scope + " ";
48   out << c.delta + " ";
49   out << c.cluster_size + " ";
50   out << "err'" << c.expected_error << "'";
51   out << "}";
52   return out;
53 }
54 
AssemblyForCase(const Case & c)55 std::string AssemblyForCase(const Case& c) {
56   std::ostringstream ss;
57 
58   if (c.shader) {
59     ss << "OpCapability Shader\n";
60   } else {
61     ss << "OpCapability Kernel\n";
62     ss << "OpCapability Addresses\n";
63   }
64   for (auto& cap : c.caps) {
65     ss << "OpCapability " << cap << "\n";
66   }
67   ss << "OpExtension \"SPV_KHR_subgroup_rotate\"\n";
68 
69   if (c.shader) {
70     ss << "OpMemoryModel Logical GLSL450\n";
71     ss << "OpEntryPoint GLCompute %main \"main\"\n";
72   } else {
73     ss << "OpMemoryModel Physical32 OpenCL\n";
74     ss << "OpEntryPoint Kernel %main \"main\"\n";
75   }
76 
77   ss << R"(
78     %void    = OpTypeVoid
79     %void_fn = OpTypeFunction %void
80     %u32 = OpTypeInt 32 0
81     %float = OpTypeFloat 32
82     %ptr = OpTypePointer Function %u32
83   )";
84 
85   if (c.shader) {
86     ss << "%i32 = OpTypeInt 32 1\n";
87   }
88 
89   ss << R"(
90     %u32_0 = OpConstant %u32 0
91     %u32_1 = OpConstant %u32 1
92     %u32_15 = OpConstant %u32 15
93     %u32_16 = OpConstant %u32 16
94     %u32_undef = OpUndef %u32
95     %u32_spec_1 = OpSpecConstant %u32 1
96     %u32_spec_16 = OpSpecConstant %u32 16
97     %f32_1 = OpConstant %float 1.0
98     %subgroup = OpConstant %u32 3
99     %workgroup = OpConstant %u32 2
100     %invalid_scope = OpConstant %u32 1
101     %val = OpConstant %u32 42
102   )";
103 
104   if (c.shader) {
105     ss << "%i32_1 = OpConstant %i32 1\n";
106   }
107 
108   ss << R"(
109     %main = OpFunction %void None %void_fn
110     %entry = OpLabel
111   )";
112 
113   ss << "%unused = OpGroupNonUniformRotateKHR ";
114   ss << c.result_type + " ";
115   ss << c.scope;
116   ss << " %val ";
117   ss << c.delta;
118   ss << " " + c.cluster_size;
119   ss << "\n";
120 
121   ss << R"(
122     OpReturn
123     OpFunctionEnd
124   )";
125 
126   return ss.str();
127 }
128 
129 using ValidateSpvKHRSubgroupRotate = spvtest::ValidateBase<Case>;
130 
TEST_P(ValidateSpvKHRSubgroupRotate,Base)131 TEST_P(ValidateSpvKHRSubgroupRotate, Base) {
132   const auto& c = GetParam();
133   const auto& assembly = AssemblyForCase(c);
134   CompileSuccessfully(assembly);
135   if (c.expected_error.empty()) {
136     EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
137   } else {
138     EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
139     EXPECT_THAT(getDiagnosticString(), HasSubstr(c.expected_error));
140   }
141 }
142 
143 INSTANTIATE_TEST_SUITE_P(
144     Valid, ValidateSpvKHRSubgroupRotate,
145     ::testing::Values(
146         Case{
147             {"GroupNonUniformRotateKHR"}, false, "%u32", "%subgroup", "%u32_1"},
148         Case{{"GroupNonUniformRotateKHR"}, true, "%u32", "%subgroup", "%u32_1"},
149         Case{{"GroupNonUniformRotateKHR"},
150              false,
151              "%u32",
152              "%subgroup",
153              "%u32_1",
154              "%u32_16"},
155         Case{{"GroupNonUniformRotateKHR"},
156              true,
157              "%u32",
158              "%subgroup",
159              "%u32_1",
160              "%u32_16"},
161         Case{{"GroupNonUniformRotateKHR"},
162              false,
163              "%u32",
164              "%subgroup",
165              "%u32_spec_1",
166              "%u32_16"},
167         Case{{"GroupNonUniformRotateKHR"},
168              true,
169              "%u32",
170              "%subgroup",
171              "%u32_1",
172              "%u32_spec_16"},
173         Case{{"GroupNonUniformRotateKHR"},
174              false,
175              "%u32",
176              "%workgroup",
177              "%u32_1"},
178         Case{
179             {"GroupNonUniformRotateKHR"}, true, "%u32", "%workgroup", "%u32_1"},
180         Case{{"GroupNonUniformRotateKHR"},
181              false,
182              "%u32",
183              "%workgroup",
184              "%u32_spec_1"},
185         Case{{"GroupNonUniformRotateKHR"},
186              true,
187              "%u32",
188              "%workgroup",
189              "%u32_spec_1"}));
190 
191 INSTANTIATE_TEST_SUITE_P(
192     RequiresCapability, ValidateSpvKHRSubgroupRotate,
193     ::testing::Values(Case{{},
194                            false,
195                            "%u32",
196                            "%subgroup",
197                            "%u32_1",
198                            "",
199                            "Opcode GroupNonUniformRotateKHR requires one of "
200                            "these capabilities: "
201                            "GroupNonUniformRotateKHR"},
202                       Case{{},
203                            true,
204                            "%u32",
205                            "%subgroup",
206                            "%u32_1",
207                            "",
208                            "Opcode GroupNonUniformRotateKHR requires one of "
209                            "these capabilities: "
210                            "GroupNonUniformRotateKHR"}));
211 
TEST_F(ValidateSpvKHRSubgroupRotate,RequiresExtension)212 TEST_F(ValidateSpvKHRSubgroupRotate, RequiresExtension) {
213   const std::string str = R"(
214     OpCapability GroupNonUniformRotateKHR
215 )";
216   CompileSuccessfully(str.c_str());
217   EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
218   EXPECT_THAT(
219       getDiagnosticString(),
220       HasSubstr(
221           "1st operand of Capability: operand GroupNonUniformRotateKHR(6026) "
222           "requires one of these extensions: SPV_KHR_subgroup_rotate"));
223 }
224 
225 INSTANTIATE_TEST_SUITE_P(
226     InvalidExecutionScope, ValidateSpvKHRSubgroupRotate,
227     ::testing::Values(
228         Case{{"GroupNonUniformRotateKHR"},
229              false,
230              "%u32",
231              "%invalid_scope",
232              "%u32_1",
233              "",
234              "Execution scope is limited to Subgroup or Workgroup"},
235         Case{{"GroupNonUniformRotateKHR"},
236              true,
237              "%u32",
238              "%invalid_scope",
239              "%u32_1",
240              "",
241              "Execution scope is limited to Subgroup or Workgroup"}));
242 
243 INSTANTIATE_TEST_SUITE_P(
244     InvalidResultType, ValidateSpvKHRSubgroupRotate,
245     ::testing::Values(Case{{"GroupNonUniformRotateKHR"},
246                            false,
247                            "%ptr",
248                            "%subgroup",
249                            "%u32_1",
250                            "",
251                            "Expected Result Type to be a scalar or vector of "
252                            "floating-point, integer or boolean type"},
253                       Case{{"GroupNonUniformRotateKHR"},
254                            true,
255                            "%ptr",
256                            "%subgroup",
257                            "%u32_1",
258                            "",
259                            "Expected Result Type to be a scalar or vector of "
260                            "floating-point, integer or boolean type"}));
261 
262 INSTANTIATE_TEST_SUITE_P(
263     MismatchedResultAndValueTypes, ValidateSpvKHRSubgroupRotate,
264     ::testing::Values(
265         Case{{"GroupNonUniformRotateKHR"},
266              false,
267              "%float",
268              "%subgroup",
269              "%u32_1",
270              "",
271              "Result Type must be the same as the type of Value"},
272         Case{{"GroupNonUniformRotateKHR"},
273              true,
274              "%float",
275              "%subgroup",
276              "%u32_1",
277              "",
278              "Result Type must be the same as the type of Value"}));
279 
280 INSTANTIATE_TEST_SUITE_P(
281     InvalidDelta, ValidateSpvKHRSubgroupRotate,
282     ::testing::Values(Case{{"GroupNonUniformRotateKHR"},
283                            false,
284                            "%u32",
285                            "%subgroup",
286                            "%f32_1",
287                            "",
288                            "Delta must be a scalar of integer type, whose "
289                            "Signedness operand is 0"},
290                       Case{{"GroupNonUniformRotateKHR"},
291                            true,
292                            "%u32",
293                            "%subgroup",
294                            "%f32_1",
295                            "",
296                            "Delta must be a scalar of integer type, whose "
297                            "Signedness operand is 0"},
298                       Case{{"GroupNonUniformRotateKHR"},
299                            true,
300                            "%u32",
301                            "%subgroup",
302                            "%i32_1",
303                            "",
304                            "Delta must be a scalar of integer type, whose "
305                            "Signedness operand is 0"}));
306 
307 INSTANTIATE_TEST_SUITE_P(
308     InvalidClusterSize, ValidateSpvKHRSubgroupRotate,
309     ::testing::Values(
310         Case{{"GroupNonUniformRotateKHR"},
311              false,
312              "%u32",
313              "%subgroup",
314              "%u32_1",
315              "%f32_1",
316              "ClusterSize must be a scalar of integer type, whose Signedness "
317              "operand is 0"},
318         Case{{"GroupNonUniformRotateKHR"},
319              true,
320              "%u32",
321              "%subgroup",
322              "%u32_1",
323              "%i32_1",
324              "ClusterSize must be a scalar of integer type, whose Signedness "
325              "operand is 0"},
326         Case{{"GroupNonUniformRotateKHR"},
327              true,
328              "%u32",
329              "%subgroup",
330              "%u32_1",
331              "%u32_0",
332              "Behavior is undefined unless ClusterSize is at least 1 and a "
333              "power of 2"},
334         Case{{"GroupNonUniformRotateKHR"},
335              true,
336              "%u32",
337              "%subgroup",
338              "%u32_1",
339              "%u32_15",
340              "Behavior is undefined unless ClusterSize is at least 1 and a "
341              "power of 2"},
342         Case{{"GroupNonUniformRotateKHR"},
343              true,
344              "%u32",
345              "%subgroup",
346              "%u32_1",
347              "%u32_undef",
348              "ClusterSize must come from a constant instruction"}));
349 
350 }  // namespace
351 }  // namespace val
352 }  // namespace spvtools
353