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::__anonbcd125c10111::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