val_storage_test.cpp 21 KB

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