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