1 // Copyright (c) 2018 Google LLC.
2 // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights
3 // reserved.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 // Tests validation rules of GLSL.450.std and OpenCL.std extended instructions.
18 // Doesn't test OpenCL.std vector size 2, 3, 4, 8 or 16 rules (not supported
19 // by standard SPIR-V).
20 
21 #include <cstring>
22 #include <sstream>
23 #include <string>
24 #include <tuple>
25 #include <utility>
26 #include <vector>
27 
28 #include "gmock/gmock.h"
29 #include "source/spirv_target_env.h"
30 #include "test/unit_spirv.h"
31 #include "test/val/val_code_generator.h"
32 #include "test/val/val_fixtures.h"
33 
34 namespace spvtools {
35 namespace val {
36 namespace {
37 
38 struct TestResult {
TestResultspvtools::val::__anond8c2e0130111::TestResult39   TestResult(spv_result_t in_validation_result = SPV_SUCCESS,
40              const char* in_error_str = nullptr,
41              const char* in_error_str2 = nullptr)
42       : validation_result(in_validation_result),
43         error_str(in_error_str),
44         error_str2(in_error_str2) {}
45   spv_result_t validation_result;
46   const char* error_str;
47   const char* error_str2;
48 };
49 
50 using ::testing::Combine;
51 using ::testing::HasSubstr;
52 using ::testing::Not;
53 using ::testing::Values;
54 using ::testing::ValuesIn;
55 
56 using ValidateBuiltIns = spvtest::ValidateBase<bool>;
57 using ValidateVulkanSubgroupBuiltIns = spvtest::ValidateBase<
58     std::tuple<const char*, const char*, const char*, const char*, TestResult>>;
59 using ValidateVulkanCombineBuiltInExecutionModelDataTypeResult =
60     spvtest::ValidateBase<std::tuple<const char*, const char*, const char*,
61                                      const char*, const char*, TestResult>>;
62 using ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult =
63     spvtest::ValidateBase<std::tuple<const char*, const char*, const char*,
64                                      const char*, TestResult>>;
65 using ValidateVulkanCombineBuiltInArrayedVariable = spvtest::ValidateBase<
66     std::tuple<const char*, const char*, const char*, const char*, TestResult>>;
67 using ValidateWebGPUCombineBuiltInArrayedVariable = spvtest::ValidateBase<
68     std::tuple<const char*, const char*, const char*, const char*, TestResult>>;
69 using ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult =
70     spvtest::ValidateBase<
71         std::tuple<const char*, const char*, const char*, const char*,
72                    const char*, const char*, const char*, TestResult>>;
73 
74 using ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult =
75     spvtest::ValidateBase<std::tuple<spv_target_env, const char*, const char*,
76                                      const char*, const char*, const char*,
77                                      const char*, const char*, TestResult>>;
78 
InitializerRequired(spv_target_env env,const char * const storage_class)79 bool InitializerRequired(spv_target_env env, const char* const storage_class) {
80   return spvIsWebGPUEnv(env) && (strncmp(storage_class, "Output", 6) == 0 ||
81                                  strncmp(storage_class, "Private", 7) == 0 ||
82                                  strncmp(storage_class, "Function", 8) == 0);
83 }
84 
GetInMainCodeGenerator(spv_target_env env,const char * const built_in,const char * const execution_model,const char * const storage_class,const char * const capabilities,const char * const extensions,const char * const data_type)85 CodeGenerator GetInMainCodeGenerator(spv_target_env env,
86                                      const char* const built_in,
87                                      const char* const execution_model,
88                                      const char* const storage_class,
89                                      const char* const capabilities,
90                                      const char* const extensions,
91                                      const char* const data_type) {
92   CodeGenerator generator =
93       spvIsWebGPUEnv(env) ? CodeGenerator::GetWebGPUShaderCodeGenerator()
94                           : CodeGenerator::GetDefaultShaderCodeGenerator();
95 
96   if (capabilities) {
97     generator.capabilities_ += capabilities;
98   }
99   if (extensions) {
100     generator.extensions_ += extensions;
101   }
102 
103   generator.before_types_ = "OpMemberDecorate %built_in_type 0 BuiltIn ";
104   generator.before_types_ += built_in;
105   generator.before_types_ += "\n";
106 
107   std::ostringstream after_types;
108 
109   after_types << "%built_in_type = OpTypeStruct " << data_type << "\n";
110   if (InitializerRequired(env, storage_class)) {
111     after_types << "%built_in_null = OpConstantNull %built_in_type\n";
112   }
113   after_types << "%built_in_ptr = OpTypePointer " << storage_class
114               << " %built_in_type\n";
115   after_types << "%built_in_var = OpVariable %built_in_ptr " << storage_class;
116   if (InitializerRequired(env, storage_class)) {
117     after_types << " %built_in_null";
118   }
119   after_types << "\n";
120   after_types << "%data_ptr = OpTypePointer " << storage_class << " "
121               << data_type << "\n";
122   generator.after_types_ = after_types.str();
123 
124   EntryPoint entry_point;
125   entry_point.name = "main";
126   entry_point.execution_model = execution_model;
127   if (strncmp(storage_class, "Input", 5) == 0 ||
128       strncmp(storage_class, "Output", 6) == 0) {
129     entry_point.interfaces = "%built_in_var";
130   }
131 
132   std::ostringstream execution_modes;
133   if (0 == std::strcmp(execution_model, "Fragment")) {
134     execution_modes << "OpExecutionMode %" << entry_point.name
135                     << " OriginUpperLeft\n";
136     if (0 == std::strcmp(built_in, "FragDepth")) {
137       execution_modes << "OpExecutionMode %" << entry_point.name
138                       << " DepthReplacing\n";
139     }
140   }
141   if (0 == std::strcmp(execution_model, "Geometry")) {
142     execution_modes << "OpExecutionMode %" << entry_point.name
143                     << " InputPoints\n";
144     execution_modes << "OpExecutionMode %" << entry_point.name
145                     << " OutputPoints\n";
146   }
147   if (0 == std::strcmp(execution_model, "GLCompute")) {
148     execution_modes << "OpExecutionMode %" << entry_point.name
149                     << " LocalSize 1 1 1\n";
150   }
151   entry_point.execution_modes = execution_modes.str();
152 
153   entry_point.body = R"(
154 %ptr = OpAccessChain %data_ptr %built_in_var %u32_0
155 )";
156   generator.entry_points_.push_back(std::move(entry_point));
157 
158   return generator;
159 }
160 
161 // Allows test parameter test to list all possible VUIDs with a delimiter that
162 // is then split here to check if one VUID was in the error message
163 MATCHER_P(AnyVUID, vuid_set, "VUID from the set is in error message") {
164   // use space as delimiter because clang-format will properly line break VUID
165   // strings which is important the entire VUID is in a single line for script
166   // to scan
167   std::string delimiter = " ";
168   std::string token;
169   std::string vuids = std::string(vuid_set);
170   size_t position;
171 
172   // Catch case were someone accidentally left spaces by trimming string
173   // clang-format off
__anond8c2e0130202(unsigned char c) 174   vuids.erase(std::find_if(vuids.rbegin(), vuids.rend(), [](unsigned char c) {
175     return (c != ' ');
176   }).base(), vuids.end());
__anond8c2e0130302(unsigned char c) 177   vuids.erase(vuids.begin(), std::find_if(vuids.begin(), vuids.end(), [](unsigned char c) {
178     return (c != ' ');
179   }));
180   // clang-format on
181 
182   do {
183     position = vuids.find(delimiter);
184     if (position != std::string::npos) {
185       token = vuids.substr(0, position);
186       vuids.erase(0, position + delimiter.length());
187     } else {
188       token = vuids.substr(0);  // last item
189     }
190 
191     // arg contains diagnostic message
192     if (arg.find(token) != std::string::npos) {
193       return true;
194     }
195   } while (position != std::string::npos);
196   return false;
197 }
198 
TEST_P(ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,InMain)199 TEST_P(ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, InMain) {
200   const char* const built_in = std::get<0>(GetParam());
201   const char* const execution_model = std::get<1>(GetParam());
202   const char* const storage_class = std::get<2>(GetParam());
203   const char* const data_type = std::get<3>(GetParam());
204   const char* const vuid = std::get<4>(GetParam());
205   const TestResult& test_result = std::get<5>(GetParam());
206 
207   CodeGenerator generator =
208       GetInMainCodeGenerator(SPV_ENV_VULKAN_1_0, built_in, execution_model,
209                              storage_class, NULL, NULL, data_type);
210 
211   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
212   ASSERT_EQ(test_result.validation_result,
213             ValidateInstructions(SPV_ENV_VULKAN_1_0));
214   if (test_result.error_str) {
215     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
216   }
217   if (test_result.error_str2) {
218     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
219   }
220   if (vuid) {
221     EXPECT_THAT(getDiagnosticString(), AnyVUID(vuid));
222   }
223 }
224 
TEST_P(ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,InMain)225 TEST_P(ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, InMain) {
226   const char* const built_in = std::get<0>(GetParam());
227   const char* const execution_model = std::get<1>(GetParam());
228   const char* const storage_class = std::get<2>(GetParam());
229   const char* const data_type = std::get<3>(GetParam());
230   const TestResult& test_result = std::get<4>(GetParam());
231 
232   CodeGenerator generator =
233       GetInMainCodeGenerator(SPV_ENV_WEBGPU_0, built_in, execution_model,
234                              storage_class, NULL, NULL, data_type);
235 
236   CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
237   ASSERT_EQ(test_result.validation_result,
238             ValidateInstructions(SPV_ENV_WEBGPU_0));
239   if (test_result.error_str) {
240     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
241   }
242   if (test_result.error_str2) {
243     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
244   }
245 }
246 
TEST_P(ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,InMain)247 TEST_P(
248     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
249     InMain) {
250   const char* const built_in = std::get<0>(GetParam());
251   const char* const execution_model = std::get<1>(GetParam());
252   const char* const storage_class = std::get<2>(GetParam());
253   const char* const data_type = std::get<3>(GetParam());
254   const char* const capabilities = std::get<4>(GetParam());
255   const char* const extensions = std::get<5>(GetParam());
256   const char* const vuid = std::get<6>(GetParam());
257   const TestResult& test_result = std::get<7>(GetParam());
258 
259   CodeGenerator generator = GetInMainCodeGenerator(
260       SPV_ENV_VULKAN_1_0, built_in, execution_model, storage_class,
261       capabilities, extensions, data_type);
262 
263   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
264   ASSERT_EQ(test_result.validation_result,
265             ValidateInstructions(SPV_ENV_VULKAN_1_0));
266   if (test_result.error_str) {
267     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
268   }
269   if (test_result.error_str2) {
270     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
271   }
272   if (vuid) {
273     EXPECT_THAT(getDiagnosticString(), AnyVUID(vuid));
274   }
275 }
276 
TEST_P(ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,InMain)277 TEST_P(
278     ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
279     InMain) {
280   const spv_target_env env = std::get<0>(GetParam());
281   const char* const built_in = std::get<1>(GetParam());
282   const char* const execution_model = std::get<2>(GetParam());
283   const char* const storage_class = std::get<3>(GetParam());
284   const char* const data_type = std::get<4>(GetParam());
285   const char* const capabilities = std::get<5>(GetParam());
286   const char* const extensions = std::get<6>(GetParam());
287   const char* const vuid = std::get<7>(GetParam());
288   const TestResult& test_result = std::get<8>(GetParam());
289 
290   CodeGenerator generator =
291       GetInMainCodeGenerator(env, built_in, execution_model, storage_class,
292                              capabilities, extensions, data_type);
293 
294   CompileSuccessfully(generator.Build(), env);
295   ASSERT_EQ(test_result.validation_result, ValidateInstructions(env));
296   if (test_result.error_str) {
297     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
298   }
299   if (test_result.error_str2) {
300     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
301   }
302   if (vuid) {
303     EXPECT_THAT(getDiagnosticString(), AnyVUID(vuid));
304   }
305 }
306 
GetInFunctionCodeGenerator(spv_target_env env,const char * const built_in,const char * const execution_model,const char * const storage_class,const char * const capabilities,const char * const extensions,const char * const data_type)307 CodeGenerator GetInFunctionCodeGenerator(spv_target_env env,
308                                          const char* const built_in,
309                                          const char* const execution_model,
310                                          const char* const storage_class,
311                                          const char* const capabilities,
312                                          const char* const extensions,
313                                          const char* const data_type) {
314   CodeGenerator generator =
315       spvIsWebGPUEnv(env) ? CodeGenerator::GetWebGPUShaderCodeGenerator()
316                           : CodeGenerator::GetDefaultShaderCodeGenerator();
317 
318   if (capabilities) {
319     generator.capabilities_ += capabilities;
320   }
321   if (extensions) {
322     generator.extensions_ += extensions;
323   }
324 
325   generator.before_types_ = "OpMemberDecorate %built_in_type 0 BuiltIn ";
326   generator.before_types_ += built_in;
327   generator.before_types_ += "\n";
328 
329   std::ostringstream after_types;
330   after_types << "%built_in_type = OpTypeStruct " << data_type << "\n";
331   if (InitializerRequired(env, storage_class)) {
332     after_types << "%built_in_null = OpConstantNull %built_in_type\n";
333   }
334   after_types << "%built_in_ptr = OpTypePointer " << storage_class
335               << " %built_in_type\n";
336   after_types << "%built_in_var = OpVariable %built_in_ptr " << storage_class;
337   if (InitializerRequired(env, storage_class)) {
338     after_types << " %built_in_null";
339   }
340   after_types << "\n";
341   after_types << "%data_ptr = OpTypePointer " << storage_class << " "
342               << data_type << "\n";
343   generator.after_types_ = after_types.str();
344 
345   EntryPoint entry_point;
346   entry_point.name = "main";
347   entry_point.execution_model = execution_model;
348   if (strncmp(storage_class, "Input", 5) == 0 ||
349       strncmp(storage_class, "Output", 6) == 0) {
350     entry_point.interfaces = "%built_in_var";
351   }
352 
353   std::ostringstream execution_modes;
354   if (0 == std::strcmp(execution_model, "Fragment")) {
355     execution_modes << "OpExecutionMode %" << entry_point.name
356                     << " OriginUpperLeft\n";
357     if (0 == std::strcmp(built_in, "FragDepth")) {
358       execution_modes << "OpExecutionMode %" << entry_point.name
359                       << " DepthReplacing\n";
360     }
361   }
362   if (0 == std::strcmp(execution_model, "Geometry")) {
363     execution_modes << "OpExecutionMode %" << entry_point.name
364                     << " InputPoints\n";
365     execution_modes << "OpExecutionMode %" << entry_point.name
366                     << " OutputPoints\n";
367   }
368   if (0 == std::strcmp(execution_model, "GLCompute")) {
369     execution_modes << "OpExecutionMode %" << entry_point.name
370                     << " LocalSize 1 1 1\n";
371   }
372   entry_point.execution_modes = execution_modes.str();
373 
374   entry_point.body = R"(
375 %val2 = OpFunctionCall %void %foo
376 )";
377 
378   std::string function_body = R"(
379 %foo = OpFunction %void None %func
380 %foo_entry = OpLabel
381 %ptr = OpAccessChain %data_ptr %built_in_var %u32_0
382 OpReturn
383 OpFunctionEnd
384 )";
385 
386   if (spvIsWebGPUEnv(env)) {
387     generator.after_types_ += function_body;
388   } else {
389     generator.add_at_the_end_ = function_body;
390   }
391 
392   generator.entry_points_.push_back(std::move(entry_point));
393 
394   return generator;
395 }
396 
TEST_P(ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,InFunction)397 TEST_P(ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, InFunction) {
398   const char* const built_in = std::get<0>(GetParam());
399   const char* const execution_model = std::get<1>(GetParam());
400   const char* const storage_class = std::get<2>(GetParam());
401   const char* const data_type = std::get<3>(GetParam());
402   const char* const vuid = std::get<4>(GetParam());
403   const TestResult& test_result = std::get<5>(GetParam());
404 
405   CodeGenerator generator =
406       GetInFunctionCodeGenerator(SPV_ENV_VULKAN_1_0, built_in, execution_model,
407                                  storage_class, NULL, NULL, data_type);
408 
409   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
410   ASSERT_EQ(test_result.validation_result,
411             ValidateInstructions(SPV_ENV_VULKAN_1_0));
412   if (test_result.error_str) {
413     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
414   }
415   if (test_result.error_str2) {
416     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
417   }
418   if (vuid) {
419     EXPECT_THAT(getDiagnosticString(), AnyVUID(vuid));
420   }
421 }
422 
TEST_P(ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,InFunction)423 TEST_P(ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, InFunction) {
424   const char* const built_in = std::get<0>(GetParam());
425   const char* const execution_model = std::get<1>(GetParam());
426   const char* const storage_class = std::get<2>(GetParam());
427   const char* const data_type = std::get<3>(GetParam());
428   const TestResult& test_result = std::get<4>(GetParam());
429 
430   CodeGenerator generator =
431       GetInFunctionCodeGenerator(SPV_ENV_WEBGPU_0, built_in, execution_model,
432                                  storage_class, NULL, NULL, data_type);
433 
434   CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
435   ASSERT_EQ(test_result.validation_result,
436             ValidateInstructions(SPV_ENV_WEBGPU_0));
437   if (test_result.error_str) {
438     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
439   }
440   if (test_result.error_str2) {
441     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
442   }
443 }
444 
TEST_P(ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,InFunction)445 TEST_P(
446     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
447     InFunction) {
448   const char* const built_in = std::get<0>(GetParam());
449   const char* const execution_model = std::get<1>(GetParam());
450   const char* const storage_class = std::get<2>(GetParam());
451   const char* const data_type = std::get<3>(GetParam());
452   const char* const capabilities = std::get<4>(GetParam());
453   const char* const extensions = std::get<5>(GetParam());
454   const char* const vuid = std::get<6>(GetParam());
455   const TestResult& test_result = std::get<7>(GetParam());
456 
457   CodeGenerator generator = GetInFunctionCodeGenerator(
458       SPV_ENV_VULKAN_1_0, built_in, execution_model, storage_class,
459       capabilities, extensions, data_type);
460 
461   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
462   ASSERT_EQ(test_result.validation_result,
463             ValidateInstructions(SPV_ENV_VULKAN_1_0));
464   if (test_result.error_str) {
465     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
466   }
467   if (test_result.error_str2) {
468     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
469   }
470   if (vuid) {
471     EXPECT_THAT(getDiagnosticString(), AnyVUID(vuid));
472   }
473 }
474 
GetVariableCodeGenerator(spv_target_env env,const char * const built_in,const char * const execution_model,const char * const storage_class,const char * const capabilities,const char * const extensions,const char * const data_type)475 CodeGenerator GetVariableCodeGenerator(spv_target_env env,
476                                        const char* const built_in,
477                                        const char* const execution_model,
478                                        const char* const storage_class,
479                                        const char* const capabilities,
480                                        const char* const extensions,
481                                        const char* const data_type) {
482   CodeGenerator generator =
483       spvIsWebGPUEnv(env) ? CodeGenerator::GetWebGPUShaderCodeGenerator()
484                           : CodeGenerator::GetDefaultShaderCodeGenerator();
485 
486   if (capabilities) {
487     generator.capabilities_ += capabilities;
488   }
489   if (extensions) {
490     generator.extensions_ += extensions;
491   }
492 
493   generator.before_types_ = "OpDecorate %built_in_var BuiltIn ";
494   generator.before_types_ += built_in;
495   generator.before_types_ += "\n";
496 
497   std::ostringstream after_types;
498   if (InitializerRequired(env, storage_class)) {
499     after_types << "%built_in_null = OpConstantNull " << data_type << "\n";
500   }
501   after_types << "%built_in_ptr = OpTypePointer " << storage_class << " "
502               << data_type << "\n";
503   after_types << "%built_in_var = OpVariable %built_in_ptr " << storage_class;
504   if (InitializerRequired(env, storage_class)) {
505     after_types << " %built_in_null";
506   }
507   after_types << "\n";
508   generator.after_types_ = after_types.str();
509 
510   EntryPoint entry_point;
511   entry_point.name = "main";
512   entry_point.execution_model = execution_model;
513   if (strncmp(storage_class, "Input", 5) == 0 ||
514       strncmp(storage_class, "Output", 6) == 0) {
515     entry_point.interfaces = "%built_in_var";
516   }
517   // Any kind of reference would do.
518   entry_point.body = R"(
519 %val = OpBitcast %u32 %built_in_var
520 )";
521 
522   std::ostringstream execution_modes;
523   if (0 == std::strcmp(execution_model, "Fragment")) {
524     execution_modes << "OpExecutionMode %" << entry_point.name
525                     << " OriginUpperLeft\n";
526     if (0 == std::strcmp(built_in, "FragDepth")) {
527       execution_modes << "OpExecutionMode %" << entry_point.name
528                       << " DepthReplacing\n";
529     }
530   }
531   if (0 == std::strcmp(execution_model, "Geometry")) {
532     execution_modes << "OpExecutionMode %" << entry_point.name
533                     << " InputPoints\n";
534     execution_modes << "OpExecutionMode %" << entry_point.name
535                     << " OutputPoints\n";
536   }
537   if (0 == std::strcmp(execution_model, "GLCompute")) {
538     execution_modes << "OpExecutionMode %" << entry_point.name
539                     << " LocalSize 1 1 1\n";
540   }
541   entry_point.execution_modes = execution_modes.str();
542 
543   generator.entry_points_.push_back(std::move(entry_point));
544 
545   return generator;
546 }
547 
TEST_P(ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,Variable)548 TEST_P(ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, Variable) {
549   const char* const built_in = std::get<0>(GetParam());
550   const char* const execution_model = std::get<1>(GetParam());
551   const char* const storage_class = std::get<2>(GetParam());
552   const char* const data_type = std::get<3>(GetParam());
553   const char* const vuid = std::get<4>(GetParam());
554   const TestResult& test_result = std::get<5>(GetParam());
555 
556   CodeGenerator generator =
557       GetVariableCodeGenerator(SPV_ENV_VULKAN_1_0, built_in, execution_model,
558                                storage_class, NULL, NULL, data_type);
559 
560   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
561   ASSERT_EQ(test_result.validation_result,
562             ValidateInstructions(SPV_ENV_VULKAN_1_0));
563   if (test_result.error_str) {
564     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
565   }
566   if (test_result.error_str2) {
567     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
568   }
569   if (vuid) {
570     EXPECT_THAT(getDiagnosticString(), AnyVUID(vuid));
571   }
572 }
573 
TEST_P(ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,Variable)574 TEST_P(ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult, Variable) {
575   const char* const built_in = std::get<0>(GetParam());
576   const char* const execution_model = std::get<1>(GetParam());
577   const char* const storage_class = std::get<2>(GetParam());
578   const char* const data_type = std::get<3>(GetParam());
579   const TestResult& test_result = std::get<4>(GetParam());
580 
581   CodeGenerator generator =
582       GetVariableCodeGenerator(SPV_ENV_WEBGPU_0, built_in, execution_model,
583                                storage_class, NULL, NULL, data_type);
584 
585   CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
586   ASSERT_EQ(test_result.validation_result,
587             ValidateInstructions(SPV_ENV_WEBGPU_0));
588   if (test_result.error_str) {
589     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
590   }
591   if (test_result.error_str2) {
592     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
593   }
594 }
595 
TEST_P(ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,Variable)596 TEST_P(
597     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
598     Variable) {
599   const char* const built_in = std::get<0>(GetParam());
600   const char* const execution_model = std::get<1>(GetParam());
601   const char* const storage_class = std::get<2>(GetParam());
602   const char* const data_type = std::get<3>(GetParam());
603   const char* const capabilities = std::get<4>(GetParam());
604   const char* const extensions = std::get<5>(GetParam());
605   const char* const vuid = std::get<6>(GetParam());
606   const TestResult& test_result = std::get<7>(GetParam());
607 
608   CodeGenerator generator = GetVariableCodeGenerator(
609       SPV_ENV_VULKAN_1_0, built_in, execution_model, storage_class,
610       capabilities, extensions, data_type);
611 
612   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
613   ASSERT_EQ(test_result.validation_result,
614             ValidateInstructions(SPV_ENV_VULKAN_1_0));
615   if (test_result.error_str) {
616     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
617   }
618   if (test_result.error_str2) {
619     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
620   }
621   if (vuid) {
622     EXPECT_THAT(getDiagnosticString(), AnyVUID(vuid));
623   }
624 }
625 
626 INSTANTIATE_TEST_SUITE_P(
627     ClipAndCullDistanceOutputSuccess,
628     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
629     Combine(Values("ClipDistance", "CullDistance"),
630             Values("Vertex", "Geometry", "TessellationControl",
631                    "TessellationEvaluation"),
632             Values("Output"), Values("%f32arr2", "%f32arr4"), Values(nullptr),
633             Values(TestResult())));
634 
635 INSTANTIATE_TEST_SUITE_P(
636     ClipAndCullDistanceInputSuccess,
637     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
638     Combine(Values("ClipDistance", "CullDistance"),
639             Values("Fragment", "Geometry", "TessellationControl",
640                    "TessellationEvaluation"),
641             Values("Input"), Values("%f32arr2", "%f32arr4"), Values(nullptr),
642             Values(TestResult())));
643 
644 INSTANTIATE_TEST_SUITE_P(
645     ClipAndCullDistanceFragmentOutput,
646     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
647     Combine(Values("ClipDistance", "CullDistance"), Values("Fragment"),
648             Values("Output"), Values("%f32arr4"), Values(nullptr),
649             Values(TestResult(
650                 SPV_ERROR_INVALID_DATA,
651                 "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance "
652                 "to be used for variables with Output storage class if "
653                 "execution model is Fragment.",
654                 "which is called with execution model Fragment."))));
655 
656 INSTANTIATE_TEST_SUITE_P(
657     VertexIdAndInstanceIdVertexInput,
658     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
659     Combine(Values("VertexId", "InstanceId"), Values("Vertex"), Values("Input"),
660             Values("%u32"), Values(nullptr),
661             Values(TestResult(
662                 SPV_ERROR_INVALID_DATA,
663                 "Vulkan spec doesn't allow BuiltIn VertexId/InstanceId to be "
664                 "used."))));
665 
666 INSTANTIATE_TEST_SUITE_P(
667     ClipAndCullDistanceVertexInput,
668     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
669     Combine(Values("ClipDistance", "CullDistance"), Values("Vertex"),
670             Values("Input"), Values("%f32arr4"), Values(nullptr),
671             Values(TestResult(
672                 SPV_ERROR_INVALID_DATA,
673                 "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance "
674                 "to be used for variables with Input storage class if "
675                 "execution model is Vertex.",
676                 "which is called with execution model Vertex."))));
677 
678 INSTANTIATE_TEST_SUITE_P(
679     ClipAndCullInvalidExecutionModel,
680     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
681     Combine(Values("ClipDistance", "CullDistance"), Values("GLCompute"),
682             Values("Input", "Output"), Values("%f32arr4"),
683             Values("VUID-ClipDistance-ClipDistance-04187 "
684                    "VUID-CullDistance-CullDistance-04196"),
685             Values(TestResult(
686                 SPV_ERROR_INVALID_DATA,
687                 "to be used only with Fragment, Vertex, TessellationControl, "
688                 "TessellationEvaluation or Geometry execution models"))));
689 
690 INSTANTIATE_TEST_SUITE_P(
691     ClipAndCullDistanceNotArray,
692     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
693     Combine(Values("ClipDistance", "CullDistance"), Values("Fragment"),
694             Values("Input"), Values("%f32vec2", "%f32vec4", "%f32"),
695             Values("VUID-ClipDistance-ClipDistance-04191 "
696                    "VUID-CullDistance-CullDistance-04200"),
697             Values(TestResult(SPV_ERROR_INVALID_DATA,
698                               "needs to be a 32-bit float array",
699                               "is not an array"))));
700 
701 INSTANTIATE_TEST_SUITE_P(
702     ClipAndCullDistanceNotFloatArray,
703     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
704     Combine(Values("ClipDistance", "CullDistance"), Values("Fragment"),
705             Values("Input"), Values("%u32arr2", "%u64arr4"),
706             Values("VUID-ClipDistance-ClipDistance-04191 "
707                    "VUID-CullDistance-CullDistance-04200"),
708             Values(TestResult(SPV_ERROR_INVALID_DATA,
709                               "needs to be a 32-bit float array",
710                               "components are not float scalar"))));
711 
712 INSTANTIATE_TEST_SUITE_P(
713     ClipAndCullDistanceNotF32Array,
714     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
715     Combine(Values("ClipDistance", "CullDistance"), Values("Fragment"),
716             Values("Input"), Values("%f64arr2", "%f64arr4"),
717             Values("VUID-ClipDistance-ClipDistance-04191 "
718                    "VUID-CullDistance-CullDistance-04200"),
719             Values(TestResult(SPV_ERROR_INVALID_DATA,
720                               "needs to be a 32-bit float array",
721                               "has components with bit width 64"))));
722 
723 INSTANTIATE_TEST_SUITE_P(
724     FragCoordSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
725     Combine(Values("FragCoord"), Values("Fragment"), Values("Input"),
726             Values("%f32vec4"), Values(nullptr), Values(TestResult())));
727 
728 INSTANTIATE_TEST_SUITE_P(
729     FragCoordSuccess, ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
730     Combine(Values("FragCoord"), Values("Fragment"), Values("Input"),
731             Values("%f32vec4"), Values(TestResult())));
732 
733 INSTANTIATE_TEST_SUITE_P(
734     FragCoordNotFragment,
735     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
736     Combine(
737         Values("FragCoord"),
738         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
739                "TessellationEvaluation"),
740         Values("Input"), Values("%f32vec4"),
741         Values("VUID-FragCoord-FragCoord-04210"),
742         Values(TestResult(SPV_ERROR_INVALID_DATA,
743                           "to be used only with Fragment execution model"))));
744 
745 INSTANTIATE_TEST_SUITE_P(
746     FragCoordNotFragment,
747     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
748     Combine(
749         Values("FragCoord"), Values("Vertex", "GLCompute"), Values("Input"),
750         Values("%f32vec4"),
751         Values(TestResult(SPV_ERROR_INVALID_DATA,
752                           "to be used only with Fragment execution model"))));
753 
754 INSTANTIATE_TEST_SUITE_P(
755     FragCoordNotInput, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
756     Combine(Values("FragCoord"), Values("Fragment"), Values("Output"),
757             Values("%f32vec4"), Values("VUID-FragCoord-FragCoord-04211"),
758             Values(TestResult(
759                 SPV_ERROR_INVALID_DATA,
760                 "to be only used for variables with Input storage class",
761                 "uses storage class Output"))));
762 
763 INSTANTIATE_TEST_SUITE_P(
764     FragCoordNotInput, ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
765     Combine(Values("FragCoord"), Values("Fragment"), Values("Output"),
766             Values("%f32vec4"),
767             Values(TestResult(
768                 SPV_ERROR_INVALID_DATA,
769                 "to be only used for variables with Input storage class",
770                 "uses storage class Output"))));
771 
772 INSTANTIATE_TEST_SUITE_P(
773     FragCoordNotFloatVector,
774     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
775     Combine(Values("FragCoord"), Values("Fragment"), Values("Input"),
776             Values("%f32arr4", "%u32vec4"),
777             Values("VUID-FragCoord-FragCoord-04212"),
778             Values(TestResult(SPV_ERROR_INVALID_DATA,
779                               "needs to be a 4-component 32-bit float vector",
780                               "is not a float vector"))));
781 
782 INSTANTIATE_TEST_SUITE_P(
783     FragCoordNotFloatVector,
784     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
785     Combine(Values("FragCoord"), Values("Fragment"), Values("Input"),
786             Values("%f32arr4", "%u32vec4"),
787             Values(TestResult(SPV_ERROR_INVALID_DATA,
788                               "needs to be a 4-component 32-bit float vector",
789                               "is not a float vector"))));
790 
791 INSTANTIATE_TEST_SUITE_P(
792     FragCoordNotFloatVec4,
793     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
794     Combine(Values("FragCoord"), Values("Fragment"), Values("Input"),
795             Values("%f32vec3"), Values("VUID-FragCoord-FragCoord-04212"),
796             Values(TestResult(SPV_ERROR_INVALID_DATA,
797                               "needs to be a 4-component 32-bit float vector",
798                               "has 3 components"))));
799 
800 INSTANTIATE_TEST_SUITE_P(
801     FragCoordNotFloatVec4,
802     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
803     Combine(Values("FragCoord"), Values("Fragment"), Values("Input"),
804             Values("%f32vec3"),
805             Values(TestResult(SPV_ERROR_INVALID_DATA,
806                               "needs to be a 4-component 32-bit float vector",
807                               "has 3 components"))));
808 
809 INSTANTIATE_TEST_SUITE_P(
810     FragCoordNotF32Vec4,
811     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
812     Combine(Values("FragCoord"), Values("Fragment"), Values("Input"),
813             Values("%f64vec4"), Values("VUID-FragCoord-FragCoord-04212"),
814             Values(TestResult(SPV_ERROR_INVALID_DATA,
815                               "needs to be a 4-component 32-bit float vector",
816                               "has components with bit width 64"))));
817 
818 INSTANTIATE_TEST_SUITE_P(
819     FragDepthSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
820     Combine(Values("FragDepth"), Values("Fragment"), Values("Output"),
821             Values("%f32"), Values(nullptr), Values(TestResult())));
822 
823 INSTANTIATE_TEST_SUITE_P(
824     FragDepthSuccess, ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
825     Combine(Values("FragDepth"), Values("Fragment"), Values("Output"),
826             Values("%f32"), Values(TestResult())));
827 
828 INSTANTIATE_TEST_SUITE_P(
829     FragDepthNotFragment,
830     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
831     Combine(
832         Values("FragDepth"),
833         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
834                "TessellationEvaluation"),
835         Values("Output"), Values("%f32"),
836         Values("VUID-FragDepth-FragDepth-04213"),
837         Values(TestResult(SPV_ERROR_INVALID_DATA,
838                           "to be used only with Fragment execution model"))));
839 
840 INSTANTIATE_TEST_SUITE_P(
841     FragDepthNotFragment,
842     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
843     Combine(
844         Values("FragDepth"), Values("Vertex", "GLCompute"), Values("Output"),
845         Values("%f32"),
846         Values(TestResult(SPV_ERROR_INVALID_DATA,
847                           "to be used only with Fragment execution model"))));
848 
849 INSTANTIATE_TEST_SUITE_P(
850     FragDepthNotOutput,
851     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
852     Combine(Values("FragDepth"), Values("Fragment"), Values("Input"),
853             Values("%f32"), Values("VUID-FragDepth-FragDepth-04214"),
854             Values(TestResult(
855                 SPV_ERROR_INVALID_DATA,
856                 "to be only used for variables with Output storage class",
857                 "uses storage class Input"))));
858 
859 INSTANTIATE_TEST_SUITE_P(
860     FragDepthNotOutput,
861     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
862     Combine(Values("FragDepth"), Values("Fragment"), Values("Input"),
863             Values("%f32"),
864             Values(TestResult(
865                 SPV_ERROR_INVALID_DATA,
866                 "to be only used for variables with Output storage class",
867                 "uses storage class Input"))));
868 
869 INSTANTIATE_TEST_SUITE_P(
870     FragDepthNotFloatScalar,
871     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
872     Combine(Values("FragDepth"), Values("Fragment"), Values("Output"),
873             Values("%f32vec4", "%u32"),
874             Values("VUID-FragDepth-FragDepth-04215"),
875             Values(TestResult(SPV_ERROR_INVALID_DATA,
876                               "needs to be a 32-bit float scalar",
877                               "is not a float scalar"))));
878 
879 INSTANTIATE_TEST_SUITE_P(
880     FragDepthNotFloatScalar,
881     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
882     Combine(Values("FragDepth"), Values("Fragment"), Values("Output"),
883             Values("%f32vec4", "%u32"),
884             Values(TestResult(SPV_ERROR_INVALID_DATA,
885                               "needs to be a 32-bit float scalar",
886                               "is not a float scalar"))));
887 
888 INSTANTIATE_TEST_SUITE_P(
889     FragDepthNotF32, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
890     Combine(Values("FragDepth"), Values("Fragment"), Values("Output"),
891             Values("%f64"), Values("VUID-FragDepth-FragDepth-04215"),
892             Values(TestResult(SPV_ERROR_INVALID_DATA,
893                               "needs to be a 32-bit float scalar",
894                               "has bit width 64"))));
895 
896 INSTANTIATE_TEST_SUITE_P(
897     FrontFacingAndHelperInvocationSuccess,
898     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
899     Combine(Values("FrontFacing", "HelperInvocation"), Values("Fragment"),
900             Values("Input"), Values("%bool"), Values(nullptr),
901             Values(TestResult())));
902 
903 INSTANTIATE_TEST_SUITE_P(
904     FrontFacingSuccess,
905     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
906     Combine(Values("FrontFacing"), Values("Fragment"), Values("Input"),
907             Values("%bool"), Values(TestResult())));
908 
909 INSTANTIATE_TEST_SUITE_P(
910     FrontFacingAndHelperInvocationNotFragment,
911     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
912     Combine(
913         Values("FrontFacing", "HelperInvocation"),
914         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
915                "TessellationEvaluation"),
916         Values("Input"), Values("%bool"),
917         Values("VUID-FrontFacing-FrontFacing-04229 "
918                "VUID-HelperInvocation-HelperInvocation-04239"),
919         Values(TestResult(SPV_ERROR_INVALID_DATA,
920                           "to be used only with Fragment execution model"))));
921 
922 INSTANTIATE_TEST_SUITE_P(
923     FrontFacingNotFragment,
924     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
925     Combine(
926         Values("FrontFacing"), Values("Vertex", "GLCompute"), Values("Input"),
927         Values("%bool"),
928         Values(TestResult(SPV_ERROR_INVALID_DATA,
929                           "to be used only with Fragment execution model"))));
930 
931 INSTANTIATE_TEST_SUITE_P(
932     FrontFacingAndHelperInvocationNotInput,
933     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
934     Combine(Values("FrontFacing", "HelperInvocation"), Values("Fragment"),
935             Values("Output"), Values("%bool"),
936             Values("VUID-FrontFacing-FrontFacing-04230 "
937                    "VUID-HelperInvocation-HelperInvocation-04240"),
938             Values(TestResult(
939                 SPV_ERROR_INVALID_DATA,
940                 "to be only used for variables with Input storage class",
941                 "uses storage class Output"))));
942 
943 INSTANTIATE_TEST_SUITE_P(
944     FrontFacingNotInput,
945     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
946     Combine(Values("FrontFacing"), Values("Fragment"), Values("Output"),
947             Values("%bool"),
948             Values(TestResult(
949                 SPV_ERROR_INVALID_DATA,
950                 "to be only used for variables with Input storage class",
951                 "uses storage class Output"))));
952 
953 INSTANTIATE_TEST_SUITE_P(
954     FrontFacingAndHelperInvocationNotBool,
955     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
956     Combine(Values("FrontFacing", "HelperInvocation"), Values("Fragment"),
957             Values("Input"), Values("%f32", "%u32"),
958             Values("VUID-FrontFacing-FrontFacing-04231 "
959                    "VUID-HelperInvocation-HelperInvocation-04241"),
960             Values(TestResult(SPV_ERROR_INVALID_DATA,
961                               "needs to be a bool scalar",
962                               "is not a bool scalar"))));
963 
964 INSTANTIATE_TEST_SUITE_P(
965     FrontFacingNotBool,
966     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
967     Combine(Values("FrontFacing"), Values("Fragment"), Values("Input"),
968             Values("%f32", "%u32"),
969             Values(TestResult(SPV_ERROR_INVALID_DATA,
970                               "needs to be a bool scalar",
971                               "is not a bool scalar"))));
972 
973 INSTANTIATE_TEST_SUITE_P(
974     ComputeShaderInputInt32Vec3Success,
975     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
976     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups",
977                    "WorkgroupId"),
978             Values("GLCompute"), Values("Input"), Values("%u32vec3"),
979             Values(nullptr), Values(TestResult())));
980 
981 INSTANTIATE_TEST_SUITE_P(
982     ComputeShaderInputInt32Vec3Success,
983     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
984     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups"),
985             Values("GLCompute"), Values("Input"), Values("%u32vec3"),
986             Values(TestResult())));
987 
988 INSTANTIATE_TEST_SUITE_P(
989     ComputeShaderInputInt32Vec3NotGLCompute,
990     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
991     Combine(
992         Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups",
993                "WorkgroupId"),
994         Values("Vertex", "Fragment", "Geometry", "TessellationControl",
995                "TessellationEvaluation"),
996         Values("Input"), Values("%u32vec3"),
997         Values("VUID-GlobalInvocationId-GlobalInvocationId-04236 "
998                "VUID-LocalInvocationId-LocalInvocationId-04281 "
999                "VUID-NumWorkgroups-NumWorkgroups-04296 "
1000                "VUID-WorkgroupId-WorkgroupId-04422"),
1001         Values(TestResult(SPV_ERROR_INVALID_DATA,
1002                           "to be used only with GLCompute execution model"))));
1003 
1004 INSTANTIATE_TEST_SUITE_P(
1005     ComputeShaderInputInt32Vec3NotGLCompute,
1006     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
1007     Combine(
1008         Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups"),
1009         Values("Vertex", "Fragment"), Values("Input"), Values("%u32vec3"),
1010         Values(TestResult(SPV_ERROR_INVALID_DATA,
1011                           "to be used only with GLCompute execution model"))));
1012 
1013 INSTANTIATE_TEST_SUITE_P(
1014     ComputeShaderInputInt32Vec3NotInput,
1015     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1016     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups",
1017                    "WorkgroupId"),
1018             Values("GLCompute"), Values("Output"), Values("%u32vec3"),
1019             Values("VUID-GlobalInvocationId-GlobalInvocationId-04237 "
1020                    "VUID-LocalInvocationId-LocalInvocationId-04282 "
1021                    "VUID-NumWorkgroups-NumWorkgroups-04297 "
1022                    "VUID-WorkgroupId-WorkgroupId-04423"),
1023             Values(TestResult(
1024                 SPV_ERROR_INVALID_DATA,
1025                 "to be only used for variables with Input storage class",
1026                 "uses storage class Output"))));
1027 
1028 INSTANTIATE_TEST_SUITE_P(
1029     ComputeShaderInputInt32Vec3NotInput,
1030     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
1031     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups"),
1032             Values("GLCompute"), Values("Output"), Values("%u32vec3"),
1033             Values(TestResult(
1034                 SPV_ERROR_INVALID_DATA,
1035                 "to be only used for variables with Input storage class",
1036                 "uses storage class Output"))));
1037 
1038 INSTANTIATE_TEST_SUITE_P(
1039     ComputeShaderInputInt32Vec3NotIntVector,
1040     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1041     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups",
1042                    "WorkgroupId"),
1043             Values("GLCompute"), Values("Input"),
1044             Values("%u32arr3", "%f32vec3"),
1045             Values("VUID-GlobalInvocationId-GlobalInvocationId-04238 "
1046                    "VUID-LocalInvocationId-LocalInvocationId-04283 "
1047                    "VUID-NumWorkgroups-NumWorkgroups-04298 "
1048                    "VUID-WorkgroupId-WorkgroupId-04424"),
1049             Values(TestResult(SPV_ERROR_INVALID_DATA,
1050                               "needs to be a 3-component 32-bit int vector",
1051                               "is not an int vector"))));
1052 
1053 INSTANTIATE_TEST_SUITE_P(
1054     ComputeShaderInputInt32Vec3NotIntVector,
1055     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
1056     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups"),
1057             Values("GLCompute"), Values("Input"),
1058             Values("%u32arr3", "%f32vec3"),
1059             Values(TestResult(SPV_ERROR_INVALID_DATA,
1060                               "needs to be a 3-component 32-bit int vector",
1061                               "is not an int vector"))));
1062 
1063 INSTANTIATE_TEST_SUITE_P(
1064     ComputeShaderInputInt32Vec3NotIntVec3,
1065     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1066     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups",
1067                    "WorkgroupId"),
1068             Values("GLCompute"), Values("Input"), Values("%u32vec4"),
1069             Values("VUID-GlobalInvocationId-GlobalInvocationId-04238 "
1070                    "VUID-LocalInvocationId-LocalInvocationId-04283 "
1071                    "VUID-NumWorkgroups-NumWorkgroups-04298 "
1072                    "VUID-WorkgroupId-WorkgroupId-04424"),
1073             Values(TestResult(SPV_ERROR_INVALID_DATA,
1074                               "needs to be a 3-component 32-bit int vector",
1075                               "has 4 components"))));
1076 
1077 INSTANTIATE_TEST_SUITE_P(
1078     ComputeShaderInputInt32Vec3NotIntVec3,
1079     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
1080     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups"),
1081             Values("GLCompute"), Values("Input"), Values("%u32vec4"),
1082             Values(TestResult(SPV_ERROR_INVALID_DATA,
1083                               "needs to be a 3-component 32-bit int vector",
1084                               "has 4 components"))));
1085 
1086 INSTANTIATE_TEST_SUITE_P(
1087     ComputeShaderInputInt32Vec3NotInt32Vec,
1088     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1089     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups",
1090                    "WorkgroupId"),
1091             Values("GLCompute"), Values("Input"), Values("%u64vec3"),
1092             Values("VUID-GlobalInvocationId-GlobalInvocationId-04238 "
1093                    "VUID-LocalInvocationId-LocalInvocationId-04283 "
1094                    "VUID-NumWorkgroups-NumWorkgroups-04298 "
1095                    "VUID-WorkgroupId-WorkgroupId-04424"),
1096             Values(TestResult(SPV_ERROR_INVALID_DATA,
1097                               "needs to be a 3-component 32-bit int vector",
1098                               "has components with bit width 64"))));
1099 
1100 INSTANTIATE_TEST_SUITE_P(
1101     InvocationIdSuccess,
1102     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1103     Combine(Values("InvocationId"), Values("Geometry", "TessellationControl"),
1104             Values("Input"), Values("%u32"), Values(nullptr),
1105             Values(TestResult())));
1106 
1107 INSTANTIATE_TEST_SUITE_P(
1108     InvocationIdInvalidExecutionModel,
1109     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1110     Combine(Values("InvocationId"),
1111             Values("Vertex", "Fragment", "GLCompute", "TessellationEvaluation"),
1112             Values("Input"), Values("%u32"),
1113             Values("VUID-InvocationId-InvocationId-04257"),
1114             Values(TestResult(SPV_ERROR_INVALID_DATA,
1115                               "to be used only with TessellationControl or "
1116                               "Geometry execution models"))));
1117 
1118 INSTANTIATE_TEST_SUITE_P(
1119     InvocationIdNotInput,
1120     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1121     Combine(Values("InvocationId"), Values("Geometry", "TessellationControl"),
1122             Values("Output"), Values("%u32"),
1123             Values("VUID-InvocationId-InvocationId-04258"),
1124             Values(TestResult(
1125                 SPV_ERROR_INVALID_DATA,
1126                 "to be only used for variables with Input storage class",
1127                 "uses storage class Output"))));
1128 
1129 INSTANTIATE_TEST_SUITE_P(
1130     InvocationIdNotIntScalar,
1131     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1132     Combine(Values("InvocationId"), Values("Geometry", "TessellationControl"),
1133             Values("Input"), Values("%f32", "%u32vec3"),
1134             Values("VUID-InvocationId-InvocationId-04259"),
1135             Values(TestResult(SPV_ERROR_INVALID_DATA,
1136                               "needs to be a 32-bit int scalar",
1137                               "is not an int scalar"))));
1138 
1139 INSTANTIATE_TEST_SUITE_P(
1140     InvocationIdNotInt32,
1141     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1142     Combine(Values("InvocationId"), Values("Geometry", "TessellationControl"),
1143             Values("Input"), Values("%u64"),
1144             Values("VUID-InvocationId-InvocationId-04259"),
1145             Values(TestResult(SPV_ERROR_INVALID_DATA,
1146                               "needs to be a 32-bit int scalar",
1147                               "has bit width 64"))));
1148 
1149 INSTANTIATE_TEST_SUITE_P(
1150     InstanceIndexSuccess,
1151     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1152     Combine(Values("InstanceIndex"), Values("Vertex"), Values("Input"),
1153             Values("%u32"), Values(nullptr), Values(TestResult())));
1154 
1155 INSTANTIATE_TEST_SUITE_P(
1156     InstanceIndexSuccess,
1157     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
1158     Combine(Values("InstanceIndex"), Values("Vertex"), Values("Input"),
1159             Values("%u32"), Values(TestResult())));
1160 
1161 INSTANTIATE_TEST_SUITE_P(
1162     InstanceIndexInvalidExecutionModel,
1163     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1164     Combine(Values("InstanceIndex"),
1165             Values("Geometry", "Fragment", "GLCompute", "TessellationControl",
1166                    "TessellationEvaluation"),
1167             Values("Input"), Values("%u32"),
1168             Values("VUID-InstanceIndex-InstanceIndex-04263"),
1169             Values(TestResult(SPV_ERROR_INVALID_DATA,
1170                               "to be used only with Vertex execution model"))));
1171 
1172 INSTANTIATE_TEST_SUITE_P(
1173     InstanceIndexInvalidExecutionModel,
1174     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
1175     Combine(Values("InstanceIndex"), Values("Fragment", "GLCompute"),
1176             Values("Input"), Values("%u32"),
1177             Values(TestResult(SPV_ERROR_INVALID_DATA,
1178                               "to be used only with Vertex execution model"))));
1179 
1180 INSTANTIATE_TEST_SUITE_P(
1181     InstanceIndexNotInput,
1182     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1183     Combine(Values("InstanceIndex"), Values("Vertex"), Values("Output"),
1184             Values("%u32"), Values("VUID-InstanceIndex-InstanceIndex-04264"),
1185             Values(TestResult(
1186                 SPV_ERROR_INVALID_DATA,
1187                 "to be only used for variables with Input storage class",
1188                 "uses storage class Output"))));
1189 
1190 INSTANTIATE_TEST_SUITE_P(
1191     InstanceIndexNotInput,
1192     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
1193     Combine(Values("InstanceIndex"), Values("Vertex"), Values("Output"),
1194             Values("%u32"),
1195             Values(TestResult(
1196                 SPV_ERROR_INVALID_DATA,
1197                 "to be only used for variables with Input storage class",
1198                 "uses storage class Output"))));
1199 
1200 INSTANTIATE_TEST_SUITE_P(
1201     InstanceIndexNotIntScalar,
1202     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1203     Combine(Values("InstanceIndex"), Values("Vertex"), Values("Input"),
1204             Values("%f32", "%u32vec3"),
1205             Values("VUID-InstanceIndex-InstanceIndex-04265"),
1206             Values(TestResult(SPV_ERROR_INVALID_DATA,
1207                               "needs to be a 32-bit int scalar",
1208                               "is not an int scalar"))));
1209 
1210 INSTANTIATE_TEST_SUITE_P(
1211     InstanceIndexNotIntScalar,
1212     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
1213     Combine(Values("InstanceIndex"), Values("Vertex"), Values("Input"),
1214             Values("%f32", "%u32vec3"),
1215             Values(TestResult(SPV_ERROR_INVALID_DATA,
1216                               "needs to be a 32-bit int scalar",
1217                               "is not an int scalar"))));
1218 
1219 INSTANTIATE_TEST_SUITE_P(
1220     InstanceIndexNotInt32,
1221     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1222     Combine(Values("InstanceIndex"), Values("Vertex"), Values("Input"),
1223             Values("%u64"), Values("VUID-InstanceIndex-InstanceIndex-04265"),
1224             Values(TestResult(SPV_ERROR_INVALID_DATA,
1225                               "needs to be a 32-bit int scalar",
1226                               "has bit width 64"))));
1227 
1228 INSTANTIATE_TEST_SUITE_P(
1229     LayerAndViewportIndexInputSuccess,
1230     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1231     Combine(Values("Layer", "ViewportIndex"), Values("Fragment"),
1232             Values("Input"), Values("%u32"), Values(nullptr),
1233             Values(TestResult())));
1234 
1235 INSTANTIATE_TEST_SUITE_P(
1236     LayerAndViewportIndexOutputSuccess,
1237     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1238     Combine(Values("Layer", "ViewportIndex"), Values("Geometry"),
1239             Values("Output"), Values("%u32"), Values(nullptr),
1240             Values(TestResult())));
1241 
1242 INSTANTIATE_TEST_SUITE_P(
1243     LayerAndViewportIndexInvalidExecutionModel,
1244     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1245     Combine(
1246         Values("Layer", "ViewportIndex"),
1247         Values("TessellationControl", "GLCompute"), Values("Input"),
1248         Values("%u32"),
1249         Values("VUID-Layer-Layer-04272 VUID-ViewportIndex-ViewportIndex-04404"),
1250         Values(
1251             TestResult(SPV_ERROR_INVALID_DATA,
1252                        "to be used only with Vertex, TessellationEvaluation, "
1253                        "Geometry, or Fragment execution models"))));
1254 
1255 INSTANTIATE_TEST_SUITE_P(
1256     ViewportIndexExecutionModelEnabledByCapability,
1257     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1258     Combine(Values("ViewportIndex"), Values("Vertex", "TessellationEvaluation"),
1259             Values("Output"), Values("%u32"), Values(nullptr),
1260             Values(TestResult(
1261                 SPV_ERROR_INVALID_DATA,
1262                 "ShaderViewportIndexLayerEXT or ShaderViewportIndex"))));
1263 
1264 INSTANTIATE_TEST_SUITE_P(
1265     LayerExecutionModelEnabledByCapability,
1266     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1267     Combine(Values("Layer"), Values("Vertex", "TessellationEvaluation"),
1268             Values("Output"), Values("%u32"), Values(nullptr),
1269             Values(TestResult(SPV_ERROR_INVALID_DATA,
1270                               "ShaderViewportIndexLayerEXT or ShaderLayer"))));
1271 
1272 INSTANTIATE_TEST_SUITE_P(
1273     LayerAndViewportIndexFragmentNotInput,
1274     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1275     Combine(
1276         Values("Layer", "ViewportIndex"), Values("Fragment"), Values("Output"),
1277         Values("%u32"),
1278         Values("VUID-Layer-Layer-04275 VUID-ViewportIndex-ViewportIndex-04407"),
1279         Values(TestResult(SPV_ERROR_INVALID_DATA,
1280                           "Output storage class if execution model is Fragment",
1281                           "which is called with execution model Fragment"))));
1282 
1283 INSTANTIATE_TEST_SUITE_P(
1284     LayerAndViewportIndexGeometryNotOutput,
1285     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1286     Combine(
1287         Values("Layer", "ViewportIndex"),
1288         Values("Vertex", "TessellationEvaluation", "Geometry"), Values("Input"),
1289         Values("%u32"),
1290         Values("VUID-Layer-Layer-04274 VUID-ViewportIndex-ViewportIndex-04406"),
1291         Values(TestResult(SPV_ERROR_INVALID_DATA,
1292                           "Input storage class if execution model is Vertex, "
1293                           "TessellationEvaluation, Geometry, or MeshNV",
1294                           "which is called with execution model"))));
1295 
1296 INSTANTIATE_TEST_SUITE_P(
1297     LayerAndViewportIndexNotIntScalar,
1298     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1299     Combine(
1300         Values("Layer", "ViewportIndex"), Values("Fragment"), Values("Input"),
1301         Values("%f32", "%u32vec3"),
1302         Values("VUID-Layer-Layer-04276 VUID-ViewportIndex-ViewportIndex-04408"),
1303         Values(TestResult(SPV_ERROR_INVALID_DATA,
1304                           "needs to be a 32-bit int scalar",
1305                           "is not an int scalar"))));
1306 
1307 INSTANTIATE_TEST_SUITE_P(
1308     LayerAndViewportIndexNotInt32,
1309     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1310     Combine(
1311         Values("Layer", "ViewportIndex"), Values("Fragment"), Values("Input"),
1312         Values("%u64"),
1313         Values("VUID-Layer-Layer-04276 VUID-ViewportIndex-ViewportIndex-04408"),
1314         Values(TestResult(SPV_ERROR_INVALID_DATA,
1315                           "needs to be a 32-bit int scalar",
1316                           "has bit width 64"))));
1317 
1318 INSTANTIATE_TEST_SUITE_P(
1319     LayerCapability,
1320     ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
1321     Combine(Values(SPV_ENV_VULKAN_1_2), Values("Layer"), Values("Vertex"),
1322             Values("Output"), Values("%u32"),
1323             Values("OpCapability ShaderLayer\n"), Values(nullptr),
1324             Values(nullptr), Values(TestResult())));
1325 
1326 INSTANTIATE_TEST_SUITE_P(
1327     ViewportIndexCapability,
1328     ValidateGenericCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
1329     Combine(Values(SPV_ENV_VULKAN_1_2), Values("ViewportIndex"),
1330             Values("Vertex"), Values("Output"), Values("%u32"),
1331             Values("OpCapability ShaderViewportIndex\n"), Values(nullptr),
1332             Values(nullptr), Values(TestResult())));
1333 
1334 INSTANTIATE_TEST_SUITE_P(
1335     PatchVerticesSuccess,
1336     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1337     Combine(Values("PatchVertices"),
1338             Values("TessellationEvaluation", "TessellationControl"),
1339             Values("Input"), Values("%u32"), Values(nullptr),
1340             Values(TestResult())));
1341 
1342 INSTANTIATE_TEST_SUITE_P(
1343     PatchVerticesInvalidExecutionModel,
1344     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1345     Combine(Values("PatchVertices"),
1346             Values("Vertex", "Fragment", "GLCompute", "Geometry"),
1347             Values("Input"), Values("%u32"),
1348             Values("VUID-PatchVertices-PatchVertices-04308"),
1349             Values(TestResult(SPV_ERROR_INVALID_DATA,
1350                               "to be used only with TessellationControl or "
1351                               "TessellationEvaluation execution models"))));
1352 
1353 INSTANTIATE_TEST_SUITE_P(
1354     PatchVerticesNotInput,
1355     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1356     Combine(Values("PatchVertices"),
1357             Values("TessellationEvaluation", "TessellationControl"),
1358             Values("Output"), Values("%u32"),
1359             Values("VUID-PatchVertices-PatchVertices-04309"),
1360             Values(TestResult(
1361                 SPV_ERROR_INVALID_DATA,
1362                 "to be only used for variables with Input storage class",
1363                 "uses storage class Output"))));
1364 
1365 INSTANTIATE_TEST_SUITE_P(
1366     PatchVerticesNotIntScalar,
1367     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1368     Combine(Values("PatchVertices"),
1369             Values("TessellationEvaluation", "TessellationControl"),
1370             Values("Input"), Values("%f32", "%u32vec3"),
1371             Values("VUID-PatchVertices-PatchVertices-04310"),
1372             Values(TestResult(SPV_ERROR_INVALID_DATA,
1373                               "needs to be a 32-bit int scalar",
1374                               "is not an int scalar"))));
1375 
1376 INSTANTIATE_TEST_SUITE_P(
1377     PatchVerticesNotInt32,
1378     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1379     Combine(Values("PatchVertices"),
1380             Values("TessellationEvaluation", "TessellationControl"),
1381             Values("Input"), Values("%u64"),
1382             Values("VUID-PatchVertices-PatchVertices-04310"),
1383             Values(TestResult(SPV_ERROR_INVALID_DATA,
1384                               "needs to be a 32-bit int scalar",
1385                               "has bit width 64"))));
1386 
1387 INSTANTIATE_TEST_SUITE_P(
1388     PointCoordSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1389     Combine(Values("PointCoord"), Values("Fragment"), Values("Input"),
1390             Values("%f32vec2"), Values(nullptr), Values(TestResult())));
1391 
1392 INSTANTIATE_TEST_SUITE_P(
1393     PointCoordNotFragment,
1394     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1395     Combine(
1396         Values("PointCoord"),
1397         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
1398                "TessellationEvaluation"),
1399         Values("Input"), Values("%f32vec2"),
1400         Values("VUID-PointCoord-PointCoord-04311"),
1401         Values(TestResult(SPV_ERROR_INVALID_DATA,
1402                           "to be used only with Fragment execution model"))));
1403 
1404 INSTANTIATE_TEST_SUITE_P(
1405     PointCoordNotInput,
1406     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1407     Combine(Values("PointCoord"), Values("Fragment"), Values("Output"),
1408             Values("%f32vec2"), Values("VUID-PointCoord-PointCoord-04312"),
1409             Values(TestResult(
1410                 SPV_ERROR_INVALID_DATA,
1411                 "to be only used for variables with Input storage class",
1412                 "uses storage class Output"))));
1413 
1414 INSTANTIATE_TEST_SUITE_P(
1415     PointCoordNotFloatVector,
1416     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1417     Combine(Values("PointCoord"), Values("Fragment"), Values("Input"),
1418             Values("%f32arr2", "%u32vec2"),
1419             Values("VUID-PointCoord-PointCoord-04313"),
1420             Values(TestResult(SPV_ERROR_INVALID_DATA,
1421                               "needs to be a 2-component 32-bit float vector",
1422                               "is not a float vector"))));
1423 
1424 INSTANTIATE_TEST_SUITE_P(
1425     PointCoordNotFloatVec3,
1426     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1427     Combine(Values("PointCoord"), Values("Fragment"), Values("Input"),
1428             Values("%f32vec3"), Values("VUID-PointCoord-PointCoord-04313"),
1429             Values(TestResult(SPV_ERROR_INVALID_DATA,
1430                               "needs to be a 2-component 32-bit float vector",
1431                               "has 3 components"))));
1432 
1433 INSTANTIATE_TEST_SUITE_P(
1434     PointCoordNotF32Vec4,
1435     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1436     Combine(Values("PointCoord"), Values("Fragment"), Values("Input"),
1437             Values("%f64vec2"), Values("VUID-PointCoord-PointCoord-04313"),
1438             Values(TestResult(SPV_ERROR_INVALID_DATA,
1439                               "needs to be a 2-component 32-bit float vector",
1440                               "has components with bit width 64"))));
1441 
1442 INSTANTIATE_TEST_SUITE_P(
1443     PointSizeOutputSuccess,
1444     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1445     Combine(Values("PointSize"),
1446             Values("Vertex", "Geometry", "TessellationControl",
1447                    "TessellationEvaluation"),
1448             Values("Output"), Values("%f32"), Values(nullptr),
1449             Values(TestResult())));
1450 
1451 INSTANTIATE_TEST_SUITE_P(
1452     PointSizeInputSuccess,
1453     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1454     Combine(Values("PointSize"),
1455             Values("Geometry", "TessellationControl", "TessellationEvaluation"),
1456             Values("Input"), Values("%f32"), Values(nullptr),
1457             Values(TestResult())));
1458 
1459 INSTANTIATE_TEST_SUITE_P(
1460     PointSizeVertexInput,
1461     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1462     Combine(Values("PointSize"), Values("Vertex"), Values("Input"),
1463             Values("%f32"), Values("VUID-PointSize-PointSize-04315"),
1464             Values(TestResult(
1465                 SPV_ERROR_INVALID_DATA,
1466                 "Vulkan spec doesn't allow BuiltIn PointSize "
1467                 "to be used for variables with Input storage class if "
1468                 "execution model is Vertex.",
1469                 "which is called with execution model Vertex."))));
1470 
1471 INSTANTIATE_TEST_SUITE_P(
1472     PointSizeInvalidExecutionModel,
1473     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1474     Combine(Values("PointSize"), Values("GLCompute", "Fragment"),
1475             Values("Input", "Output"), Values("%f32"),
1476             Values("VUID-PointSize-PointSize-04314"),
1477             Values(TestResult(
1478                 SPV_ERROR_INVALID_DATA,
1479                 "to be used only with Vertex, TessellationControl, "
1480                 "TessellationEvaluation or Geometry execution models"))));
1481 
1482 INSTANTIATE_TEST_SUITE_P(
1483     PointSizeNotFloatScalar,
1484     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1485     Combine(Values("PointSize"), Values("Vertex"), Values("Output"),
1486             Values("%f32vec4", "%u32"),
1487             Values("VUID-PointSize-PointSize-04317"),
1488             Values(TestResult(SPV_ERROR_INVALID_DATA,
1489                               "needs to be a 32-bit float scalar",
1490                               "is not a float scalar"))));
1491 
1492 INSTANTIATE_TEST_SUITE_P(
1493     PointSizeNotF32, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1494     Combine(Values("PointSize"), Values("Vertex"), Values("Output"),
1495             Values("%f64"), Values("VUID-PointSize-PointSize-04317"),
1496             Values(TestResult(SPV_ERROR_INVALID_DATA,
1497                               "needs to be a 32-bit float scalar",
1498                               "has bit width 64"))));
1499 
1500 INSTANTIATE_TEST_SUITE_P(
1501     PositionOutputSuccess,
1502     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1503     Combine(Values("Position"),
1504             Values("Vertex", "Geometry", "TessellationControl",
1505                    "TessellationEvaluation"),
1506             Values("Output"), Values("%f32vec4"), Values(nullptr),
1507             Values(TestResult())));
1508 
1509 INSTANTIATE_TEST_SUITE_P(
1510     PositionOutputSuccess,
1511     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
1512     Combine(Values("Position"), Values("Vertex"), Values("Output"),
1513             Values("%f32vec4"), Values(TestResult())));
1514 
1515 INSTANTIATE_TEST_SUITE_P(
1516     PositionOutputFailure,
1517     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
1518     Combine(Values("Position"), Values("Fragment", "GLCompute"),
1519             Values("Output"), Values("%f32vec4"),
1520             Values(TestResult(SPV_ERROR_INVALID_DATA,
1521                               "WebGPU spec allows BuiltIn Position to be used "
1522                               "only with the Vertex execution model."))));
1523 
1524 INSTANTIATE_TEST_SUITE_P(
1525     PositionInputSuccess,
1526     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1527     Combine(Values("Position"),
1528             Values("Geometry", "TessellationControl", "TessellationEvaluation"),
1529             Values("Input"), Values("%f32vec4"), Values(nullptr),
1530             Values(TestResult())));
1531 
1532 INSTANTIATE_TEST_SUITE_P(
1533     PositionInputFailure,
1534     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
1535     Combine(
1536         Values("Position"), Values("Vertex", "Fragment", "GLCompute"),
1537         Values("Input"), Values("%f32vec4"),
1538         Values(TestResult(SPV_ERROR_INVALID_DATA,
1539                           "WebGPU spec allows BuiltIn Position to be only used "
1540                           "for variables with Output storage class"))));
1541 
1542 INSTANTIATE_TEST_SUITE_P(
1543     PositionVertexInput,
1544     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1545     Combine(Values("Position"), Values("Vertex"), Values("Input"),
1546             Values("%f32vec4"), Values("VUID-Position-Position-04320"),
1547             Values(TestResult(
1548                 SPV_ERROR_INVALID_DATA,
1549                 "Vulkan spec doesn't allow BuiltIn Position "
1550                 "to be used for variables with Input storage class if "
1551                 "execution model is Vertex.",
1552                 "which is called with execution model Vertex."))));
1553 
1554 INSTANTIATE_TEST_SUITE_P(
1555     PositionInvalidExecutionModel,
1556     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1557     Combine(Values("Position"), Values("GLCompute", "Fragment"),
1558             Values("Input", "Output"), Values("%f32vec4"),
1559             Values("VUID-Position-Position-04318"),
1560             Values(TestResult(
1561                 SPV_ERROR_INVALID_DATA,
1562                 "to be used only with Vertex, TessellationControl, "
1563                 "TessellationEvaluation or Geometry execution models"))));
1564 
1565 INSTANTIATE_TEST_SUITE_P(
1566     PositionNotFloatVector,
1567     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1568     Combine(Values("Position"), Values("Geometry"), Values("Input"),
1569             Values("%f32arr4", "%u32vec4"),
1570             Values("VUID-Position-Position-04321"),
1571             Values(TestResult(SPV_ERROR_INVALID_DATA,
1572                               "needs to be a 4-component 32-bit float vector",
1573                               "is not a float vector"))));
1574 
1575 INSTANTIATE_TEST_SUITE_P(
1576     PositionNotFloatVector,
1577     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
1578     Combine(
1579         Values("Position"), Values("Vertex"), Values("Output"),
1580         Values("%f32arr4", "%u32vec4"),
1581         Values(TestResult(SPV_ERROR_INVALID_DATA,
1582                           "needs to be a 4-component 32-bit float vector"))));
1583 
1584 INSTANTIATE_TEST_SUITE_P(
1585     PositionNotFloatVec4,
1586     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1587     Combine(Values("Position"), Values("Geometry"), Values("Input"),
1588             Values("%f32vec3"), Values("VUID-Position-Position-04321"),
1589             Values(TestResult(SPV_ERROR_INVALID_DATA,
1590                               "needs to be a 4-component 32-bit float vector",
1591                               "has 3 components"))));
1592 
1593 INSTANTIATE_TEST_SUITE_P(
1594     PositionNotFloatVec4,
1595     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
1596     Combine(
1597         Values("Position"), Values("Vertex"), Values("Output"),
1598         Values("%f32vec3"),
1599         Values(TestResult(SPV_ERROR_INVALID_DATA,
1600                           "needs to be a 4-component 32-bit float vector"))));
1601 
1602 INSTANTIATE_TEST_SUITE_P(
1603     PositionNotF32Vec4,
1604     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1605     Combine(Values("Position"), Values("Geometry"), Values("Input"),
1606             Values("%f64vec4"), Values("VUID-Position-Position-04321"),
1607             Values(TestResult(SPV_ERROR_INVALID_DATA,
1608                               "needs to be a 4-component 32-bit float vector",
1609                               "has components with bit width 64"))));
1610 
1611 INSTANTIATE_TEST_SUITE_P(
1612     PrimitiveIdInputSuccess,
1613     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1614     Combine(Values("PrimitiveId"),
1615             Values("Fragment", "TessellationControl", "TessellationEvaluation",
1616                    "Geometry"),
1617             Values("Input"), Values("%u32"), Values(nullptr),
1618             Values(TestResult())));
1619 
1620 INSTANTIATE_TEST_SUITE_P(
1621     PrimitiveIdOutputSuccess,
1622     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1623     Combine(Values("PrimitiveId"), Values("Geometry"), Values("Output"),
1624             Values("%u32"), Values(nullptr), Values(TestResult())));
1625 
1626 INSTANTIATE_TEST_SUITE_P(
1627     PrimitiveIdInvalidExecutionModel,
1628     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1629     Combine(Values("PrimitiveId"), Values("Vertex", "GLCompute"),
1630             Values("Input"), Values("%u32"),
1631             Values("VUID-PrimitiveId-PrimitiveId-04330"),
1632             Values(TestResult(
1633                 SPV_ERROR_INVALID_DATA,
1634                 "to be used only with Fragment, TessellationControl, "
1635                 "TessellationEvaluation or Geometry execution models"))));
1636 
1637 INSTANTIATE_TEST_SUITE_P(
1638     PrimitiveIdFragmentNotInput,
1639     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1640     Combine(
1641         Values("PrimitiveId"), Values("Fragment"), Values("Output"),
1642         Values("%u32"), Values("VUID-PrimitiveId-PrimitiveId-04334"),
1643         Values(TestResult(SPV_ERROR_INVALID_DATA,
1644                           "Output storage class if execution model is Fragment",
1645                           "which is called with execution model Fragment"))));
1646 
1647 INSTANTIATE_TEST_SUITE_P(
1648     PrimitiveIdGeometryNotInput,
1649     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1650     Combine(Values("PrimitiveId"),
1651             Values("TessellationControl", "TessellationEvaluation"),
1652             Values("Output"), Values("%u32"),
1653             Values("VUID-PrimitiveId-PrimitiveId-04334"),
1654             Values(TestResult(
1655                 SPV_ERROR_INVALID_DATA,
1656                 "Output storage class if execution model is Tessellation",
1657                 "which is called with execution model Tessellation"))));
1658 
1659 INSTANTIATE_TEST_SUITE_P(
1660     PrimitiveIdNotIntScalar,
1661     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1662     Combine(Values("PrimitiveId"), Values("Fragment"), Values("Input"),
1663             Values("%f32", "%u32vec3"),
1664             Values("VUID-PrimitiveId-PrimitiveId-04337"),
1665             Values(TestResult(SPV_ERROR_INVALID_DATA,
1666                               "needs to be a 32-bit int scalar",
1667                               "is not an int scalar"))));
1668 
1669 INSTANTIATE_TEST_SUITE_P(
1670     PrimitiveIdNotInt32,
1671     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1672     Combine(Values("PrimitiveId"), Values("Fragment"), Values("Input"),
1673             Values("%u64"), Values("VUID-PrimitiveId-PrimitiveId-04337"),
1674             Values(TestResult(SPV_ERROR_INVALID_DATA,
1675                               "needs to be a 32-bit int scalar",
1676                               "has bit width 64"))));
1677 
1678 INSTANTIATE_TEST_SUITE_P(
1679     SampleIdSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1680     Combine(Values("SampleId"), Values("Fragment"), Values("Input"),
1681             Values("%u32"), Values(nullptr), Values(TestResult())));
1682 
1683 INSTANTIATE_TEST_SUITE_P(
1684     SampleIdInvalidExecutionModel,
1685     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1686     Combine(
1687         Values("SampleId"),
1688         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
1689                "TessellationEvaluation"),
1690         Values("Input"), Values("%u32"), Values("VUID-SampleId-SampleId-04354"),
1691         Values(TestResult(SPV_ERROR_INVALID_DATA,
1692                           "to be used only with Fragment execution model"))));
1693 
1694 INSTANTIATE_TEST_SUITE_P(
1695     SampleIdNotInput, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1696     Combine(
1697         Values("SampleId"), Values("Fragment"), Values("Output"),
1698         Values("%u32"), Values("VUID-SampleId-SampleId-04355"),
1699         Values(TestResult(SPV_ERROR_INVALID_DATA,
1700                           "Vulkan spec allows BuiltIn SampleId to be only used "
1701                           "for variables with Input storage class"))));
1702 
1703 INSTANTIATE_TEST_SUITE_P(
1704     SampleIdNotIntScalar,
1705     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1706     Combine(Values("SampleId"), Values("Fragment"), Values("Input"),
1707             Values("%f32", "%u32vec3"), Values("VUID-SampleId-SampleId-04356"),
1708             Values(TestResult(SPV_ERROR_INVALID_DATA,
1709                               "needs to be a 32-bit int scalar",
1710                               "is not an int scalar"))));
1711 
1712 INSTANTIATE_TEST_SUITE_P(
1713     SampleIdNotInt32, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1714     Combine(Values("SampleId"), Values("Fragment"), Values("Input"),
1715             Values("%u64"), Values("VUID-SampleId-SampleId-04356"),
1716             Values(TestResult(SPV_ERROR_INVALID_DATA,
1717                               "needs to be a 32-bit int scalar",
1718                               "has bit width 64"))));
1719 
1720 INSTANTIATE_TEST_SUITE_P(
1721     SampleMaskSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1722     Combine(Values("SampleMask"), Values("Fragment"), Values("Input", "Output"),
1723             Values("%u32arr2", "%u32arr4"), Values(nullptr),
1724             Values(TestResult())));
1725 
1726 INSTANTIATE_TEST_SUITE_P(
1727     SampleMaskInvalidExecutionModel,
1728     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1729     Combine(
1730         Values("SampleMask"),
1731         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
1732                "TessellationEvaluation"),
1733         Values("Input"), Values("%u32arr2"),
1734         Values("VUID-SampleMask-SampleMask-04357"),
1735         Values(TestResult(SPV_ERROR_INVALID_DATA,
1736                           "to be used only with Fragment execution model"))));
1737 
1738 INSTANTIATE_TEST_SUITE_P(
1739     SampleMaskWrongStorageClass,
1740     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1741     Combine(Values("SampleMask"), Values("Fragment"), Values("Workgroup"),
1742             Values("%u32arr2"), Values("VUID-SampleMask-SampleMask-04358"),
1743             Values(TestResult(
1744                 SPV_ERROR_INVALID_DATA,
1745                 "Vulkan spec allows BuiltIn SampleMask to be only used for "
1746                 "variables with Input or Output storage class"))));
1747 
1748 INSTANTIATE_TEST_SUITE_P(
1749     SampleMaskNotArray,
1750     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1751     Combine(Values("SampleMask"), Values("Fragment"), Values("Input"),
1752             Values("%f32", "%u32vec3"),
1753             Values("VUID-SampleMask-SampleMask-04359"),
1754             Values(TestResult(SPV_ERROR_INVALID_DATA,
1755                               "needs to be a 32-bit int array",
1756                               "is not an array"))));
1757 
1758 INSTANTIATE_TEST_SUITE_P(
1759     SampleMaskNotIntArray,
1760     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1761     Combine(Values("SampleMask"), Values("Fragment"), Values("Input"),
1762             Values("%f32arr2"), Values("VUID-SampleMask-SampleMask-04359"),
1763             Values(TestResult(SPV_ERROR_INVALID_DATA,
1764                               "needs to be a 32-bit int array",
1765                               "components are not int scalar"))));
1766 
1767 INSTANTIATE_TEST_SUITE_P(
1768     SampleMaskNotInt32Array,
1769     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1770     Combine(Values("SampleMask"), Values("Fragment"), Values("Input"),
1771             Values("%u64arr2"), Values("VUID-SampleMask-SampleMask-04359"),
1772             Values(TestResult(SPV_ERROR_INVALID_DATA,
1773                               "needs to be a 32-bit int array",
1774                               "has components with bit width 64"))));
1775 
1776 INSTANTIATE_TEST_SUITE_P(
1777     SamplePositionSuccess,
1778     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1779     Combine(Values("SamplePosition"), Values("Fragment"), Values("Input"),
1780             Values("%f32vec2"), Values(nullptr), Values(TestResult())));
1781 
1782 INSTANTIATE_TEST_SUITE_P(
1783     SamplePositionNotFragment,
1784     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1785     Combine(
1786         Values("SamplePosition"),
1787         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
1788                "TessellationEvaluation"),
1789         Values("Input"), Values("%f32vec2"),
1790         Values("VUID-SamplePosition-SamplePosition-04360"),
1791         Values(TestResult(SPV_ERROR_INVALID_DATA,
1792                           "to be used only with Fragment execution model"))));
1793 
1794 INSTANTIATE_TEST_SUITE_P(
1795     SamplePositionNotInput,
1796     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1797     Combine(Values("SamplePosition"), Values("Fragment"), Values("Output"),
1798             Values("%f32vec2"),
1799             Values("VUID-SamplePosition-SamplePosition-04361"),
1800             Values(TestResult(
1801                 SPV_ERROR_INVALID_DATA,
1802                 "to be only used for variables with Input storage class",
1803                 "uses storage class Output"))));
1804 
1805 INSTANTIATE_TEST_SUITE_P(
1806     SamplePositionNotFloatVector,
1807     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1808     Combine(Values("SamplePosition"), Values("Fragment"), Values("Input"),
1809             Values("%f32arr2", "%u32vec4"),
1810             Values("VUID-SamplePosition-SamplePosition-04362"),
1811             Values(TestResult(SPV_ERROR_INVALID_DATA,
1812                               "needs to be a 2-component 32-bit float vector",
1813                               "is not a float vector"))));
1814 
1815 INSTANTIATE_TEST_SUITE_P(
1816     SamplePositionNotFloatVec2,
1817     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1818     Combine(Values("SamplePosition"), Values("Fragment"), Values("Input"),
1819             Values("%f32vec3"),
1820             Values("VUID-SamplePosition-SamplePosition-04362"),
1821             Values(TestResult(SPV_ERROR_INVALID_DATA,
1822                               "needs to be a 2-component 32-bit float vector",
1823                               "has 3 components"))));
1824 
1825 INSTANTIATE_TEST_SUITE_P(
1826     SamplePositionNotF32Vec2,
1827     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1828     Combine(Values("SamplePosition"), Values("Fragment"), Values("Input"),
1829             Values("%f64vec2"),
1830             Values("VUID-SamplePosition-SamplePosition-04362"),
1831             Values(TestResult(SPV_ERROR_INVALID_DATA,
1832                               "needs to be a 2-component 32-bit float vector",
1833                               "has components with bit width 64"))));
1834 
1835 INSTANTIATE_TEST_SUITE_P(
1836     TessCoordSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1837     Combine(Values("TessCoord"), Values("TessellationEvaluation"),
1838             Values("Input"), Values("%f32vec3"), Values(nullptr),
1839             Values(TestResult())));
1840 
1841 INSTANTIATE_TEST_SUITE_P(
1842     TessCoordNotFragment,
1843     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1844     Combine(
1845         Values("TessCoord"),
1846         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
1847                "Fragment"),
1848         Values("Input"), Values("%f32vec3"),
1849         Values("VUID-TessCoord-TessCoord-04387"),
1850         Values(TestResult(
1851             SPV_ERROR_INVALID_DATA,
1852             "to be used only with TessellationEvaluation execution model"))));
1853 
1854 INSTANTIATE_TEST_SUITE_P(
1855     TessCoordNotInput, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1856     Combine(Values("TessCoord"), Values("Fragment"), Values("Output"),
1857             Values("%f32vec3"), Values("VUID-TessCoord-TessCoord-04388"),
1858             Values(TestResult(
1859                 SPV_ERROR_INVALID_DATA,
1860                 "to be only used for variables with Input storage class",
1861                 "uses storage class Output"))));
1862 
1863 INSTANTIATE_TEST_SUITE_P(
1864     TessCoordNotFloatVector,
1865     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1866     Combine(Values("TessCoord"), Values("Fragment"), Values("Input"),
1867             Values("%f32arr3", "%u32vec4"),
1868             Values("VUID-TessCoord-TessCoord-04389"),
1869             Values(TestResult(SPV_ERROR_INVALID_DATA,
1870                               "needs to be a 3-component 32-bit float vector",
1871                               "is not a float vector"))));
1872 
1873 INSTANTIATE_TEST_SUITE_P(
1874     TessCoordNotFloatVec3,
1875     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1876     Combine(Values("TessCoord"), Values("Fragment"), Values("Input"),
1877             Values("%f32vec2"), Values("VUID-TessCoord-TessCoord-04389"),
1878             Values(TestResult(SPV_ERROR_INVALID_DATA,
1879                               "needs to be a 3-component 32-bit float vector",
1880                               "has 2 components"))));
1881 
1882 INSTANTIATE_TEST_SUITE_P(
1883     TessCoordNotF32Vec3,
1884     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1885     Combine(Values("TessCoord"), Values("Fragment"), Values("Input"),
1886             Values("%f64vec3"), Values("VUID-TessCoord-TessCoord-04389"),
1887             Values(TestResult(SPV_ERROR_INVALID_DATA,
1888                               "needs to be a 3-component 32-bit float vector",
1889                               "has components with bit width 64"))));
1890 
1891 INSTANTIATE_TEST_SUITE_P(
1892     TessLevelOuterTeseInputSuccess,
1893     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1894     Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"),
1895             Values("Input"), Values("%f32arr4"), Values(nullptr),
1896             Values(TestResult())));
1897 
1898 INSTANTIATE_TEST_SUITE_P(
1899     TessLevelOuterTescOutputSuccess,
1900     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1901     Combine(Values("TessLevelOuter"), Values("TessellationControl"),
1902             Values("Output"), Values("%f32arr4"), Values(nullptr),
1903             Values(TestResult())));
1904 
1905 INSTANTIATE_TEST_SUITE_P(
1906     TessLevelOuterInvalidExecutionModel,
1907     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1908     Combine(Values("TessLevelOuter"),
1909             Values("Vertex", "GLCompute", "Geometry", "Fragment"),
1910             Values("Input"), Values("%f32arr4"),
1911             Values("VUID-TessLevelOuter-TessLevelOuter-04390"),
1912             Values(TestResult(SPV_ERROR_INVALID_DATA,
1913                               "to be used only with TessellationControl or "
1914                               "TessellationEvaluation execution models."))));
1915 
1916 INSTANTIATE_TEST_SUITE_P(
1917     TessLevelOuterOutputTese,
1918     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1919     Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"),
1920             Values("Output"), Values("%f32arr4"), Values(nullptr),
1921             Values(TestResult(
1922                 SPV_ERROR_INVALID_DATA,
1923                 "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
1924                 "used for variables with Output storage class if execution "
1925                 "model is TessellationEvaluation."))));
1926 
1927 INSTANTIATE_TEST_SUITE_P(
1928     TessLevelOuterInputTesc,
1929     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1930     Combine(Values("TessLevelOuter"), Values("TessellationControl"),
1931             Values("Input"), Values("%f32arr4"), Values(nullptr),
1932             Values(TestResult(
1933                 SPV_ERROR_INVALID_DATA,
1934                 "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
1935                 "used for variables with Input storage class if execution "
1936                 "model is TessellationControl."))));
1937 
1938 INSTANTIATE_TEST_SUITE_P(
1939     TessLevelOuterNotArray,
1940     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1941     Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"),
1942             Values("Input"), Values("%f32vec4", "%f32"),
1943             Values("VUID-TessLevelOuter-TessLevelOuter-04393"),
1944             Values(TestResult(SPV_ERROR_INVALID_DATA,
1945                               "needs to be a 4-component 32-bit float array",
1946                               "is not an array"))));
1947 
1948 INSTANTIATE_TEST_SUITE_P(
1949     TessLevelOuterNotFloatArray,
1950     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1951     Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"),
1952             Values("Input"), Values("%u32arr4"),
1953             Values("VUID-TessLevelOuter-TessLevelOuter-04393"),
1954             Values(TestResult(SPV_ERROR_INVALID_DATA,
1955                               "needs to be a 4-component 32-bit float array",
1956                               "components are not float scalar"))));
1957 
1958 INSTANTIATE_TEST_SUITE_P(
1959     TessLevelOuterNotFloatArr4,
1960     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1961     Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"),
1962             Values("Input"), Values("%f32arr3"),
1963             Values("VUID-TessLevelOuter-TessLevelOuter-04393"),
1964             Values(TestResult(SPV_ERROR_INVALID_DATA,
1965                               "needs to be a 4-component 32-bit float array",
1966                               "has 3 components"))));
1967 
1968 INSTANTIATE_TEST_SUITE_P(
1969     TessLevelOuterNotF32Arr4,
1970     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1971     Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"),
1972             Values("Input"), Values("%f64arr4"),
1973             Values("VUID-TessLevelOuter-TessLevelOuter-04393"),
1974             Values(TestResult(SPV_ERROR_INVALID_DATA,
1975                               "needs to be a 4-component 32-bit float array",
1976                               "has components with bit width 64"))));
1977 
1978 INSTANTIATE_TEST_SUITE_P(
1979     TessLevelInnerTeseInputSuccess,
1980     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1981     Combine(Values("TessLevelInner"), Values("TessellationEvaluation"),
1982             Values("Input"), Values("%f32arr2"), Values(nullptr),
1983             Values(TestResult())));
1984 
1985 INSTANTIATE_TEST_SUITE_P(
1986     TessLevelInnerTescOutputSuccess,
1987     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1988     Combine(Values("TessLevelInner"), Values("TessellationControl"),
1989             Values("Output"), Values("%f32arr2"), Values(nullptr),
1990             Values(TestResult())));
1991 
1992 INSTANTIATE_TEST_SUITE_P(
1993     TessLevelInnerInvalidExecutionModel,
1994     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1995     Combine(Values("TessLevelInner"),
1996             Values("Vertex", "GLCompute", "Geometry", "Fragment"),
1997             Values("Input"), Values("%f32arr2"),
1998             Values("VUID-TessLevelInner-TessLevelInner-04394"),
1999             Values(TestResult(SPV_ERROR_INVALID_DATA,
2000                               "to be used only with TessellationControl or "
2001                               "TessellationEvaluation execution models."))));
2002 
2003 INSTANTIATE_TEST_SUITE_P(
2004     TessLevelInnerOutputTese,
2005     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
2006     Combine(Values("TessLevelInner"), Values("TessellationEvaluation"),
2007             Values("Output"), Values("%f32arr2"), Values(nullptr),
2008             Values(TestResult(
2009                 SPV_ERROR_INVALID_DATA,
2010                 "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
2011                 "used for variables with Output storage class if execution "
2012                 "model is TessellationEvaluation."))));
2013 
2014 INSTANTIATE_TEST_SUITE_P(
2015     TessLevelInnerInputTesc,
2016     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
2017     Combine(Values("TessLevelInner"), Values("TessellationControl"),
2018             Values("Input"), Values("%f32arr2"), Values(nullptr),
2019             Values(TestResult(
2020                 SPV_ERROR_INVALID_DATA,
2021                 "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
2022                 "used for variables with Input storage class if execution "
2023                 "model is TessellationControl."))));
2024 
2025 INSTANTIATE_TEST_SUITE_P(
2026     TessLevelInnerNotArray,
2027     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
2028     Combine(Values("TessLevelInner"), Values("TessellationEvaluation"),
2029             Values("Input"), Values("%f32vec2", "%f32"),
2030             Values("VUID-TessLevelInner-TessLevelInner-04397"),
2031             Values(TestResult(SPV_ERROR_INVALID_DATA,
2032                               "needs to be a 2-component 32-bit float array",
2033                               "is not an array"))));
2034 
2035 INSTANTIATE_TEST_SUITE_P(
2036     TessLevelInnerNotFloatArray,
2037     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
2038     Combine(Values("TessLevelInner"), Values("TessellationEvaluation"),
2039             Values("Input"), Values("%u32arr2"),
2040             Values("VUID-TessLevelInner-TessLevelInner-04397"),
2041             Values(TestResult(SPV_ERROR_INVALID_DATA,
2042                               "needs to be a 2-component 32-bit float array",
2043                               "components are not float scalar"))));
2044 
2045 INSTANTIATE_TEST_SUITE_P(
2046     TessLevelInnerNotFloatArr2,
2047     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
2048     Combine(Values("TessLevelInner"), Values("TessellationEvaluation"),
2049             Values("Input"), Values("%f32arr3"),
2050             Values("VUID-TessLevelInner-TessLevelInner-04397"),
2051             Values(TestResult(SPV_ERROR_INVALID_DATA,
2052                               "needs to be a 2-component 32-bit float array",
2053                               "has 3 components"))));
2054 
2055 INSTANTIATE_TEST_SUITE_P(
2056     TessLevelInnerNotF32Arr2,
2057     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
2058     Combine(Values("TessLevelInner"), Values("TessellationEvaluation"),
2059             Values("Input"), Values("%f64arr2"),
2060             Values("VUID-TessLevelInner-TessLevelInner-04397"),
2061             Values(TestResult(SPV_ERROR_INVALID_DATA,
2062                               "needs to be a 2-component 32-bit float array",
2063                               "has components with bit width 64"))));
2064 
2065 INSTANTIATE_TEST_SUITE_P(
2066     VertexIndexSuccess,
2067     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
2068     Combine(Values("VertexIndex"), Values("Vertex"), Values("Input"),
2069             Values("%u32"), Values(nullptr), Values(TestResult())));
2070 
2071 INSTANTIATE_TEST_SUITE_P(
2072     VertexIndexSuccess,
2073     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
2074     Combine(Values("VertexIndex"), Values("Vertex"), Values("Input"),
2075             Values("%u32"), Values(TestResult())));
2076 
2077 INSTANTIATE_TEST_SUITE_P(
2078     VertexIndexInvalidExecutionModel,
2079     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
2080     Combine(Values("VertexIndex"),
2081             Values("Fragment", "GLCompute", "Geometry", "TessellationControl",
2082                    "TessellationEvaluation"),
2083             Values("Input"), Values("%u32"),
2084             Values("VUID-VertexIndex-VertexIndex-04398"),
2085             Values(TestResult(SPV_ERROR_INVALID_DATA,
2086                               "to be used only with Vertex execution model"))));
2087 
2088 INSTANTIATE_TEST_SUITE_P(
2089     VertexIndexInvalidExecutionModel,
2090     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
2091     Combine(Values("VertexIndex"), Values("Fragment", "GLCompute"),
2092             Values("Input"), Values("%u32"),
2093             Values(TestResult(SPV_ERROR_INVALID_DATA,
2094                               "to be used only with Vertex execution model"))));
2095 
2096 INSTANTIATE_TEST_SUITE_P(
2097     VertexIndexNotInput,
2098     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
2099     Combine(
2100         Values("VertexIndex"), Values("Vertex"), Values("Output"),
2101         Values("%u32"), Values("VUID-VertexIndex-VertexIndex-04399"),
2102         Values(TestResult(SPV_ERROR_INVALID_DATA,
2103                           "Vulkan spec allows BuiltIn VertexIndex to be only "
2104                           "used for variables with Input storage class"))));
2105 
2106 INSTANTIATE_TEST_SUITE_P(
2107     VertexIndexNotInput,
2108     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
2109     Combine(
2110         Values("VertexIndex"), Values("Vertex"), Values("Output"),
2111         Values("%u32"),
2112         Values(TestResult(SPV_ERROR_INVALID_DATA,
2113                           "WebGPU spec allows BuiltIn VertexIndex to be only "
2114                           "used for variables with Input storage class"))));
2115 
2116 INSTANTIATE_TEST_SUITE_P(
2117     VertexIndexNotIntScalar,
2118     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
2119     Combine(Values("VertexIndex"), Values("Vertex"), Values("Input"),
2120             Values("%f32", "%u32vec3"),
2121             Values("VUID-VertexIndex-VertexIndex-04400"),
2122             Values(TestResult(SPV_ERROR_INVALID_DATA,
2123                               "needs to be a 32-bit int scalar",
2124                               "is not an int scalar"))));
2125 
2126 INSTANTIATE_TEST_SUITE_P(
2127     VertexIndexNotIntScalar,
2128     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
2129     Combine(Values("VertexIndex"), Values("Vertex"), Values("Input"),
2130             Values("%f32", "%u32vec3"),
2131             Values(TestResult(SPV_ERROR_INVALID_DATA,
2132                               "needs to be a 32-bit int scalar",
2133                               "is not an int scalar"))));
2134 
2135 INSTANTIATE_TEST_SUITE_P(
2136     VertexIndexNotInt32,
2137     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
2138     Combine(Values("VertexIndex"), Values("Vertex"), Values("Input"),
2139             Values("%u64"), Values("VUID-VertexIndex-VertexIndex-04400"),
2140             Values(TestResult(SPV_ERROR_INVALID_DATA,
2141                               "needs to be a 32-bit int scalar",
2142                               "has bit width 64"))));
2143 
2144 INSTANTIATE_TEST_SUITE_P(
2145     LocalInvocationIndexSuccess,
2146     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
2147     Combine(Values("LocalInvocationIndex"), Values("GLCompute"),
2148             Values("Input"), Values("%u32"), Values(TestResult())));
2149 
2150 INSTANTIATE_TEST_SUITE_P(
2151     LocalInvocationIndexInvalidExecutionModel,
2152     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
2153     Combine(
2154         Values("LocalInvocationIndex"), Values("Fragment", "Vertex"),
2155         Values("Input"), Values("%u32"),
2156         Values(TestResult(SPV_ERROR_INVALID_DATA,
2157                           "to be used only with GLCompute execution model"))));
2158 
2159 INSTANTIATE_TEST_SUITE_P(
2160     LocalInvocationIndexNotInput,
2161     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
2162     Combine(
2163         Values("LocalInvocationIndex"), Values("GLCompute"), Values("Output"),
2164         Values("%u32"),
2165         Values(TestResult(SPV_ERROR_INVALID_DATA,
2166                           "WebGPU spec allows BuiltIn LocalInvocationIndex to "
2167                           "be only used for variables with Input storage "
2168                           "class"))));
2169 
2170 INSTANTIATE_TEST_SUITE_P(
2171     LocalInvocationIndexNotIntScalar,
2172     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
2173     Combine(Values("LocalInvocationIndex"), Values("GLCompute"),
2174             Values("Input"), Values("%f32", "%u32vec3"),
2175             Values(TestResult(SPV_ERROR_INVALID_DATA,
2176                               "needs to be a 32-bit int", "is not an int"))));
2177 
2178 INSTANTIATE_TEST_SUITE_P(
2179     AllowListRejection,
2180     ValidateWebGPUCombineBuiltInExecutionModelDataTypeResult,
2181     Combine(Values("PointSize", "ClipDistance", "CullDistance", "VertexId",
2182                    "InstanceId", "PointCoord", "SampleMask", "HelperInvocation",
2183                    "WorkgroupId"),
2184             Values("Vertex"), Values("Input"), Values("%u32"),
2185             Values(TestResult(SPV_ERROR_INVALID_DATA,
2186                               "WebGPU does not allow BuiltIn"))));
2187 
2188 INSTANTIATE_TEST_SUITE_P(
2189     BaseInstanceOrVertexSuccess,
2190     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
2191     Combine(Values("BaseInstance", "BaseVertex"), Values("Vertex"),
2192             Values("Input"), Values("%u32"),
2193             Values("OpCapability DrawParameters\n"),
2194             Values("OpExtension \"SPV_KHR_shader_draw_parameters\"\n"),
2195             Values(nullptr), Values(TestResult())));
2196 
2197 INSTANTIATE_TEST_SUITE_P(
2198     BaseInstanceOrVertexInvalidExecutionModel,
2199     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
2200     Combine(Values("BaseInstance", "BaseVertex"),
2201             Values("Fragment", "GLCompute", "Geometry", "TessellationControl",
2202                    "TessellationEvaluation"),
2203             Values("Input"), Values("%u32"),
2204             Values("OpCapability DrawParameters\n"),
2205             Values("OpExtension \"SPV_KHR_shader_draw_parameters\"\n"),
2206             Values("VUID-BaseInstance-BaseInstance-04181 "
2207                    "VUID-BaseVertex-BaseVertex-04184"),
2208             Values(TestResult(SPV_ERROR_INVALID_DATA,
2209                               "to be used only with Vertex execution model"))));
2210 
2211 INSTANTIATE_TEST_SUITE_P(
2212     BaseInstanceOrVertexNotInput,
2213     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
2214     Combine(Values("BaseInstance", "BaseVertex"), Values("Vertex"),
2215             Values("Output"), Values("%u32"),
2216             Values("OpCapability DrawParameters\n"),
2217             Values("OpExtension \"SPV_KHR_shader_draw_parameters\"\n"),
2218             Values("VUID-BaseInstance-BaseInstance-04182 "
2219                    "VUID-BaseVertex-BaseVertex-04185"),
2220             Values(TestResult(SPV_ERROR_INVALID_DATA, "Vulkan spec allows",
2221                               "used for variables with Input storage class"))));
2222 
2223 INSTANTIATE_TEST_SUITE_P(
2224     BaseInstanceOrVertexNotIntScalar,
2225     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
2226     Combine(Values("BaseInstance", "BaseVertex"), Values("Vertex"),
2227             Values("Input"), Values("%f32", "%u32vec3"),
2228             Values("OpCapability DrawParameters\n"),
2229             Values("OpExtension \"SPV_KHR_shader_draw_parameters\"\n"),
2230             Values("VUID-BaseInstance-BaseInstance-04183 "
2231                    "VUID-BaseVertex-BaseVertex-04186"),
2232             Values(TestResult(SPV_ERROR_INVALID_DATA,
2233                               "needs to be a 32-bit int scalar",
2234                               "is not an int scalar"))));
2235 
2236 INSTANTIATE_TEST_SUITE_P(
2237     DrawIndexSuccess,
2238     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
2239     Combine(Values("DrawIndex"), Values("Vertex"), Values("Input"),
2240             Values("%u32"), Values("OpCapability DrawParameters\n"),
2241             Values("OpExtension \"SPV_KHR_shader_draw_parameters\"\n"),
2242             Values(nullptr), Values(TestResult())));
2243 
2244 INSTANTIATE_TEST_SUITE_P(
2245     DrawIndexMeshSuccess,
2246     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
2247     Combine(
2248         Values("DrawIndex"), Values("MeshNV", "TaskNV"), Values("Input"),
2249         Values("%u32"), Values("OpCapability MeshShadingNV\n"),
2250         Values("OpExtension \"SPV_KHR_shader_draw_parameters\"\nOpExtension "
2251                "\"SPV_NV_mesh_shader\"\n"),
2252         Values(nullptr), Values(TestResult())));
2253 
2254 INSTANTIATE_TEST_SUITE_P(
2255     DrawIndexInvalidExecutionModel,
2256     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
2257     Combine(Values("DrawIndex"),
2258             Values("Fragment", "GLCompute", "Geometry", "TessellationControl",
2259                    "TessellationEvaluation"),
2260             Values("Input"), Values("%u32"),
2261             Values("OpCapability DrawParameters\n"),
2262             Values("OpExtension \"SPV_KHR_shader_draw_parameters\"\n"),
2263             Values("VUID-DrawIndex-DrawIndex-04207"),
2264             Values(TestResult(SPV_ERROR_INVALID_DATA,
2265                               "to be used only with Vertex, MeshNV, or TaskNV "
2266                               "execution model"))));
2267 
2268 INSTANTIATE_TEST_SUITE_P(
2269     DrawIndexNotInput,
2270     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
2271     Combine(Values("DrawIndex"), Values("Vertex"), Values("Output"),
2272             Values("%u32"), Values("OpCapability DrawParameters\n"),
2273             Values("OpExtension \"SPV_KHR_shader_draw_parameters\"\n"),
2274             Values("VUID-DrawIndex-DrawIndex-04208"),
2275             Values(TestResult(SPV_ERROR_INVALID_DATA, "Vulkan spec allows",
2276                               "used for variables with Input storage class"))));
2277 
2278 INSTANTIATE_TEST_SUITE_P(
2279     DrawIndexNotIntScalar,
2280     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
2281     Combine(Values("DrawIndex"), Values("Vertex"), Values("Input"),
2282             Values("%f32", "%u32vec3"), Values("OpCapability DrawParameters\n"),
2283             Values("OpExtension \"SPV_KHR_shader_draw_parameters\"\n"),
2284             Values("VUID-DrawIndex-DrawIndex-04209"),
2285             Values(TestResult(SPV_ERROR_INVALID_DATA,
2286                               "needs to be a 32-bit int scalar",
2287                               "is not an int scalar"))));
2288 
2289 INSTANTIATE_TEST_SUITE_P(
2290     ViewIndexSuccess,
2291     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
2292     Combine(Values("ViewIndex"),
2293             Values("Fragment", "Vertex", "Geometry", "TessellationControl",
2294                    "TessellationEvaluation"),
2295             Values("Input"), Values("%u32"), Values("OpCapability MultiView\n"),
2296             Values("OpExtension \"SPV_KHR_multiview\"\n"), Values(nullptr),
2297             Values(TestResult())));
2298 
2299 INSTANTIATE_TEST_SUITE_P(
2300     ViewIndexInvalidExecutionModel,
2301     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
2302     Combine(Values("ViewIndex"), Values("GLCompute"), Values("Input"),
2303             Values("%u32"), Values("OpCapability MultiView\n"),
2304             Values("OpExtension \"SPV_KHR_multiview\"\n"),
2305             Values("VUID-ViewIndex-ViewIndex-04401"),
2306             Values(TestResult(
2307                 SPV_ERROR_INVALID_DATA,
2308                 "to be not be used with GLCompute execution model"))));
2309 
2310 INSTANTIATE_TEST_SUITE_P(
2311     ViewIndexNotInput,
2312     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
2313     Combine(Values("ViewIndex"), Values("Vertex"), Values("Output"),
2314             Values("%u32"), Values("OpCapability MultiView\n"),
2315             Values("OpExtension \"SPV_KHR_multiview\"\n"),
2316             Values("VUID-ViewIndex-ViewIndex-04402"),
2317             Values(TestResult(SPV_ERROR_INVALID_DATA, "Vulkan spec allows",
2318                               "used for variables with Input storage class"))));
2319 
2320 INSTANTIATE_TEST_SUITE_P(
2321     ViewIndexNotIntScalar,
2322     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
2323     Combine(Values("ViewIndex"), Values("Vertex"), Values("Input"),
2324             Values("%f32", "%u32vec3"), Values("OpCapability MultiView\n"),
2325             Values("OpExtension \"SPV_KHR_multiview\"\n"),
2326             Values("VUID-ViewIndex-ViewIndex-04403"),
2327             Values(TestResult(SPV_ERROR_INVALID_DATA,
2328                               "needs to be a 32-bit int scalar",
2329                               "is not an int scalar"))));
2330 
2331 INSTANTIATE_TEST_SUITE_P(
2332     DeviceIndexSuccess,
2333     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
2334     Combine(Values("DeviceIndex"),
2335             Values("Fragment", "Vertex", "Geometry", "TessellationControl",
2336                    "TessellationEvaluation", "GLCompute"),
2337             Values("Input"), Values("%u32"),
2338             Values("OpCapability DeviceGroup\n"),
2339             Values("OpExtension \"SPV_KHR_device_group\"\n"), Values(nullptr),
2340             Values(TestResult())));
2341 
2342 INSTANTIATE_TEST_SUITE_P(
2343     DeviceIndexNotInput,
2344     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
2345     Combine(Values("DeviceIndex"), Values("Fragment", "Vertex", "GLCompute"),
2346             Values("Output"), Values("%u32"),
2347             Values("OpCapability DeviceGroup\n"),
2348             Values("OpExtension \"SPV_KHR_device_group\"\n"),
2349             Values("VUID-DeviceIndex-DeviceIndex-04205"),
2350             Values(TestResult(SPV_ERROR_INVALID_DATA, "Vulkan spec allows",
2351                               "used for variables with Input storage class"))));
2352 
2353 INSTANTIATE_TEST_SUITE_P(
2354     DeviceIndexNotIntScalar,
2355     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
2356     Combine(Values("DeviceIndex"), Values("Fragment", "Vertex", "GLCompute"),
2357             Values("Input"), Values("%f32", "%u32vec3"),
2358             Values("OpCapability DeviceGroup\n"),
2359             Values("OpExtension \"SPV_KHR_device_group\"\n"),
2360             Values("VUID-DeviceIndex-DeviceIndex-04206"),
2361             Values(TestResult(SPV_ERROR_INVALID_DATA,
2362                               "needs to be a 32-bit int scalar",
2363                               "is not an int scalar"))));
2364 
GetArrayedVariableCodeGenerator(spv_target_env env,const char * const built_in,const char * const execution_model,const char * const storage_class,const char * const data_type)2365 CodeGenerator GetArrayedVariableCodeGenerator(spv_target_env env,
2366                                               const char* const built_in,
2367                                               const char* const execution_model,
2368                                               const char* const storage_class,
2369                                               const char* const data_type) {
2370   CodeGenerator generator =
2371       spvIsWebGPUEnv(env) ? CodeGenerator::GetWebGPUShaderCodeGenerator()
2372                           : CodeGenerator::GetDefaultShaderCodeGenerator();
2373 
2374   generator.before_types_ = "OpDecorate %built_in_var BuiltIn ";
2375   generator.before_types_ += built_in;
2376   generator.before_types_ += "\n";
2377 
2378   std::ostringstream after_types;
2379   after_types << "%built_in_array = OpTypeArray " << data_type << " %u32_3\n";
2380   if (InitializerRequired(env, storage_class)) {
2381     after_types << "%built_in_array_null = OpConstantNull %built_in_array\n";
2382   }
2383 
2384   after_types << "%built_in_ptr = OpTypePointer " << storage_class
2385               << " %built_in_array\n";
2386   after_types << "%built_in_var = OpVariable %built_in_ptr " << storage_class;
2387   if (InitializerRequired(env, storage_class)) {
2388     after_types << " %built_in_array_null";
2389   }
2390   after_types << "\n";
2391   generator.after_types_ = after_types.str();
2392 
2393   EntryPoint entry_point;
2394   entry_point.name = "main";
2395   entry_point.execution_model = execution_model;
2396   entry_point.interfaces = "%built_in_var";
2397   // Any kind of reference would do.
2398   entry_point.body = R"(
2399 %val = OpBitcast %u32 %built_in_var
2400 )";
2401 
2402   std::ostringstream execution_modes;
2403   if (0 == std::strcmp(execution_model, "Fragment")) {
2404     execution_modes << "OpExecutionMode %" << entry_point.name
2405                     << " OriginUpperLeft\n";
2406     if (0 == std::strcmp(built_in, "FragDepth")) {
2407       execution_modes << "OpExecutionMode %" << entry_point.name
2408                       << " DepthReplacing\n";
2409     }
2410   }
2411   if (0 == std::strcmp(execution_model, "Geometry")) {
2412     execution_modes << "OpExecutionMode %" << entry_point.name
2413                     << " InputPoints\n";
2414     execution_modes << "OpExecutionMode %" << entry_point.name
2415                     << " OutputPoints\n";
2416   }
2417   if (0 == std::strcmp(execution_model, "GLCompute")) {
2418     execution_modes << "OpExecutionMode %" << entry_point.name
2419                     << " LocalSize 1 1 1\n";
2420   }
2421   entry_point.execution_modes = execution_modes.str();
2422 
2423   generator.entry_points_.push_back(std::move(entry_point));
2424 
2425   return generator;
2426 }
2427 
TEST_P(ValidateVulkanCombineBuiltInArrayedVariable,Variable)2428 TEST_P(ValidateVulkanCombineBuiltInArrayedVariable, Variable) {
2429   const char* const built_in = std::get<0>(GetParam());
2430   const char* const execution_model = std::get<1>(GetParam());
2431   const char* const storage_class = std::get<2>(GetParam());
2432   const char* const data_type = std::get<3>(GetParam());
2433   const TestResult& test_result = std::get<4>(GetParam());
2434 
2435   CodeGenerator generator = GetArrayedVariableCodeGenerator(
2436       SPV_ENV_VULKAN_1_0, built_in, execution_model, storage_class, data_type);
2437 
2438   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
2439   ASSERT_EQ(test_result.validation_result,
2440             ValidateInstructions(SPV_ENV_VULKAN_1_0));
2441   if (test_result.error_str) {
2442     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
2443   }
2444   if (test_result.error_str2) {
2445     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
2446   }
2447 }
2448 
TEST_P(ValidateWebGPUCombineBuiltInArrayedVariable,Variable)2449 TEST_P(ValidateWebGPUCombineBuiltInArrayedVariable, Variable) {
2450   const char* const built_in = std::get<0>(GetParam());
2451   const char* const execution_model = std::get<1>(GetParam());
2452   const char* const storage_class = std::get<2>(GetParam());
2453   const char* const data_type = std::get<3>(GetParam());
2454   const TestResult& test_result = std::get<4>(GetParam());
2455 
2456   CodeGenerator generator = GetArrayedVariableCodeGenerator(
2457       SPV_ENV_WEBGPU_0, built_in, execution_model, storage_class, data_type);
2458 
2459   CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
2460   ASSERT_EQ(test_result.validation_result,
2461             ValidateInstructions(SPV_ENV_WEBGPU_0));
2462   if (test_result.error_str) {
2463     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
2464   }
2465   if (test_result.error_str2) {
2466     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
2467   }
2468 }
2469 
2470 INSTANTIATE_TEST_SUITE_P(PointSizeArrayedF32TessControl,
2471                          ValidateVulkanCombineBuiltInArrayedVariable,
2472                          Combine(Values("PointSize"),
2473                                  Values("TessellationControl"), Values("Input"),
2474                                  Values("%f32"), Values(TestResult())));
2475 
2476 INSTANTIATE_TEST_SUITE_P(
2477     PointSizeArrayedF64TessControl, ValidateVulkanCombineBuiltInArrayedVariable,
2478     Combine(Values("PointSize"), Values("TessellationControl"), Values("Input"),
2479             Values("%f64"),
2480             Values(TestResult(SPV_ERROR_INVALID_DATA,
2481                               "needs to be a 32-bit float scalar",
2482                               "has bit width 64"))));
2483 
2484 INSTANTIATE_TEST_SUITE_P(
2485     PointSizeArrayedF32Vertex, ValidateVulkanCombineBuiltInArrayedVariable,
2486     Combine(Values("PointSize"), Values("Vertex"), Values("Output"),
2487             Values("%f32"),
2488             Values(TestResult(SPV_ERROR_INVALID_DATA,
2489                               "needs to be a 32-bit float scalar",
2490                               "is not a float scalar"))));
2491 
2492 INSTANTIATE_TEST_SUITE_P(PositionArrayedF32Vec4TessControl,
2493                          ValidateVulkanCombineBuiltInArrayedVariable,
2494                          Combine(Values("Position"),
2495                                  Values("TessellationControl"), Values("Input"),
2496                                  Values("%f32vec4"), Values(TestResult())));
2497 
2498 INSTANTIATE_TEST_SUITE_P(
2499     PositionArrayedF32Vec3TessControl,
2500     ValidateVulkanCombineBuiltInArrayedVariable,
2501     Combine(Values("Position"), Values("TessellationControl"), Values("Input"),
2502             Values("%f32vec3"),
2503             Values(TestResult(SPV_ERROR_INVALID_DATA,
2504                               "needs to be a 4-component 32-bit float vector",
2505                               "has 3 components"))));
2506 
2507 INSTANTIATE_TEST_SUITE_P(
2508     PositionArrayedF32Vec4Vertex, ValidateVulkanCombineBuiltInArrayedVariable,
2509     Combine(Values("Position"), Values("Vertex"), Values("Output"),
2510             Values("%f32vec4"),
2511             Values(TestResult(SPV_ERROR_INVALID_DATA,
2512                               "needs to be a 4-component 32-bit float vector",
2513                               "is not a float vector"))));
2514 
2515 INSTANTIATE_TEST_SUITE_P(
2516     PositionArrayedF32Vec4Vertex, ValidateWebGPUCombineBuiltInArrayedVariable,
2517     Combine(Values("Position"), Values("Vertex"), Values("Output"),
2518             Values("%f32vec4"),
2519             Values(TestResult(SPV_ERROR_INVALID_DATA,
2520                               "needs to be a 4-component 32-bit float vector",
2521                               "is not a float vector"))));
2522 
2523 INSTANTIATE_TEST_SUITE_P(
2524     ClipAndCullDistanceOutputSuccess,
2525     ValidateVulkanCombineBuiltInArrayedVariable,
2526     Combine(Values("ClipDistance", "CullDistance"),
2527             Values("Geometry", "TessellationControl", "TessellationEvaluation"),
2528             Values("Output"), Values("%f32arr2", "%f32arr4"),
2529             Values(TestResult())));
2530 
2531 INSTANTIATE_TEST_SUITE_P(
2532     ClipAndCullDistanceVertexInput, ValidateVulkanCombineBuiltInArrayedVariable,
2533     Combine(Values("ClipDistance", "CullDistance"), Values("Fragment"),
2534             Values("Input"), Values("%f32arr4"),
2535             Values(TestResult(SPV_ERROR_INVALID_DATA,
2536                               "needs to be a 32-bit float array",
2537                               "components are not float scalar"))));
2538 
2539 INSTANTIATE_TEST_SUITE_P(
2540     ClipAndCullDistanceNotArray, ValidateVulkanCombineBuiltInArrayedVariable,
2541     Combine(Values("ClipDistance", "CullDistance"),
2542             Values("Geometry", "TessellationControl", "TessellationEvaluation"),
2543             Values("Input"), Values("%f32vec2", "%f32vec4"),
2544             Values(TestResult(SPV_ERROR_INVALID_DATA,
2545                               "needs to be a 32-bit float array",
2546                               "components are not float scalar"))));
2547 
2548 INSTANTIATE_TEST_SUITE_P(
2549     SMBuiltinsInputSuccess,
2550     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
2551     Combine(Values("SMCountNV", "SMIDNV", "WarpsPerSMNV", "WarpIDNV"),
2552             Values("Vertex", "Fragment", "TessellationControl",
2553                    "TessellationEvaluation", "Geometry", "GLCompute"),
2554             Values("Input"), Values("%u32"),
2555             Values("OpCapability ShaderSMBuiltinsNV\n"),
2556             Values("OpExtension \"SPV_NV_shader_sm_builtins\"\n"),
2557             Values(nullptr), Values(TestResult())));
2558 
2559 INSTANTIATE_TEST_SUITE_P(
2560     SMBuiltinsInputMeshSuccess,
2561     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
2562     Combine(
2563         Values("SMCountNV", "SMIDNV", "WarpsPerSMNV", "WarpIDNV"),
2564         Values("MeshNV", "TaskNV"), Values("Input"), Values("%u32"),
2565         Values("OpCapability ShaderSMBuiltinsNV\nOpCapability MeshShadingNV\n"),
2566         Values("OpExtension \"SPV_NV_shader_sm_builtins\"\nOpExtension "
2567                "\"SPV_NV_mesh_shader\"\n"),
2568         Values(nullptr), Values(TestResult())));
2569 
2570 INSTANTIATE_TEST_SUITE_P(
2571     SMBuiltinsInputRaySuccess,
2572     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
2573     Combine(
2574         Values("SMCountNV", "SMIDNV", "WarpsPerSMNV", "WarpIDNV"),
2575         Values("RayGenerationNV", "IntersectionNV", "AnyHitNV", "ClosestHitNV",
2576                "MissNV", "CallableNV"),
2577         Values("Input"), Values("%u32"),
2578         Values("OpCapability ShaderSMBuiltinsNV\nOpCapability RayTracingNV\n"),
2579         Values("OpExtension \"SPV_NV_shader_sm_builtins\"\nOpExtension "
2580                "\"SPV_NV_ray_tracing\"\n"),
2581         Values(nullptr), Values(TestResult())));
2582 
2583 INSTANTIATE_TEST_SUITE_P(
2584     SMBuiltinsNotInput,
2585     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
2586     Combine(Values("SMCountNV", "SMIDNV", "WarpsPerSMNV", "WarpIDNV"),
2587             Values("Vertex", "Fragment", "TessellationControl",
2588                    "TessellationEvaluation", "Geometry", "GLCompute"),
2589             Values("Output"), Values("%u32"),
2590             Values("OpCapability ShaderSMBuiltinsNV\n"),
2591             Values("OpExtension \"SPV_NV_shader_sm_builtins\"\n"),
2592             Values(nullptr),
2593             Values(TestResult(
2594                 SPV_ERROR_INVALID_DATA,
2595                 "to be only used for variables with Input storage class",
2596                 "uses storage class Output"))));
2597 
2598 INSTANTIATE_TEST_SUITE_P(
2599     SMBuiltinsNotIntScalar,
2600     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
2601     Combine(Values("SMCountNV", "SMIDNV", "WarpsPerSMNV", "WarpIDNV"),
2602             Values("Vertex", "Fragment", "TessellationControl",
2603                    "TessellationEvaluation", "Geometry", "GLCompute"),
2604             Values("Input"), Values("%f32", "%u32vec3"),
2605             Values("OpCapability ShaderSMBuiltinsNV\n"),
2606             Values("OpExtension \"SPV_NV_shader_sm_builtins\"\n"),
2607             Values(nullptr),
2608             Values(TestResult(SPV_ERROR_INVALID_DATA,
2609                               "needs to be a 32-bit int scalar",
2610                               "is not an int scalar"))));
2611 
2612 INSTANTIATE_TEST_SUITE_P(
2613     SMBuiltinsNotInt32,
2614     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
2615     Combine(Values("SMCountNV", "SMIDNV", "WarpsPerSMNV", "WarpIDNV"),
2616             Values("Vertex", "Fragment", "TessellationControl",
2617                    "TessellationEvaluation", "Geometry", "GLCompute"),
2618             Values("Input"), Values("%u64"),
2619             Values("OpCapability ShaderSMBuiltinsNV\n"),
2620             Values("OpExtension \"SPV_NV_shader_sm_builtins\"\n"),
2621             Values(nullptr),
2622             Values(TestResult(SPV_ERROR_INVALID_DATA,
2623                               "needs to be a 32-bit int scalar",
2624                               "has bit width 64"))));
2625 
GetWorkgroupSizeSuccessGenerator(spv_target_env env)2626 CodeGenerator GetWorkgroupSizeSuccessGenerator(spv_target_env env) {
2627   CodeGenerator generator =
2628       env == SPV_ENV_WEBGPU_0 ? CodeGenerator::GetWebGPUShaderCodeGenerator()
2629                               : CodeGenerator::GetDefaultShaderCodeGenerator();
2630 
2631   generator.before_types_ = R"(
2632 OpDecorate %workgroup_size BuiltIn WorkgroupSize
2633 )";
2634 
2635   generator.after_types_ = R"(
2636 %workgroup_size = OpConstantComposite %u32vec3 %u32_1 %u32_1 %u32_1
2637 )";
2638 
2639   EntryPoint entry_point;
2640   entry_point.name = "main";
2641   entry_point.execution_model = "GLCompute";
2642   entry_point.body = R"(
2643 %copy = OpCopyObject %u32vec3 %workgroup_size
2644 )";
2645   generator.entry_points_.push_back(std::move(entry_point));
2646 
2647   return generator;
2648 }
2649 
TEST_F(ValidateBuiltIns,VulkanWorkgroupSizeSuccess)2650 TEST_F(ValidateBuiltIns, VulkanWorkgroupSizeSuccess) {
2651   CodeGenerator generator =
2652       GetWorkgroupSizeSuccessGenerator(SPV_ENV_VULKAN_1_0);
2653   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
2654   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2655 }
2656 
TEST_F(ValidateBuiltIns,WebGPUWorkgroupSizeSuccess)2657 TEST_F(ValidateBuiltIns, WebGPUWorkgroupSizeSuccess) {
2658   CodeGenerator generator = GetWorkgroupSizeSuccessGenerator(SPV_ENV_WEBGPU_0);
2659   CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
2660   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
2661 }
2662 
GetWorkgroupSizeFragmentGenerator(spv_target_env env)2663 CodeGenerator GetWorkgroupSizeFragmentGenerator(spv_target_env env) {
2664   CodeGenerator generator =
2665       env == SPV_ENV_WEBGPU_0 ? CodeGenerator::GetWebGPUShaderCodeGenerator()
2666                               : CodeGenerator::GetDefaultShaderCodeGenerator();
2667 
2668   generator.before_types_ = R"(
2669 OpDecorate %workgroup_size BuiltIn WorkgroupSize
2670 )";
2671 
2672   generator.after_types_ = R"(
2673 %workgroup_size = OpConstantComposite %u32vec3 %u32_1 %u32_1 %u32_1
2674 )";
2675 
2676   EntryPoint entry_point;
2677   entry_point.name = "main";
2678   entry_point.execution_model = "Fragment";
2679   entry_point.execution_modes = "OpExecutionMode %main OriginUpperLeft";
2680   entry_point.body = R"(
2681 %copy = OpCopyObject %u32vec3 %workgroup_size
2682 )";
2683   generator.entry_points_.push_back(std::move(entry_point));
2684 
2685   return generator;
2686 }
2687 
TEST_F(ValidateBuiltIns,VulkanWorkgroupSizeFragment)2688 TEST_F(ValidateBuiltIns, VulkanWorkgroupSizeFragment) {
2689   CodeGenerator generator =
2690       GetWorkgroupSizeFragmentGenerator(SPV_ENV_VULKAN_1_0);
2691 
2692   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
2693   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2694   EXPECT_THAT(getDiagnosticString(),
2695               HasSubstr("Vulkan spec allows BuiltIn WorkgroupSize to be used "
2696                         "only with GLCompute execution model"));
2697   EXPECT_THAT(getDiagnosticString(),
2698               HasSubstr("is referencing ID <2> (OpConstantComposite) which is "
2699                         "decorated with BuiltIn WorkgroupSize in function <1> "
2700                         "called with execution model Fragment"));
2701   EXPECT_THAT(getDiagnosticString(),
2702               AnyVUID("VUID-WorkgroupSize-WorkgroupSize-04425 "
2703                       "VUID-WorkgroupSize-WorkgroupSize-04427"));
2704 }
2705 
TEST_F(ValidateBuiltIns,WebGPUWorkgroupSizeFragment)2706 TEST_F(ValidateBuiltIns, WebGPUWorkgroupSizeFragment) {
2707   CodeGenerator generator = GetWorkgroupSizeFragmentGenerator(SPV_ENV_WEBGPU_0);
2708 
2709   CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
2710   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
2711   EXPECT_THAT(getDiagnosticString(),
2712               HasSubstr("WebGPU spec allows BuiltIn WorkgroupSize to be used "
2713                         "only with GLCompute execution model"));
2714   EXPECT_THAT(getDiagnosticString(),
2715               HasSubstr("is referencing ID <2> (OpConstantComposite) which is "
2716                         "decorated with BuiltIn WorkgroupSize in function <1> "
2717                         "called with execution model Fragment"));
2718 }
2719 
TEST_F(ValidateBuiltIns,WorkgroupSizeNotConstant)2720 TEST_F(ValidateBuiltIns, WorkgroupSizeNotConstant) {
2721   CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
2722   generator.before_types_ = R"(
2723 OpDecorate %copy BuiltIn WorkgroupSize
2724 )";
2725 
2726   generator.after_types_ = R"(
2727 %workgroup_size = OpConstantComposite %u32vec3 %u32_1 %u32_1 %u32_1
2728 )";
2729 
2730   EntryPoint entry_point;
2731   entry_point.name = "main";
2732   entry_point.execution_model = "GLCompute";
2733   entry_point.body = R"(
2734 %copy = OpCopyObject %u32vec3 %workgroup_size
2735 )";
2736   generator.entry_points_.push_back(std::move(entry_point));
2737 
2738   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
2739   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2740   EXPECT_THAT(
2741       getDiagnosticString(),
2742       HasSubstr("BuiltIns can only target variables, structs or constants"));
2743 }
2744 
GetWorkgroupSizeNotVectorGenerator(spv_target_env env)2745 CodeGenerator GetWorkgroupSizeNotVectorGenerator(spv_target_env env) {
2746   CodeGenerator generator =
2747       env == SPV_ENV_WEBGPU_0 ? CodeGenerator::GetWebGPUShaderCodeGenerator()
2748                               : CodeGenerator::GetDefaultShaderCodeGenerator();
2749 
2750   generator.before_types_ = R"(
2751 OpDecorate %workgroup_size BuiltIn WorkgroupSize
2752 )";
2753 
2754   generator.after_types_ = R"(
2755 %workgroup_size = OpConstant %u32 16
2756 )";
2757 
2758   EntryPoint entry_point;
2759   entry_point.name = "main";
2760   entry_point.execution_model = "GLCompute";
2761   entry_point.body = R"(
2762 %copy = OpCopyObject %u32 %workgroup_size
2763 )";
2764   generator.entry_points_.push_back(std::move(entry_point));
2765 
2766   return generator;
2767 }
2768 
TEST_F(ValidateBuiltIns,VulkanWorkgroupSizeNotVector)2769 TEST_F(ValidateBuiltIns, VulkanWorkgroupSizeNotVector) {
2770   CodeGenerator generator =
2771       GetWorkgroupSizeNotVectorGenerator(SPV_ENV_VULKAN_1_0);
2772 
2773   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
2774   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2775   EXPECT_THAT(getDiagnosticString(),
2776               HasSubstr("According to the Vulkan spec BuiltIn WorkgroupSize "
2777                         "variable needs to be a 3-component 32-bit int vector. "
2778                         "ID <2> (OpConstant) is not an int vector."));
2779   EXPECT_THAT(getDiagnosticString(),
2780               AnyVUID("VUID-WorkgroupSize-WorkgroupSize-04427"));
2781 }
2782 
TEST_F(ValidateBuiltIns,WebGPUWorkgroupSizeNotVector)2783 TEST_F(ValidateBuiltIns, WebGPUWorkgroupSizeNotVector) {
2784   CodeGenerator generator =
2785       GetWorkgroupSizeNotVectorGenerator(SPV_ENV_WEBGPU_0);
2786 
2787   CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
2788   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
2789   EXPECT_THAT(getDiagnosticString(),
2790               HasSubstr("According to the WebGPU spec BuiltIn WorkgroupSize "
2791                         "variable needs to be a 3-component 32-bit int vector. "
2792                         "ID <2> (OpConstant) is not an int vector."));
2793 }
2794 
GetWorkgroupSizeNotIntVectorGenerator(spv_target_env env)2795 CodeGenerator GetWorkgroupSizeNotIntVectorGenerator(spv_target_env env) {
2796   CodeGenerator generator =
2797       env == SPV_ENV_WEBGPU_0 ? CodeGenerator::GetWebGPUShaderCodeGenerator()
2798                               : CodeGenerator::GetDefaultShaderCodeGenerator();
2799 
2800   generator.before_types_ = R"(
2801 OpDecorate %workgroup_size BuiltIn WorkgroupSize
2802 )";
2803 
2804   generator.after_types_ = R"(
2805 %workgroup_size = OpConstantComposite %f32vec3 %f32_1 %f32_1 %f32_1
2806 )";
2807 
2808   EntryPoint entry_point;
2809   entry_point.name = "main";
2810   entry_point.execution_model = "GLCompute";
2811   entry_point.body = R"(
2812 %copy = OpCopyObject %f32vec3 %workgroup_size
2813 )";
2814   generator.entry_points_.push_back(std::move(entry_point));
2815 
2816   return generator;
2817 }
2818 
TEST_F(ValidateBuiltIns,VulkanWorkgroupSizeNotIntVector)2819 TEST_F(ValidateBuiltIns, VulkanWorkgroupSizeNotIntVector) {
2820   CodeGenerator generator =
2821       GetWorkgroupSizeNotIntVectorGenerator(SPV_ENV_VULKAN_1_0);
2822 
2823   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
2824   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2825   EXPECT_THAT(getDiagnosticString(),
2826               HasSubstr("According to the Vulkan spec BuiltIn WorkgroupSize "
2827                         "variable needs to be a 3-component 32-bit int vector. "
2828                         "ID <2> (OpConstantComposite) is not an int vector."));
2829   EXPECT_THAT(getDiagnosticString(),
2830               AnyVUID("VUID-WorkgroupSize-WorkgroupSize-04427"));
2831 }
2832 
TEST_F(ValidateBuiltIns,WebGPUWorkgroupSizeNotIntVector)2833 TEST_F(ValidateBuiltIns, WebGPUWorkgroupSizeNotIntVector) {
2834   CodeGenerator generator =
2835       GetWorkgroupSizeNotIntVectorGenerator(SPV_ENV_WEBGPU_0);
2836 
2837   CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
2838   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
2839   EXPECT_THAT(getDiagnosticString(),
2840               HasSubstr("According to the WebGPU spec BuiltIn WorkgroupSize "
2841                         "variable needs to be a 3-component 32-bit int vector. "
2842                         "ID <2> (OpConstantComposite) is not an int vector."));
2843 }
2844 
GetWorkgroupSizeNotVec3Generator(spv_target_env env)2845 CodeGenerator GetWorkgroupSizeNotVec3Generator(spv_target_env env) {
2846   CodeGenerator generator =
2847       env == SPV_ENV_WEBGPU_0 ? CodeGenerator::GetWebGPUShaderCodeGenerator()
2848                               : CodeGenerator::GetDefaultShaderCodeGenerator();
2849 
2850   generator.before_types_ = R"(
2851 OpDecorate %workgroup_size BuiltIn WorkgroupSize
2852 )";
2853 
2854   generator.after_types_ = R"(
2855 %workgroup_size = OpConstantComposite %u32vec2 %u32_1 %u32_1
2856 )";
2857 
2858   EntryPoint entry_point;
2859   entry_point.name = "main";
2860   entry_point.execution_model = "GLCompute";
2861   entry_point.body = R"(
2862 %copy = OpCopyObject %u32vec2 %workgroup_size
2863 )";
2864   generator.entry_points_.push_back(std::move(entry_point));
2865 
2866   return generator;
2867 }
2868 
TEST_F(ValidateBuiltIns,VulkanWorkgroupSizeNotVec3)2869 TEST_F(ValidateBuiltIns, VulkanWorkgroupSizeNotVec3) {
2870   CodeGenerator generator =
2871       GetWorkgroupSizeNotVec3Generator(SPV_ENV_VULKAN_1_0);
2872 
2873   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
2874   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2875   EXPECT_THAT(getDiagnosticString(),
2876               HasSubstr("According to the Vulkan spec BuiltIn WorkgroupSize "
2877                         "variable needs to be a 3-component 32-bit int vector. "
2878                         "ID <2> (OpConstantComposite) has 2 components."));
2879   EXPECT_THAT(getDiagnosticString(),
2880               AnyVUID("VUID-WorkgroupSize-WorkgroupSize-04427"));
2881 }
2882 
TEST_F(ValidateBuiltIns,WebGPUWorkgroupSizeNotVec3)2883 TEST_F(ValidateBuiltIns, WebGPUWorkgroupSizeNotVec3) {
2884   CodeGenerator generator = GetWorkgroupSizeNotVec3Generator(SPV_ENV_WEBGPU_0);
2885 
2886   CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
2887   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
2888   EXPECT_THAT(getDiagnosticString(),
2889               HasSubstr("According to the WebGPU spec BuiltIn WorkgroupSize "
2890                         "variable needs to be a 3-component 32-bit int vector. "
2891                         "ID <2> (OpConstantComposite) has 2 components."));
2892 }
2893 
TEST_F(ValidateBuiltIns,WorkgroupSizeNotInt32Vec)2894 TEST_F(ValidateBuiltIns, WorkgroupSizeNotInt32Vec) {
2895   CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
2896   generator.before_types_ = R"(
2897 OpDecorate %workgroup_size BuiltIn WorkgroupSize
2898 )";
2899 
2900   generator.after_types_ = R"(
2901 %workgroup_size = OpConstantComposite %u64vec3 %u64_1 %u64_1 %u64_1
2902 )";
2903 
2904   EntryPoint entry_point;
2905   entry_point.name = "main";
2906   entry_point.execution_model = "GLCompute";
2907   entry_point.body = R"(
2908 %copy = OpCopyObject %u64vec3 %workgroup_size
2909 )";
2910   generator.entry_points_.push_back(std::move(entry_point));
2911 
2912   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
2913   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2914   EXPECT_THAT(
2915       getDiagnosticString(),
2916       HasSubstr("According to the Vulkan spec BuiltIn WorkgroupSize variable "
2917                 "needs to be a 3-component 32-bit int vector. ID <2> "
2918                 "(OpConstantComposite) has components with bit width 64."));
2919   EXPECT_THAT(getDiagnosticString(),
2920               AnyVUID("VUID-WorkgroupSize-WorkgroupSize-04427"));
2921 }
2922 
TEST_F(ValidateBuiltIns,WorkgroupSizePrivateVar)2923 TEST_F(ValidateBuiltIns, WorkgroupSizePrivateVar) {
2924   CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
2925   generator.before_types_ = R"(
2926 OpDecorate %workgroup_size BuiltIn WorkgroupSize
2927 )";
2928 
2929   generator.after_types_ = R"(
2930 %workgroup_size = OpConstantComposite %u32vec3 %u32_1 %u32_1 %u32_1
2931 %private_ptr_u32vec3 = OpTypePointer Private %u32vec3
2932 %var = OpVariable %private_ptr_u32vec3 Private %workgroup_size
2933 )";
2934 
2935   EntryPoint entry_point;
2936   entry_point.name = "main";
2937   entry_point.execution_model = "GLCompute";
2938   entry_point.body = R"(
2939 )";
2940   generator.entry_points_.push_back(std::move(entry_point));
2941 
2942   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
2943   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2944 }
2945 
TEST_F(ValidateBuiltIns,GeometryPositionInOutSuccess)2946 TEST_F(ValidateBuiltIns, GeometryPositionInOutSuccess) {
2947   CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
2948 
2949   generator.before_types_ = R"(
2950 OpDecorate %input_type Block
2951 OpMemberDecorate %input_type 0 BuiltIn Position
2952 OpDecorate %output_type Block
2953 OpMemberDecorate %output_type 0 BuiltIn Position
2954 )";
2955 
2956   generator.after_types_ = R"(
2957 %input_type = OpTypeStruct %f32vec4
2958 %arrayed_input_type = OpTypeArray %input_type %u32_3
2959 %input_ptr = OpTypePointer Input %arrayed_input_type
2960 %input = OpVariable %input_ptr Input
2961 %input_f32vec4_ptr = OpTypePointer Input %f32vec4
2962 %output_type = OpTypeStruct %f32vec4
2963 %output_ptr = OpTypePointer Output %output_type
2964 %output = OpVariable %output_ptr Output
2965 %output_f32vec4_ptr = OpTypePointer Output %f32vec4
2966 )";
2967 
2968   EntryPoint entry_point;
2969   entry_point.name = "main";
2970   entry_point.execution_model = "Geometry";
2971   entry_point.interfaces = "%input %output";
2972   entry_point.body = R"(
2973 %input_pos = OpAccessChain %input_f32vec4_ptr %input %u32_0 %u32_0
2974 %output_pos = OpAccessChain %output_f32vec4_ptr %output %u32_0
2975 %pos = OpLoad %f32vec4 %input_pos
2976 OpStore %output_pos %pos
2977 )";
2978   generator.entry_points_.push_back(std::move(entry_point));
2979   generator.entry_points_[0].execution_modes =
2980       "OpExecutionMode %main InputPoints\nOpExecutionMode %main OutputPoints\n";
2981 
2982   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
2983   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2984 }
2985 
TEST_F(ValidateBuiltIns,WorkgroupIdNotVec3)2986 TEST_F(ValidateBuiltIns, WorkgroupIdNotVec3) {
2987   CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
2988   generator.before_types_ = R"(
2989 OpDecorate %workgroup_size BuiltIn WorkgroupSize
2990 OpDecorate %workgroup_id BuiltIn WorkgroupId
2991 )";
2992 
2993   generator.after_types_ = R"(
2994 %workgroup_size = OpConstantComposite %u32vec3 %u32_1 %u32_1 %u32_1
2995      %input_ptr = OpTypePointer Input %u32vec2
2996   %workgroup_id = OpVariable %input_ptr Input
2997 )";
2998 
2999   EntryPoint entry_point;
3000   entry_point.name = "main";
3001   entry_point.execution_model = "GLCompute";
3002   entry_point.interfaces = "%workgroup_id";
3003   entry_point.body = R"(
3004 %copy_size = OpCopyObject %u32vec3 %workgroup_size
3005   %load_id = OpLoad %u32vec2 %workgroup_id
3006 )";
3007   generator.entry_points_.push_back(std::move(entry_point));
3008 
3009   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
3010   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
3011   EXPECT_THAT(getDiagnosticString(),
3012               HasSubstr("According to the Vulkan spec BuiltIn WorkgroupId "
3013                         "variable needs to be a 3-component 32-bit int vector. "
3014                         "ID <2> (OpVariable) has 2 components."));
3015 }
3016 
TEST_F(ValidateBuiltIns,TwoBuiltInsFirstFails)3017 TEST_F(ValidateBuiltIns, TwoBuiltInsFirstFails) {
3018   CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
3019 
3020   generator.before_types_ = R"(
3021 OpMemberDecorate %input_type 0 BuiltIn FragCoord
3022 OpMemberDecorate %output_type 0 BuiltIn Position
3023 )";
3024 
3025   generator.after_types_ = R"(
3026 %input_type = OpTypeStruct %f32vec4
3027 %input_ptr = OpTypePointer Input %input_type
3028 %input = OpVariable %input_ptr Input
3029 %input_f32vec4_ptr = OpTypePointer Input %f32vec4
3030 %output_type = OpTypeStruct %f32vec4
3031 %output_ptr = OpTypePointer Output %output_type
3032 %output = OpVariable %output_ptr Output
3033 %output_f32vec4_ptr = OpTypePointer Output %f32vec4
3034 )";
3035 
3036   EntryPoint entry_point;
3037   entry_point.name = "main";
3038   entry_point.execution_model = "Geometry";
3039   entry_point.interfaces = "%input %output";
3040   entry_point.body = R"(
3041 %input_pos = OpAccessChain %input_f32vec4_ptr %input %u32_0
3042 %output_pos = OpAccessChain %output_f32vec4_ptr %output %u32_0
3043 %pos = OpLoad %f32vec4 %input_pos
3044 OpStore %output_pos %pos
3045 )";
3046   generator.entry_points_.push_back(std::move(entry_point));
3047   generator.entry_points_[0].execution_modes =
3048       "OpExecutionMode %main InputPoints\nOpExecutionMode %main OutputPoints\n";
3049 
3050   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
3051   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
3052   EXPECT_THAT(getDiagnosticString(),
3053               HasSubstr("Vulkan spec allows BuiltIn FragCoord to be used only "
3054                         "with Fragment execution model"));
3055 }
3056 
TEST_F(ValidateBuiltIns,TwoBuiltInsSecondFails)3057 TEST_F(ValidateBuiltIns, TwoBuiltInsSecondFails) {
3058   CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
3059 
3060   generator.before_types_ = R"(
3061 OpMemberDecorate %input_type 0 BuiltIn Position
3062 OpMemberDecorate %output_type 0 BuiltIn FragCoord
3063 )";
3064 
3065   generator.after_types_ = R"(
3066 %input_type = OpTypeStruct %f32vec4
3067 %input_ptr = OpTypePointer Input %input_type
3068 %input = OpVariable %input_ptr Input
3069 %input_f32vec4_ptr = OpTypePointer Input %f32vec4
3070 %output_type = OpTypeStruct %f32vec4
3071 %output_ptr = OpTypePointer Output %output_type
3072 %output = OpVariable %output_ptr Output
3073 %output_f32vec4_ptr = OpTypePointer Output %f32vec4
3074 )";
3075 
3076   EntryPoint entry_point;
3077   entry_point.name = "main";
3078   entry_point.execution_model = "Geometry";
3079   entry_point.interfaces = "%input %output";
3080   entry_point.body = R"(
3081 %input_pos = OpAccessChain %input_f32vec4_ptr %input %u32_0
3082 %output_pos = OpAccessChain %output_f32vec4_ptr %output %u32_0
3083 %pos = OpLoad %f32vec4 %input_pos
3084 OpStore %output_pos %pos
3085 )";
3086   generator.entry_points_.push_back(std::move(entry_point));
3087   generator.entry_points_[0].execution_modes =
3088       "OpExecutionMode %main InputPoints\nOpExecutionMode %main OutputPoints\n";
3089 
3090   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
3091   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
3092   EXPECT_THAT(getDiagnosticString(),
3093               HasSubstr("Vulkan spec allows BuiltIn FragCoord to be only used "
3094                         "for variables with Input storage class"));
3095 }
3096 
TEST_F(ValidateBuiltIns,VertexPositionVariableSuccess)3097 TEST_F(ValidateBuiltIns, VertexPositionVariableSuccess) {
3098   CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
3099   generator.before_types_ = R"(
3100 OpDecorate %position BuiltIn Position
3101 )";
3102 
3103   generator.after_types_ = R"(
3104 %f32vec4_ptr_output = OpTypePointer Output %f32vec4
3105 %position = OpVariable %f32vec4_ptr_output Output
3106 )";
3107 
3108   EntryPoint entry_point;
3109   entry_point.name = "main";
3110   entry_point.execution_model = "Vertex";
3111   entry_point.interfaces = "%position";
3112   entry_point.body = R"(
3113 OpStore %position %f32vec4_0123
3114 )";
3115   generator.entry_points_.push_back(std::move(entry_point));
3116 
3117   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
3118   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
3119 }
3120 
TEST_F(ValidateBuiltIns,FragmentPositionTwoEntryPoints)3121 TEST_F(ValidateBuiltIns, FragmentPositionTwoEntryPoints) {
3122   CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
3123   generator.before_types_ = R"(
3124 OpMemberDecorate %output_type 0 BuiltIn Position
3125 )";
3126 
3127   generator.after_types_ = R"(
3128 %output_type = OpTypeStruct %f32vec4
3129 %output_ptr = OpTypePointer Output %output_type
3130 %output = OpVariable %output_ptr Output
3131 %output_f32vec4_ptr = OpTypePointer Output %f32vec4
3132 )";
3133 
3134   EntryPoint entry_point;
3135   entry_point.name = "vmain";
3136   entry_point.execution_model = "Vertex";
3137   entry_point.interfaces = "%output";
3138   entry_point.body = R"(
3139 %val1 = OpFunctionCall %void %foo
3140 )";
3141   generator.entry_points_.push_back(std::move(entry_point));
3142 
3143   entry_point.name = "fmain";
3144   entry_point.execution_model = "Fragment";
3145   entry_point.interfaces = "%output";
3146   entry_point.execution_modes = "OpExecutionMode %fmain OriginUpperLeft";
3147   entry_point.body = R"(
3148 %val2 = OpFunctionCall %void %foo
3149 )";
3150   generator.entry_points_.push_back(std::move(entry_point));
3151 
3152   generator.add_at_the_end_ = R"(
3153 %foo = OpFunction %void None %func
3154 %foo_entry = OpLabel
3155 %position = OpAccessChain %output_f32vec4_ptr %output %u32_0
3156 OpStore %position %f32vec4_0123
3157 OpReturn
3158 OpFunctionEnd
3159 )";
3160 
3161   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
3162   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
3163   EXPECT_THAT(getDiagnosticString(),
3164               HasSubstr("Vulkan spec allows BuiltIn Position to be used only "
3165                         "with Vertex, TessellationControl, "
3166                         "TessellationEvaluation or Geometry execution models"));
3167   EXPECT_THAT(getDiagnosticString(),
3168               HasSubstr("called with execution model Fragment"));
3169 }
3170 
GetNoDepthReplacingGenerator(spv_target_env env)3171 CodeGenerator GetNoDepthReplacingGenerator(spv_target_env env) {
3172   CodeGenerator generator =
3173       spvIsWebGPUEnv(env) ? CodeGenerator::GetWebGPUShaderCodeGenerator()
3174                           : CodeGenerator::GetDefaultShaderCodeGenerator();
3175 
3176   generator.before_types_ = R"(
3177 OpMemberDecorate %output_type 0 BuiltIn FragDepth
3178 )";
3179 
3180   generator.after_types_ = R"(
3181 %output_type = OpTypeStruct %f32
3182 %output_null = OpConstantNull %output_type
3183 %output_ptr = OpTypePointer Output %output_type
3184 %output = OpVariable %output_ptr Output %output_null
3185 %output_f32_ptr = OpTypePointer Output %f32
3186 )";
3187 
3188   EntryPoint entry_point;
3189   entry_point.name = "main";
3190   entry_point.execution_model = "Fragment";
3191   entry_point.interfaces = "%output";
3192   entry_point.execution_modes = "OpExecutionMode %main OriginUpperLeft";
3193   entry_point.body = R"(
3194 %val2 = OpFunctionCall %void %foo
3195 )";
3196   generator.entry_points_.push_back(std::move(entry_point));
3197 
3198   const std::string function_body = R"(
3199 %foo = OpFunction %void None %func
3200 %foo_entry = OpLabel
3201 %frag_depth = OpAccessChain %output_f32_ptr %output %u32_0
3202 OpStore %frag_depth %f32_1
3203 OpReturn
3204 OpFunctionEnd
3205 )";
3206 
3207   if (spvIsWebGPUEnv(env)) {
3208     generator.after_types_ += function_body;
3209   } else {
3210     generator.add_at_the_end_ = function_body;
3211   }
3212 
3213   return generator;
3214 }
3215 
TEST_F(ValidateBuiltIns,VulkanFragmentFragDepthNoDepthReplacing)3216 TEST_F(ValidateBuiltIns, VulkanFragmentFragDepthNoDepthReplacing) {
3217   CodeGenerator generator = GetNoDepthReplacingGenerator(SPV_ENV_VULKAN_1_0);
3218 
3219   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
3220   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
3221   EXPECT_THAT(getDiagnosticString(),
3222               HasSubstr("Vulkan spec requires DepthReplacing execution mode to "
3223                         "be declared when using BuiltIn FragDepth"));
3224   EXPECT_THAT(getDiagnosticString(),
3225               HasSubstr("VUID-FragDepth-FragDepth-04216"));
3226 }
3227 
TEST_F(ValidateBuiltIns,WebGPUFragmentFragDepthNoDepthReplacing)3228 TEST_F(ValidateBuiltIns, WebGPUFragmentFragDepthNoDepthReplacing) {
3229   CodeGenerator generator = GetNoDepthReplacingGenerator(SPV_ENV_WEBGPU_0);
3230 
3231   CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
3232   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
3233   EXPECT_THAT(getDiagnosticString(),
3234               HasSubstr("WebGPU spec requires DepthReplacing execution mode to "
3235                         "be declared when using BuiltIn FragDepth"));
3236 }
3237 
GetOneMainHasDepthReplacingOtherHasntGenerator(spv_target_env env)3238 CodeGenerator GetOneMainHasDepthReplacingOtherHasntGenerator(
3239     spv_target_env env) {
3240   CodeGenerator generator =
3241       spvIsWebGPUEnv(env) ? CodeGenerator::GetWebGPUShaderCodeGenerator()
3242                           : CodeGenerator::GetDefaultShaderCodeGenerator();
3243 
3244   generator.before_types_ = R"(
3245 OpMemberDecorate %output_type 0 BuiltIn FragDepth
3246 )";
3247 
3248   generator.after_types_ = R"(
3249 %output_type = OpTypeStruct %f32
3250 %output_null = OpConstantNull %output_type
3251 %output_ptr = OpTypePointer Output %output_type
3252 %output = OpVariable %output_ptr Output %output_null
3253 %output_f32_ptr = OpTypePointer Output %f32
3254 )";
3255 
3256   EntryPoint entry_point;
3257   entry_point.name = "main_d_r";
3258   entry_point.execution_model = "Fragment";
3259   entry_point.interfaces = "%output";
3260   entry_point.execution_modes =
3261       "OpExecutionMode %main_d_r OriginUpperLeft\n"
3262       "OpExecutionMode %main_d_r DepthReplacing";
3263   entry_point.body = R"(
3264 %val2 = OpFunctionCall %void %foo
3265 )";
3266   generator.entry_points_.push_back(std::move(entry_point));
3267 
3268   entry_point.name = "main_no_d_r";
3269   entry_point.execution_model = "Fragment";
3270   entry_point.interfaces = "%output";
3271   entry_point.execution_modes = "OpExecutionMode %main_no_d_r OriginUpperLeft";
3272   entry_point.body = R"(
3273 %val3 = OpFunctionCall %void %foo
3274 )";
3275   generator.entry_points_.push_back(std::move(entry_point));
3276 
3277   const std::string function_body = R"(
3278 %foo = OpFunction %void None %func
3279 %foo_entry = OpLabel
3280 %frag_depth = OpAccessChain %output_f32_ptr %output %u32_0
3281 OpStore %frag_depth %f32_1
3282 OpReturn
3283 OpFunctionEnd
3284 )";
3285 
3286   if (spvIsWebGPUEnv(env)) {
3287     generator.after_types_ += function_body;
3288   } else {
3289     generator.add_at_the_end_ = function_body;
3290   }
3291 
3292   return generator;
3293 }
3294 
TEST_F(ValidateBuiltIns,VulkanFragmentFragDepthOneMainHasDepthReplacingOtherHasnt)3295 TEST_F(ValidateBuiltIns,
3296        VulkanFragmentFragDepthOneMainHasDepthReplacingOtherHasnt) {
3297   CodeGenerator generator =
3298       GetOneMainHasDepthReplacingOtherHasntGenerator(SPV_ENV_VULKAN_1_0);
3299 
3300   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
3301   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
3302   EXPECT_THAT(getDiagnosticString(),
3303               HasSubstr("Vulkan spec requires DepthReplacing execution mode to "
3304                         "be declared when using BuiltIn FragDepth"));
3305   EXPECT_THAT(getDiagnosticString(),
3306               HasSubstr("VUID-FragDepth-FragDepth-04216"));
3307 }
3308 
TEST_F(ValidateBuiltIns,WebGPUFragmentFragDepthOneMainHasDepthReplacingOtherHasnt)3309 TEST_F(ValidateBuiltIns,
3310        WebGPUFragmentFragDepthOneMainHasDepthReplacingOtherHasnt) {
3311   CodeGenerator generator =
3312       GetOneMainHasDepthReplacingOtherHasntGenerator(SPV_ENV_WEBGPU_0);
3313 
3314   CompileSuccessfully(generator.Build(), SPV_ENV_WEBGPU_0);
3315   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
3316   EXPECT_THAT(getDiagnosticString(),
3317               HasSubstr("WebGPU spec requires DepthReplacing execution mode to "
3318                         "be declared when using BuiltIn FragDepth"));
3319 }
3320 
TEST_F(ValidateBuiltIns,AllowInstanceIdWithIntersectionShader)3321 TEST_F(ValidateBuiltIns, AllowInstanceIdWithIntersectionShader) {
3322   CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
3323   generator.capabilities_ += R"(
3324 OpCapability RayTracingNV
3325 )";
3326 
3327   generator.extensions_ = R"(
3328 OpExtension "SPV_NV_ray_tracing"
3329 )";
3330 
3331   generator.before_types_ = R"(
3332 OpMemberDecorate %input_type 0 BuiltIn InstanceId
3333 )";
3334 
3335   generator.after_types_ = R"(
3336 %input_type = OpTypeStruct %u32
3337 %input_ptr = OpTypePointer Input %input_type
3338 %input = OpVariable %input_ptr Input
3339 )";
3340 
3341   EntryPoint entry_point;
3342   entry_point.name = "main_d_r";
3343   entry_point.execution_model = "IntersectionNV";
3344   entry_point.interfaces = "%input";
3345   entry_point.body = R"(
3346 %val2 = OpFunctionCall %void %foo
3347 )";
3348   generator.entry_points_.push_back(std::move(entry_point));
3349 
3350   generator.add_at_the_end_ = R"(
3351 %foo = OpFunction %void None %func
3352 %foo_entry = OpLabel
3353 OpReturn
3354 OpFunctionEnd
3355 )";
3356 
3357   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
3358   EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
3359 }
3360 
TEST_F(ValidateBuiltIns,DisallowInstanceIdWithRayGenShader)3361 TEST_F(ValidateBuiltIns, DisallowInstanceIdWithRayGenShader) {
3362   CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
3363   generator.capabilities_ += R"(
3364 OpCapability RayTracingNV
3365 )";
3366 
3367   generator.extensions_ = R"(
3368 OpExtension "SPV_NV_ray_tracing"
3369 )";
3370 
3371   generator.before_types_ = R"(
3372 OpMemberDecorate %input_type 0 BuiltIn InstanceId
3373 )";
3374 
3375   generator.after_types_ = R"(
3376 %input_type = OpTypeStruct %u32
3377 %input_ptr = OpTypePointer Input %input_type
3378 %input_ptr_u32 = OpTypePointer Input %u32
3379 %input = OpVariable %input_ptr Input
3380 )";
3381 
3382   EntryPoint entry_point;
3383   entry_point.name = "main_d_r";
3384   entry_point.execution_model = "RayGenerationNV";
3385   entry_point.interfaces = "%input";
3386   entry_point.body = R"(
3387 %input_member = OpAccessChain %input_ptr_u32 %input %u32_0
3388 )";
3389   generator.entry_points_.push_back(std::move(entry_point));
3390 
3391   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
3392   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
3393   EXPECT_THAT(getDiagnosticString(),
3394               HasSubstr("Vulkan spec allows BuiltIn InstanceId to be used "
3395                         "only with IntersectionNV, ClosestHitNV and "
3396                         "AnyHitNV execution models"));
3397 }
3398 
TEST_F(ValidateBuiltIns,ValidBuiltinsForMeshShader)3399 TEST_F(ValidateBuiltIns, ValidBuiltinsForMeshShader) {
3400   CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
3401   generator.capabilities_ += R"(
3402 OpCapability MeshShadingNV
3403 )";
3404 
3405   generator.extensions_ = R"(
3406 OpExtension "SPV_NV_mesh_shader"
3407 )";
3408 
3409   generator.before_types_ = R"(
3410 OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId
3411 OpDecorate %gl_PrimitiveID PerPrimitiveNV
3412 OpDecorate %gl_Layer BuiltIn Layer
3413 OpDecorate %gl_Layer PerPrimitiveNV
3414 OpDecorate %gl_ViewportIndex BuiltIn ViewportIndex
3415 OpDecorate %gl_ViewportIndex PerPrimitiveNV
3416 )";
3417 
3418   generator.after_types_ = R"(
3419 %u32_81 = OpConstant %u32 81
3420 %_arr_int_uint_81 = OpTypeArray %i32 %u32_81
3421 %_ptr_Output__arr_int_uint_81 = OpTypePointer Output %_arr_int_uint_81
3422 %gl_PrimitiveID = OpVariable %_ptr_Output__arr_int_uint_81 Output
3423 %gl_Layer = OpVariable %_ptr_Output__arr_int_uint_81 Output
3424 %gl_ViewportIndex = OpVariable %_ptr_Output__arr_int_uint_81 Output
3425 )";
3426 
3427   EntryPoint entry_point;
3428   entry_point.name = "main_d_r";
3429   entry_point.execution_model = "MeshNV";
3430   entry_point.interfaces = "%gl_PrimitiveID %gl_Layer %gl_ViewportIndex";
3431   generator.entry_points_.push_back(std::move(entry_point));
3432 
3433   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_1);
3434   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3435 }
3436 
TEST_F(ValidateBuiltIns,InvalidBuiltinsForMeshShader)3437 TEST_F(ValidateBuiltIns, InvalidBuiltinsForMeshShader) {
3438   CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
3439   generator.capabilities_ += R"(
3440 OpCapability MeshShadingNV
3441 )";
3442 
3443   generator.extensions_ = R"(
3444 OpExtension "SPV_NV_mesh_shader"
3445 )";
3446 
3447   generator.before_types_ = R"(
3448 OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId
3449 OpDecorate %gl_PrimitiveID PerPrimitiveNV
3450 OpDecorate %gl_Layer BuiltIn Layer
3451 OpDecorate %gl_Layer PerPrimitiveNV
3452 OpDecorate %gl_ViewportIndex BuiltIn ViewportIndex
3453 OpDecorate %gl_ViewportIndex PerPrimitiveNV
3454 )";
3455 
3456   generator.after_types_ = R"(
3457 %u32_81 = OpConstant %u32 81
3458 %_arr_float_uint_81 = OpTypeArray %f32 %u32_81
3459 %_ptr_Output__arr_float_uint_81 = OpTypePointer Output %_arr_float_uint_81
3460 %gl_PrimitiveID = OpVariable %_ptr_Output__arr_float_uint_81 Output
3461 %gl_Layer = OpVariable %_ptr_Output__arr_float_uint_81 Output
3462 %gl_ViewportIndex = OpVariable %_ptr_Output__arr_float_uint_81 Output
3463 )";
3464 
3465   EntryPoint entry_point;
3466   entry_point.name = "main_d_r";
3467   entry_point.execution_model = "MeshNV";
3468   entry_point.interfaces = "%gl_PrimitiveID %gl_Layer %gl_ViewportIndex";
3469   generator.entry_points_.push_back(std::move(entry_point));
3470 
3471   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_1);
3472   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3473   EXPECT_THAT(getDiagnosticString(),
3474               HasSubstr("needs to be a 32-bit int scalar"));
3475   EXPECT_THAT(getDiagnosticString(), HasSubstr("is not an int scalar"));
3476 }
3477 
TEST_F(ValidateBuiltIns,GetUnderlyingTypeNoAssert)3478 TEST_F(ValidateBuiltIns, GetUnderlyingTypeNoAssert) {
3479   std::string spirv = R"(
3480                       OpCapability Shader
3481                       OpMemoryModel Logical GLSL450
3482                       OpEntryPoint Fragment %4 "PSMa" %12 %17
3483                       OpExecutionMode %4 OriginUpperLeft
3484                       OpDecorate %gl_PointCoord BuiltIn PointCoord
3485                       OpDecorate %12 Location 0
3486                       OpDecorate %17 Location 0
3487               %void = OpTypeVoid
3488                  %3 = OpTypeFunction %void
3489              %float = OpTypeFloat 32
3490            %v4float = OpTypeVector %float 4
3491        %gl_PointCoord = OpTypeStruct %v4float
3492        %_ptr_Input_v4float = OpTypePointer Input %v4float
3493        %_ptr_Output_v4float = OpTypePointer Output %v4float
3494                 %12 = OpVariable %_ptr_Input_v4float Input
3495                 %17 = OpVariable %_ptr_Output_v4float Output
3496                  %4 = OpFunction %void None %3
3497                 %15 = OpLabel
3498                       OpReturn
3499                       OpFunctionEnd)";
3500   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3501   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3502   EXPECT_THAT(getDiagnosticString(),
3503               HasSubstr("did not find an member index to get underlying data "
3504                         "type"));
3505 }
3506 
TEST_P(ValidateVulkanSubgroupBuiltIns,InMain)3507 TEST_P(ValidateVulkanSubgroupBuiltIns, InMain) {
3508   const char* const built_in = std::get<0>(GetParam());
3509   const char* const execution_model = std::get<1>(GetParam());
3510   const char* const storage_class = std::get<2>(GetParam());
3511   const char* const data_type = std::get<3>(GetParam());
3512   const TestResult& test_result = std::get<4>(GetParam());
3513 
3514   CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
3515   generator.capabilities_ += R"(
3516 OpCapability GroupNonUniformBallot
3517 )";
3518 
3519   generator.before_types_ = "OpDecorate %built_in_var BuiltIn ";
3520   generator.before_types_ += built_in;
3521   generator.before_types_ += "\n";
3522 
3523   std::ostringstream after_types;
3524   after_types << "%built_in_ptr = OpTypePointer " << storage_class << " "
3525               << data_type << "\n";
3526   after_types << "%built_in_var = OpVariable %built_in_ptr " << storage_class;
3527   after_types << "\n";
3528   generator.after_types_ = after_types.str();
3529 
3530   EntryPoint entry_point;
3531   entry_point.name = "main";
3532   entry_point.execution_model = execution_model;
3533   if (strncmp(storage_class, "Input", 5) == 0 ||
3534       strncmp(storage_class, "Output", 6) == 0) {
3535     entry_point.interfaces = "%built_in_var";
3536   }
3537   entry_point.body =
3538       std::string("%ld = OpLoad ") + data_type + " %built_in_var\n";
3539 
3540   std::ostringstream execution_modes;
3541   if (0 == std::strcmp(execution_model, "Fragment")) {
3542     execution_modes << "OpExecutionMode %" << entry_point.name
3543                     << " OriginUpperLeft\n";
3544     if (0 == std::strcmp(built_in, "FragDepth")) {
3545       execution_modes << "OpExecutionMode %" << entry_point.name
3546                       << " DepthReplacing\n";
3547     }
3548   }
3549   if (0 == std::strcmp(execution_model, "Geometry")) {
3550     execution_modes << "OpExecutionMode %" << entry_point.name
3551                     << " InputPoints\n";
3552     execution_modes << "OpExecutionMode %" << entry_point.name
3553                     << " OutputPoints\n";
3554   }
3555   if (0 == std::strcmp(execution_model, "GLCompute")) {
3556     execution_modes << "OpExecutionMode %" << entry_point.name
3557                     << " LocalSize 1 1 1\n";
3558   }
3559   entry_point.execution_modes = execution_modes.str();
3560 
3561   generator.entry_points_.push_back(std::move(entry_point));
3562 
3563   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_1);
3564   ASSERT_EQ(test_result.validation_result,
3565             ValidateInstructions(SPV_ENV_VULKAN_1_1));
3566   if (test_result.error_str) {
3567     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
3568   }
3569   if (test_result.error_str2) {
3570     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
3571   }
3572 }
3573 
3574 INSTANTIATE_TEST_SUITE_P(
3575     SubgroupMaskNotVec4, ValidateVulkanSubgroupBuiltIns,
3576     Combine(Values("SubgroupEqMask", "SubgroupGeMask", "SubgroupGtMask",
3577                    "SubgroupLeMask", "SubgroupLtMask"),
3578             Values("GLCompute"), Values("Input"), Values("%u32vec3"),
3579             Values(TestResult(SPV_ERROR_INVALID_DATA,
3580                               "needs to be a 4-component 32-bit int vector"))));
3581 
3582 INSTANTIATE_TEST_SUITE_P(
3583     SubgroupMaskNotU32, ValidateVulkanSubgroupBuiltIns,
3584     Combine(Values("SubgroupEqMask", "SubgroupGeMask", "SubgroupGtMask",
3585                    "SubgroupLeMask", "SubgroupLtMask"),
3586             Values("GLCompute"), Values("Input"), Values("%f32vec4"),
3587             Values(TestResult(SPV_ERROR_INVALID_DATA,
3588                               "needs to be a 4-component 32-bit int vector"))));
3589 
3590 INSTANTIATE_TEST_SUITE_P(
3591     SubgroupMaskNotInput, ValidateVulkanSubgroupBuiltIns,
3592     Combine(Values("SubgroupEqMask", "SubgroupGeMask", "SubgroupGtMask",
3593                    "SubgroupLeMask", "SubgroupLtMask"),
3594             Values("GLCompute"), Values("Output", "Workgroup", "Private"),
3595             Values("%u32vec4"),
3596             Values(TestResult(
3597                 SPV_ERROR_INVALID_DATA,
3598                 "to be only used for variables with Input storage class"))));
3599 
3600 INSTANTIATE_TEST_SUITE_P(SubgroupMaskOk, ValidateVulkanSubgroupBuiltIns,
3601                          Combine(Values("SubgroupEqMask", "SubgroupGeMask",
3602                                         "SubgroupGtMask", "SubgroupLeMask",
3603                                         "SubgroupLtMask"),
3604                                  Values("GLCompute"), Values("Input"),
3605                                  Values("%u32vec4"),
3606                                  Values(TestResult(SPV_SUCCESS, ""))));
3607 
TEST_F(ValidateBuiltIns,SubgroupMaskMemberDecorate)3608 TEST_F(ValidateBuiltIns, SubgroupMaskMemberDecorate) {
3609   const std::string text = R"(
3610 OpCapability Shader
3611 OpCapability GroupNonUniformBallot
3612 OpMemoryModel Logical GLSL450
3613 OpEntryPoint GLCompute %foo "foo"
3614 OpExecutionMode %foo LocalSize 1 1 1
3615 OpMemberDecorate %struct 0 BuiltIn SubgroupEqMask
3616 %void = OpTypeVoid
3617 %int = OpTypeInt 32 0
3618 %struct = OpTypeStruct %int
3619 %void_fn = OpTypeFunction %void
3620 %foo = OpFunction %void None %void_fn
3621 %entry = OpLabel
3622 OpReturn
3623 OpFunctionEnd
3624 )";
3625 
3626   CompileSuccessfully(text, SPV_ENV_VULKAN_1_1);
3627   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3628   EXPECT_THAT(
3629       getDiagnosticString(),
3630       HasSubstr(
3631           "BuiltIn SubgroupEqMask cannot be used as a member decoration"));
3632 }
3633 
3634 INSTANTIATE_TEST_SUITE_P(
3635     SubgroupInvocationIdAndSizeNotU32, ValidateVulkanSubgroupBuiltIns,
3636     Combine(Values("SubgroupLocalInvocationId", "SubgroupSize"),
3637             Values("GLCompute"), Values("Input"), Values("%f32"),
3638             Values(TestResult(SPV_ERROR_INVALID_DATA,
3639                               "needs to be a 32-bit int"))));
3640 
3641 INSTANTIATE_TEST_SUITE_P(
3642     SubgroupInvocationIdAndSizeNotInput, ValidateVulkanSubgroupBuiltIns,
3643     Combine(Values("SubgroupLocalInvocationId", "SubgroupSize"),
3644             Values("GLCompute"), Values("Output", "Workgroup", "Private"),
3645             Values("%u32"),
3646             Values(TestResult(
3647                 SPV_ERROR_INVALID_DATA,
3648                 "to be only used for variables with Input storage class"))));
3649 
3650 INSTANTIATE_TEST_SUITE_P(
3651     SubgroupInvocationIdAndSizeOk, ValidateVulkanSubgroupBuiltIns,
3652     Combine(Values("SubgroupLocalInvocationId", "SubgroupSize"),
3653             Values("GLCompute"), Values("Input"), Values("%u32"),
3654             Values(TestResult(SPV_SUCCESS, ""))));
3655 
TEST_F(ValidateBuiltIns,SubgroupSizeMemberDecorate)3656 TEST_F(ValidateBuiltIns, SubgroupSizeMemberDecorate) {
3657   const std::string text = R"(
3658 OpCapability Shader
3659 OpCapability GroupNonUniform
3660 OpMemoryModel Logical GLSL450
3661 OpEntryPoint GLCompute %foo "foo"
3662 OpExecutionMode %foo LocalSize 1 1 1
3663 OpMemberDecorate %struct 0 BuiltIn SubgroupSize
3664 %void = OpTypeVoid
3665 %int = OpTypeInt 32 0
3666 %struct = OpTypeStruct %int
3667 %void_fn = OpTypeFunction %void
3668 %foo = OpFunction %void None %void_fn
3669 %entry = OpLabel
3670 OpReturn
3671 OpFunctionEnd
3672 )";
3673 
3674   CompileSuccessfully(text, SPV_ENV_VULKAN_1_1);
3675   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3676   EXPECT_THAT(
3677       getDiagnosticString(),
3678       HasSubstr("BuiltIn SubgroupSize cannot be used as a member decoration"));
3679 }
3680 
3681 INSTANTIATE_TEST_SUITE_P(
3682     SubgroupNumAndIdNotU32, ValidateVulkanSubgroupBuiltIns,
3683     Combine(Values("SubgroupId", "NumSubgroups"), Values("GLCompute"),
3684             Values("Input"), Values("%f32"),
3685             Values(TestResult(SPV_ERROR_INVALID_DATA,
3686                               "needs to be a 32-bit int"))));
3687 
3688 INSTANTIATE_TEST_SUITE_P(
3689     SubgroupNumAndIdNotInput, ValidateVulkanSubgroupBuiltIns,
3690     Combine(Values("SubgroupId", "NumSubgroups"), Values("GLCompute"),
3691             Values("Output", "Workgroup", "Private"), Values("%u32"),
3692             Values(TestResult(
3693                 SPV_ERROR_INVALID_DATA,
3694                 "to be only used for variables with Input storage class"))));
3695 
3696 INSTANTIATE_TEST_SUITE_P(SubgroupNumAndIdOk, ValidateVulkanSubgroupBuiltIns,
3697                          Combine(Values("SubgroupId", "NumSubgroups"),
3698                                  Values("GLCompute"), Values("Input"),
3699                                  Values("%u32"),
3700                                  Values(TestResult(SPV_SUCCESS, ""))));
3701 
TEST_F(ValidateBuiltIns,SubgroupIdMemberDecorate)3702 TEST_F(ValidateBuiltIns, SubgroupIdMemberDecorate) {
3703   const std::string text = R"(
3704 OpCapability Shader
3705 OpCapability GroupNonUniform
3706 OpMemoryModel Logical GLSL450
3707 OpEntryPoint GLCompute %foo "foo"
3708 OpExecutionMode %foo LocalSize 1 1 1
3709 OpMemberDecorate %struct 0 BuiltIn SubgroupId
3710 %void = OpTypeVoid
3711 %int = OpTypeInt 32 0
3712 %struct = OpTypeStruct %int
3713 %void_fn = OpTypeFunction %void
3714 %foo = OpFunction %void None %void_fn
3715 %entry = OpLabel
3716 OpReturn
3717 OpFunctionEnd
3718 )";
3719 
3720   CompileSuccessfully(text, SPV_ENV_VULKAN_1_1);
3721   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3722   EXPECT_THAT(
3723       getDiagnosticString(),
3724       HasSubstr("BuiltIn SubgroupId cannot be used as a member decoration"));
3725 }
3726 
TEST_F(ValidateBuiltIns,TargetIsType)3727 TEST_F(ValidateBuiltIns, TargetIsType) {
3728   const std::string text = R"(
3729 OpCapability Shader
3730 OpCapability Linkage
3731 OpMemoryModel Logical GLSL450
3732 OpDecorate %void BuiltIn Position
3733 %void = OpTypeVoid
3734 )";
3735 
3736   CompileSuccessfully(text);
3737   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
3738   EXPECT_THAT(
3739       getDiagnosticString(),
3740       HasSubstr("BuiltIns can only target variables, structs or constants"));
3741 }
3742 
TEST_F(ValidateBuiltIns,TargetIsVariable)3743 TEST_F(ValidateBuiltIns, TargetIsVariable) {
3744   const std::string text = R"(
3745 OpCapability Shader
3746 OpCapability Linkage
3747 OpMemoryModel Logical GLSL450
3748 OpDecorate %wg_var BuiltIn Position
3749 %int = OpTypeInt 32 0
3750 %int_wg_ptr = OpTypePointer Workgroup %int
3751 %wg_var = OpVariable %int_wg_ptr Workgroup
3752 )";
3753 
3754   CompileSuccessfully(text);
3755   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3756 }
3757 
TEST_F(ValidateBuiltIns,TargetIsStruct)3758 TEST_F(ValidateBuiltIns, TargetIsStruct) {
3759   const std::string text = R"(
3760 OpCapability Shader
3761 OpCapability Linkage
3762 OpMemoryModel Logical GLSL450
3763 OpDecorate %struct BuiltIn Position
3764 %struct = OpTypeStruct
3765 )";
3766 
3767   CompileSuccessfully(text);
3768   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3769 }
3770 
TEST_F(ValidateBuiltIns,TargetIsConstant)3771 TEST_F(ValidateBuiltIns, TargetIsConstant) {
3772   const std::string text = R"(
3773 OpCapability Shader
3774 OpCapability Linkage
3775 OpMemoryModel Logical GLSL450
3776 OpDecorate %int0 BuiltIn Position
3777 %int = OpTypeInt 32 0
3778 %int0 = OpConstant %int 0
3779 )";
3780 
3781   CompileSuccessfully(text);
3782   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3783 }
3784 
TEST_F(ValidateBuiltIns,TargetIsSpecConstant)3785 TEST_F(ValidateBuiltIns, TargetIsSpecConstant) {
3786   const std::string text = R"(
3787 OpCapability Shader
3788 OpCapability Linkage
3789 OpMemoryModel Logical GLSL450
3790 OpDecorate %int0 BuiltIn Position
3791 %int = OpTypeInt 32 0
3792 %int0 = OpSpecConstant %int 0
3793 )";
3794 
3795   CompileSuccessfully(text);
3796   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3797 }
3798 
3799 INSTANTIATE_TEST_SUITE_P(
3800     PrimitiveShadingRateOutputSuccess,
3801     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
3802     Combine(Values("PrimitiveShadingRateKHR"), Values("Vertex", "Geometry"),
3803             Values("Output"), Values("%u32"),
3804             Values("OpCapability FragmentShadingRateKHR\n"),
3805             Values("OpExtension \"SPV_KHR_fragment_shading_rate\"\n"),
3806             Values(nullptr), Values(TestResult())));
3807 
3808 INSTANTIATE_TEST_SUITE_P(
3809     PrimitiveShadingRateMeshOutputSuccess,
3810     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
3811     Combine(Values("PrimitiveShadingRateKHR"), Values("MeshNV"),
3812             Values("Output"), Values("%u32"),
3813             Values("OpCapability FragmentShadingRateKHR\nOpCapability "
3814                    "MeshShadingNV\n"),
3815             Values("OpExtension \"SPV_KHR_fragment_shading_rate\"\nOpExtension "
3816                    "\"SPV_NV_mesh_shader\"\n"),
3817             Values(nullptr), Values(TestResult())));
3818 
3819 INSTANTIATE_TEST_SUITE_P(
3820     PrimitiveShadingRateInvalidExecutionModel,
3821     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
3822     Combine(
3823         Values("PrimitiveShadingRateKHR"), Values("Fragment"), Values("Output"),
3824         Values("%u32"), Values("OpCapability FragmentShadingRateKHR\n"),
3825         Values("OpExtension \"SPV_KHR_fragment_shading_rate\"\n"),
3826         Values("VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04484 "),
3827         Values(TestResult(
3828             SPV_ERROR_INVALID_DATA,
3829             "Vulkan spec allows BuiltIn PrimitiveShadingRateKHR to be used "
3830             "only with Vertex, Geometry, or MeshNV execution models."))));
3831 
3832 INSTANTIATE_TEST_SUITE_P(
3833     PrimitiveShadingRateInvalidStorageClass,
3834     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
3835     Combine(
3836         Values("PrimitiveShadingRateKHR"), Values("Vertex"), Values("Input"),
3837         Values("%u32"), Values("OpCapability FragmentShadingRateKHR\n"),
3838         Values("OpExtension \"SPV_KHR_fragment_shading_rate\"\n"),
3839         Values("VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04485 "),
3840         Values(TestResult(
3841             SPV_ERROR_INVALID_DATA,
3842             "Vulkan spec allows BuiltIn PrimitiveShadingRateKHR to be only "
3843             "used for variables with Output storage class."))));
3844 
3845 INSTANTIATE_TEST_SUITE_P(
3846     PrimitiveShadingRateInvalidType,
3847     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
3848     Combine(
3849         Values("PrimitiveShadingRateKHR"), Values("Vertex"), Values("Output"),
3850         Values("%f32"), Values("OpCapability FragmentShadingRateKHR\n"),
3851         Values("OpExtension \"SPV_KHR_fragment_shading_rate\"\n"),
3852         Values("VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04486 "),
3853         Values(TestResult(
3854             SPV_ERROR_INVALID_DATA,
3855             "According to the Vulkan spec BuiltIn PrimitiveShadingRateKHR "
3856             "variable needs to be a 32-bit int scalar."))));
3857 
3858 INSTANTIATE_TEST_SUITE_P(
3859     ShadingRateInputSuccess,
3860     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
3861     Combine(Values("ShadingRateKHR"), Values("Fragment"), Values("Input"),
3862             Values("%u32"), Values("OpCapability FragmentShadingRateKHR\n"),
3863             Values("OpExtension \"SPV_KHR_fragment_shading_rate\"\n"),
3864             Values(nullptr), Values(TestResult())));
3865 
3866 INSTANTIATE_TEST_SUITE_P(
3867     ShadingRateInvalidExecutionModel,
3868     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
3869     Combine(Values("ShadingRateKHR"), Values("Vertex"), Values("Input"),
3870             Values("%u32"), Values("OpCapability FragmentShadingRateKHR\n"),
3871             Values("OpExtension \"SPV_KHR_fragment_shading_rate\"\n"),
3872             Values("VUID-ShadingRateKHR-ShadingRateKHR-04490 "),
3873             Values(TestResult(
3874                 SPV_ERROR_INVALID_DATA,
3875                 "Vulkan spec allows BuiltIn ShadingRateKHR to be used "
3876                 "only with the Fragment execution model."))));
3877 
3878 INSTANTIATE_TEST_SUITE_P(
3879     ShadingRateInvalidStorageClass,
3880     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
3881     Combine(Values("ShadingRateKHR"), Values("Fragment"), Values("Output"),
3882             Values("%u32"), Values("OpCapability FragmentShadingRateKHR\n"),
3883             Values("OpExtension \"SPV_KHR_fragment_shading_rate\"\n"),
3884             Values("VUID-ShadingRateKHR-ShadingRateKHR-04491 "),
3885             Values(TestResult(
3886                 SPV_ERROR_INVALID_DATA,
3887                 "Vulkan spec allows BuiltIn ShadingRateKHR to be only "
3888                 "used for variables with Input storage class."))));
3889 
3890 INSTANTIATE_TEST_SUITE_P(
3891     ShadingRateInvalidType,
3892     ValidateVulkanCombineBuiltInExecutionModelDataTypeCapabilityExtensionResult,
3893     Combine(
3894         Values("ShadingRateKHR"), Values("Fragment"), Values("Input"),
3895         Values("%f32"), Values("OpCapability FragmentShadingRateKHR\n"),
3896         Values("OpExtension \"SPV_KHR_fragment_shading_rate\"\n"),
3897         Values("VUID-ShadingRateKHR-ShadingRateKHR-04492 "),
3898         Values(TestResult(SPV_ERROR_INVALID_DATA,
3899                           "According to the Vulkan spec BuiltIn ShadingRateKHR "
3900                           "variable needs to be a 32-bit int scalar."))));
3901 }  // namespace
3902 }  // namespace val
3903 }  // namespace spvtools
3904