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