• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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