• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2018 Google LLC.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // Tests validation rules of GLSL.450.std and OpenCL.std extended instructions.
16 // Doesn't test OpenCL.std vector size 2, 3, 4, 8 or 16 rules (not supported
17 // by standard SPIR-V).
18 
19 #include <cstring>
20 #include <sstream>
21 #include <string>
22 #include <tuple>
23 #include <utility>
24 #include <vector>
25 
26 #include "gmock/gmock.h"
27 #include "test/unit_spirv.h"
28 #include "test/val/val_fixtures.h"
29 
30 namespace spvtools {
31 namespace val {
32 namespace {
33 
34 struct TestResult {
TestResultspvtools::val::__anon483421aa0111::TestResult35   TestResult(spv_result_t in_validation_result = SPV_SUCCESS,
36              const char* in_error_str = nullptr,
37              const char* in_error_str2 = nullptr)
38       : validation_result(in_validation_result),
39         error_str(in_error_str),
40         error_str2(in_error_str2) {}
41   spv_result_t validation_result;
42   const char* error_str;
43   const char* error_str2;
44 };
45 
46 using ::testing::Combine;
47 using ::testing::HasSubstr;
48 using ::testing::Not;
49 using ::testing::Values;
50 using ::testing::ValuesIn;
51 
52 using ValidateBuiltIns = spvtest::ValidateBase<bool>;
53 using ValidateVulkanCombineBuiltInExecutionModelDataTypeResult =
54     spvtest::ValidateBase<std::tuple<const char*, const char*, const char*,
55                                      const char*, TestResult>>;
56 using ValidateVulkanCombineBuiltInArrayedVariable = spvtest::ValidateBase<
57     std::tuple<const char*, const char*, const char*, const char*, TestResult>>;
58 
59 struct EntryPoint {
60   std::string name;
61   std::string execution_model;
62   std::string execution_modes;
63   std::string body;
64   std::string interfaces;
65 };
66 
67 class CodeGenerator {
68  public:
69   std::string Build() const;
70 
71   std::vector<EntryPoint> entry_points_;
72   std::string capabilities_;
73   std::string extensions_;
74   std::string memory_model_;
75   std::string before_types_;
76   std::string types_;
77   std::string after_types_;
78   std::string add_at_the_end_;
79 };
80 
Build() const81 std::string CodeGenerator::Build() const {
82   std::ostringstream ss;
83 
84   ss << capabilities_;
85   ss << extensions_;
86   ss << memory_model_;
87 
88   for (const EntryPoint& entry_point : entry_points_) {
89     ss << "OpEntryPoint " << entry_point.execution_model << " %"
90        << entry_point.name << " \"" << entry_point.name << "\" "
91        << entry_point.interfaces << "\n";
92   }
93 
94   for (const EntryPoint& entry_point : entry_points_) {
95     ss << entry_point.execution_modes << "\n";
96   }
97 
98   ss << before_types_;
99   ss << types_;
100   ss << after_types_;
101 
102   for (const EntryPoint& entry_point : entry_points_) {
103     ss << "\n";
104     ss << "%" << entry_point.name << " = OpFunction %void None %func\n";
105     ss << "%" << entry_point.name << "_entry = OpLabel\n";
106     ss << entry_point.body;
107     ss << "\nOpReturn\nOpFunctionEnd\n";
108   }
109 
110   ss << add_at_the_end_;
111 
112   return ss.str();
113 }
114 
GetDefaultShaderCapabilities()115 std::string GetDefaultShaderCapabilities() {
116   return R"(
117 OpCapability Shader
118 OpCapability Geometry
119 OpCapability Tessellation
120 OpCapability Float64
121 OpCapability Int64
122 OpCapability MultiViewport
123 OpCapability SampleRateShading
124 )";
125 }
126 
GetDefaultShaderTypes()127 std::string GetDefaultShaderTypes() {
128   return R"(
129 %void = OpTypeVoid
130 %func = OpTypeFunction %void
131 %bool = OpTypeBool
132 %f32 = OpTypeFloat 32
133 %f64 = OpTypeFloat 64
134 %u32 = OpTypeInt 32 0
135 %u64 = OpTypeInt 64 0
136 %f32vec2 = OpTypeVector %f32 2
137 %f32vec3 = OpTypeVector %f32 3
138 %f32vec4 = OpTypeVector %f32 4
139 %f64vec2 = OpTypeVector %f64 2
140 %f64vec3 = OpTypeVector %f64 3
141 %f64vec4 = OpTypeVector %f64 4
142 %u32vec2 = OpTypeVector %u32 2
143 %u32vec3 = OpTypeVector %u32 3
144 %u64vec3 = OpTypeVector %u64 3
145 %u32vec4 = OpTypeVector %u32 4
146 %u64vec2 = OpTypeVector %u64 2
147 
148 %f32_0 = OpConstant %f32 0
149 %f32_1 = OpConstant %f32 1
150 %f32_2 = OpConstant %f32 2
151 %f32_3 = OpConstant %f32 3
152 %f32_4 = OpConstant %f32 4
153 %f32_h = OpConstant %f32 0.5
154 %f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
155 %f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2
156 %f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2
157 %f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3
158 %f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
159 %f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4
160 
161 %f64_0 = OpConstant %f64 0
162 %f64_1 = OpConstant %f64 1
163 %f64_2 = OpConstant %f64 2
164 %f64_3 = OpConstant %f64 3
165 %f64vec2_01 = OpConstantComposite %f64vec2 %f64_0 %f64_1
166 %f64vec3_012 = OpConstantComposite %f64vec3 %f64_0 %f64_1 %f64_2
167 %f64vec4_0123 = OpConstantComposite %f64vec4 %f64_0 %f64_1 %f64_2 %f64_3
168 
169 %u32_0 = OpConstant %u32 0
170 %u32_1 = OpConstant %u32 1
171 %u32_2 = OpConstant %u32 2
172 %u32_3 = OpConstant %u32 3
173 %u32_4 = OpConstant %u32 4
174 
175 %u64_0 = OpConstant %u64 0
176 %u64_1 = OpConstant %u64 1
177 %u64_2 = OpConstant %u64 2
178 %u64_3 = OpConstant %u64 3
179 
180 %u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
181 %u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2
182 %u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
183 %u64vec2_01 = OpConstantComposite %u64vec2 %u64_0 %u64_1
184 
185 %u32arr2 = OpTypeArray %u32 %u32_2
186 %u32arr3 = OpTypeArray %u32 %u32_3
187 %u32arr4 = OpTypeArray %u32 %u32_4
188 %u64arr2 = OpTypeArray %u64 %u32_2
189 %u64arr3 = OpTypeArray %u64 %u32_3
190 %u64arr4 = OpTypeArray %u64 %u32_4
191 %f32arr2 = OpTypeArray %f32 %u32_2
192 %f32arr3 = OpTypeArray %f32 %u32_3
193 %f32arr4 = OpTypeArray %f32 %u32_4
194 %f64arr2 = OpTypeArray %f64 %u32_2
195 %f64arr3 = OpTypeArray %f64 %u32_3
196 %f64arr4 = OpTypeArray %f64 %u32_4
197 
198 %f32vec3arr3 = OpTypeArray %f32vec3 %u32_3
199 %f32vec4arr3 = OpTypeArray %f32vec4 %u32_3
200 %f64vec4arr3 = OpTypeArray %f64vec4 %u32_3
201 )";
202 }
203 
GetDefaultShaderCodeGenerator()204 CodeGenerator GetDefaultShaderCodeGenerator() {
205   CodeGenerator generator;
206   generator.capabilities_ = GetDefaultShaderCapabilities();
207   generator.memory_model_ = "OpMemoryModel Logical GLSL450\n";
208   generator.types_ = GetDefaultShaderTypes();
209   return generator;
210 }
211 
TEST_P(ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,InMain)212 TEST_P(ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, InMain) {
213   const char* const built_in = std::get<0>(GetParam());
214   const char* const execution_model = std::get<1>(GetParam());
215   const char* const storage_class = std::get<2>(GetParam());
216   const char* const data_type = std::get<3>(GetParam());
217   const TestResult& test_result = std::get<4>(GetParam());
218 
219   CodeGenerator generator = GetDefaultShaderCodeGenerator();
220   generator.before_types_ = "OpMemberDecorate %built_in_type 0 BuiltIn ";
221   generator.before_types_ += built_in;
222   generator.before_types_ += "\n";
223 
224   std::ostringstream after_types;
225   after_types << "%built_in_type = OpTypeStruct " << data_type << "\n";
226   after_types << "%built_in_ptr = OpTypePointer " << storage_class
227               << " %built_in_type\n";
228   after_types << "%built_in_var = OpVariable %built_in_ptr " << storage_class
229               << "\n";
230   after_types << "%data_ptr = OpTypePointer " << storage_class << " "
231               << data_type << "\n";
232   generator.after_types_ = after_types.str();
233 
234   EntryPoint entry_point;
235   entry_point.name = "main";
236   entry_point.execution_model = execution_model;
237   if (strncmp(storage_class, "Input", 5) == 0 ||
238       strncmp(storage_class, "Output", 6) == 0) {
239     entry_point.interfaces = "%built_in_var";
240   }
241 
242   std::ostringstream execution_modes;
243   if (0 == std::strcmp(execution_model, "Fragment")) {
244     execution_modes << "OpExecutionMode %" << entry_point.name
245                     << " OriginUpperLeft\n";
246     if (0 == std::strcmp(built_in, "FragDepth")) {
247       execution_modes << "OpExecutionMode %" << entry_point.name
248                       << " DepthReplacing\n";
249     }
250   }
251   if (0 == std::strcmp(execution_model, "Geometry")) {
252     execution_modes << "OpExecutionMode %" << entry_point.name
253                     << " InputPoints\n";
254     execution_modes << "OpExecutionMode %" << entry_point.name
255                     << " OutputPoints\n";
256   }
257   if (0 == std::strcmp(execution_model, "GLCompute")) {
258     execution_modes << "OpExecutionMode %" << entry_point.name
259                     << " LocalSize 1 1 1\n";
260   }
261   entry_point.execution_modes = execution_modes.str();
262 
263   entry_point.body = R"(
264 %ptr = OpAccessChain %data_ptr %built_in_var %u32_0
265 )";
266   generator.entry_points_.push_back(std::move(entry_point));
267 
268   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
269   ASSERT_EQ(test_result.validation_result,
270             ValidateInstructions(SPV_ENV_VULKAN_1_0));
271   if (test_result.error_str) {
272     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
273   }
274   if (test_result.error_str2) {
275     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
276   }
277 }
278 
TEST_P(ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,InFunction)279 TEST_P(ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, InFunction) {
280   const char* const built_in = std::get<0>(GetParam());
281   const char* const execution_model = std::get<1>(GetParam());
282   const char* const storage_class = std::get<2>(GetParam());
283   const char* const data_type = std::get<3>(GetParam());
284   const TestResult& test_result = std::get<4>(GetParam());
285 
286   CodeGenerator generator = GetDefaultShaderCodeGenerator();
287   generator.before_types_ = "OpMemberDecorate %built_in_type 0 BuiltIn ";
288   generator.before_types_ += built_in;
289   generator.before_types_ += "\n";
290 
291   std::ostringstream after_types;
292   after_types << "%built_in_type = OpTypeStruct " << data_type << "\n";
293   after_types << "%built_in_ptr = OpTypePointer " << storage_class
294               << " %built_in_type\n";
295   after_types << "%built_in_var = OpVariable %built_in_ptr " << storage_class
296               << "\n";
297   after_types << "%data_ptr = OpTypePointer " << storage_class << " "
298               << data_type << "\n";
299   generator.after_types_ = after_types.str();
300 
301   EntryPoint entry_point;
302   entry_point.name = "main";
303   entry_point.execution_model = execution_model;
304   if (strncmp(storage_class, "Input", 5) == 0 ||
305       strncmp(storage_class, "Output", 6) == 0) {
306     entry_point.interfaces = "%built_in_var";
307   }
308 
309   std::ostringstream execution_modes;
310   if (0 == std::strcmp(execution_model, "Fragment")) {
311     execution_modes << "OpExecutionMode %" << entry_point.name
312                     << " OriginUpperLeft\n";
313     if (0 == std::strcmp(built_in, "FragDepth")) {
314       execution_modes << "OpExecutionMode %" << entry_point.name
315                       << " DepthReplacing\n";
316     }
317   }
318   if (0 == std::strcmp(execution_model, "Geometry")) {
319     execution_modes << "OpExecutionMode %" << entry_point.name
320                     << " InputPoints\n";
321     execution_modes << "OpExecutionMode %" << entry_point.name
322                     << " OutputPoints\n";
323   }
324   if (0 == std::strcmp(execution_model, "GLCompute")) {
325     execution_modes << "OpExecutionMode %" << entry_point.name
326                     << " LocalSize 1 1 1\n";
327   }
328   entry_point.execution_modes = execution_modes.str();
329 
330   entry_point.body = R"(
331 %val2 = OpFunctionCall %void %foo
332 )";
333 
334   generator.add_at_the_end_ = R"(
335 %foo = OpFunction %void None %func
336 %foo_entry = OpLabel
337 %ptr = OpAccessChain %data_ptr %built_in_var %u32_0
338 OpReturn
339 OpFunctionEnd
340 )";
341   generator.entry_points_.push_back(std::move(entry_point));
342 
343   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
344   ASSERT_EQ(test_result.validation_result,
345             ValidateInstructions(SPV_ENV_VULKAN_1_0));
346   if (test_result.error_str) {
347     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
348   }
349   if (test_result.error_str2) {
350     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
351   }
352 }
353 
TEST_P(ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,Variable)354 TEST_P(ValidateVulkanCombineBuiltInExecutionModelDataTypeResult, Variable) {
355   const char* const built_in = std::get<0>(GetParam());
356   const char* const execution_model = std::get<1>(GetParam());
357   const char* const storage_class = std::get<2>(GetParam());
358   const char* const data_type = std::get<3>(GetParam());
359   const TestResult& test_result = std::get<4>(GetParam());
360 
361   CodeGenerator generator = GetDefaultShaderCodeGenerator();
362   generator.before_types_ = "OpDecorate %built_in_var BuiltIn ";
363   generator.before_types_ += built_in;
364   generator.before_types_ += "\n";
365 
366   std::ostringstream after_types;
367   after_types << "%built_in_ptr = OpTypePointer " << storage_class << " "
368               << data_type << "\n";
369   after_types << "%built_in_var = OpVariable %built_in_ptr " << storage_class
370               << "\n";
371   generator.after_types_ = after_types.str();
372 
373   EntryPoint entry_point;
374   entry_point.name = "main";
375   entry_point.execution_model = execution_model;
376   if (strncmp(storage_class, "Input", 5) == 0 ||
377       strncmp(storage_class, "Output", 6) == 0) {
378     entry_point.interfaces = "%built_in_var";
379   }
380   // Any kind of reference would do.
381   entry_point.body = R"(
382 %val = OpBitcast %u64 %built_in_var
383 )";
384 
385   std::ostringstream execution_modes;
386   if (0 == std::strcmp(execution_model, "Fragment")) {
387     execution_modes << "OpExecutionMode %" << entry_point.name
388                     << " OriginUpperLeft\n";
389     if (0 == std::strcmp(built_in, "FragDepth")) {
390       execution_modes << "OpExecutionMode %" << entry_point.name
391                       << " DepthReplacing\n";
392     }
393   }
394   if (0 == std::strcmp(execution_model, "Geometry")) {
395     execution_modes << "OpExecutionMode %" << entry_point.name
396                     << " InputPoints\n";
397     execution_modes << "OpExecutionMode %" << entry_point.name
398                     << " OutputPoints\n";
399   }
400   if (0 == std::strcmp(execution_model, "GLCompute")) {
401     execution_modes << "OpExecutionMode %" << entry_point.name
402                     << " LocalSize 1 1 1\n";
403   }
404   entry_point.execution_modes = execution_modes.str();
405 
406   generator.entry_points_.push_back(std::move(entry_point));
407 
408   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
409   ASSERT_EQ(test_result.validation_result,
410             ValidateInstructions(SPV_ENV_VULKAN_1_0));
411   if (test_result.error_str) {
412     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
413   }
414   if (test_result.error_str2) {
415     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
416   }
417 }
418 
419 INSTANTIATE_TEST_CASE_P(
420     ClipAndCullDistanceOutputSuccess,
421     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
422     Combine(Values("ClipDistance", "CullDistance"),
423             Values("Vertex", "Geometry", "TessellationControl",
424                    "TessellationEvaluation"),
425             Values("Output"), Values("%f32arr2", "%f32arr4"),
426             Values(TestResult())), );
427 
428 INSTANTIATE_TEST_CASE_P(
429     ClipAndCullDistanceInputSuccess,
430     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
431     Combine(Values("ClipDistance", "CullDistance"),
432             Values("Fragment", "Geometry", "TessellationControl",
433                    "TessellationEvaluation"),
434             Values("Input"), Values("%f32arr2", "%f32arr4"),
435             Values(TestResult())), );
436 
437 INSTANTIATE_TEST_CASE_P(
438     ClipAndCullDistanceFragmentOutput,
439     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
440     Combine(Values("ClipDistance", "CullDistance"), Values("Fragment"),
441             Values("Output"), Values("%f32arr4"),
442             Values(TestResult(
443                 SPV_ERROR_INVALID_DATA,
444                 "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance "
445                 "to be used for variables with Output storage class if "
446                 "execution model is Fragment.",
447                 "which is called with execution model Fragment."))), );
448 
449 INSTANTIATE_TEST_CASE_P(
450     VertexIdAndInstanceIdVertexInput,
451     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
452     Combine(Values("VertexId", "InstanceId"), Values("Vertex"), Values("Input"),
453             Values("%u32"),
454             Values(TestResult(
455                 SPV_ERROR_INVALID_DATA,
456                 "Vulkan spec doesn't allow BuiltIn VertexId/InstanceId to be "
457                 "used."))), );
458 
459 INSTANTIATE_TEST_CASE_P(
460     ClipAndCullDistanceVertexInput,
461     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
462     Combine(Values("ClipDistance", "CullDistance"), Values("Vertex"),
463             Values("Input"), Values("%f32arr4"),
464             Values(TestResult(
465                 SPV_ERROR_INVALID_DATA,
466                 "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance "
467                 "to be used for variables with Input storage class if "
468                 "execution model is Vertex.",
469                 "which is called with execution model Vertex."))), );
470 
471 INSTANTIATE_TEST_CASE_P(
472     ClipAndCullInvalidExecutionModel,
473     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
474     Combine(Values("ClipDistance", "CullDistance"), Values("GLCompute"),
475             Values("Input", "Output"), Values("%f32arr4"),
476             Values(TestResult(
477                 SPV_ERROR_INVALID_DATA,
478                 "to be used only with Fragment, Vertex, TessellationControl, "
479                 "TessellationEvaluation or Geometry execution models"))), );
480 
481 INSTANTIATE_TEST_CASE_P(
482     ClipAndCullDistanceNotArray,
483     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
484     Combine(Values("ClipDistance", "CullDistance"), Values("Fragment"),
485             Values("Input"), Values("%f32vec2", "%f32vec4", "%f32"),
486             Values(TestResult(SPV_ERROR_INVALID_DATA,
487                               "needs to be a 32-bit float array",
488                               "is not an array"))), );
489 
490 INSTANTIATE_TEST_CASE_P(
491     ClipAndCullDistanceNotFloatArray,
492     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
493     Combine(Values("ClipDistance", "CullDistance"), Values("Fragment"),
494             Values("Input"), Values("%u32arr2", "%u64arr4"),
495             Values(TestResult(SPV_ERROR_INVALID_DATA,
496                               "needs to be a 32-bit float array",
497                               "components are not float scalar"))), );
498 
499 INSTANTIATE_TEST_CASE_P(
500     ClipAndCullDistanceNotF32Array,
501     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
502     Combine(Values("ClipDistance", "CullDistance"), Values("Fragment"),
503             Values("Input"), Values("%f64arr2", "%f64arr4"),
504             Values(TestResult(SPV_ERROR_INVALID_DATA,
505                               "needs to be a 32-bit float array",
506                               "has components with bit width 64"))), );
507 
508 INSTANTIATE_TEST_CASE_P(
509     FragCoordSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
510     Combine(Values("FragCoord"), Values("Fragment"), Values("Input"),
511             Values("%f32vec4"), Values(TestResult())), );
512 
513 INSTANTIATE_TEST_CASE_P(
514     FragCoordNotFragment,
515     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
516     Combine(
517         Values("FragCoord"),
518         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
519                "TessellationEvaluation"),
520         Values("Input"), Values("%f32vec4"),
521         Values(TestResult(SPV_ERROR_INVALID_DATA,
522                           "to be used only with Fragment execution model"))), );
523 
524 INSTANTIATE_TEST_CASE_P(
525     FragCoordNotInput, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
526     Combine(Values("FragCoord"), Values("Fragment"), Values("Output"),
527             Values("%f32vec4"),
528             Values(TestResult(
529                 SPV_ERROR_INVALID_DATA,
530                 "to be only used for variables with Input storage class",
531                 "uses storage class Output"))), );
532 
533 INSTANTIATE_TEST_CASE_P(
534     FragCoordNotFloatVector,
535     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
536     Combine(Values("FragCoord"), Values("Fragment"), Values("Input"),
537             Values("%f32arr4", "%u32vec4"),
538             Values(TestResult(SPV_ERROR_INVALID_DATA,
539                               "needs to be a 4-component 32-bit float vector",
540                               "is not a float vector"))), );
541 
542 INSTANTIATE_TEST_CASE_P(
543     FragCoordNotFloatVec4,
544     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
545     Combine(Values("FragCoord"), Values("Fragment"), Values("Input"),
546             Values("%f32vec3"),
547             Values(TestResult(SPV_ERROR_INVALID_DATA,
548                               "needs to be a 4-component 32-bit float vector",
549                               "has 3 components"))), );
550 
551 INSTANTIATE_TEST_CASE_P(
552     FragCoordNotF32Vec4,
553     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
554     Combine(Values("FragCoord"), Values("Fragment"), Values("Input"),
555             Values("%f64vec4"),
556             Values(TestResult(SPV_ERROR_INVALID_DATA,
557                               "needs to be a 4-component 32-bit float vector",
558                               "has components with bit width 64"))), );
559 
560 INSTANTIATE_TEST_CASE_P(
561     FragDepthSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
562     Combine(Values("FragDepth"), Values("Fragment"), Values("Output"),
563             Values("%f32"), Values(TestResult())), );
564 
565 INSTANTIATE_TEST_CASE_P(
566     FragDepthNotFragment,
567     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
568     Combine(
569         Values("FragDepth"),
570         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
571                "TessellationEvaluation"),
572         Values("Output"), Values("%f32"),
573         Values(TestResult(SPV_ERROR_INVALID_DATA,
574                           "to be used only with Fragment execution model"))), );
575 
576 INSTANTIATE_TEST_CASE_P(
577     FragDepthNotOutput,
578     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
579     Combine(Values("FragDepth"), Values("Fragment"), Values("Input"),
580             Values("%f32"),
581             Values(TestResult(
582                 SPV_ERROR_INVALID_DATA,
583                 "to be only used for variables with Output storage class",
584                 "uses storage class Input"))), );
585 
586 INSTANTIATE_TEST_CASE_P(
587     FragDepthNotFloatScalar,
588     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
589     Combine(Values("FragDepth"), Values("Fragment"), Values("Output"),
590             Values("%f32vec4", "%u32"),
591             Values(TestResult(SPV_ERROR_INVALID_DATA,
592                               "needs to be a 32-bit float scalar",
593                               "is not a float scalar"))), );
594 
595 INSTANTIATE_TEST_CASE_P(
596     FragDepthNotF32, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
597     Combine(Values("FragDepth"), Values("Fragment"), Values("Output"),
598             Values("%f64"),
599             Values(TestResult(SPV_ERROR_INVALID_DATA,
600                               "needs to be a 32-bit float scalar",
601                               "has bit width 64"))), );
602 
603 INSTANTIATE_TEST_CASE_P(
604     FrontFacingAndHelperInvocationSuccess,
605     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
606     Combine(Values("FrontFacing", "HelperInvocation"), Values("Fragment"),
607             Values("Input"), Values("%bool"), Values(TestResult())), );
608 
609 INSTANTIATE_TEST_CASE_P(
610     FrontFacingAndHelperInvocationNotFragment,
611     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
612     Combine(
613         Values("FrontFacing", "HelperInvocation"),
614         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
615                "TessellationEvaluation"),
616         Values("Input"), Values("%bool"),
617         Values(TestResult(SPV_ERROR_INVALID_DATA,
618                           "to be used only with Fragment execution model"))), );
619 
620 INSTANTIATE_TEST_CASE_P(
621     FrontFacingAndHelperInvocationNotInput,
622     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
623     Combine(Values("FrontFacing", "HelperInvocation"), Values("Fragment"),
624             Values("Output"), Values("%bool"),
625             Values(TestResult(
626                 SPV_ERROR_INVALID_DATA,
627                 "to be only used for variables with Input storage class",
628                 "uses storage class Output"))), );
629 
630 INSTANTIATE_TEST_CASE_P(
631     FrontFacingAndHelperInvocationNotBool,
632     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
633     Combine(Values("FrontFacing", "HelperInvocation"), Values("Fragment"),
634             Values("Input"), Values("%f32", "%u32"),
635             Values(TestResult(SPV_ERROR_INVALID_DATA,
636                               "needs to be a bool scalar",
637                               "is not a bool scalar"))), );
638 
639 INSTANTIATE_TEST_CASE_P(
640     ComputeShaderInputInt32Vec3Success,
641     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
642     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups",
643                    "WorkgroupId"),
644             Values("GLCompute"), Values("Input"), Values("%u32vec3"),
645             Values(TestResult())), );
646 
647 INSTANTIATE_TEST_CASE_P(
648     ComputeShaderInputInt32Vec3NotGLCompute,
649     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
650     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups",
651                    "WorkgroupId"),
652             Values("Vertex", "Fragment", "Geometry", "TessellationControl",
653                    "TessellationEvaluation"),
654             Values("Input"), Values("%u32vec3"),
655             Values(TestResult(
656                 SPV_ERROR_INVALID_DATA,
657                 "to be used only with GLCompute execution model"))), );
658 
659 INSTANTIATE_TEST_CASE_P(
660     ComputeShaderInputInt32Vec3NotInput,
661     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
662     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups",
663                    "WorkgroupId"),
664             Values("GLCompute"), Values("Output"), Values("%u32vec3"),
665             Values(TestResult(
666                 SPV_ERROR_INVALID_DATA,
667                 "to be only used for variables with Input storage class",
668                 "uses storage class Output"))), );
669 
670 INSTANTIATE_TEST_CASE_P(
671     ComputeShaderInputInt32Vec3NotIntVector,
672     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
673     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups",
674                    "WorkgroupId"),
675             Values("GLCompute"), Values("Input"),
676             Values("%u32arr3", "%f32vec3"),
677             Values(TestResult(SPV_ERROR_INVALID_DATA,
678                               "needs to be a 3-component 32-bit int vector",
679                               "is not an int vector"))), );
680 
681 INSTANTIATE_TEST_CASE_P(
682     ComputeShaderInputInt32Vec3NotIntVec3,
683     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
684     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups",
685                    "WorkgroupId"),
686             Values("GLCompute"), Values("Input"), Values("%u32vec4"),
687             Values(TestResult(SPV_ERROR_INVALID_DATA,
688                               "needs to be a 3-component 32-bit int vector",
689                               "has 4 components"))), );
690 
691 INSTANTIATE_TEST_CASE_P(
692     ComputeShaderInputInt32Vec3NotInt32Vec,
693     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
694     Combine(Values("GlobalInvocationId", "LocalInvocationId", "NumWorkgroups",
695                    "WorkgroupId"),
696             Values("GLCompute"), Values("Input"), Values("%u64vec3"),
697             Values(TestResult(SPV_ERROR_INVALID_DATA,
698                               "needs to be a 3-component 32-bit int vector",
699                               "has components with bit width 64"))), );
700 
701 INSTANTIATE_TEST_CASE_P(
702     InvocationIdSuccess,
703     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
704     Combine(Values("InvocationId"), Values("Geometry", "TessellationControl"),
705             Values("Input"), Values("%u32"), Values(TestResult())), );
706 
707 INSTANTIATE_TEST_CASE_P(
708     InvocationIdInvalidExecutionModel,
709     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
710     Combine(Values("InvocationId"),
711             Values("Vertex", "Fragment", "GLCompute", "TessellationEvaluation"),
712             Values("Input"), Values("%u32"),
713             Values(TestResult(SPV_ERROR_INVALID_DATA,
714                               "to be used only with TessellationControl or "
715                               "Geometry execution models"))), );
716 
717 INSTANTIATE_TEST_CASE_P(
718     InvocationIdNotInput,
719     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
720     Combine(Values("InvocationId"), Values("Geometry", "TessellationControl"),
721             Values("Output"), Values("%u32"),
722             Values(TestResult(
723                 SPV_ERROR_INVALID_DATA,
724                 "to be only used for variables with Input storage class",
725                 "uses storage class Output"))), );
726 
727 INSTANTIATE_TEST_CASE_P(
728     InvocationIdNotIntScalar,
729     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
730     Combine(Values("InvocationId"), Values("Geometry", "TessellationControl"),
731             Values("Input"), Values("%f32", "%u32vec3"),
732             Values(TestResult(SPV_ERROR_INVALID_DATA,
733                               "needs to be a 32-bit int scalar",
734                               "is not an int scalar"))), );
735 
736 INSTANTIATE_TEST_CASE_P(
737     InvocationIdNotInt32,
738     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
739     Combine(Values("InvocationId"), Values("Geometry", "TessellationControl"),
740             Values("Input"), Values("%u64"),
741             Values(TestResult(SPV_ERROR_INVALID_DATA,
742                               "needs to be a 32-bit int scalar",
743                               "has bit width 64"))), );
744 
745 INSTANTIATE_TEST_CASE_P(
746     InstanceIndexSuccess,
747     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
748     Combine(Values("InstanceIndex"), Values("Vertex"), Values("Input"),
749             Values("%u32"), Values(TestResult())), );
750 
751 INSTANTIATE_TEST_CASE_P(
752     InstanceIndexInvalidExecutionModel,
753     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
754     Combine(
755         Values("InstanceIndex"),
756         Values("Geometry", "Fragment", "GLCompute", "TessellationControl",
757                "TessellationEvaluation"),
758         Values("Input"), Values("%u32"),
759         Values(TestResult(SPV_ERROR_INVALID_DATA,
760                           "to be used only with Vertex execution model"))), );
761 
762 INSTANTIATE_TEST_CASE_P(
763     InstanceIndexNotInput,
764     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
765     Combine(Values("InstanceIndex"), Values("Vertex"), Values("Output"),
766             Values("%u32"),
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_CASE_P(
773     InstanceIndexNotIntScalar,
774     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
775     Combine(Values("InstanceIndex"), Values("Vertex"), Values("Input"),
776             Values("%f32", "%u32vec3"),
777             Values(TestResult(SPV_ERROR_INVALID_DATA,
778                               "needs to be a 32-bit int scalar",
779                               "is not an int scalar"))), );
780 
781 INSTANTIATE_TEST_CASE_P(
782     InstanceIndexNotInt32,
783     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
784     Combine(Values("InstanceIndex"), Values("Vertex"), Values("Input"),
785             Values("%u64"),
786             Values(TestResult(SPV_ERROR_INVALID_DATA,
787                               "needs to be a 32-bit int scalar",
788                               "has bit width 64"))), );
789 
790 INSTANTIATE_TEST_CASE_P(
791     LayerAndViewportIndexInputSuccess,
792     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
793     Combine(Values("Layer", "ViewportIndex"), Values("Fragment"),
794             Values("Input"), Values("%u32"), Values(TestResult())), );
795 
796 INSTANTIATE_TEST_CASE_P(
797     LayerAndViewportIndexOutputSuccess,
798     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
799     Combine(Values("Layer", "ViewportIndex"), Values("Geometry"),
800             Values("Output"), Values("%u32"), Values(TestResult())), );
801 
802 INSTANTIATE_TEST_CASE_P(
803     LayerAndViewportIndexInvalidExecutionModel,
804     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
805     Combine(Values("Layer", "ViewportIndex"),
806             Values("TessellationControl", "GLCompute"), Values("Input"),
807             Values("%u32"),
808             Values(TestResult(
809                 SPV_ERROR_INVALID_DATA,
810                 "to be used only with Vertex, TessellationEvaluation, "
811                 "Geometry, or Fragment execution models"))), );
812 
813 INSTANTIATE_TEST_CASE_P(
814     LayerAndViewportIndexExecutionModelEnabledByCapability,
815     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
816     Combine(Values("Layer", "ViewportIndex"),
817             Values("Vertex", "TessellationEvaluation"), Values("Output"),
818             Values("%u32"),
819             Values(TestResult(
820                 SPV_ERROR_INVALID_DATA,
821                 "requires the ShaderViewportIndexLayerEXT capability"))), );
822 
823 INSTANTIATE_TEST_CASE_P(
824     LayerAndViewportIndexFragmentNotInput,
825     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
826     Combine(
827         Values("Layer", "ViewportIndex"), Values("Fragment"), Values("Output"),
828         Values("%u32"),
829         Values(TestResult(SPV_ERROR_INVALID_DATA,
830                           "Output storage class if execution model is Fragment",
831                           "which is called with execution model Fragment"))), );
832 
833 INSTANTIATE_TEST_CASE_P(
834     LayerAndViewportIndexGeometryNotOutput,
835     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
836     Combine(
837         Values("Layer", "ViewportIndex"),
838         Values("Vertex", "TessellationEvaluation", "Geometry"), Values("Input"),
839         Values("%u32"),
840         Values(TestResult(SPV_ERROR_INVALID_DATA,
841                           "Input storage class if execution model is Vertex, "
842                           "TessellationEvaluation, or Geometry",
843                           "which is called with execution model"))), );
844 
845 INSTANTIATE_TEST_CASE_P(
846     LayerAndViewportIndexNotIntScalar,
847     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
848     Combine(Values("Layer", "ViewportIndex"), Values("Fragment"),
849             Values("Input"), Values("%f32", "%u32vec3"),
850             Values(TestResult(SPV_ERROR_INVALID_DATA,
851                               "needs to be a 32-bit int scalar",
852                               "is not an int scalar"))), );
853 
854 INSTANTIATE_TEST_CASE_P(
855     LayerAndViewportIndexNotInt32,
856     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
857     Combine(Values("Layer", "ViewportIndex"), Values("Fragment"),
858             Values("Input"), Values("%u64"),
859             Values(TestResult(SPV_ERROR_INVALID_DATA,
860                               "needs to be a 32-bit int scalar",
861                               "has bit width 64"))), );
862 
863 INSTANTIATE_TEST_CASE_P(
864     PatchVerticesSuccess,
865     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
866     Combine(Values("PatchVertices"),
867             Values("TessellationEvaluation", "TessellationControl"),
868             Values("Input"), Values("%u32"), Values(TestResult())), );
869 
870 INSTANTIATE_TEST_CASE_P(
871     PatchVerticesInvalidExecutionModel,
872     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
873     Combine(Values("PatchVertices"),
874             Values("Vertex", "Fragment", "GLCompute", "Geometry"),
875             Values("Input"), Values("%u32"),
876             Values(TestResult(SPV_ERROR_INVALID_DATA,
877                               "to be used only with TessellationControl or "
878                               "TessellationEvaluation execution models"))), );
879 
880 INSTANTIATE_TEST_CASE_P(
881     PatchVerticesNotInput,
882     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
883     Combine(Values("PatchVertices"),
884             Values("TessellationEvaluation", "TessellationControl"),
885             Values("Output"), Values("%u32"),
886             Values(TestResult(
887                 SPV_ERROR_INVALID_DATA,
888                 "to be only used for variables with Input storage class",
889                 "uses storage class Output"))), );
890 
891 INSTANTIATE_TEST_CASE_P(
892     PatchVerticesNotIntScalar,
893     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
894     Combine(Values("PatchVertices"),
895             Values("TessellationEvaluation", "TessellationControl"),
896             Values("Input"), Values("%f32", "%u32vec3"),
897             Values(TestResult(SPV_ERROR_INVALID_DATA,
898                               "needs to be a 32-bit int scalar",
899                               "is not an int scalar"))), );
900 
901 INSTANTIATE_TEST_CASE_P(
902     PatchVerticesNotInt32,
903     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
904     Combine(Values("PatchVertices"),
905             Values("TessellationEvaluation", "TessellationControl"),
906             Values("Input"), Values("%u64"),
907             Values(TestResult(SPV_ERROR_INVALID_DATA,
908                               "needs to be a 32-bit int scalar",
909                               "has bit width 64"))), );
910 
911 INSTANTIATE_TEST_CASE_P(
912     PointCoordSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
913     Combine(Values("PointCoord"), Values("Fragment"), Values("Input"),
914             Values("%f32vec2"), Values(TestResult())), );
915 
916 INSTANTIATE_TEST_CASE_P(
917     PointCoordNotFragment,
918     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
919     Combine(
920         Values("PointCoord"),
921         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
922                "TessellationEvaluation"),
923         Values("Input"), Values("%f32vec2"),
924         Values(TestResult(SPV_ERROR_INVALID_DATA,
925                           "to be used only with Fragment execution model"))), );
926 
927 INSTANTIATE_TEST_CASE_P(
928     PointCoordNotInput,
929     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
930     Combine(Values("PointCoord"), Values("Fragment"), Values("Output"),
931             Values("%f32vec2"),
932             Values(TestResult(
933                 SPV_ERROR_INVALID_DATA,
934                 "to be only used for variables with Input storage class",
935                 "uses storage class Output"))), );
936 
937 INSTANTIATE_TEST_CASE_P(
938     PointCoordNotFloatVector,
939     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
940     Combine(Values("PointCoord"), Values("Fragment"), Values("Input"),
941             Values("%f32arr2", "%u32vec2"),
942             Values(TestResult(SPV_ERROR_INVALID_DATA,
943                               "needs to be a 2-component 32-bit float vector",
944                               "is not a float vector"))), );
945 
946 INSTANTIATE_TEST_CASE_P(
947     PointCoordNotFloatVec3,
948     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
949     Combine(Values("PointCoord"), Values("Fragment"), Values("Input"),
950             Values("%f32vec3"),
951             Values(TestResult(SPV_ERROR_INVALID_DATA,
952                               "needs to be a 2-component 32-bit float vector",
953                               "has 3 components"))), );
954 
955 INSTANTIATE_TEST_CASE_P(
956     PointCoordNotF32Vec4,
957     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
958     Combine(Values("PointCoord"), Values("Fragment"), Values("Input"),
959             Values("%f64vec2"),
960             Values(TestResult(SPV_ERROR_INVALID_DATA,
961                               "needs to be a 2-component 32-bit float vector",
962                               "has components with bit width 64"))), );
963 
964 INSTANTIATE_TEST_CASE_P(
965     PointSizeOutputSuccess,
966     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
967     Combine(Values("PointSize"),
968             Values("Vertex", "Geometry", "TessellationControl",
969                    "TessellationEvaluation"),
970             Values("Output"), Values("%f32"), Values(TestResult())), );
971 
972 INSTANTIATE_TEST_CASE_P(
973     PointSizeInputSuccess,
974     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
975     Combine(Values("PointSize"),
976             Values("Geometry", "TessellationControl", "TessellationEvaluation"),
977             Values("Input"), Values("%f32"), Values(TestResult())), );
978 
979 INSTANTIATE_TEST_CASE_P(
980     PointSizeVertexInput,
981     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
982     Combine(Values("PointSize"), Values("Vertex"), Values("Input"),
983             Values("%f32"),
984             Values(TestResult(
985                 SPV_ERROR_INVALID_DATA,
986                 "Vulkan spec doesn't allow BuiltIn PointSize "
987                 "to be used for variables with Input storage class if "
988                 "execution model is Vertex.",
989                 "which is called with execution model Vertex."))), );
990 
991 INSTANTIATE_TEST_CASE_P(
992     PointSizeInvalidExecutionModel,
993     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
994     Combine(Values("PointSize"), Values("GLCompute", "Fragment"),
995             Values("Input", "Output"), Values("%f32"),
996             Values(TestResult(
997                 SPV_ERROR_INVALID_DATA,
998                 "to be used only with Vertex, TessellationControl, "
999                 "TessellationEvaluation or Geometry execution models"))), );
1000 
1001 INSTANTIATE_TEST_CASE_P(
1002     PointSizeNotFloatScalar,
1003     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1004     Combine(Values("PointSize"), Values("Vertex"), Values("Output"),
1005             Values("%f32vec4", "%u32"),
1006             Values(TestResult(SPV_ERROR_INVALID_DATA,
1007                               "needs to be a 32-bit float scalar",
1008                               "is not a float scalar"))), );
1009 
1010 INSTANTIATE_TEST_CASE_P(
1011     PointSizeNotF32, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1012     Combine(Values("PointSize"), Values("Vertex"), Values("Output"),
1013             Values("%f64"),
1014             Values(TestResult(SPV_ERROR_INVALID_DATA,
1015                               "needs to be a 32-bit float scalar",
1016                               "has bit width 64"))), );
1017 
1018 INSTANTIATE_TEST_CASE_P(
1019     PositionOutputSuccess,
1020     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1021     Combine(Values("Position"),
1022             Values("Vertex", "Geometry", "TessellationControl",
1023                    "TessellationEvaluation"),
1024             Values("Output"), Values("%f32vec4"), Values(TestResult())), );
1025 
1026 INSTANTIATE_TEST_CASE_P(
1027     PositionInputSuccess,
1028     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1029     Combine(Values("Position"),
1030             Values("Geometry", "TessellationControl", "TessellationEvaluation"),
1031             Values("Input"), Values("%f32vec4"), Values(TestResult())), );
1032 
1033 INSTANTIATE_TEST_CASE_P(
1034     PositionVertexInput,
1035     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1036     Combine(Values("Position"), Values("Vertex"), Values("Input"),
1037             Values("%f32vec4"),
1038             Values(TestResult(
1039                 SPV_ERROR_INVALID_DATA,
1040                 "Vulkan spec doesn't allow BuiltIn Position "
1041                 "to be used for variables with Input storage class if "
1042                 "execution model is Vertex.",
1043                 "which is called with execution model Vertex."))), );
1044 
1045 INSTANTIATE_TEST_CASE_P(
1046     PositionInvalidExecutionModel,
1047     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1048     Combine(Values("Position"), Values("GLCompute", "Fragment"),
1049             Values("Input", "Output"), Values("%f32vec4"),
1050             Values(TestResult(
1051                 SPV_ERROR_INVALID_DATA,
1052                 "to be used only with Vertex, TessellationControl, "
1053                 "TessellationEvaluation or Geometry execution models"))), );
1054 
1055 INSTANTIATE_TEST_CASE_P(
1056     PositionNotFloatVector,
1057     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1058     Combine(Values("Position"), Values("Geometry"), Values("Input"),
1059             Values("%f32arr4", "%u32vec4"),
1060             Values(TestResult(SPV_ERROR_INVALID_DATA,
1061                               "needs to be a 4-component 32-bit float vector",
1062                               "is not a float vector"))), );
1063 
1064 INSTANTIATE_TEST_CASE_P(
1065     PositionNotFloatVec4,
1066     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1067     Combine(Values("Position"), Values("Geometry"), Values("Input"),
1068             Values("%f32vec3"),
1069             Values(TestResult(SPV_ERROR_INVALID_DATA,
1070                               "needs to be a 4-component 32-bit float vector",
1071                               "has 3 components"))), );
1072 
1073 INSTANTIATE_TEST_CASE_P(
1074     PositionNotF32Vec4,
1075     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1076     Combine(Values("Position"), Values("Geometry"), Values("Input"),
1077             Values("%f64vec4"),
1078             Values(TestResult(SPV_ERROR_INVALID_DATA,
1079                               "needs to be a 4-component 32-bit float vector",
1080                               "has components with bit width 64"))), );
1081 
1082 INSTANTIATE_TEST_CASE_P(
1083     PrimitiveIdInputSuccess,
1084     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1085     Combine(Values("PrimitiveId"),
1086             Values("Fragment", "TessellationControl", "TessellationEvaluation",
1087                    "Geometry"),
1088             Values("Input"), Values("%u32"), Values(TestResult())), );
1089 
1090 INSTANTIATE_TEST_CASE_P(
1091     PrimitiveIdOutputSuccess,
1092     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1093     Combine(Values("PrimitiveId"), Values("Geometry"), Values("Output"),
1094             Values("%u32"), Values(TestResult())), );
1095 
1096 INSTANTIATE_TEST_CASE_P(
1097     PrimitiveIdInvalidExecutionModel,
1098     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1099     Combine(Values("PrimitiveId"), Values("Vertex", "GLCompute"),
1100             Values("Input"), Values("%u32"),
1101             Values(TestResult(
1102                 SPV_ERROR_INVALID_DATA,
1103                 "to be used only with Fragment, TessellationControl, "
1104                 "TessellationEvaluation or Geometry execution models"))), );
1105 
1106 INSTANTIATE_TEST_CASE_P(
1107     PrimitiveIdFragmentNotInput,
1108     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1109     Combine(
1110         Values("PrimitiveId"), Values("Fragment"), Values("Output"),
1111         Values("%u32"),
1112         Values(TestResult(SPV_ERROR_INVALID_DATA,
1113                           "Output storage class if execution model is Fragment",
1114                           "which is called with execution model Fragment"))), );
1115 
1116 INSTANTIATE_TEST_CASE_P(
1117     PrimitiveIdGeometryNotInput,
1118     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1119     Combine(Values("PrimitiveId"),
1120             Values("TessellationControl", "TessellationEvaluation"),
1121             Values("Output"), Values("%u32"),
1122             Values(TestResult(
1123                 SPV_ERROR_INVALID_DATA,
1124                 "Output storage class if execution model is Tessellation",
1125                 "which is called with execution model Tessellation"))), );
1126 
1127 INSTANTIATE_TEST_CASE_P(
1128     PrimitiveIdNotIntScalar,
1129     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1130     Combine(Values("PrimitiveId"), Values("Fragment"), Values("Input"),
1131             Values("%f32", "%u32vec3"),
1132             Values(TestResult(SPV_ERROR_INVALID_DATA,
1133                               "needs to be a 32-bit int scalar",
1134                               "is not an int scalar"))), );
1135 
1136 INSTANTIATE_TEST_CASE_P(
1137     PrimitiveIdNotInt32,
1138     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1139     Combine(Values("PrimitiveId"), Values("Fragment"), Values("Input"),
1140             Values("%u64"),
1141             Values(TestResult(SPV_ERROR_INVALID_DATA,
1142                               "needs to be a 32-bit int scalar",
1143                               "has bit width 64"))), );
1144 
1145 INSTANTIATE_TEST_CASE_P(
1146     SampleIdSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1147     Combine(Values("SampleId"), Values("Fragment"), Values("Input"),
1148             Values("%u32"), Values(TestResult())), );
1149 
1150 INSTANTIATE_TEST_CASE_P(
1151     SampleIdInvalidExecutionModel,
1152     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1153     Combine(
1154         Values("SampleId"),
1155         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
1156                "TessellationEvaluation"),
1157         Values("Input"), Values("%u32"),
1158         Values(TestResult(SPV_ERROR_INVALID_DATA,
1159                           "to be used only with Fragment execution model"))), );
1160 
1161 INSTANTIATE_TEST_CASE_P(
1162     SampleIdNotInput, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1163     Combine(
1164         Values("SampleId"), Values("Fragment"), Values("Output"),
1165         Values("%u32"),
1166         Values(TestResult(SPV_ERROR_INVALID_DATA,
1167                           "Vulkan spec allows BuiltIn SampleId to be only used "
1168                           "for variables with Input storage class"))), );
1169 
1170 INSTANTIATE_TEST_CASE_P(
1171     SampleIdNotIntScalar,
1172     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1173     Combine(Values("SampleId"), Values("Fragment"), Values("Input"),
1174             Values("%f32", "%u32vec3"),
1175             Values(TestResult(SPV_ERROR_INVALID_DATA,
1176                               "needs to be a 32-bit int scalar",
1177                               "is not an int scalar"))), );
1178 
1179 INSTANTIATE_TEST_CASE_P(
1180     SampleIdNotInt32, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1181     Combine(Values("SampleId"), Values("Fragment"), Values("Input"),
1182             Values("%u64"),
1183             Values(TestResult(SPV_ERROR_INVALID_DATA,
1184                               "needs to be a 32-bit int scalar",
1185                               "has bit width 64"))), );
1186 
1187 INSTANTIATE_TEST_CASE_P(
1188     SampleMaskSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1189     Combine(Values("SampleMask"), Values("Fragment"), Values("Input", "Output"),
1190             Values("%u32arr2", "%u32arr4"), Values(TestResult())), );
1191 
1192 INSTANTIATE_TEST_CASE_P(
1193     SampleMaskInvalidExecutionModel,
1194     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1195     Combine(
1196         Values("SampleMask"),
1197         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
1198                "TessellationEvaluation"),
1199         Values("Input"), Values("%u32arr2"),
1200         Values(TestResult(SPV_ERROR_INVALID_DATA,
1201                           "to be used only with Fragment execution model"))), );
1202 
1203 INSTANTIATE_TEST_CASE_P(
1204     SampleMaskWrongStorageClass,
1205     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1206     Combine(Values("SampleMask"), Values("Fragment"), Values("Workgroup"),
1207             Values("%u32arr2"),
1208             Values(TestResult(
1209                 SPV_ERROR_INVALID_DATA,
1210                 "Vulkan spec allows BuiltIn SampleMask to be only used for "
1211                 "variables with Input or Output storage class"))), );
1212 
1213 INSTANTIATE_TEST_CASE_P(
1214     SampleMaskNotArray,
1215     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1216     Combine(Values("SampleMask"), Values("Fragment"), Values("Input"),
1217             Values("%f32", "%u32vec3"),
1218             Values(TestResult(SPV_ERROR_INVALID_DATA,
1219                               "needs to be a 32-bit int array",
1220                               "is not an array"))), );
1221 
1222 INSTANTIATE_TEST_CASE_P(
1223     SampleMaskNotIntArray,
1224     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1225     Combine(Values("SampleMask"), Values("Fragment"), Values("Input"),
1226             Values("%f32arr2"),
1227             Values(TestResult(SPV_ERROR_INVALID_DATA,
1228                               "needs to be a 32-bit int array",
1229                               "components are not int scalar"))), );
1230 
1231 INSTANTIATE_TEST_CASE_P(
1232     SampleMaskNotInt32Array,
1233     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1234     Combine(Values("SampleMask"), Values("Fragment"), Values("Input"),
1235             Values("%u64arr2"),
1236             Values(TestResult(SPV_ERROR_INVALID_DATA,
1237                               "needs to be a 32-bit int array",
1238                               "has components with bit width 64"))), );
1239 
1240 INSTANTIATE_TEST_CASE_P(
1241     SamplePositionSuccess,
1242     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1243     Combine(Values("SamplePosition"), Values("Fragment"), Values("Input"),
1244             Values("%f32vec2"), Values(TestResult())), );
1245 
1246 INSTANTIATE_TEST_CASE_P(
1247     SamplePositionNotFragment,
1248     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1249     Combine(
1250         Values("SamplePosition"),
1251         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
1252                "TessellationEvaluation"),
1253         Values("Input"), Values("%f32vec2"),
1254         Values(TestResult(SPV_ERROR_INVALID_DATA,
1255                           "to be used only with Fragment execution model"))), );
1256 
1257 INSTANTIATE_TEST_CASE_P(
1258     SamplePositionNotInput,
1259     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1260     Combine(Values("SamplePosition"), Values("Fragment"), Values("Output"),
1261             Values("%f32vec2"),
1262             Values(TestResult(
1263                 SPV_ERROR_INVALID_DATA,
1264                 "to be only used for variables with Input storage class",
1265                 "uses storage class Output"))), );
1266 
1267 INSTANTIATE_TEST_CASE_P(
1268     SamplePositionNotFloatVector,
1269     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1270     Combine(Values("SamplePosition"), Values("Fragment"), Values("Input"),
1271             Values("%f32arr2", "%u32vec4"),
1272             Values(TestResult(SPV_ERROR_INVALID_DATA,
1273                               "needs to be a 2-component 32-bit float vector",
1274                               "is not a float vector"))), );
1275 
1276 INSTANTIATE_TEST_CASE_P(
1277     SamplePositionNotFloatVec2,
1278     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1279     Combine(Values("SamplePosition"), Values("Fragment"), Values("Input"),
1280             Values("%f32vec3"),
1281             Values(TestResult(SPV_ERROR_INVALID_DATA,
1282                               "needs to be a 2-component 32-bit float vector",
1283                               "has 3 components"))), );
1284 
1285 INSTANTIATE_TEST_CASE_P(
1286     SamplePositionNotF32Vec2,
1287     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1288     Combine(Values("SamplePosition"), Values("Fragment"), Values("Input"),
1289             Values("%f64vec2"),
1290             Values(TestResult(SPV_ERROR_INVALID_DATA,
1291                               "needs to be a 2-component 32-bit float vector",
1292                               "has components with bit width 64"))), );
1293 
1294 INSTANTIATE_TEST_CASE_P(
1295     TessCoordSuccess, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1296     Combine(Values("TessCoord"), Values("TessellationEvaluation"),
1297             Values("Input"), Values("%f32vec3"), Values(TestResult())), );
1298 
1299 INSTANTIATE_TEST_CASE_P(
1300     TessCoordNotFragment,
1301     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1302     Combine(
1303         Values("TessCoord"),
1304         Values("Vertex", "GLCompute", "Geometry", "TessellationControl",
1305                "Fragment"),
1306         Values("Input"), Values("%f32vec3"),
1307         Values(TestResult(
1308             SPV_ERROR_INVALID_DATA,
1309             "to be used only with TessellationEvaluation execution model"))), );
1310 
1311 INSTANTIATE_TEST_CASE_P(
1312     TessCoordNotInput, ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1313     Combine(Values("TessCoord"), Values("Fragment"), Values("Output"),
1314             Values("%f32vec3"),
1315             Values(TestResult(
1316                 SPV_ERROR_INVALID_DATA,
1317                 "to be only used for variables with Input storage class",
1318                 "uses storage class Output"))), );
1319 
1320 INSTANTIATE_TEST_CASE_P(
1321     TessCoordNotFloatVector,
1322     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1323     Combine(Values("TessCoord"), Values("Fragment"), Values("Input"),
1324             Values("%f32arr3", "%u32vec4"),
1325             Values(TestResult(SPV_ERROR_INVALID_DATA,
1326                               "needs to be a 3-component 32-bit float vector",
1327                               "is not a float vector"))), );
1328 
1329 INSTANTIATE_TEST_CASE_P(
1330     TessCoordNotFloatVec3,
1331     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1332     Combine(Values("TessCoord"), Values("Fragment"), Values("Input"),
1333             Values("%f32vec2"),
1334             Values(TestResult(SPV_ERROR_INVALID_DATA,
1335                               "needs to be a 3-component 32-bit float vector",
1336                               "has 2 components"))), );
1337 
1338 INSTANTIATE_TEST_CASE_P(
1339     TessCoordNotF32Vec3,
1340     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1341     Combine(Values("TessCoord"), Values("Fragment"), Values("Input"),
1342             Values("%f64vec3"),
1343             Values(TestResult(SPV_ERROR_INVALID_DATA,
1344                               "needs to be a 3-component 32-bit float vector",
1345                               "has components with bit width 64"))), );
1346 
1347 INSTANTIATE_TEST_CASE_P(
1348     TessLevelOuterTeseInputSuccess,
1349     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1350     Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"),
1351             Values("Input"), Values("%f32arr4"), Values(TestResult())), );
1352 
1353 INSTANTIATE_TEST_CASE_P(
1354     TessLevelOuterTescOutputSuccess,
1355     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1356     Combine(Values("TessLevelOuter"), Values("TessellationControl"),
1357             Values("Output"), Values("%f32arr4"), Values(TestResult())), );
1358 
1359 INSTANTIATE_TEST_CASE_P(
1360     TessLevelOuterInvalidExecutionModel,
1361     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1362     Combine(Values("TessLevelOuter"),
1363             Values("Vertex", "GLCompute", "Geometry", "Fragment"),
1364             Values("Input"), Values("%f32arr4"),
1365             Values(TestResult(SPV_ERROR_INVALID_DATA,
1366                               "to be used only with TessellationControl or "
1367                               "TessellationEvaluation execution models."))), );
1368 
1369 INSTANTIATE_TEST_CASE_P(
1370     TessLevelOuterOutputTese,
1371     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1372     Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"),
1373             Values("Output"), Values("%f32arr4"),
1374             Values(TestResult(
1375                 SPV_ERROR_INVALID_DATA,
1376                 "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
1377                 "used for variables with Output storage class if execution "
1378                 "model is TessellationEvaluation."))), );
1379 
1380 INSTANTIATE_TEST_CASE_P(
1381     TessLevelOuterInputTesc,
1382     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1383     Combine(Values("TessLevelOuter"), Values("TessellationControl"),
1384             Values("Input"), Values("%f32arr4"),
1385             Values(TestResult(
1386                 SPV_ERROR_INVALID_DATA,
1387                 "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
1388                 "used for variables with Input storage class if execution "
1389                 "model is TessellationControl."))), );
1390 
1391 INSTANTIATE_TEST_CASE_P(
1392     TessLevelOuterNotArray,
1393     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1394     Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"),
1395             Values("Input"), Values("%f32vec4", "%f32"),
1396             Values(TestResult(SPV_ERROR_INVALID_DATA,
1397                               "needs to be a 4-component 32-bit float array",
1398                               "is not an array"))), );
1399 
1400 INSTANTIATE_TEST_CASE_P(
1401     TessLevelOuterNotFloatArray,
1402     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1403     Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"),
1404             Values("Input"), Values("%u32arr4"),
1405             Values(TestResult(SPV_ERROR_INVALID_DATA,
1406                               "needs to be a 4-component 32-bit float array",
1407                               "components are not float scalar"))), );
1408 
1409 INSTANTIATE_TEST_CASE_P(
1410     TessLevelOuterNotFloatArr4,
1411     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1412     Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"),
1413             Values("Input"), Values("%f32arr3"),
1414             Values(TestResult(SPV_ERROR_INVALID_DATA,
1415                               "needs to be a 4-component 32-bit float array",
1416                               "has 3 components"))), );
1417 
1418 INSTANTIATE_TEST_CASE_P(
1419     TessLevelOuterNotF32Arr4,
1420     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1421     Combine(Values("TessLevelOuter"), Values("TessellationEvaluation"),
1422             Values("Input"), Values("%f64arr4"),
1423             Values(TestResult(SPV_ERROR_INVALID_DATA,
1424                               "needs to be a 4-component 32-bit float array",
1425                               "has components with bit width 64"))), );
1426 
1427 INSTANTIATE_TEST_CASE_P(
1428     TessLevelInnerTeseInputSuccess,
1429     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1430     Combine(Values("TessLevelInner"), Values("TessellationEvaluation"),
1431             Values("Input"), Values("%f32arr2"), Values(TestResult())), );
1432 
1433 INSTANTIATE_TEST_CASE_P(
1434     TessLevelInnerTescOutputSuccess,
1435     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1436     Combine(Values("TessLevelInner"), Values("TessellationControl"),
1437             Values("Output"), Values("%f32arr2"), Values(TestResult())), );
1438 
1439 INSTANTIATE_TEST_CASE_P(
1440     TessLevelInnerInvalidExecutionModel,
1441     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1442     Combine(Values("TessLevelInner"),
1443             Values("Vertex", "GLCompute", "Geometry", "Fragment"),
1444             Values("Input"), Values("%f32arr2"),
1445             Values(TestResult(SPV_ERROR_INVALID_DATA,
1446                               "to be used only with TessellationControl or "
1447                               "TessellationEvaluation execution models."))), );
1448 
1449 INSTANTIATE_TEST_CASE_P(
1450     TessLevelInnerOutputTese,
1451     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1452     Combine(Values("TessLevelInner"), Values("TessellationEvaluation"),
1453             Values("Output"), Values("%f32arr2"),
1454             Values(TestResult(
1455                 SPV_ERROR_INVALID_DATA,
1456                 "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
1457                 "used for variables with Output storage class if execution "
1458                 "model is TessellationEvaluation."))), );
1459 
1460 INSTANTIATE_TEST_CASE_P(
1461     TessLevelInnerInputTesc,
1462     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1463     Combine(Values("TessLevelInner"), Values("TessellationControl"),
1464             Values("Input"), Values("%f32arr2"),
1465             Values(TestResult(
1466                 SPV_ERROR_INVALID_DATA,
1467                 "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
1468                 "used for variables with Input storage class if execution "
1469                 "model is TessellationControl."))), );
1470 
1471 INSTANTIATE_TEST_CASE_P(
1472     TessLevelInnerNotArray,
1473     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1474     Combine(Values("TessLevelInner"), Values("TessellationEvaluation"),
1475             Values("Input"), Values("%f32vec2", "%f32"),
1476             Values(TestResult(SPV_ERROR_INVALID_DATA,
1477                               "needs to be a 2-component 32-bit float array",
1478                               "is not an array"))), );
1479 
1480 INSTANTIATE_TEST_CASE_P(
1481     TessLevelInnerNotFloatArray,
1482     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1483     Combine(Values("TessLevelInner"), Values("TessellationEvaluation"),
1484             Values("Input"), Values("%u32arr2"),
1485             Values(TestResult(SPV_ERROR_INVALID_DATA,
1486                               "needs to be a 2-component 32-bit float array",
1487                               "components are not float scalar"))), );
1488 
1489 INSTANTIATE_TEST_CASE_P(
1490     TessLevelInnerNotFloatArr2,
1491     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1492     Combine(Values("TessLevelInner"), Values("TessellationEvaluation"),
1493             Values("Input"), Values("%f32arr3"),
1494             Values(TestResult(SPV_ERROR_INVALID_DATA,
1495                               "needs to be a 2-component 32-bit float array",
1496                               "has 3 components"))), );
1497 
1498 INSTANTIATE_TEST_CASE_P(
1499     TessLevelInnerNotF32Arr2,
1500     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1501     Combine(Values("TessLevelInner"), Values("TessellationEvaluation"),
1502             Values("Input"), Values("%f64arr2"),
1503             Values(TestResult(SPV_ERROR_INVALID_DATA,
1504                               "needs to be a 2-component 32-bit float array",
1505                               "has components with bit width 64"))), );
1506 
1507 INSTANTIATE_TEST_CASE_P(
1508     VertexIndexSuccess,
1509     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1510     Combine(Values("VertexIndex"), Values("Vertex"), Values("Input"),
1511             Values("%u32"), Values(TestResult())), );
1512 
1513 INSTANTIATE_TEST_CASE_P(
1514     VertexIndexInvalidExecutionModel,
1515     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1516     Combine(
1517         Values("VertexIndex"),
1518         Values("Fragment", "GLCompute", "Geometry", "TessellationControl",
1519                "TessellationEvaluation"),
1520         Values("Input"), Values("%u32"),
1521         Values(TestResult(SPV_ERROR_INVALID_DATA,
1522                           "to be used only with Vertex execution model"))), );
1523 
1524 INSTANTIATE_TEST_CASE_P(
1525     VertexIndexNotInput,
1526     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1527     Combine(
1528         Values("VertexIndex"), Values("Vertex"), Values("Output"),
1529         Values("%u32"),
1530         Values(TestResult(SPV_ERROR_INVALID_DATA,
1531                           "Vulkan spec allows BuiltIn VertexIndex to be only "
1532                           "used for variables with Input storage class"))), );
1533 
1534 INSTANTIATE_TEST_CASE_P(
1535     VertexIndexNotIntScalar,
1536     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1537     Combine(Values("VertexIndex"), Values("Vertex"), Values("Input"),
1538             Values("%f32", "%u32vec3"),
1539             Values(TestResult(SPV_ERROR_INVALID_DATA,
1540                               "needs to be a 32-bit int scalar",
1541                               "is not an int scalar"))), );
1542 
1543 INSTANTIATE_TEST_CASE_P(
1544     VertexIndexNotInt32,
1545     ValidateVulkanCombineBuiltInExecutionModelDataTypeResult,
1546     Combine(Values("VertexIndex"), Values("Vertex"), Values("Input"),
1547             Values("%u64"),
1548             Values(TestResult(SPV_ERROR_INVALID_DATA,
1549                               "needs to be a 32-bit int scalar",
1550                               "has bit width 64"))), );
1551 
TEST_P(ValidateVulkanCombineBuiltInArrayedVariable,Variable)1552 TEST_P(ValidateVulkanCombineBuiltInArrayedVariable, Variable) {
1553   const char* const built_in = std::get<0>(GetParam());
1554   const char* const execution_model = std::get<1>(GetParam());
1555   const char* const storage_class = std::get<2>(GetParam());
1556   const char* const data_type = std::get<3>(GetParam());
1557   const TestResult& test_result = std::get<4>(GetParam());
1558 
1559   CodeGenerator generator = GetDefaultShaderCodeGenerator();
1560   generator.before_types_ = "OpDecorate %built_in_var BuiltIn ";
1561   generator.before_types_ += built_in;
1562   generator.before_types_ += "\n";
1563 
1564   std::ostringstream after_types;
1565   after_types << "%built_in_array = OpTypeArray " << data_type << " %u32_3\n";
1566   after_types << "%built_in_ptr = OpTypePointer " << storage_class
1567               << " %built_in_array\n";
1568   after_types << "%built_in_var = OpVariable %built_in_ptr " << storage_class
1569               << "\n";
1570   generator.after_types_ = after_types.str();
1571 
1572   EntryPoint entry_point;
1573   entry_point.name = "main";
1574   entry_point.execution_model = execution_model;
1575   entry_point.interfaces = "%built_in_var";
1576   // Any kind of reference would do.
1577   entry_point.body = R"(
1578 %val = OpBitcast %u64 %built_in_var
1579 )";
1580 
1581   std::ostringstream execution_modes;
1582   if (0 == std::strcmp(execution_model, "Fragment")) {
1583     execution_modes << "OpExecutionMode %" << entry_point.name
1584                     << " OriginUpperLeft\n";
1585     if (0 == std::strcmp(built_in, "FragDepth")) {
1586       execution_modes << "OpExecutionMode %" << entry_point.name
1587                       << " DepthReplacing\n";
1588     }
1589   }
1590   if (0 == std::strcmp(execution_model, "Geometry")) {
1591     execution_modes << "OpExecutionMode %" << entry_point.name
1592                     << " InputPoints\n";
1593     execution_modes << "OpExecutionMode %" << entry_point.name
1594                     << " OutputPoints\n";
1595   }
1596   if (0 == std::strcmp(execution_model, "GLCompute")) {
1597     execution_modes << "OpExecutionMode %" << entry_point.name
1598                     << " LocalSize 1 1 1\n";
1599   }
1600   entry_point.execution_modes = execution_modes.str();
1601 
1602   generator.entry_points_.push_back(std::move(entry_point));
1603 
1604   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
1605   ASSERT_EQ(test_result.validation_result,
1606             ValidateInstructions(SPV_ENV_VULKAN_1_0));
1607   if (test_result.error_str) {
1608     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
1609   }
1610   if (test_result.error_str2) {
1611     EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str2));
1612   }
1613 }
1614 
1615 INSTANTIATE_TEST_CASE_P(PointSizeArrayedF32TessControl,
1616                         ValidateVulkanCombineBuiltInArrayedVariable,
1617                         Combine(Values("PointSize"),
1618                                 Values("TessellationControl"), Values("Input"),
1619                                 Values("%f32"), Values(TestResult())), );
1620 
1621 INSTANTIATE_TEST_CASE_P(
1622     PointSizeArrayedF64TessControl, ValidateVulkanCombineBuiltInArrayedVariable,
1623     Combine(Values("PointSize"), Values("TessellationControl"), Values("Input"),
1624             Values("%f64"),
1625             Values(TestResult(SPV_ERROR_INVALID_DATA,
1626                               "needs to be a 32-bit float scalar",
1627                               "has bit width 64"))), );
1628 
1629 INSTANTIATE_TEST_CASE_P(
1630     PointSizeArrayedF32Vertex, ValidateVulkanCombineBuiltInArrayedVariable,
1631     Combine(Values("PointSize"), Values("Vertex"), Values("Output"),
1632             Values("%f32"),
1633             Values(TestResult(SPV_ERROR_INVALID_DATA,
1634                               "needs to be a 32-bit float scalar",
1635                               "is not a float scalar"))), );
1636 
1637 INSTANTIATE_TEST_CASE_P(PositionArrayedF32Vec4TessControl,
1638                         ValidateVulkanCombineBuiltInArrayedVariable,
1639                         Combine(Values("Position"),
1640                                 Values("TessellationControl"), Values("Input"),
1641                                 Values("%f32vec4"), Values(TestResult())), );
1642 
1643 INSTANTIATE_TEST_CASE_P(
1644     PositionArrayedF32Vec3TessControl,
1645     ValidateVulkanCombineBuiltInArrayedVariable,
1646     Combine(Values("Position"), Values("TessellationControl"), Values("Input"),
1647             Values("%f32vec3"),
1648             Values(TestResult(SPV_ERROR_INVALID_DATA,
1649                               "needs to be a 4-component 32-bit float vector",
1650                               "has 3 components"))), );
1651 
1652 INSTANTIATE_TEST_CASE_P(
1653     PositionArrayedF32Vec4Vertex, ValidateVulkanCombineBuiltInArrayedVariable,
1654     Combine(Values("Position"), Values("Vertex"), Values("Output"),
1655             Values("%f32"),
1656             Values(TestResult(SPV_ERROR_INVALID_DATA,
1657                               "needs to be a 4-component 32-bit float vector",
1658                               "is not a float vector"))), );
1659 
1660 INSTANTIATE_TEST_CASE_P(
1661     ClipAndCullDistanceOutputSuccess,
1662     ValidateVulkanCombineBuiltInArrayedVariable,
1663     Combine(Values("ClipDistance", "CullDistance"),
1664             Values("Geometry", "TessellationControl", "TessellationEvaluation"),
1665             Values("Output"), Values("%f32arr2", "%f32arr4"),
1666             Values(TestResult())), );
1667 
1668 INSTANTIATE_TEST_CASE_P(
1669     ClipAndCullDistanceVertexInput, ValidateVulkanCombineBuiltInArrayedVariable,
1670     Combine(Values("ClipDistance", "CullDistance"), Values("Fragment"),
1671             Values("Input"), Values("%f32arr4"),
1672             Values(TestResult(SPV_ERROR_INVALID_DATA,
1673                               "needs to be a 32-bit float array",
1674                               "components are not float scalar"))), );
1675 
1676 INSTANTIATE_TEST_CASE_P(
1677     ClipAndCullDistanceNotArray, ValidateVulkanCombineBuiltInArrayedVariable,
1678     Combine(Values("ClipDistance", "CullDistance"),
1679             Values("Geometry", "TessellationControl", "TessellationEvaluation"),
1680             Values("Input"), Values("%f32vec2", "%f32vec4"),
1681             Values(TestResult(SPV_ERROR_INVALID_DATA,
1682                               "needs to be a 32-bit float array",
1683                               "components are not float scalar"))), );
1684 
TEST_F(ValidateBuiltIns,WorkgroupSizeSuccess)1685 TEST_F(ValidateBuiltIns, WorkgroupSizeSuccess) {
1686   CodeGenerator generator = GetDefaultShaderCodeGenerator();
1687   generator.before_types_ = R"(
1688 OpDecorate %workgroup_size BuiltIn WorkgroupSize
1689 )";
1690 
1691   generator.after_types_ = R"(
1692 %workgroup_size = OpConstantComposite %u32vec3 %u32_1 %u32_1 %u32_1
1693 )";
1694 
1695   EntryPoint entry_point;
1696   entry_point.name = "main";
1697   entry_point.execution_model = "GLCompute";
1698   entry_point.body = R"(
1699 %copy = OpCopyObject %u32vec3 %workgroup_size
1700 )";
1701   generator.entry_points_.push_back(std::move(entry_point));
1702 
1703   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
1704   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1705 }
1706 
TEST_F(ValidateBuiltIns,WorkgroupSizeFragment)1707 TEST_F(ValidateBuiltIns, WorkgroupSizeFragment) {
1708   CodeGenerator generator = GetDefaultShaderCodeGenerator();
1709   generator.before_types_ = R"(
1710 OpDecorate %workgroup_size BuiltIn WorkgroupSize
1711 )";
1712 
1713   generator.after_types_ = R"(
1714 %workgroup_size = OpConstantComposite %u32vec3 %u32_1 %u32_1 %u32_1
1715 )";
1716 
1717   EntryPoint entry_point;
1718   entry_point.name = "main";
1719   entry_point.execution_model = "Fragment";
1720   entry_point.execution_modes = "OpExecutionMode %main OriginUpperLeft";
1721   entry_point.body = R"(
1722 %copy = OpCopyObject %u32vec3 %workgroup_size
1723 )";
1724   generator.entry_points_.push_back(std::move(entry_point));
1725 
1726   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
1727   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1728   EXPECT_THAT(getDiagnosticString(),
1729               HasSubstr("Vulkan spec allows BuiltIn WorkgroupSize to be used "
1730                         "only with GLCompute execution model"));
1731   EXPECT_THAT(getDiagnosticString(),
1732               HasSubstr("is referencing ID <2> (OpConstantComposite) which is "
1733                         "decorated with BuiltIn WorkgroupSize in function <1> "
1734                         "called with execution model Fragment"));
1735 }
1736 
TEST_F(ValidateBuiltIns,WorkgroupSizeNotConstant)1737 TEST_F(ValidateBuiltIns, WorkgroupSizeNotConstant) {
1738   CodeGenerator generator = GetDefaultShaderCodeGenerator();
1739   generator.before_types_ = R"(
1740 OpDecorate %copy BuiltIn WorkgroupSize
1741 )";
1742 
1743   generator.after_types_ = R"(
1744 %workgroup_size = OpConstantComposite %u32vec3 %u32_1 %u32_1 %u32_1
1745 )";
1746 
1747   EntryPoint entry_point;
1748   entry_point.name = "main";
1749   entry_point.execution_model = "GLCompute";
1750   entry_point.body = R"(
1751 %copy = OpCopyObject %u32vec3 %workgroup_size
1752 )";
1753   generator.entry_points_.push_back(std::move(entry_point));
1754 
1755   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
1756   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1757   EXPECT_THAT(getDiagnosticString(),
1758               HasSubstr("Vulkan spec requires BuiltIn WorkgroupSize to be a "
1759                         "constant. ID <2> (OpCopyObject) is not a constant"));
1760 }
1761 
TEST_F(ValidateBuiltIns,WorkgroupSizeNotVector)1762 TEST_F(ValidateBuiltIns, WorkgroupSizeNotVector) {
1763   CodeGenerator generator = GetDefaultShaderCodeGenerator();
1764   generator.before_types_ = R"(
1765 OpDecorate %workgroup_size BuiltIn WorkgroupSize
1766 )";
1767 
1768   generator.after_types_ = R"(
1769 %workgroup_size = OpConstant %u32 16
1770 )";
1771 
1772   EntryPoint entry_point;
1773   entry_point.name = "main";
1774   entry_point.execution_model = "GLCompute";
1775   entry_point.body = R"(
1776 %copy = OpCopyObject %u32 %workgroup_size
1777 )";
1778   generator.entry_points_.push_back(std::move(entry_point));
1779 
1780   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
1781   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1782   EXPECT_THAT(getDiagnosticString(),
1783               HasSubstr("According to the Vulkan spec BuiltIn WorkgroupSize "
1784                         "variable needs to be a 3-component 32-bit int vector. "
1785                         "ID <2> (OpConstant) is not an int vector."));
1786 }
1787 
TEST_F(ValidateBuiltIns,WorkgroupSizeNotIntVector)1788 TEST_F(ValidateBuiltIns, WorkgroupSizeNotIntVector) {
1789   CodeGenerator generator = GetDefaultShaderCodeGenerator();
1790   generator.before_types_ = R"(
1791 OpDecorate %workgroup_size BuiltIn WorkgroupSize
1792 )";
1793 
1794   generator.after_types_ = R"(
1795 %workgroup_size = OpConstantComposite %f32vec3 %f32_1 %f32_1 %f32_1
1796 )";
1797 
1798   EntryPoint entry_point;
1799   entry_point.name = "main";
1800   entry_point.execution_model = "GLCompute";
1801   entry_point.body = R"(
1802 %copy = OpCopyObject %f32vec3 %workgroup_size
1803 )";
1804   generator.entry_points_.push_back(std::move(entry_point));
1805 
1806   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
1807   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1808   EXPECT_THAT(getDiagnosticString(),
1809               HasSubstr("According to the Vulkan spec BuiltIn WorkgroupSize "
1810                         "variable needs to be a 3-component 32-bit int vector. "
1811                         "ID <2> (OpConstantComposite) is not an int vector."));
1812 }
1813 
TEST_F(ValidateBuiltIns,WorkgroupSizeNotVec3)1814 TEST_F(ValidateBuiltIns, WorkgroupSizeNotVec3) {
1815   CodeGenerator generator = GetDefaultShaderCodeGenerator();
1816   generator.before_types_ = R"(
1817 OpDecorate %workgroup_size BuiltIn WorkgroupSize
1818 )";
1819 
1820   generator.after_types_ = R"(
1821 %workgroup_size = OpConstantComposite %u32vec2 %u32_1 %u32_1
1822 )";
1823 
1824   EntryPoint entry_point;
1825   entry_point.name = "main";
1826   entry_point.execution_model = "GLCompute";
1827   entry_point.body = R"(
1828 %copy = OpCopyObject %u32vec2 %workgroup_size
1829 )";
1830   generator.entry_points_.push_back(std::move(entry_point));
1831 
1832   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
1833   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1834   EXPECT_THAT(getDiagnosticString(),
1835               HasSubstr("According to the Vulkan spec BuiltIn WorkgroupSize "
1836                         "variable needs to be a 3-component 32-bit int vector. "
1837                         "ID <2> (OpConstantComposite) has 2 components."));
1838 }
1839 
TEST_F(ValidateBuiltIns,WorkgroupSizeNotInt32Vec)1840 TEST_F(ValidateBuiltIns, WorkgroupSizeNotInt32Vec) {
1841   CodeGenerator generator = GetDefaultShaderCodeGenerator();
1842   generator.before_types_ = R"(
1843 OpDecorate %workgroup_size BuiltIn WorkgroupSize
1844 )";
1845 
1846   generator.after_types_ = R"(
1847 %workgroup_size = OpConstantComposite %u64vec3 %u64_1 %u64_1 %u64_1
1848 )";
1849 
1850   EntryPoint entry_point;
1851   entry_point.name = "main";
1852   entry_point.execution_model = "GLCompute";
1853   entry_point.body = R"(
1854 %copy = OpCopyObject %u64vec3 %workgroup_size
1855 )";
1856   generator.entry_points_.push_back(std::move(entry_point));
1857 
1858   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
1859   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1860   EXPECT_THAT(
1861       getDiagnosticString(),
1862       HasSubstr("According to the Vulkan spec BuiltIn WorkgroupSize variable "
1863                 "needs to be a 3-component 32-bit int vector. ID <2> "
1864                 "(OpConstantComposite) has components with bit width 64."));
1865 }
1866 
TEST_F(ValidateBuiltIns,WorkgroupSizePrivateVar)1867 TEST_F(ValidateBuiltIns, WorkgroupSizePrivateVar) {
1868   CodeGenerator generator = GetDefaultShaderCodeGenerator();
1869   generator.before_types_ = R"(
1870 OpDecorate %workgroup_size BuiltIn WorkgroupSize
1871 )";
1872 
1873   generator.after_types_ = R"(
1874 %workgroup_size = OpConstantComposite %u32vec3 %u32_1 %u32_1 %u32_1
1875 %private_ptr_u32vec3 = OpTypePointer Private %u32vec3
1876 %var = OpVariable %private_ptr_u32vec3 Private %workgroup_size
1877 )";
1878 
1879   EntryPoint entry_point;
1880   entry_point.name = "main";
1881   entry_point.execution_model = "GLCompute";
1882   entry_point.body = R"(
1883 )";
1884   generator.entry_points_.push_back(std::move(entry_point));
1885 
1886   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
1887   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1888 }
1889 
TEST_F(ValidateBuiltIns,GeometryPositionInOutSuccess)1890 TEST_F(ValidateBuiltIns, GeometryPositionInOutSuccess) {
1891   CodeGenerator generator = GetDefaultShaderCodeGenerator();
1892 
1893   generator.before_types_ = R"(
1894 OpMemberDecorate %input_type 0 BuiltIn Position
1895 OpMemberDecorate %output_type 0 BuiltIn Position
1896 )";
1897 
1898   generator.after_types_ = R"(
1899 %input_type = OpTypeStruct %f32vec4
1900 %arrayed_input_type = OpTypeArray %input_type %u32_3
1901 %input_ptr = OpTypePointer Input %arrayed_input_type
1902 %input = OpVariable %input_ptr Input
1903 %input_f32vec4_ptr = OpTypePointer Input %f32vec4
1904 %output_type = OpTypeStruct %f32vec4
1905 %arrayed_output_type = OpTypeArray %output_type %u32_3
1906 %output_ptr = OpTypePointer Output %arrayed_output_type
1907 %output = OpVariable %output_ptr Output
1908 %output_f32vec4_ptr = OpTypePointer Output %f32vec4
1909 )";
1910 
1911   EntryPoint entry_point;
1912   entry_point.name = "main";
1913   entry_point.execution_model = "Geometry";
1914   entry_point.interfaces = "%input %output";
1915   entry_point.body = R"(
1916 %input_pos = OpAccessChain %input_f32vec4_ptr %input %u32_0 %u32_0
1917 %output_pos = OpAccessChain %output_f32vec4_ptr %output %u32_0 %u32_0
1918 %pos = OpLoad %f32vec4 %input_pos
1919 OpStore %output_pos %pos
1920 )";
1921   generator.entry_points_.push_back(std::move(entry_point));
1922   generator.entry_points_[0].execution_modes =
1923       "OpExecutionMode %main InputPoints\nOpExecutionMode %main OutputPoints\n";
1924 
1925   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
1926   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1927 }
1928 
TEST_F(ValidateBuiltIns,WorkgroupIdNotVec3)1929 TEST_F(ValidateBuiltIns, WorkgroupIdNotVec3) {
1930   CodeGenerator generator = GetDefaultShaderCodeGenerator();
1931   generator.before_types_ = R"(
1932 OpDecorate %workgroup_size BuiltIn WorkgroupSize
1933 OpDecorate %workgroup_id BuiltIn WorkgroupId
1934 )";
1935 
1936   generator.after_types_ = R"(
1937 %workgroup_size = OpConstantComposite %u32vec3 %u32_1 %u32_1 %u32_1
1938      %input_ptr = OpTypePointer Input %u32vec2
1939   %workgroup_id = OpVariable %input_ptr Input
1940 )";
1941 
1942   EntryPoint entry_point;
1943   entry_point.name = "main";
1944   entry_point.execution_model = "GLCompute";
1945   entry_point.interfaces = "%workgroup_id";
1946   entry_point.body = R"(
1947 %copy_size = OpCopyObject %u32vec3 %workgroup_size
1948   %load_id = OpLoad %u32vec2 %workgroup_id
1949 )";
1950   generator.entry_points_.push_back(std::move(entry_point));
1951 
1952   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
1953   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1954   EXPECT_THAT(getDiagnosticString(),
1955               HasSubstr("According to the Vulkan spec BuiltIn WorkgroupId "
1956                         "variable needs to be a 3-component 32-bit int vector. "
1957                         "ID <2> (OpVariable) has 2 components."));
1958 }
1959 
TEST_F(ValidateBuiltIns,TwoBuiltInsFirstFails)1960 TEST_F(ValidateBuiltIns, TwoBuiltInsFirstFails) {
1961   CodeGenerator generator = GetDefaultShaderCodeGenerator();
1962 
1963   generator.before_types_ = R"(
1964 OpMemberDecorate %input_type 0 BuiltIn FragCoord
1965 OpMemberDecorate %output_type 0 BuiltIn Position
1966 )";
1967 
1968   generator.after_types_ = R"(
1969 %input_type = OpTypeStruct %f32vec4
1970 %input_ptr = OpTypePointer Input %input_type
1971 %input = OpVariable %input_ptr Input
1972 %input_f32vec4_ptr = OpTypePointer Input %f32vec4
1973 %output_type = OpTypeStruct %f32vec4
1974 %output_ptr = OpTypePointer Output %output_type
1975 %output = OpVariable %output_ptr Output
1976 %output_f32vec4_ptr = OpTypePointer Output %f32vec4
1977 )";
1978 
1979   EntryPoint entry_point;
1980   entry_point.name = "main";
1981   entry_point.execution_model = "Geometry";
1982   entry_point.interfaces = "%input %output";
1983   entry_point.body = R"(
1984 %input_pos = OpAccessChain %input_f32vec4_ptr %input %u32_0
1985 %output_pos = OpAccessChain %output_f32vec4_ptr %output %u32_0
1986 %pos = OpLoad %f32vec4 %input_pos
1987 OpStore %output_pos %pos
1988 )";
1989   generator.entry_points_.push_back(std::move(entry_point));
1990   generator.entry_points_[0].execution_modes =
1991       "OpExecutionMode %main InputPoints\nOpExecutionMode %main OutputPoints\n";
1992 
1993   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
1994   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1995   EXPECT_THAT(getDiagnosticString(),
1996               HasSubstr("Vulkan spec allows BuiltIn FragCoord to be used only "
1997                         "with Fragment execution model"));
1998 }
1999 
TEST_F(ValidateBuiltIns,TwoBuiltInsSecondFails)2000 TEST_F(ValidateBuiltIns, TwoBuiltInsSecondFails) {
2001   CodeGenerator generator = GetDefaultShaderCodeGenerator();
2002 
2003   generator.before_types_ = R"(
2004 OpMemberDecorate %input_type 0 BuiltIn Position
2005 OpMemberDecorate %output_type 0 BuiltIn FragCoord
2006 )";
2007 
2008   generator.after_types_ = R"(
2009 %input_type = OpTypeStruct %f32vec4
2010 %input_ptr = OpTypePointer Input %input_type
2011 %input = OpVariable %input_ptr Input
2012 %input_f32vec4_ptr = OpTypePointer Input %f32vec4
2013 %output_type = OpTypeStruct %f32vec4
2014 %output_ptr = OpTypePointer Output %output_type
2015 %output = OpVariable %output_ptr Output
2016 %output_f32vec4_ptr = OpTypePointer Output %f32vec4
2017 )";
2018 
2019   EntryPoint entry_point;
2020   entry_point.name = "main";
2021   entry_point.execution_model = "Geometry";
2022   entry_point.interfaces = "%input %output";
2023   entry_point.body = R"(
2024 %input_pos = OpAccessChain %input_f32vec4_ptr %input %u32_0
2025 %output_pos = OpAccessChain %output_f32vec4_ptr %output %u32_0
2026 %pos = OpLoad %f32vec4 %input_pos
2027 OpStore %output_pos %pos
2028 )";
2029   generator.entry_points_.push_back(std::move(entry_point));
2030   generator.entry_points_[0].execution_modes =
2031       "OpExecutionMode %main InputPoints\nOpExecutionMode %main OutputPoints\n";
2032 
2033   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
2034   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2035   EXPECT_THAT(getDiagnosticString(),
2036               HasSubstr("Vulkan spec allows BuiltIn FragCoord to be only used "
2037                         "for variables with Input storage class"));
2038 }
2039 
TEST_F(ValidateBuiltIns,VertexPositionVariableSuccess)2040 TEST_F(ValidateBuiltIns, VertexPositionVariableSuccess) {
2041   CodeGenerator generator = GetDefaultShaderCodeGenerator();
2042   generator.before_types_ = R"(
2043 OpDecorate %position BuiltIn Position
2044 )";
2045 
2046   generator.after_types_ = R"(
2047 %f32vec4_ptr_output = OpTypePointer Output %f32vec4
2048 %position = OpVariable %f32vec4_ptr_output Output
2049 )";
2050 
2051   EntryPoint entry_point;
2052   entry_point.name = "main";
2053   entry_point.execution_model = "Vertex";
2054   entry_point.interfaces = "%position";
2055   entry_point.body = R"(
2056 OpStore %position %f32vec4_0123
2057 )";
2058   generator.entry_points_.push_back(std::move(entry_point));
2059 
2060   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
2061   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2062 }
2063 
TEST_F(ValidateBuiltIns,FragmentPositionTwoEntryPoints)2064 TEST_F(ValidateBuiltIns, FragmentPositionTwoEntryPoints) {
2065   CodeGenerator generator = GetDefaultShaderCodeGenerator();
2066   generator.before_types_ = R"(
2067 OpMemberDecorate %output_type 0 BuiltIn Position
2068 )";
2069 
2070   generator.after_types_ = R"(
2071 %output_type = OpTypeStruct %f32vec4
2072 %output_ptr = OpTypePointer Output %output_type
2073 %output = OpVariable %output_ptr Output
2074 %output_f32vec4_ptr = OpTypePointer Output %f32vec4
2075 )";
2076 
2077   EntryPoint entry_point;
2078   entry_point.name = "vmain";
2079   entry_point.execution_model = "Vertex";
2080   entry_point.interfaces = "%output";
2081   entry_point.body = R"(
2082 %val1 = OpFunctionCall %void %foo
2083 )";
2084   generator.entry_points_.push_back(std::move(entry_point));
2085 
2086   entry_point.name = "fmain";
2087   entry_point.execution_model = "Fragment";
2088   entry_point.interfaces = "%output";
2089   entry_point.execution_modes = "OpExecutionMode %fmain OriginUpperLeft";
2090   entry_point.body = R"(
2091 %val2 = OpFunctionCall %void %foo
2092 )";
2093   generator.entry_points_.push_back(std::move(entry_point));
2094 
2095   generator.add_at_the_end_ = R"(
2096 %foo = OpFunction %void None %func
2097 %foo_entry = OpLabel
2098 %position = OpAccessChain %output_f32vec4_ptr %output %u32_0
2099 OpStore %position %f32vec4_0123
2100 OpReturn
2101 OpFunctionEnd
2102 )";
2103 
2104   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
2105   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2106   EXPECT_THAT(getDiagnosticString(),
2107               HasSubstr("Vulkan spec allows BuiltIn Position to be used only "
2108                         "with Vertex, TessellationControl, "
2109                         "TessellationEvaluation or Geometry execution models"));
2110   EXPECT_THAT(getDiagnosticString(),
2111               HasSubstr("called with execution model Fragment"));
2112 }
2113 
TEST_F(ValidateBuiltIns,FragmentFragDepthNoDepthReplacing)2114 TEST_F(ValidateBuiltIns, FragmentFragDepthNoDepthReplacing) {
2115   CodeGenerator generator = GetDefaultShaderCodeGenerator();
2116   generator.before_types_ = R"(
2117 OpMemberDecorate %output_type 0 BuiltIn FragDepth
2118 )";
2119 
2120   generator.after_types_ = R"(
2121 %output_type = OpTypeStruct %f32
2122 %output_ptr = OpTypePointer Output %output_type
2123 %output = OpVariable %output_ptr Output
2124 %output_f32_ptr = OpTypePointer Output %f32
2125 )";
2126 
2127   EntryPoint entry_point;
2128   entry_point.name = "main";
2129   entry_point.execution_model = "Fragment";
2130   entry_point.interfaces = "%output";
2131   entry_point.execution_modes = "OpExecutionMode %main OriginUpperLeft";
2132   entry_point.body = R"(
2133 %val2 = OpFunctionCall %void %foo
2134 )";
2135   generator.entry_points_.push_back(std::move(entry_point));
2136 
2137   generator.add_at_the_end_ = R"(
2138 %foo = OpFunction %void None %func
2139 %foo_entry = OpLabel
2140 %frag_depth = OpAccessChain %output_f32_ptr %output %u32_0
2141 OpStore %frag_depth %f32_1
2142 OpReturn
2143 OpFunctionEnd
2144 )";
2145 
2146   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
2147   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2148   EXPECT_THAT(getDiagnosticString(),
2149               HasSubstr("Vulkan spec requires DepthReplacing execution mode to "
2150                         "be declared when using BuiltIn FragDepth"));
2151 }
2152 
TEST_F(ValidateBuiltIns,FragmentFragDepthOneMainHasDepthReplacingOtherHasnt)2153 TEST_F(ValidateBuiltIns, FragmentFragDepthOneMainHasDepthReplacingOtherHasnt) {
2154   CodeGenerator generator = GetDefaultShaderCodeGenerator();
2155   generator.before_types_ = R"(
2156 OpMemberDecorate %output_type 0 BuiltIn FragDepth
2157 )";
2158 
2159   generator.after_types_ = R"(
2160 %output_type = OpTypeStruct %f32
2161 %output_ptr = OpTypePointer Output %output_type
2162 %output = OpVariable %output_ptr Output
2163 %output_f32_ptr = OpTypePointer Output %f32
2164 )";
2165 
2166   EntryPoint entry_point;
2167   entry_point.name = "main_d_r";
2168   entry_point.execution_model = "Fragment";
2169   entry_point.interfaces = "%output";
2170   entry_point.execution_modes =
2171       "OpExecutionMode %main_d_r OriginUpperLeft\n"
2172       "OpExecutionMode %main_d_r DepthReplacing";
2173   entry_point.body = R"(
2174 %val2 = OpFunctionCall %void %foo
2175 )";
2176   generator.entry_points_.push_back(std::move(entry_point));
2177 
2178   entry_point.name = "main_no_d_r";
2179   entry_point.execution_model = "Fragment";
2180   entry_point.interfaces = "%output";
2181   entry_point.execution_modes = "OpExecutionMode %main_no_d_r OriginUpperLeft";
2182   entry_point.body = R"(
2183 %val3 = OpFunctionCall %void %foo
2184 )";
2185   generator.entry_points_.push_back(std::move(entry_point));
2186 
2187   generator.add_at_the_end_ = R"(
2188 %foo = OpFunction %void None %func
2189 %foo_entry = OpLabel
2190 %frag_depth = OpAccessChain %output_f32_ptr %output %u32_0
2191 OpStore %frag_depth %f32_1
2192 OpReturn
2193 OpFunctionEnd
2194 )";
2195 
2196   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
2197   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2198   EXPECT_THAT(getDiagnosticString(),
2199               HasSubstr("Vulkan spec requires DepthReplacing execution mode to "
2200                         "be declared when using BuiltIn FragDepth"));
2201 }
2202 
TEST_F(ValidateBuiltIns,AllowInstanceIdWithIntersectionShader)2203 TEST_F(ValidateBuiltIns, AllowInstanceIdWithIntersectionShader) {
2204   CodeGenerator generator = GetDefaultShaderCodeGenerator();
2205   generator.capabilities_ += R"(
2206 OpCapability RayTracingNV
2207 )";
2208 
2209   generator.extensions_ = R"(
2210 OpExtension "SPV_NV_ray_tracing"
2211 )";
2212 
2213   generator.before_types_ = R"(
2214 OpMemberDecorate %input_type 0 BuiltIn InstanceId
2215 )";
2216 
2217   generator.after_types_ = R"(
2218 %input_type = OpTypeStruct %u32
2219 %input_ptr = OpTypePointer Input %input_type
2220 %input = OpVariable %input_ptr Input
2221 )";
2222 
2223   EntryPoint entry_point;
2224   entry_point.name = "main_d_r";
2225   entry_point.execution_model = "IntersectionNV";
2226   entry_point.interfaces = "%input";
2227   entry_point.body = R"(
2228 %val2 = OpFunctionCall %void %foo
2229 )";
2230   generator.entry_points_.push_back(std::move(entry_point));
2231 
2232   generator.add_at_the_end_ = R"(
2233 %foo = OpFunction %void None %func
2234 %foo_entry = OpLabel
2235 OpReturn
2236 OpFunctionEnd
2237 )";
2238 
2239   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
2240   EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2241 }
2242 
TEST_F(ValidateBuiltIns,DisallowInstanceIdWithRayGenShader)2243 TEST_F(ValidateBuiltIns, DisallowInstanceIdWithRayGenShader) {
2244   CodeGenerator generator = GetDefaultShaderCodeGenerator();
2245   generator.capabilities_ += R"(
2246 OpCapability RayTracingNV
2247 )";
2248 
2249   generator.extensions_ = R"(
2250 OpExtension "SPV_NV_ray_tracing"
2251 )";
2252 
2253   generator.before_types_ = R"(
2254 OpMemberDecorate %input_type 0 BuiltIn InstanceId
2255 )";
2256 
2257   generator.after_types_ = R"(
2258 %input_type = OpTypeStruct %u32
2259 %input_ptr = OpTypePointer Input %input_type
2260 %input_ptr_u32 = OpTypePointer Input %u32
2261 %input = OpVariable %input_ptr Input
2262 )";
2263 
2264   EntryPoint entry_point;
2265   entry_point.name = "main_d_r";
2266   entry_point.execution_model = "RayGenerationNV";
2267   entry_point.interfaces = "%input";
2268   entry_point.body = R"(
2269 %input_member = OpAccessChain %input_ptr_u32 %input %u32_0
2270 )";
2271   generator.entry_points_.push_back(std::move(entry_point));
2272 
2273   CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
2274   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2275   EXPECT_THAT(getDiagnosticString(),
2276               HasSubstr("Vulkan spec allows BuiltIn InstanceId to be used "
2277                         "only with IntersectionNV, ClosestHitNV and "
2278                         "AnyHitNV execution models"));
2279 }
2280 
2281 }  // namespace
2282 }  // namespace val
2283 }  // namespace spvtools
2284