1 // Copyright (c) 2018 Google LLC.
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 <sstream>
16 #include <string>
17 #include <tuple>
18
19 #include "gmock/gmock.h"
20 #include "test/unit_spirv.h"
21 #include "test/val/val_fixtures.h"
22
23 namespace spvtools {
24 namespace val {
25 namespace {
26
27 using ::testing::Combine;
28 using ::testing::HasSubstr;
29 using ::testing::Values;
30 using ::testing::ValuesIn;
31
GenerateShaderCode( const std::string& body, const std::string& capabilities_and_extensions = �, const std::string& execution_model = �)32 std::string GenerateShaderCode(
33 const std::string& body,
34 const std::string& capabilities_and_extensions = "",
35 const std::string& execution_model = "GLCompute") {
36 std::ostringstream ss;
37 ss << R"(
38 OpCapability Shader
39 OpCapability GroupNonUniform
40 OpCapability GroupNonUniformVote
41 OpCapability GroupNonUniformBallot
42 OpCapability GroupNonUniformShuffle
43 OpCapability GroupNonUniformShuffleRelative
44 OpCapability GroupNonUniformArithmetic
45 OpCapability GroupNonUniformClustered
46 OpCapability GroupNonUniformQuad
47 OpCapability GroupNonUniformPartitionedNV
48 OpExtension "SPV_NV_shader_subgroup_partitioned"
49 )";
50
51 ss << capabilities_and_extensions;
52 ss << "OpMemoryModel Logical GLSL450\n";
53 ss << "OpEntryPoint " << execution_model << " %main \"main\"\n";
54 if (execution_model == "GLCompute") {
55 ss << "OpExecutionMode %main LocalSize 1 1 1\n";
56 }
57
58 ss << R"(
59 %void = OpTypeVoid
60 %func = OpTypeFunction %void
61 %bool = OpTypeBool
62 %u32 = OpTypeInt 32 0
63 %int = OpTypeInt 32 1
64 %float = OpTypeFloat 32
65 %u32vec4 = OpTypeVector %u32 4
66 %u32vec3 = OpTypeVector %u32 3
67 %v2bool = OpTypeVector %bool 2
68 %v4float = OpTypeVector %float 4
69 %struct = OpTypeStruct %int
70 %v4int = OpTypeVector %int 4
71
72 %true = OpConstantTrue %bool
73 %false = OpConstantFalse %bool
74
75 %u32_0 = OpConstant %u32 0
76 %int_0 = OpConstant %int 0
77
78 %float_0 = OpConstant %float 0
79
80 %u32vec4_null = OpConstantComposite %u32vec4 %u32_0 %u32_0 %u32_0 %u32_0
81 %u32vec3_null = OpConstantComposite %u32vec3 %u32_0 %u32_0 %u32_0
82 %v2bool_false = OpConstantNull %v2bool
83 %v4float_null = OpConstantNull %v4float
84 %struct_null = OpConstantNull %struct
85 %v4int_null = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0
86
87 %u32_undef = OpUndef %u32
88
89 %cross_device = OpConstant %u32 0
90 %device = OpConstant %u32 1
91 %workgroup = OpConstant %u32 2
92 %subgroup = OpConstant %u32 3
93 %invocation = OpConstant %u32 4
94
95 %reduce = OpConstant %u32 0
96 %inclusive_scan = OpConstant %u32 1
97 %exclusive_scan = OpConstant %u32 2
98 %clustered_reduce = OpConstant %u32 3
99
100 %main = OpFunction %void None %func
101 %main_entry = OpLabel
102 )";
103
104 ss << body;
105
106 ss << R"(
107 OpReturn
108 OpFunctionEnd)";
109
110 return ss.str();
111 }
112
113 spv::Scope scopes[] = {spv::Scope::CrossDevice, spv::Scope::Device,
114 spv::Scope::Workgroup, spv::Scope::Subgroup,
115 spv::Scope::Invocation};
116
117 using ValidateGroupNonUniform = spvtest::ValidateBase<bool>;
118 using GroupNonUniform = spvtest::ValidateBase<
119 std::tuple<std::string, std::string, spv::Scope, std::string, std::string>>;
120
ConvertScope(spv::Scope scope)121 std::string ConvertScope(spv::Scope scope) {
122 switch (scope) {
123 case spv::Scope::CrossDevice:
124 return "%cross_device";
125 case spv::Scope::Device:
126 return "%device";
127 case spv::Scope::Workgroup:
128 return "%workgroup";
129 case spv::Scope::Subgroup:
130 return "%subgroup";
131 case spv::Scope::Invocation:
132 return "%invocation";
133 default:
134 return "";
135 }
136 }
137
ConvertMatch(const std::string& type)138 std::string ConvertMatch(const std::string& type) {
139 if (type == "%bool") {
140 return "%true";
141 } else if (type == "%u32") {
142 return "%u32_0";
143 } else if (type == "%int") {
144 return "%int_0";
145 } else if (type == "%float") {
146 return "%float_0";
147 } else if (type == "%u32vec4") {
148 return "%u32vec4_null";
149 } else if (type == "%u32vec3") {
150 return "%u32vec3_null";
151 } else if (type == "%v2bool") {
152 return "%v2bool_false";
153 } else if (type == "%v4float") {
154 return "%v4float_null";
155 } else if (type == "%struct") {
156 return "%struct_null";
157 } else if (type == "%v4int") {
158 return "%v4int_null";
159 }
160
161 return "INVALID";
162 }
163
TEST_P(GroupNonUniform, Vulkan1p1)164 TEST_P(GroupNonUniform, Vulkan1p1) {
165 std::string opcode = std::get<0>(GetParam());
166 std::string type = std::get<1>(GetParam());
167 spv::Scope execution_scope = std::get<2>(GetParam());
168 std::string args = std::get<3>(GetParam());
169 std::string error = std::get<4>(GetParam());
170
171 const std::string match = "match_res";
172 size_t pos = std::string::npos;
173 while ((pos = args.find(match)) != std::string::npos) {
174 const std::string replace = ConvertMatch(type);
175 args = args.substr(0, pos) + replace + args.substr(pos + match.size());
176 }
177
178 std::ostringstream sstr;
179 sstr << "%result = " << opcode << " ";
180 sstr << type << " ";
181 sstr << ConvertScope(execution_scope) << " ";
182 sstr << args << "\n";
183
184 CompileSuccessfully(GenerateShaderCode(sstr.str()), SPV_ENV_VULKAN_1_1);
185 spv_result_t result = ValidateInstructions(SPV_ENV_VULKAN_1_1);
186 if (error == "") {
187 if (execution_scope == spv::Scope::Subgroup) {
188 EXPECT_EQ(SPV_SUCCESS, result);
189 } else {
190 EXPECT_EQ(SPV_ERROR_INVALID_DATA, result);
191 EXPECT_THAT(getDiagnosticString(),
192 AnyVUID("VUID-StandaloneSpirv-None-04642"));
193 EXPECT_THAT(
194 getDiagnosticString(),
195 HasSubstr(
196 "in Vulkan environment Execution scope is limited to Subgroup"));
197 }
198 } else {
199 EXPECT_EQ(SPV_ERROR_INVALID_DATA, result);
200 EXPECT_THAT(getDiagnosticString(), HasSubstr(error));
201 }
202 }
203
TEST_P(GroupNonUniform, Spirv1p3)204 TEST_P(GroupNonUniform, Spirv1p3) {
205 std::string opcode = std::get<0>(GetParam());
206 std::string type = std::get<1>(GetParam());
207 spv::Scope execution_scope = std::get<2>(GetParam());
208 std::string args = std::get<3>(GetParam());
209 std::string error = std::get<4>(GetParam());
210
211 const std::string match = "match_res";
212 size_t pos = std::string::npos;
213 while ((pos = args.find(match)) != std::string::npos) {
214 const std::string replace = ConvertMatch(type);
215 args = args.substr(0, pos) + replace + args.substr(pos + match.size());
216 }
217
218 std::ostringstream sstr;
219 sstr << "%result = " << opcode << " ";
220 sstr << type << " ";
221 sstr << ConvertScope(execution_scope) << " ";
222 sstr << args << "\n";
223
224 CompileSuccessfully(GenerateShaderCode(sstr.str()), SPV_ENV_UNIVERSAL_1_3);
225 spv_result_t result = ValidateInstructions(SPV_ENV_UNIVERSAL_1_3);
226 if (error == "") {
227 if (execution_scope == spv::Scope::Subgroup ||
228 execution_scope == spv::Scope::Workgroup) {
229 EXPECT_EQ(SPV_SUCCESS, result);
230 } else {
231 EXPECT_EQ(SPV_ERROR_INVALID_DATA, result);
232 EXPECT_THAT(
233 getDiagnosticString(),
234 HasSubstr("Execution scope is limited to Subgroup or Workgroup"));
235 }
236 } else {
237 EXPECT_EQ(SPV_ERROR_INVALID_DATA, result);
238 EXPECT_THAT(getDiagnosticString(), HasSubstr(error));
239 }
240 }
241
242 INSTANTIATE_TEST_SUITE_P(GroupNonUniformElect, GroupNonUniform,
243 Combine(Values("OpGroupNonUniformElect"),
244 Values("%bool"), ValuesIn(scopes), Values(""),
245 Values("")));
246
247 INSTANTIATE_TEST_SUITE_P(GroupNonUniformVote, GroupNonUniform,
248 Combine(Values("OpGroupNonUniformAll",
249 "OpGroupNonUniformAny",
250 "OpGroupNonUniformAllEqual"),
251 Values("%bool"), ValuesIn(scopes),
252 Values("%true"), Values("")));
253
254 INSTANTIATE_TEST_SUITE_P(GroupNonUniformBroadcast, GroupNonUniform,
255 Combine(Values("OpGroupNonUniformBroadcast"),
256 Values("%bool"), ValuesIn(scopes),
257 Values("%true %u32_0"), Values("")));
258
259 INSTANTIATE_TEST_SUITE_P(GroupNonUniformBroadcastFirst, GroupNonUniform,
260 Combine(Values("OpGroupNonUniformBroadcastFirst"),
261 Values("%bool"), ValuesIn(scopes),
262 Values("%true"), Values("")));
263
264 INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallot, GroupNonUniform,
265 Combine(Values("OpGroupNonUniformBallot"),
266 Values("%u32vec4"), ValuesIn(scopes),
267 Values("%true"), Values("")));
268
269 INSTANTIATE_TEST_SUITE_P(GroupNonUniformInverseBallot, GroupNonUniform,
270 Combine(Values("OpGroupNonUniformInverseBallot"),
271 Values("%bool"), ValuesIn(scopes),
272 Values("%u32vec4_null"), Values("")));
273
274 INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotBitExtract, GroupNonUniform,
275 Combine(Values("OpGroupNonUniformBallotBitExtract"),
276 Values("%bool"), ValuesIn(scopes),
277 Values("%u32vec4_null %u32_0"), Values("")));
278
279 INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotBitCount, GroupNonUniform,
280 Combine(Values("OpGroupNonUniformBallotBitCount"),
281 Values("%u32"), ValuesIn(scopes),
282 Values("Reduce %u32vec4_null"), Values("")));
283
284 INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotFind, GroupNonUniform,
285 Combine(Values("OpGroupNonUniformBallotFindLSB",
286 "OpGroupNonUniformBallotFindMSB"),
287 Values("%u32"), ValuesIn(scopes),
288 Values("%u32vec4_null"), Values("")));
289
290 INSTANTIATE_TEST_SUITE_P(GroupNonUniformShuffle, GroupNonUniform,
291 Combine(Values("OpGroupNonUniformShuffle",
292 "OpGroupNonUniformShuffleXor",
293 "OpGroupNonUniformShuffleUp",
294 "OpGroupNonUniformShuffleDown"),
295 Values("%u32"), ValuesIn(scopes),
296 Values("%u32_0 %u32_0"), Values("")));
297
298 INSTANTIATE_TEST_SUITE_P(
299 GroupNonUniformIntegerArithmetic, GroupNonUniform,
300 Combine(Values("OpGroupNonUniformIAdd", "OpGroupNonUniformIMul",
301 "OpGroupNonUniformSMin", "OpGroupNonUniformUMin",
302 "OpGroupNonUniformSMax", "OpGroupNonUniformUMax",
303 "OpGroupNonUniformBitwiseAnd", "OpGroupNonUniformBitwiseOr",
304 "OpGroupNonUniformBitwiseXor"),
305 Values("%u32"), ValuesIn(scopes), Values("Reduce %u32_0"),
306 Values("")));
307
308 INSTANTIATE_TEST_SUITE_P(
309 GroupNonUniformFloatArithmetic, GroupNonUniform,
310 Combine(Values("OpGroupNonUniformFAdd", "OpGroupNonUniformFMul",
311 "OpGroupNonUniformFMin", "OpGroupNonUniformFMax"),
312 Values("%float"), ValuesIn(scopes), Values("Reduce %float_0"),
313 Values("")));
314
315 INSTANTIATE_TEST_SUITE_P(GroupNonUniformLogicalArithmetic, GroupNonUniform,
316 Combine(Values("OpGroupNonUniformLogicalAnd",
317 "OpGroupNonUniformLogicalOr",
318 "OpGroupNonUniformLogicalXor"),
319 Values("%bool"), ValuesIn(scopes),
320 Values("Reduce %true"), Values("")));
321
322 INSTANTIATE_TEST_SUITE_P(GroupNonUniformQuad, GroupNonUniform,
323 Combine(Values("OpGroupNonUniformQuadBroadcast",
324 "OpGroupNonUniformQuadSwap"),
325 Values("%u32"), ValuesIn(scopes),
326 Values("%u32_0 %u32_0"), Values("")));
327
328 INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotBitCountScope, GroupNonUniform,
329 Combine(Values("OpGroupNonUniformBallotBitCount"),
330 Values("%u32"), ValuesIn(scopes),
331 Values("Reduce %u32vec4_null"), Values("")));
332
333 INSTANTIATE_TEST_SUITE_P(
334 GroupNonUniformBallotBitCountBadResultType, GroupNonUniform,
335 Combine(
336 Values("OpGroupNonUniformBallotBitCount"), Values("%float", "%int"),
337 Values(spv::Scope::Subgroup), Values("Reduce %u32vec4_null"),
338 Values("Expected Result Type to be an unsigned integer type scalar.")));
339
340 INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotBitCountBadValue, GroupNonUniform,
341 Combine(Values("OpGroupNonUniformBallotBitCount"),
342 Values("%u32"), Values(spv::Scope::Subgroup),
343 Values("Reduce %u32vec3_null", "Reduce %u32_0",
344 "Reduce %float_0"),
345 Values("Expected Value to be a vector of four "
346 "components of integer type scalar")));
347
348 INSTANTIATE_TEST_SUITE_P(GroupNonUniformElectGood, GroupNonUniform,
349 Combine(Values("OpGroupNonUniformElect"),
350 Values("%bool"), Values(spv::Scope::Subgroup),
351 Values(""), Values("")));
352
353 INSTANTIATE_TEST_SUITE_P(
354 GroupNonUniformElectBadResultType, GroupNonUniform,
355 Combine(Values("OpGroupNonUniformElect"),
356 Values("%void", "%u32", "%int", "%float", "%u32vec4", "%u32vec3",
357 "%v2bool", "%v4float", "%struct"),
358 Values(spv::Scope::Subgroup), Values(""),
359 Values("Result must be a boolean scalar type")));
360
361 INSTANTIATE_TEST_SUITE_P(GroupNonUniformAnyAllGood, GroupNonUniform,
362 Combine(Values("OpGroupNonUniformAny",
363 "OpGroupNonUniformAll"),
364 Values("%bool"), Values(spv::Scope::Subgroup),
365 Values("%true", "%false"), Values("")));
366
367 INSTANTIATE_TEST_SUITE_P(
368 GroupNonUniformAnyAllBadResultType, GroupNonUniform,
369 Combine(Values("OpGroupNonUniformAny", "OpGroupNonUniformAll"),
370 Values("%void", "%u32", "%int", "%float", "%u32vec4", "%u32vec3",
371 "%v2bool", "%v4float", "%struct"),
372 Values(spv::Scope::Subgroup), Values("%true"),
373 Values("Result must be a boolean scalar type")));
374
375 INSTANTIATE_TEST_SUITE_P(
376 GroupNonUniformAnyAllBadOperand, GroupNonUniform,
377 Combine(Values("OpGroupNonUniformAny", "OpGroupNonUniformAll"),
378 Values("%bool"), Values(spv::Scope::Subgroup),
379 Values("%u32_0", "%int_0", "%float_0", "%u32vec4_null",
380 "%u32vec3_null", "%v2bool_false", "%v4float_null",
381 "%struct_null"),
382 Values("Predicate must be a boolean scalar type")));
383
384 INSTANTIATE_TEST_SUITE_P(GroupNonUniformAllEqualGood, GroupNonUniform,
385 Combine(Values("OpGroupNonUniformAllEqual"),
386 Values("%bool"), Values(spv::Scope::Subgroup),
387 Values("%true", "%false"), Values("")));
388
389 INSTANTIATE_TEST_SUITE_P(
390 GroupNonUniformAllEqualBadResultType, GroupNonUniform,
391 Combine(Values("OpGroupNonUniformAllEqual"),
392 Values("%void", "%u32", "%int", "%float", "%u32vec4", "%u32vec3",
393 "%v2bool", "%v4float", "%struct"),
394 Values(spv::Scope::Subgroup), Values("%true"),
395 Values("Result must be a boolean scalar type")));
396
397 INSTANTIATE_TEST_SUITE_P(
398 GroupNonUniformAllEqualBadOperand, GroupNonUniform,
399 Combine(Values("OpGroupNonUniformAllEqual"), Values("%bool"),
400 Values(spv::Scope::Subgroup), Values("%struct_null"),
401 Values("Value must be a scalar or vector of integer, "
402 "floating-point, or boolean type")));
403
404 INSTANTIATE_TEST_SUITE_P(GroupNonUniformBroadcastGood, GroupNonUniform,
405 Combine(Values("OpGroupNonUniformBroadcast",
406 "OpGroupNonUniformQuadBroadcast",
407 "OpGroupNonUniformQuadSwap"),
408 Values("%bool", "%u32", "%int", "%float",
409 "%u32vec4", "%u32vec3", "%v2bool",
410 "%v4float", "%v4int"),
411 Values(spv::Scope::Subgroup),
412 Values("match_res %u32_0"), Values("")));
413
414 INSTANTIATE_TEST_SUITE_P(
415 GroupNonUniformBroadcastShuffleBadResultType, GroupNonUniform,
416 Combine(Values("OpGroupNonUniformBroadcast", "OpGroupNonUniformShuffle",
417 "OpGroupNonUniformShuffleXor", "OpGroupNonUniformShuffleUp",
418 "OpGroupNonUniformShuffleDown",
419 "OpGroupNonUniformQuadBroadcast",
420 "OpGroupNonUniformQuadSwap"),
421 Values("%void", "%struct"), Values(spv::Scope::Subgroup),
422 Values("%u32_0 %u32_0"),
423 Values("Result must be a scalar or vector of integer, "
424 "floating-point, or boolean type")));
425
426 INSTANTIATE_TEST_SUITE_P(
427 GroupNonUniformBroadcastShuffleBadOperand1, GroupNonUniform,
428 Combine(Values("OpGroupNonUniformBroadcast", "OpGroupNonUniformShuffle",
429 "OpGroupNonUniformShuffleXor", "OpGroupNonUniformShuffleUp",
430 "OpGroupNonUniformShuffleDown",
431 "OpGroupNonUniformQuadBroadcast",
432 "OpGroupNonUniformQuadSwap"),
433 Values("%bool"), Values(spv::Scope::Subgroup),
434 Values("%u32_0 %u32_0", "%int_0 %u32_0", "%float_0 %u32_0",
435 "%u32vec4_null %u32_0", "%u32vec3_null %u32_0",
436 "%v2bool_false %u32_0", "%v4float_null %u32_0",
437 "%struct_null %u32_0", "%v4int_null %u32_0"),
438 Values("The type of Value must match the Result type")));
439
440 INSTANTIATE_TEST_SUITE_P(
441 GroupNonUniformBroadcastShuffleBadOperand2, GroupNonUniform,
442 Combine(Values("OpGroupNonUniformBroadcast", "OpGroupNonUniformShuffle",
443 "OpGroupNonUniformShuffleXor", "OpGroupNonUniformShuffleUp",
444 "OpGroupNonUniformShuffleDown",
445 "OpGroupNonUniformQuadBroadcast",
446 "OpGroupNonUniformQuadSwap"),
447 Values("%bool"), Values(spv::Scope::Subgroup),
448 Values("%true %true", "%true %int_0", "%true %float_0",
449 "%true %u32vec4_null", "%true %u32vec3_null",
450 "%true %v4float_null", "%true %v2bool_false",
451 "%true %struct_null", "%true %v4int_null"),
452 Values("must be an unsigned integer scalar")));
453
454 INSTANTIATE_TEST_SUITE_P(GroupNonUniformBroadcastShuffleOperand2NotConstant,
455 GroupNonUniform,
456 Combine(Values("OpGroupNonUniformBroadcast",
457 "OpGroupNonUniformQuadBroadcast",
458 "OpGroupNonUniformQuadSwap"),
459 Values("%bool"), Values(spv::Scope::Subgroup),
460 Values("%true %u32_undef"),
461 Values("must be a constant instruction")));
462
463 INSTANTIATE_TEST_SUITE_P(GroupNonUniformBroadcastFirstGood, GroupNonUniform,
464 Combine(Values("OpGroupNonUniformBroadcastFirst"),
465 Values("%bool", "%u32", "%int", "%float",
466 "%u32vec4", "%u32vec3", "%v2bool",
467 "%v4float", "%v4int"),
468 Values(spv::Scope::Subgroup),
469 Values("match_res"), Values("")));
470
471 INSTANTIATE_TEST_SUITE_P(
472 GroupNonUniformBroadcasFirsttBadResultType, GroupNonUniform,
473 Combine(Values("OpGroupNonUniformBroadcastFirst"),
474 Values("%void", "%struct"), Values(spv::Scope::Subgroup),
475 Values("%u32_0"),
476 Values("Result must be a scalar or vector of integer, "
477 "floating-point, or boolean type")));
478
479 INSTANTIATE_TEST_SUITE_P(
480 GroupNonUniformBroadcastBadOperand, GroupNonUniform,
481 Combine(Values("OpGroupNonUniformBroadcastFirst"), Values("%bool"),
482 Values(spv::Scope::Subgroup),
483 Values("%u32_0", "%int_0", "%float_0", "%u32vec4_null",
484 "%u32vec3_null", "%v2bool_false", "%v4float_null",
485 "%struct_null", "%v4int_null"),
486 Values("The type of Value must match the Result type")));
487
488 INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotGood, GroupNonUniform,
489 Combine(Values("OpGroupNonUniformBallot"),
490 Values("%u32vec4"),
491 Values(spv::Scope::Subgroup),
492 Values("%true", "%false"), Values("")));
493
494 INSTANTIATE_TEST_SUITE_P(
495 GroupNonUniformBallotBadResultType, GroupNonUniform,
496 Combine(Values("OpGroupNonUniformBallot"),
497 Values("%void", "%bool", "%u32", "%int", "%float", "%u32vec3",
498 "%v2bool", "%v4float", "%struct", "%v4int"),
499 Values(spv::Scope::Subgroup), Values("%true", "%false"),
500 Values("Result must be a 4-component unsigned integer vector")));
501
502 INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotBadOperand, GroupNonUniform,
503 Combine(Values("OpGroupNonUniformBallot"),
504 Values("%u32vec4"),
505 Values(spv::Scope::Subgroup),
506 Values("%u32_0", "%int_0", "%float_0",
507 "%u32vec4_null", "%u32vec3_null",
508 "%v2bool_false", "%v4float_null",
509 "%struct_null", "%v4int_null"),
510 Values("Predicate must be a boolean scalar")));
511
512 INSTANTIATE_TEST_SUITE_P(GroupNonUniformInverseBallotGood, GroupNonUniform,
513 Combine(Values("OpGroupNonUniformInverseBallot"),
514 Values("%bool"), Values(spv::Scope::Subgroup),
515 Values("%u32vec4_null"), Values("")));
516
517 INSTANTIATE_TEST_SUITE_P(
518 GroupNonUniformInverseBallotBadResultType, GroupNonUniform,
519 Combine(Values("OpGroupNonUniformInverseBallot"),
520 Values("%void", "%u32", "%int", "%float", "%u32vec4", "%u32vec3",
521 "%v2bool", "%v4float", "%struct", "%v4int"),
522 Values(spv::Scope::Subgroup), Values("%u32vec4_null"),
523 Values("Result must be a boolean scalar")));
524
525 INSTANTIATE_TEST_SUITE_P(
526 GroupNonUniformInverseBallotBadOperand, GroupNonUniform,
527 Combine(Values("OpGroupNonUniformInverseBallot"), Values("%bool"),
528 Values(spv::Scope::Subgroup),
529 Values("%true", "%false", "%u32_0", "%int_0", "%float_0",
530 "%u32vec3_null", "%v2bool_false", "%v4float_null",
531 "%struct_null", "%v4int_null"),
532 Values("Value must be a 4-component unsigned integer vector")));
533
534 INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotBitExtractGood, GroupNonUniform,
535 Combine(Values("OpGroupNonUniformBallotBitExtract"),
536 Values("%bool"), Values(spv::Scope::Subgroup),
537 Values("%u32vec4_null %u32_0"), Values("")));
538
539 INSTANTIATE_TEST_SUITE_P(
540 GroupNonUniformBallotBitExtractBadResultType, GroupNonUniform,
541 Combine(Values("OpGroupNonUniformBallotBitExtract"),
542 Values("%void", "%u32", "%int", "%float", "%u32vec4", "%u32vec3",
543 "%v2bool", "%v4float", "%struct", "%v4int"),
544 Values(spv::Scope::Subgroup), Values("%u32vec4_null %u32_0"),
545 Values("Result must be a boolean scalar")));
546
547 INSTANTIATE_TEST_SUITE_P(
548 GroupNonUniformBallotBitExtractBadOperand1, GroupNonUniform,
549 Combine(Values("OpGroupNonUniformBallotBitExtract"), Values("%bool"),
550 Values(spv::Scope::Subgroup),
551 Values("%true %u32_0", "%false %u32_0", "%u32_0 %u32_0",
552 "%int_0 %u32_0", "%float_0 %u32_0", "%u32vec3_null %u32_0",
553 "%v2bool_false %u32_0", "%v4float_null %u32_0",
554 "%struct_null %u32_0", "%v4int_null %u32_0"),
555 Values("Value must be a 4-component unsigned integer vector")));
556
557 INSTANTIATE_TEST_SUITE_P(
558 GroupNonUniformBallotBitExtractBadOperand2, GroupNonUniform,
559 Combine(Values("OpGroupNonUniformBallotBitExtract"), Values("%bool"),
560 Values(spv::Scope::Subgroup),
561 Values("%u32vec4_null %true", "%u32vec4_null %false",
562 "%u32vec4_null %int_0", "%u32vec4_null %float_0",
563 "%u32vec4_null %u32vec3_null", "%u32vec4_null %v2bool_false",
564 "%u32vec4_null %v4float_null", "%u32vec4_null %struct_null",
565 "%u32vec4_null %v4int_null"),
566 Values("Id must be an unsigned integer scalar")));
567
568 INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotFindGood, GroupNonUniform,
569 Combine(Values("OpGroupNonUniformBallotFindLSB",
570 "OpGroupNonUniformBallotFindMSB"),
571 Values("%u32"), Values(spv::Scope::Subgroup),
572 Values("%u32vec4_null"), Values("")));
573
574 INSTANTIATE_TEST_SUITE_P(
575 GroupNonUniformBallotFindBadResultType, GroupNonUniform,
576 Combine(Values("OpGroupNonUniformBallotFindLSB",
577 "OpGroupNonUniformBallotFindMSB"),
578 Values("%void", "%bool", "%int", "%float", "%u32vec4", "%u32vec3",
579 "%v2bool", "%v4float", "%struct", "%v4int"),
580 Values(spv::Scope::Subgroup), Values("%u32vec4_null"),
581 Values("Result must be an unsigned integer scalar")));
582
583 INSTANTIATE_TEST_SUITE_P(
584 GroupNonUniformBallotFindBadOperand, GroupNonUniform,
585 Combine(Values("OpGroupNonUniformBallotFindLSB",
586 "OpGroupNonUniformBallotFindMSB"),
587 Values("%u32"), Values(spv::Scope::Subgroup),
588 Values("%true", "%false", "%u32_0", "%int_0", "%float_0",
589 "%u32vec3_null", "%v2bool_false", "%v4float_null",
590 "%struct_null", "%v4int_null"),
591 Values("Value must be a 4-component unsigned integer vector")));
592
593 INSTANTIATE_TEST_SUITE_P(
594 GroupNonUniformIntegerArithmeticGood, GroupNonUniform,
595 Combine(Values("OpGroupNonUniformIAdd", "OpGroupNonUniformIMul",
596 "OpGroupNonUniformSMin", "OpGroupNonUniformSMax",
597 "OpGroupNonUniformBitwiseAnd", "OpGroupNonUniformBitwiseOr",
598 "OpGroupNonUniformBitwiseXor"),
599 Values("%u32", "%int", "%u32vec4", "%u32vec3", "%v4int"),
600 Values(spv::Scope::Subgroup),
601 Values("Reduce match_res", "InclusiveScan match_res",
602 "ExclusiveScan match_res",
603 "ClusteredReduce match_res %u32_0",
604 "PartitionedReduceNV match_res %u32vec4_null",
605 "PartitionedInclusiveScanNV match_res %u32vec4_null",
606 "PartitionedExclusiveScanNV match_res %v4int_null"),
607 Values("")));
608
609 INSTANTIATE_TEST_SUITE_P(
610 GroupNonUniformIntegerArithmeticBadResultType, GroupNonUniform,
611 Combine(Values("OpGroupNonUniformIAdd", "OpGroupNonUniformIMul",
612 "OpGroupNonUniformSMin", "OpGroupNonUniformSMax",
613 "OpGroupNonUniformBitwiseAnd", "OpGroupNonUniformBitwiseOr",
614 "OpGroupNonUniformBitwiseXor"),
615 Values("%bool", "%float", "%v4float", "%struct"),
616 Values(spv::Scope::Subgroup),
617 Values("Reduce match_res", "InclusiveScan match_res",
618 "ExclusiveScan match_res",
619 "ClusteredReduce match_res %u32_0"),
620 Values("Result must be an integer scalar or vector")));
621
622 INSTANTIATE_TEST_SUITE_P(
623 GroupNonUniformIntegerArithmeticBadValue, GroupNonUniform,
624 Combine(Values("OpGroupNonUniformIAdd", "OpGroupNonUniformIMul",
625 "OpGroupNonUniformSMin", "OpGroupNonUniformSMax",
626 "OpGroupNonUniformBitwiseAnd", "OpGroupNonUniformBitwiseOr",
627 "OpGroupNonUniformBitwiseXor"),
628 Values("%int", "%u32vec4", "%u32vec3", "%v4int"),
629 Values(spv::Scope::Subgroup),
630 Values("Reduce %u32_0", "InclusiveScan %u32_0",
631 "ExclusiveScan %u32_0", "ClusteredReduce %u32_0 %u32_0"),
632 Values("The type of Value must match the Result type")));
633
634 INSTANTIATE_TEST_SUITE_P(
635 GroupNonUniformIntegerArithmeticMissingClusterSize, GroupNonUniform,
636 Combine(
637 Values("OpGroupNonUniformIAdd", "OpGroupNonUniformIMul",
638 "OpGroupNonUniformSMin", "OpGroupNonUniformUMin",
639 "OpGroupNonUniformSMax", "OpGroupNonUniformUMax",
640 "OpGroupNonUniformBitwiseAnd", "OpGroupNonUniformBitwiseOr",
641 "OpGroupNonUniformBitwiseXor"),
642 Values("%u32"), Values(spv::Scope::Subgroup),
643 Values("ClusteredReduce match_res"),
644 Values(
645 "ClusterSize must be present when Operation is ClusteredReduce")));
646
647 INSTANTIATE_TEST_SUITE_P(
648 GroupNonUniformIntegerArithmeticMissingBallot, GroupNonUniform,
649 Combine(
650 Values("OpGroupNonUniformIAdd", "OpGroupNonUniformIMul",
651 "OpGroupNonUniformSMin", "OpGroupNonUniformUMin",
652 "OpGroupNonUniformSMax", "OpGroupNonUniformUMax",
653 "OpGroupNonUniformBitwiseAnd", "OpGroupNonUniformBitwiseOr",
654 "OpGroupNonUniformBitwiseXor"),
655 Values("%u32"), Values(spv::Scope::Subgroup),
656 Values("PartitionedReduceNV match_res",
657 "PartitionedInclusiveScanNV match_res",
658 "PartitionedExclusiveScanNV match_res"),
659 Values("Ballot must be present when Operation is PartitionedReduceNV, "
660 "PartitionedInclusiveScanNV, or PartitionedExclusiveScanNV")));
661
662 INSTANTIATE_TEST_SUITE_P(
663 GroupNonUniformIntegerArithmeticBadClusterSizeType, GroupNonUniform,
664 Combine(Values("OpGroupNonUniformIAdd", "OpGroupNonUniformIMul",
665 "OpGroupNonUniformSMin", "OpGroupNonUniformUMin",
666 "OpGroupNonUniformSMax", "OpGroupNonUniformUMax",
667 "OpGroupNonUniformBitwiseAnd", "OpGroupNonUniformBitwiseOr",
668 "OpGroupNonUniformBitwiseXor"),
669 Values("%u32"), Values(spv::Scope::Subgroup),
670 Values("ClusteredReduce match_res %true",
671 "ClusteredReduce match_res %false",
672 "ClusteredReduce match_res %int_0",
673 "ClusteredReduce match_res %float_0",
674 "ClusteredReduce match_res %u32vec4_null",
675 "ClusteredReduce match_res %u32vec3_null",
676 "ClusteredReduce match_res %v2bool_false",
677 "ClusteredReduce match_res %v4float_null",
678 "ClusteredReduce match_res %struct_null",
679 "ClusteredReduce match_res %v4int_null"),
680 Values("ClusterSize must be an unsigned integer scalar")));
681
682 INSTANTIATE_TEST_SUITE_P(
683 GroupNonUniformIntegerArithmeticBadBallotType, GroupNonUniform,
684 Combine(Values("OpGroupNonUniformIAdd", "OpGroupNonUniformIMul",
685 "OpGroupNonUniformSMin", "OpGroupNonUniformUMin",
686 "OpGroupNonUniformSMax", "OpGroupNonUniformUMax",
687 "OpGroupNonUniformBitwiseAnd", "OpGroupNonUniformBitwiseOr",
688 "OpGroupNonUniformBitwiseXor"),
689 Values("%u32"), Values(spv::Scope::Subgroup),
690 Values("PartitionedReduceNV match_res %true",
691 "PartitionedReduceNV match_res %false",
692 "PartitionedReduceNV match_res %int_0",
693 "PartitionedReduceNV match_res %float_0",
694 "PartitionedReduceNV match_res %u32_0",
695 "PartitionedReduceNV match_res %u32vec3_null",
696 "PartitionedReduceNV match_res %v2bool_false",
697 "PartitionedReduceNV match_res %v4float_null",
698 "PartitionedReduceNV match_res %struct_null"),
699 Values("Ballot must be a 4-component integer vector")));
700
701 INSTANTIATE_TEST_SUITE_P(
702 GroupNonUniformIntegerArithmeticClusterSizeNotConstant, GroupNonUniform,
703 Combine(Values("OpGroupNonUniformIAdd", "OpGroupNonUniformIMul",
704 "OpGroupNonUniformSMin", "OpGroupNonUniformUMin",
705 "OpGroupNonUniformSMax", "OpGroupNonUniformUMax",
706 "OpGroupNonUniformBitwiseAnd", "OpGroupNonUniformBitwiseOr",
707 "OpGroupNonUniformBitwiseXor"),
708 Values("%u32"), Values(spv::Scope::Subgroup),
709 Values("ClusteredReduce match_res %u32_undef"),
710 Values("ClusterSize must be a constant instruction")));
711
712 INSTANTIATE_TEST_SUITE_P(
713 GroupNonUniformUnsignedIntegerArithmeticGood, GroupNonUniform,
714 Combine(Values("OpGroupNonUniformUMin", "OpGroupNonUniformUMax"),
715 Values("%u32", "%u32vec4", "%u32vec3"),
716 Values(spv::Scope::Subgroup),
717 Values("Reduce match_res", "InclusiveScan match_res",
718 "ExclusiveScan match_res",
719 "ClusteredReduce match_res %u32_0"),
720 Values("")));
721
722 INSTANTIATE_TEST_SUITE_P(
723 GroupNonUniformUnsignedIntegerArithmeticBadResultType, GroupNonUniform,
724 Combine(Values("OpGroupNonUniformUMin", "OpGroupNonUniformUMax"),
725 Values("%bool", "%int", "%float", "%v4float", "%struct", "%v4int"),
726 Values(spv::Scope::Subgroup),
727 Values("Reduce match_res", "InclusiveScan match_res",
728 "ExclusiveScan match_res",
729 "ClusteredReduce match_res %u32_0"),
730 Values("Result must be an unsigned integer scalar or vector")));
731
732 INSTANTIATE_TEST_SUITE_P(
733 GroupNonUniformUnsignedIntegerArithmeticBadValue, GroupNonUniform,
734 Combine(Values("OpGroupNonUniformUMin", "OpGroupNonUniformUMax"),
735 Values("%u32vec4", "%u32vec3"), Values(spv::Scope::Subgroup),
736 Values("Reduce %u32_0", "InclusiveScan %u32_0",
737 "ExclusiveScan %u32_0", "ClusteredReduce %u32_0 %u32_0"),
738 Values("The type of Value must match the Result type")));
739
740 INSTANTIATE_TEST_SUITE_P(
741 GroupNonUniformFloatArithmeticGood, GroupNonUniform,
742 Combine(Values("OpGroupNonUniformFAdd", "OpGroupNonUniformFMul",
743 "OpGroupNonUniformFMin", "OpGroupNonUniformFMax"),
744 Values("%float", "%v4float"), Values(spv::Scope::Subgroup),
745 Values("Reduce match_res", "InclusiveScan match_res",
746 "ExclusiveScan match_res",
747 "ClusteredReduce match_res %u32_0"),
748 Values("")));
749
750 INSTANTIATE_TEST_SUITE_P(
751 GroupNonUniformFloatArithmeticBadResultType, GroupNonUniform,
752 Combine(Values("OpGroupNonUniformFAdd", "OpGroupNonUniformFMul",
753 "OpGroupNonUniformFMin", "OpGroupNonUniformFMax"),
754 Values("%bool", "%u32", "%int", "%u32vec4", "%u32vec3", "%struct",
755 "%v4int"),
756 Values(spv::Scope::Subgroup),
757 Values("Reduce match_res", "InclusiveScan match_res",
758 "ExclusiveScan match_res",
759 "ClusteredReduce match_res %u32_0"),
760 Values("Result must be a floating-point scalar or vector")));
761
762 INSTANTIATE_TEST_SUITE_P(
763 GroupNonUniformFloatArithmeticBadValue, GroupNonUniform,
764 Combine(Values("OpGroupNonUniformFAdd", "OpGroupNonUniformFMul",
765 "OpGroupNonUniformFMin", "OpGroupNonUniformFMax"),
766 Values("%v4float"), Values(spv::Scope::Subgroup),
767 Values("Reduce %float_0", "InclusiveScan %float_0",
768 "ExclusiveScan %float_0", "ClusteredReduce %float_0 %u32_0"),
769 Values("The type of Value must match the Result type")));
770
771 INSTANTIATE_TEST_SUITE_P(
772 GroupNonUniformFloatArithmeticMissingClusterSize, GroupNonUniform,
773 Combine(
774 Values("OpGroupNonUniformFAdd", "OpGroupNonUniformFMul",
775 "OpGroupNonUniformFMin", "OpGroupNonUniformFMax"),
776 Values("%float"), Values(spv::Scope::Subgroup),
777 Values("ClusteredReduce match_res"),
778 Values(
779 "ClusterSize must be present when Operation is ClusteredReduce")));
780
781 INSTANTIATE_TEST_SUITE_P(
782 GroupNonUniformFloatArithmeticBadClusterSizeType, GroupNonUniform,
783 Combine(Values("OpGroupNonUniformFAdd", "OpGroupNonUniformFMul",
784 "OpGroupNonUniformFMin", "OpGroupNonUniformFMax"),
785 Values("%float"), Values(spv::Scope::Subgroup),
786 Values("ClusteredReduce match_res %true",
787 "ClusteredReduce match_res %false",
788 "ClusteredReduce match_res %int_0",
789 "ClusteredReduce match_res %float_0",
790 "ClusteredReduce match_res %u32vec4_null",
791 "ClusteredReduce match_res %u32vec3_null",
792 "ClusteredReduce match_res %v2bool_false",
793 "ClusteredReduce match_res %v4float_null",
794 "ClusteredReduce match_res %struct_null",
795 "ClusteredReduce match_res %v4int_null"),
796 Values("ClusterSize must be an unsigned integer scalar")));
797
798 INSTANTIATE_TEST_SUITE_P(
799 GroupNonUniformFloatArithmeticClusterSizeNotConstant, GroupNonUniform,
800 Combine(Values("OpGroupNonUniformFAdd", "OpGroupNonUniformFMul",
801 "OpGroupNonUniformFMin", "OpGroupNonUniformFMax"),
802 Values("%float"), Values(spv::Scope::Subgroup),
803 Values("ClusteredReduce match_res %u32_undef"),
804 Values("ClusterSize must be a constant instruction")));
805
806 INSTANTIATE_TEST_SUITE_P(
807 GroupNonUniformBooleanArithmeticGood, GroupNonUniform,
808 Combine(Values("OpGroupNonUniformLogicalAnd", "OpGroupNonUniformLogicalOr",
809 "OpGroupNonUniformLogicalXor"),
810 Values("%bool", "%v2bool"), Values(spv::Scope::Subgroup),
811 Values("Reduce match_res", "InclusiveScan match_res",
812 "ExclusiveScan match_res",
813 "ClusteredReduce match_res %u32_0"),
814 Values("")));
815
816 INSTANTIATE_TEST_SUITE_P(
817 GroupNonUniformBooleanArithmeticBadResultType, GroupNonUniform,
818 Combine(Values("OpGroupNonUniformLogicalAnd", "OpGroupNonUniformLogicalOr",
819 "OpGroupNonUniformLogicalXor"),
820 Values("%u32", "%int", "%float", "%u32vec4", "%u32vec3", "%struct",
821 "%v4float", "%v4int"),
822 Values(spv::Scope::Subgroup),
823 Values("Reduce match_res", "InclusiveScan match_res",
824 "ExclusiveScan match_res",
825 "ClusteredReduce match_res %u32_0"),
826 Values("Result must be a boolean scalar or vector")));
827
828 INSTANTIATE_TEST_SUITE_P(
829 GroupNonUniformBooleanArithmeticBadValue, GroupNonUniform,
830 Combine(Values("OpGroupNonUniformLogicalAnd", "OpGroupNonUniformLogicalOr",
831 "OpGroupNonUniformLogicalXor"),
832 Values("%v2bool"), Values(spv::Scope::Subgroup),
833 Values("Reduce %true", "InclusiveScan %true",
834 "ExclusiveScan %false", "ClusteredReduce %false %u32_0"),
835 Values("The type of Value must match the Result type")));
836
837 INSTANTIATE_TEST_SUITE_P(
838 GroupNonUniformBooleanArithmeticMissingClusterSize, GroupNonUniform,
839 Combine(
840 Values("OpGroupNonUniformLogicalAnd", "OpGroupNonUniformLogicalOr",
841 "OpGroupNonUniformLogicalXor"),
842 Values("%bool"), Values(spv::Scope::Subgroup),
843 Values("ClusteredReduce match_res"),
844 Values(
845 "ClusterSize must be present when Operation is ClusteredReduce")));
846
847 INSTANTIATE_TEST_SUITE_P(
848 GroupNonUniformBooleanArithmeticBadClusterSizeType, GroupNonUniform,
849 Combine(Values("OpGroupNonUniformLogicalAnd", "OpGroupNonUniformLogicalOr",
850 "OpGroupNonUniformLogicalXor"),
851 Values("%bool"), Values(spv::Scope::Subgroup),
852 Values("ClusteredReduce match_res %true",
853 "ClusteredReduce match_res %false",
854 "ClusteredReduce match_res %int_0",
855 "ClusteredReduce match_res %float_0",
856 "ClusteredReduce match_res %u32vec4_null",
857 "ClusteredReduce match_res %u32vec3_null",
858 "ClusteredReduce match_res %v2bool_false",
859 "ClusteredReduce match_res %v4float_null",
860 "ClusteredReduce match_res %struct_null",
861 "ClusteredReduce match_res %v4int_null"),
862 Values("ClusterSize must be an unsigned integer scalar")));
863
864 INSTANTIATE_TEST_SUITE_P(
865 GroupNonUniformBooleanArithmeticClusterSizeNotConstant, GroupNonUniform,
866 Combine(Values("OpGroupNonUniformLogicalAnd", "OpGroupNonUniformLogicalOr",
867 "OpGroupNonUniformLogicalXor"),
868 Values("%bool"), Values(spv::Scope::Subgroup),
869 Values("ClusteredReduce match_res %u32_undef"),
870 Values("ClusterSize must be a constant instruction")));
871
TEST_F(ValidateGroupNonUniform, VulkanGroupNonUniformBallotBitCountOperation)872 TEST_F(ValidateGroupNonUniform, VulkanGroupNonUniformBallotBitCountOperation) {
873 std::string test = R"(
874 OpCapability Shader
875 OpCapability GroupNonUniform
876 OpCapability GroupNonUniformBallot
877 OpCapability GroupNonUniformClustered
878 OpMemoryModel Logical GLSL450
879 OpEntryPoint GLCompute %main "main"
880 OpExecutionMode %main LocalSize 1 1 1
881 %void = OpTypeVoid
882 %func = OpTypeFunction %void
883 %u32 = OpTypeInt 32 0
884 %u32vec4 = OpTypeVector %u32 4
885 %u32_0 = OpConstant %u32 0
886 %u32vec4_null = OpConstantComposite %u32vec4 %u32_0 %u32_0 %u32_0 %u32_0
887 %subgroup = OpConstant %u32 3
888 %main = OpFunction %void None %func
889 %main_entry = OpLabel
890 %result = OpGroupNonUniformBallotBitCount %u32 %subgroup ClusteredReduce %u32vec4_null
891 OpReturn
892 OpFunctionEnd
893 )";
894
895 CompileSuccessfully(test, SPV_ENV_VULKAN_1_1);
896 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1));
897 EXPECT_THAT(
898 getDiagnosticString(),
899 AnyVUID("VUID-StandaloneSpirv-OpGroupNonUniformBallotBitCount-04685"));
900 EXPECT_THAT(
901 getDiagnosticString(),
902 HasSubstr(
903 "In Vulkan: The OpGroupNonUniformBallotBitCount group operation must "
904 "be only: Reduce, InclusiveScan, or ExclusiveScan."));
905 }
906
TEST_F(ValidateGroupNonUniform, BroadcastNonConstantSpv1p4)907 TEST_F(ValidateGroupNonUniform, BroadcastNonConstantSpv1p4) {
908 const std::string text = R"(
909 OpCapability Shader
910 OpCapability GroupNonUniformBallot
911 OpMemoryModel Logical GLSL450
912 OpEntryPoint GLCompute %main "main" %var
913 OpExecutionMode %main LocalSize 1 1 1
914 OpDecorate %var DescriptorSet 0
915 OpDecorate %var Binding 0
916 OpDecorate %struct Block
917 OpMemberDecorate %struct 0 Offset 0
918 %void = OpTypeVoid
919 %int = OpTypeInt 32 0
920 %int_0 = OpConstant %int 0
921 %subgroup = OpConstant %int 3
922 %struct = OpTypeStruct %int
923 %ptr_struct = OpTypePointer StorageBuffer %struct
924 %ptr_int = OpTypePointer StorageBuffer %int
925 %var = OpVariable %ptr_struct StorageBuffer
926 %void_fn = OpTypeFunction %void
927 %main = OpFunction %void None %void_fn
928 %entry = OpLabel
929 %gep = OpAccessChain %ptr_int %var %int_0
930 %ld = OpLoad %int %gep
931 %broadcast = OpGroupNonUniformBroadcast %int %subgroup %int_0 %ld
932 OpReturn
933 OpFunctionEnd
934 )";
935
936 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
937 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
938 ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
939 EXPECT_THAT(
940 getDiagnosticString(),
941 HasSubstr("Before SPIR-V 1.5, Id must be a constant instruction"));
942 }
943
TEST_F(ValidateGroupNonUniform, BroadcastNonConstantSpv1p5)944 TEST_F(ValidateGroupNonUniform, BroadcastNonConstantSpv1p5) {
945 const std::string text = R"(
946 OpCapability Shader
947 OpCapability GroupNonUniformBallot
948 OpMemoryModel Logical GLSL450
949 OpEntryPoint GLCompute %main "main" %var
950 OpExecutionMode %main LocalSize 1 1 1
951 OpDecorate %var DescriptorSet 0
952 OpDecorate %var Binding 0
953 OpDecorate %struct Block
954 OpMemberDecorate %struct 0 Offset 0
955 %void = OpTypeVoid
956 %int = OpTypeInt 32 0
957 %int_0 = OpConstant %int 0
958 %subgroup = OpConstant %int 3
959 %struct = OpTypeStruct %int
960 %ptr_struct = OpTypePointer StorageBuffer %struct
961 %ptr_int = OpTypePointer StorageBuffer %int
962 %var = OpVariable %ptr_struct StorageBuffer
963 %void_fn = OpTypeFunction %void
964 %main = OpFunction %void None %void_fn
965 %entry = OpLabel
966 %gep = OpAccessChain %ptr_int %var %int_0
967 %ld = OpLoad %int %gep
968 %broadcast = OpGroupNonUniformBroadcast %int %subgroup %int_0 %ld
969 OpReturn
970 OpFunctionEnd
971 )";
972
973 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_5);
974 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
975 }
976
TEST_F(ValidateGroupNonUniform, QuadBroadcastNonConstantSpv1p4)977 TEST_F(ValidateGroupNonUniform, QuadBroadcastNonConstantSpv1p4) {
978 const std::string text = R"(
979 OpCapability Shader
980 OpCapability GroupNonUniformQuad
981 OpMemoryModel Logical GLSL450
982 OpEntryPoint GLCompute %main "main" %var
983 OpExecutionMode %main LocalSize 1 1 1
984 OpDecorate %var DescriptorSet 0
985 OpDecorate %var Binding 0
986 OpDecorate %struct Block
987 OpMemberDecorate %struct 0 Offset 0
988 %void = OpTypeVoid
989 %int = OpTypeInt 32 0
990 %int_0 = OpConstant %int 0
991 %subgroup = OpConstant %int 3
992 %struct = OpTypeStruct %int
993 %ptr_struct = OpTypePointer StorageBuffer %struct
994 %ptr_int = OpTypePointer StorageBuffer %int
995 %var = OpVariable %ptr_struct StorageBuffer
996 %void_fn = OpTypeFunction %void
997 %main = OpFunction %void None %void_fn
998 %entry = OpLabel
999 %gep = OpAccessChain %ptr_int %var %int_0
1000 %ld = OpLoad %int %gep
1001 %broadcast = OpGroupNonUniformQuadBroadcast %int %subgroup %int_0 %ld
1002 OpReturn
1003 OpFunctionEnd
1004 )";
1005
1006 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
1007 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1008 ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1009 EXPECT_THAT(
1010 getDiagnosticString(),
1011 HasSubstr("Before SPIR-V 1.5, Index must be a constant instruction"));
1012 }
1013
TEST_F(ValidateGroupNonUniform, QuadBroadcastNonConstantSpv1p5)1014 TEST_F(ValidateGroupNonUniform, QuadBroadcastNonConstantSpv1p5) {
1015 const std::string text = R"(
1016 OpCapability Shader
1017 OpCapability GroupNonUniformQuad
1018 OpMemoryModel Logical GLSL450
1019 OpEntryPoint GLCompute %main "main" %var
1020 OpExecutionMode %main LocalSize 1 1 1
1021 OpDecorate %var DescriptorSet 0
1022 OpDecorate %var Binding 0
1023 OpDecorate %struct Block
1024 OpMemberDecorate %struct 0 Offset 0
1025 %void = OpTypeVoid
1026 %int = OpTypeInt 32 0
1027 %int_0 = OpConstant %int 0
1028 %subgroup = OpConstant %int 3
1029 %struct = OpTypeStruct %int
1030 %ptr_struct = OpTypePointer StorageBuffer %struct
1031 %ptr_int = OpTypePointer StorageBuffer %int
1032 %var = OpVariable %ptr_struct StorageBuffer
1033 %void_fn = OpTypeFunction %void
1034 %main = OpFunction %void None %void_fn
1035 %entry = OpLabel
1036 %gep = OpAccessChain %ptr_int %var %int_0
1037 %ld = OpLoad %int %gep
1038 %broadcast = OpGroupNonUniformQuadBroadcast %int %subgroup %int_0 %ld
1039 OpReturn
1040 OpFunctionEnd
1041 )";
1042
1043 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_5);
1044 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
1045 }
1046
1047 } // namespace
1048 } // namespace val
1049 } // namespace spvtools
1050