val_storage_test.cpp 21 KB

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