1 // Copyright (c) 2015-2016 The Khronos Group Inc.
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 // Validation tests for OpVariable storage class
16
17 #include <sstream>
18 #include <string>
19 #include <tuple>
20
21 #include "gmock/gmock.h"
22 #include "test/val/val_fixtures.h"
23
24 namespace spvtools {
25 namespace val {
26 namespace {
27
28 using ::testing::HasSubstr;
29 using ::testing::Values;
30 using ValidateStorage = spvtest::ValidateBase<std::string>;
31 using ValidateStorageExecutionModel = spvtest::ValidateBase<std::string>;
32
TEST_F(ValidateStorage,FunctionStorageInsideFunction)33 TEST_F(ValidateStorage, FunctionStorageInsideFunction) {
34 char str[] = R"(
35 OpCapability Shader
36 OpCapability Linkage
37 OpMemoryModel Logical GLSL450
38 %intt = OpTypeInt 32 1
39 %voidt = OpTypeVoid
40 %vfunct = OpTypeFunction %voidt
41 %ptrt = OpTypePointer Function %intt
42 %func = OpFunction %voidt None %vfunct
43 %funcl = OpLabel
44 %var = OpVariable %ptrt Function
45 OpReturn
46 OpFunctionEnd
47 )";
48
49 CompileSuccessfully(str);
50 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
51 }
52
TEST_F(ValidateStorage,FunctionStorageOutsideFunction)53 TEST_F(ValidateStorage, FunctionStorageOutsideFunction) {
54 char str[] = R"(
55 OpCapability Shader
56 OpCapability Linkage
57 OpMemoryModel Logical GLSL450
58 %intt = OpTypeInt 32 1
59 %voidt = OpTypeVoid
60 %vfunct = OpTypeFunction %voidt
61 %ptrt = OpTypePointer Function %intt
62 %var = OpVariable %ptrt Function
63 %func = OpFunction %voidt None %vfunct
64 %funcl = OpLabel
65 OpReturn
66 OpFunctionEnd
67 )";
68
69 CompileSuccessfully(str);
70 ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions());
71 EXPECT_THAT(getDiagnosticString(),
72 HasSubstr("Variables can not have a function[7] storage class "
73 "outside of a function"));
74 }
75
TEST_F(ValidateStorage,OtherStorageOutsideFunction)76 TEST_F(ValidateStorage, OtherStorageOutsideFunction) {
77 char str[] = R"(
78 OpCapability Shader
79 OpCapability Kernel
80 OpCapability AtomicStorage
81 OpCapability Linkage
82 OpMemoryModel Logical GLSL450
83 %intt = OpTypeInt 32 0
84 %voidt = OpTypeVoid
85 %vfunct = OpTypeFunction %voidt
86 %uniconptrt = OpTypePointer UniformConstant %intt
87 %unicon = OpVariable %uniconptrt UniformConstant
88 %inputptrt = OpTypePointer Input %intt
89 %input = OpVariable %inputptrt Input
90 %unifptrt = OpTypePointer Uniform %intt
91 %unif = OpVariable %unifptrt Uniform
92 %outputptrt = OpTypePointer Output %intt
93 %output = OpVariable %outputptrt Output
94 %wgroupptrt = OpTypePointer Workgroup %intt
95 %wgroup = OpVariable %wgroupptrt Workgroup
96 %xwgrpptrt = OpTypePointer CrossWorkgroup %intt
97 %xwgrp = OpVariable %xwgrpptrt CrossWorkgroup
98 %privptrt = OpTypePointer Private %intt
99 %priv = OpVariable %privptrt Private
100 %pushcoptrt = OpTypePointer PushConstant %intt
101 %pushco = OpVariable %pushcoptrt PushConstant
102 %atomcptrt = OpTypePointer AtomicCounter %intt
103 %atomct = OpVariable %atomcptrt AtomicCounter
104 %imageptrt = OpTypePointer Image %intt
105 %image = OpVariable %imageptrt Image
106 %func = OpFunction %voidt None %vfunct
107 %funcl = OpLabel
108 OpReturn
109 OpFunctionEnd
110 )";
111
112 CompileSuccessfully(str);
113 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
114 }
115
116 // clang-format off
TEST_P(ValidateStorage,OtherStorageInsideFunction)117 TEST_P(ValidateStorage, OtherStorageInsideFunction) {
118 std::stringstream ss;
119 ss << R"(
120 OpCapability Shader
121 OpCapability Kernel
122 OpCapability AtomicStorage
123 OpCapability Linkage
124 OpMemoryModel Logical GLSL450
125 %intt = OpTypeInt 32 0
126 %voidt = OpTypeVoid
127 %vfunct = OpTypeFunction %voidt
128 %ptrt = OpTypePointer Function %intt
129 %func = OpFunction %voidt None %vfunct
130 %funcl = OpLabel
131 %var = OpVariable %ptrt )" << GetParam() << R"(
132 OpReturn
133 OpFunctionEnd
134 )";
135
136 CompileSuccessfully(ss.str());
137 ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions());
138 EXPECT_THAT(getDiagnosticString(), HasSubstr(
139 "Variables must have a function[7] storage class inside of a function"));
140 }
141
142 INSTANTIATE_TEST_SUITE_P(MatrixOp, ValidateStorage,
143 ::testing::Values(
144 "Input",
145 "Uniform",
146 "Output",
147 "Workgroup",
148 "CrossWorkgroup",
149 "Private",
150 "PushConstant",
151 "AtomicCounter",
152 "Image"));
153 // clang-format on
154
TEST_F(ValidateStorage,GenericVariableOutsideFunction)155 TEST_F(ValidateStorage, GenericVariableOutsideFunction) {
156 const auto str = R"(
157 OpCapability Kernel
158 OpCapability Linkage
159 OpCapability GenericPointer
160 OpMemoryModel Logical OpenCL
161 %intt = OpTypeInt 32 0
162 %ptrt = OpTypePointer Function %intt
163 %var = OpVariable %ptrt Generic
164 )";
165 CompileSuccessfully(str);
166 ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
167 EXPECT_THAT(getDiagnosticString(),
168 HasSubstr("OpVariable storage class cannot be Generic"));
169 }
170
TEST_F(ValidateStorage,GenericVariableInsideFunction)171 TEST_F(ValidateStorage, GenericVariableInsideFunction) {
172 const auto str = R"(
173 OpCapability Shader
174 OpCapability Linkage
175 OpCapability GenericPointer
176 OpMemoryModel Logical GLSL450
177 %intt = OpTypeInt 32 1
178 %voidt = OpTypeVoid
179 %vfunct = OpTypeFunction %voidt
180 %ptrt = OpTypePointer Function %intt
181 %func = OpFunction %voidt None %vfunct
182 %funcl = OpLabel
183 %var = OpVariable %ptrt Generic
184 OpReturn
185 OpFunctionEnd
186 )";
187 CompileSuccessfully(str);
188 EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
189 EXPECT_THAT(getDiagnosticString(),
190 HasSubstr("OpVariable storage class cannot be Generic"));
191 }
192
TEST_F(ValidateStorage,RelaxedLogicalPointerFunctionParam)193 TEST_F(ValidateStorage, RelaxedLogicalPointerFunctionParam) {
194 const auto str = R"(
195 OpCapability Shader
196 OpCapability Linkage
197 OpMemoryModel Logical GLSL450
198 %intt = OpTypeInt 32 1
199 %voidt = OpTypeVoid
200 %ptrt = OpTypePointer Function %intt
201 %vfunct = OpTypeFunction %voidt
202 %vifunct = OpTypeFunction %voidt %ptrt
203 %wgroupptrt = OpTypePointer Workgroup %intt
204 %wgroup = OpVariable %wgroupptrt Workgroup
205 %main = OpFunction %voidt None %vfunct
206 %mainl = OpLabel
207 %ret = OpFunctionCall %voidt %func %wgroup
208 OpReturn
209 OpFunctionEnd
210 %func = OpFunction %voidt None %vifunct
211 %arg = OpFunctionParameter %ptrt
212 %funcl = OpLabel
213 OpReturn
214 OpFunctionEnd
215 )";
216 CompileSuccessfully(str);
217 getValidatorOptions()->before_hlsl_legalization = true;
218 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
219 }
220
TEST_F(ValidateStorage,RelaxedLogicalPointerFunctionParamBad)221 TEST_F(ValidateStorage, RelaxedLogicalPointerFunctionParamBad) {
222 const auto str = R"(
223 OpCapability Shader
224 OpCapability Linkage
225 OpMemoryModel Logical GLSL450
226 %floatt = OpTypeFloat 32
227 %intt = OpTypeInt 32 1
228 %voidt = OpTypeVoid
229 %ptrt = OpTypePointer Function %intt
230 %vfunct = OpTypeFunction %voidt
231 %vifunct = OpTypeFunction %voidt %ptrt
232 %wgroupptrt = OpTypePointer Workgroup %floatt
233 %wgroup = OpVariable %wgroupptrt Workgroup
234 %main = OpFunction %voidt None %vfunct
235 %mainl = OpLabel
236 %ret = OpFunctionCall %voidt %func %wgroup
237 OpReturn
238 OpFunctionEnd
239 %func = OpFunction %voidt None %vifunct
240 %arg = OpFunctionParameter %ptrt
241 %funcl = OpLabel
242 OpReturn
243 OpFunctionEnd
244 )";
245 CompileSuccessfully(str);
246 getValidatorOptions()->relax_logical_pointer = true;
247 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
248 EXPECT_THAT(getDiagnosticString(),
249 HasSubstr("OpFunctionCall Argument <id> '"));
250 }
251
GenerateExecutionModelCode(const std::string & execution_model,const std::string & storage_class,bool store)252 std::string GenerateExecutionModelCode(const std::string& execution_model,
253 const std::string& storage_class,
254 bool store) {
255 const std::string mode = (execution_model.compare("GLCompute") == 0)
256 ? "OpExecutionMode %func LocalSize 1 1 1"
257 : "";
258 const std::string operation =
259 (store) ? "OpStore %var %int0" : "%load = OpLoad %intt %var";
260 std::ostringstream ss;
261 ss << R"(
262 OpCapability Shader
263 OpCapability RayTracingKHR
264 OpExtension "SPV_KHR_ray_tracing"
265 OpMemoryModel Logical GLSL450
266 OpEntryPoint )"
267 << execution_model << R"( %func "func" %var
268 )" << mode << R"(
269 OpDecorate %var Location 0
270 %intt = OpTypeInt 32 0
271 %int0 = OpConstant %intt 0
272 %voidt = OpTypeVoid
273 %vfunct = OpTypeFunction %voidt
274 %ptr = OpTypePointer )"
275 << storage_class << R"( %intt
276 %var = OpVariable %ptr )" << storage_class << R"(
277 %func = OpFunction %voidt None %vfunct
278 %funcl = OpLabel
279 )" << operation << R"(
280 OpReturn
281 OpFunctionEnd
282 )";
283
284 return ss.str();
285 }
286
TEST_P(ValidateStorageExecutionModel,VulkanOutsideStoreFailure)287 TEST_P(ValidateStorageExecutionModel, VulkanOutsideStoreFailure) {
288 std::string execution_model = GetParam();
289 CompileSuccessfully(
290 GenerateExecutionModelCode(execution_model, "Output", true).c_str(),
291 SPV_ENV_VULKAN_1_0);
292 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
293 EXPECT_THAT(getDiagnosticString(),
294 AnyVUID("VUID-StandaloneSpirv-None-04644"));
295 EXPECT_THAT(
296 getDiagnosticString(),
297 HasSubstr("in Vulkan environment, Output Storage Class must not be used "
298 "in GLCompute, RayGenerationKHR, IntersectionKHR, AnyHitKHR, "
299 "ClosestHitKHR, MissKHR, or CallableKHR execution models"));
300 }
301
TEST_P(ValidateStorageExecutionModel,CallableDataStore)302 TEST_P(ValidateStorageExecutionModel, CallableDataStore) {
303 std::string execution_model = GetParam();
304 CompileSuccessfully(
305 GenerateExecutionModelCode(execution_model, "CallableDataKHR", true)
306 .c_str(),
307 SPV_ENV_VULKAN_1_2);
308 if (execution_model.compare("RayGenerationKHR") == 0 ||
309 execution_model.compare("ClosestHitKHR") == 0 ||
310 execution_model.compare("CallableKHR") == 0 ||
311 execution_model.compare("MissKHR") == 0) {
312 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
313 } else {
314 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
315 EXPECT_THAT(getDiagnosticString(),
316 AnyVUID("VUID-StandaloneSpirv-CallableDataKHR-04704"));
317 EXPECT_THAT(
318 getDiagnosticString(),
319 HasSubstr(
320 "CallableDataKHR Storage Class is limited to RayGenerationKHR, "
321 "ClosestHitKHR, CallableKHR, and MissKHR execution model"));
322 }
323 }
324
TEST_P(ValidateStorageExecutionModel,CallableDataLoad)325 TEST_P(ValidateStorageExecutionModel, CallableDataLoad) {
326 std::string execution_model = GetParam();
327 CompileSuccessfully(
328 GenerateExecutionModelCode(execution_model, "CallableDataKHR", false)
329 .c_str(),
330 SPV_ENV_VULKAN_1_2);
331 if (execution_model.compare("RayGenerationKHR") == 0 ||
332 execution_model.compare("ClosestHitKHR") == 0 ||
333 execution_model.compare("CallableKHR") == 0 ||
334 execution_model.compare("MissKHR") == 0) {
335 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
336 } else {
337 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
338 EXPECT_THAT(getDiagnosticString(),
339 AnyVUID("VUID-StandaloneSpirv-CallableDataKHR-04704"));
340 EXPECT_THAT(
341 getDiagnosticString(),
342 HasSubstr(
343 "CallableDataKHR Storage Class is limited to RayGenerationKHR, "
344 "ClosestHitKHR, CallableKHR, and MissKHR execution model"));
345 }
346 }
347
TEST_P(ValidateStorageExecutionModel,IncomingCallableDataStore)348 TEST_P(ValidateStorageExecutionModel, IncomingCallableDataStore) {
349 std::string execution_model = GetParam();
350 CompileSuccessfully(GenerateExecutionModelCode(
351 execution_model, "IncomingCallableDataKHR", true)
352 .c_str(),
353 SPV_ENV_VULKAN_1_2);
354 if (execution_model.compare("CallableKHR") == 0) {
355 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
356 } else {
357 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
358 EXPECT_THAT(getDiagnosticString(),
359 AnyVUID("VUID-StandaloneSpirv-IncomingCallableDataKHR-04705"));
360 EXPECT_THAT(getDiagnosticString(),
361 HasSubstr("IncomingCallableDataKHR Storage Class is limited to "
362 "CallableKHR execution model"));
363 }
364 }
365
TEST_P(ValidateStorageExecutionModel,IncomingCallableDataLoad)366 TEST_P(ValidateStorageExecutionModel, IncomingCallableDataLoad) {
367 std::string execution_model = GetParam();
368 CompileSuccessfully(GenerateExecutionModelCode(
369 execution_model, "IncomingCallableDataKHR", false)
370 .c_str(),
371 SPV_ENV_VULKAN_1_2);
372 if (execution_model.compare("CallableKHR") == 0) {
373 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
374 } else {
375 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
376 EXPECT_THAT(getDiagnosticString(),
377 AnyVUID("VUID-StandaloneSpirv-IncomingCallableDataKHR-04705"));
378 EXPECT_THAT(getDiagnosticString(),
379 HasSubstr("IncomingCallableDataKHR Storage Class is limited to "
380 "CallableKHR execution model"));
381 }
382 }
383
TEST_P(ValidateStorageExecutionModel,RayPayloadStore)384 TEST_P(ValidateStorageExecutionModel, RayPayloadStore) {
385 std::string execution_model = GetParam();
386 CompileSuccessfully(
387 GenerateExecutionModelCode(execution_model, "RayPayloadKHR", true)
388 .c_str(),
389 SPV_ENV_VULKAN_1_2);
390 if (execution_model.compare("RayGenerationKHR") == 0 ||
391 execution_model.compare("ClosestHitKHR") == 0 ||
392 execution_model.compare("MissKHR") == 0) {
393 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
394 } else {
395 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
396 EXPECT_THAT(getDiagnosticString(),
397 AnyVUID("VUID-StandaloneSpirv-RayPayloadKHR-04698"));
398 EXPECT_THAT(
399 getDiagnosticString(),
400 HasSubstr("RayPayloadKHR Storage Class is limited to RayGenerationKHR, "
401 "ClosestHitKHR, and MissKHR execution model"));
402 }
403 }
404
TEST_P(ValidateStorageExecutionModel,RayPayloadLoad)405 TEST_P(ValidateStorageExecutionModel, RayPayloadLoad) {
406 std::string execution_model = GetParam();
407 CompileSuccessfully(
408 GenerateExecutionModelCode(execution_model, "RayPayloadKHR", false)
409 .c_str(),
410 SPV_ENV_VULKAN_1_2);
411 if (execution_model.compare("RayGenerationKHR") == 0 ||
412 execution_model.compare("ClosestHitKHR") == 0 ||
413 execution_model.compare("MissKHR") == 0) {
414 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
415 } else {
416 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
417 EXPECT_THAT(getDiagnosticString(),
418 AnyVUID("VUID-StandaloneSpirv-RayPayloadKHR-04698"));
419 EXPECT_THAT(
420 getDiagnosticString(),
421 HasSubstr("RayPayloadKHR Storage Class is limited to RayGenerationKHR, "
422 "ClosestHitKHR, and MissKHR execution model"));
423 }
424 }
425
TEST_P(ValidateStorageExecutionModel,HitAttributeStore)426 TEST_P(ValidateStorageExecutionModel, HitAttributeStore) {
427 std::string execution_model = GetParam();
428 CompileSuccessfully(
429 GenerateExecutionModelCode(execution_model, "HitAttributeKHR", true)
430 .c_str(),
431 SPV_ENV_VULKAN_1_2);
432 if (execution_model.compare("IntersectionKHR") == 0) {
433 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
434 } else if (execution_model.compare("AnyHitKHR") == 0 ||
435 execution_model.compare("ClosestHitKHR") == 0) {
436 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
437 EXPECT_THAT(getDiagnosticString(),
438 AnyVUID("VUID-StandaloneSpirv-HitAttributeKHR-04703"));
439 EXPECT_THAT(getDiagnosticString(),
440 HasSubstr("HitAttributeKHR Storage Class variables are read "
441 "only with AnyHitKHR and ClosestHitKHR"));
442 } else {
443 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
444 EXPECT_THAT(getDiagnosticString(),
445 AnyVUID("VUID-StandaloneSpirv-HitAttributeKHR-04701"));
446 EXPECT_THAT(
447 getDiagnosticString(),
448 HasSubstr(
449 "HitAttributeKHR Storage Class is limited to IntersectionKHR, "
450 "AnyHitKHR, sand ClosestHitKHR execution model"));
451 }
452 }
453
TEST_P(ValidateStorageExecutionModel,HitAttributeLoad)454 TEST_P(ValidateStorageExecutionModel, HitAttributeLoad) {
455 std::string execution_model = GetParam();
456 CompileSuccessfully(
457 GenerateExecutionModelCode(execution_model, "HitAttributeKHR", false)
458 .c_str(),
459 SPV_ENV_VULKAN_1_2);
460 if (execution_model.compare("IntersectionKHR") == 0 ||
461 execution_model.compare("AnyHitKHR") == 0 ||
462 execution_model.compare("ClosestHitKHR") == 0) {
463 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
464 } else {
465 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
466 EXPECT_THAT(getDiagnosticString(),
467 AnyVUID("VUID-StandaloneSpirv-HitAttributeKHR-04701"));
468 EXPECT_THAT(
469 getDiagnosticString(),
470 HasSubstr(
471 "HitAttributeKHR Storage Class is limited to IntersectionKHR, "
472 "AnyHitKHR, sand ClosestHitKHR execution model"));
473 }
474 }
475
TEST_P(ValidateStorageExecutionModel,IncomingRayPayloadStore)476 TEST_P(ValidateStorageExecutionModel, IncomingRayPayloadStore) {
477 std::string execution_model = GetParam();
478 CompileSuccessfully(
479 GenerateExecutionModelCode(execution_model, "IncomingRayPayloadKHR", true)
480 .c_str(),
481 SPV_ENV_VULKAN_1_2);
482 if (execution_model.compare("AnyHitKHR") == 0 ||
483 execution_model.compare("ClosestHitKHR") == 0 ||
484 execution_model.compare("MissKHR") == 0) {
485 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
486 } else {
487 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
488 EXPECT_THAT(getDiagnosticString(),
489 AnyVUID("VUID-StandaloneSpirv-IncomingRayPayloadKHR-04699"));
490 EXPECT_THAT(
491 getDiagnosticString(),
492 HasSubstr("IncomingRayPayloadKHR Storage Class is limited to "
493 "AnyHitKHR, ClosestHitKHR, and MissKHR execution model"));
494 }
495 }
496
TEST_P(ValidateStorageExecutionModel,IncomingRayPayloadLoad)497 TEST_P(ValidateStorageExecutionModel, IncomingRayPayloadLoad) {
498 std::string execution_model = GetParam();
499 CompileSuccessfully(GenerateExecutionModelCode(execution_model,
500 "IncomingRayPayloadKHR", false)
501 .c_str(),
502 SPV_ENV_VULKAN_1_2);
503 if (execution_model.compare("AnyHitKHR") == 0 ||
504 execution_model.compare("ClosestHitKHR") == 0 ||
505 execution_model.compare("MissKHR") == 0) {
506 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
507 } else {
508 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
509 EXPECT_THAT(getDiagnosticString(),
510 AnyVUID("VUID-StandaloneSpirv-IncomingRayPayloadKHR-04699"));
511 EXPECT_THAT(
512 getDiagnosticString(),
513 HasSubstr("IncomingRayPayloadKHR Storage Class is limited to "
514 "AnyHitKHR, ClosestHitKHR, and MissKHR execution model"));
515 }
516 }
517
TEST_P(ValidateStorageExecutionModel,ShaderRecordBufferStore)518 TEST_P(ValidateStorageExecutionModel, ShaderRecordBufferStore) {
519 std::string execution_model = GetParam();
520 CompileSuccessfully(
521 GenerateExecutionModelCode(execution_model, "ShaderRecordBufferKHR", true)
522 .c_str(),
523 SPV_ENV_VULKAN_1_2);
524 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
525 EXPECT_THAT(
526 getDiagnosticString(),
527 HasSubstr("ShaderRecordBufferKHR Storage Class variables are read only"));
528 }
529
TEST_P(ValidateStorageExecutionModel,ShaderRecordBufferLoad)530 TEST_P(ValidateStorageExecutionModel, ShaderRecordBufferLoad) {
531 std::string execution_model = GetParam();
532 CompileSuccessfully(GenerateExecutionModelCode(execution_model,
533 "ShaderRecordBufferKHR", false)
534 .c_str(),
535 SPV_ENV_VULKAN_1_2);
536 if (execution_model.compare("RayGenerationKHR") == 0 ||
537 execution_model.compare("IntersectionKHR") == 0 ||
538 execution_model.compare("AnyHitKHR") == 0 ||
539 execution_model.compare("ClosestHitKHR") == 0 ||
540 execution_model.compare("CallableKHR") == 0 ||
541 execution_model.compare("MissKHR") == 0) {
542 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
543 } else {
544 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
545 EXPECT_THAT(getDiagnosticString(),
546 AnyVUID("VUID-StandaloneSpirv-ShaderRecordBufferKHR-07119"));
547 EXPECT_THAT(
548 getDiagnosticString(),
549 HasSubstr("ShaderRecordBufferKHR Storage Class is limited to "
550 "RayGenerationKHR, IntersectionKHR, AnyHitKHR, "
551 "ClosestHitKHR, CallableKHR, and MissKHR execution model"));
552 }
553 }
554
555 INSTANTIATE_TEST_SUITE_P(MatrixExecutionModel, ValidateStorageExecutionModel,
556 ::testing::Values("RayGenerationKHR",
557 "IntersectionKHR", "AnyHitKHR",
558 "ClosestHitKHR", "MissKHR",
559 "CallableKHR", "GLCompute"));
560
561 } // namespace
562 } // namespace val
563 } // namespace spvtools
564