val_barriers_test.cpp 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567
  1. // Copyright (c) 2018 Google LLC.
  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. #include <sstream>
  15. #include <string>
  16. #include "gmock/gmock.h"
  17. #include "test/unit_spirv.h"
  18. #include "test/val/val_fixtures.h"
  19. namespace spvtools {
  20. namespace val {
  21. namespace {
  22. using ::testing::HasSubstr;
  23. using ::testing::Not;
  24. using ValidateBarriers = spvtest::ValidateBase<bool>;
  25. std::string GenerateShaderCodeImpl(
  26. const std::string& body, const std::string& capabilities_and_extensions,
  27. const std::string& definitions, const std::string& execution_model,
  28. const std::string& memory_model) {
  29. std::ostringstream ss;
  30. ss << R"(
  31. OpCapability Shader
  32. )";
  33. ss << capabilities_and_extensions;
  34. ss << memory_model << std::endl;
  35. ss << "OpEntryPoint " << execution_model << " %main \"main\"\n";
  36. if (execution_model == "Fragment") {
  37. ss << "OpExecutionMode %main OriginUpperLeft\n";
  38. } else if (execution_model == "Geometry") {
  39. ss << "OpExecutionMode %main InputPoints\n";
  40. ss << "OpExecutionMode %main OutputPoints\n";
  41. } else if (execution_model == "GLCompute") {
  42. ss << "OpExecutionMode %main LocalSize 1 1 1\n";
  43. }
  44. ss << R"(
  45. %void = OpTypeVoid
  46. %func = OpTypeFunction %void
  47. %bool = OpTypeBool
  48. %f32 = OpTypeFloat 32
  49. %u32 = OpTypeInt 32 0
  50. %f32_0 = OpConstant %f32 0
  51. %f32_1 = OpConstant %f32 1
  52. %u32_0 = OpConstant %u32 0
  53. %u32_1 = OpConstant %u32 1
  54. %u32_4 = OpConstant %u32 4
  55. )";
  56. ss << definitions;
  57. ss << R"(
  58. %cross_device = OpConstant %u32 0
  59. %device = OpConstant %u32 1
  60. %workgroup = OpConstant %u32 2
  61. %subgroup = OpConstant %u32 3
  62. %invocation = OpConstant %u32 4
  63. %queuefamily = OpConstant %u32 5
  64. %shadercall = OpConstant %u32 6
  65. %none = OpConstant %u32 0
  66. %acquire = OpConstant %u32 2
  67. %release = OpConstant %u32 4
  68. %acquire_release = OpConstant %u32 8
  69. %acquire_and_release = OpConstant %u32 6
  70. %sequentially_consistent = OpConstant %u32 16
  71. %acquire_release_uniform_workgroup = OpConstant %u32 328
  72. %acquire_uniform_workgroup = OpConstant %u32 322
  73. %release_uniform_workgroup = OpConstant %u32 324
  74. %acquire_and_release_uniform = OpConstant %u32 70
  75. %acquire_release_subgroup = OpConstant %u32 136
  76. %acquire_release_workgroup = OpConstant %u32 264
  77. %uniform = OpConstant %u32 64
  78. %uniform_workgroup = OpConstant %u32 320
  79. %workgroup_memory = OpConstant %u32 256
  80. %image_memory = OpConstant %u32 2048
  81. %uniform_image_memory = OpConstant %u32 2112
  82. %main = OpFunction %void None %func
  83. %main_entry = OpLabel
  84. )";
  85. ss << body;
  86. ss << R"(
  87. OpReturn
  88. OpFunctionEnd)";
  89. return ss.str();
  90. }
  91. std::string GenerateShaderCode(
  92. const std::string& body,
  93. const std::string& capabilities_and_extensions = "",
  94. const std::string& execution_model = "GLCompute") {
  95. const std::string int64_capability = R"(
  96. OpCapability Int64
  97. )";
  98. const std::string int64_declarations = R"(
  99. %u64 = OpTypeInt 64 0
  100. %u64_0 = OpConstant %u64 0
  101. %u64_1 = OpConstant %u64 1
  102. )";
  103. const std::string memory_model = "OpMemoryModel Logical GLSL450";
  104. return GenerateShaderCodeImpl(
  105. body, int64_capability + capabilities_and_extensions, int64_declarations,
  106. execution_model, memory_model);
  107. }
  108. std::string GenerateVulkanVertexShaderCode(
  109. const std::string& body,
  110. const std::string& capabilities_and_extensions = "",
  111. const std::string& execution_model = "Vertex") {
  112. const std::string memory_model = "OpMemoryModel Logical GLSL450";
  113. return GenerateShaderCodeImpl(body, capabilities_and_extensions, "",
  114. execution_model, memory_model);
  115. }
  116. std::string GenerateKernelCode(
  117. const std::string& body,
  118. const std::string& capabilities_and_extensions = "") {
  119. std::ostringstream ss;
  120. ss << R"(
  121. OpCapability Addresses
  122. OpCapability Kernel
  123. OpCapability Linkage
  124. OpCapability Int64
  125. OpCapability NamedBarrier
  126. )";
  127. ss << capabilities_and_extensions;
  128. ss << R"(
  129. OpMemoryModel Physical32 OpenCL
  130. %void = OpTypeVoid
  131. %func = OpTypeFunction %void
  132. %bool = OpTypeBool
  133. %f32 = OpTypeFloat 32
  134. %u32 = OpTypeInt 32 0
  135. %u64 = OpTypeInt 64 0
  136. %f32_0 = OpConstant %f32 0
  137. %f32_1 = OpConstant %f32 1
  138. %f32_4 = OpConstant %f32 4
  139. %u32_0 = OpConstant %u32 0
  140. %u32_1 = OpConstant %u32 1
  141. %u32_4 = OpConstant %u32 4
  142. %u64_0 = OpConstant %u64 0
  143. %u64_1 = OpConstant %u64 1
  144. %u64_4 = OpConstant %u64 4
  145. %cross_device = OpConstant %u32 0
  146. %device = OpConstant %u32 1
  147. %workgroup = OpConstant %u32 2
  148. %subgroup = OpConstant %u32 3
  149. %invocation = OpConstant %u32 4
  150. %none = OpConstant %u32 0
  151. %acquire = OpConstant %u32 2
  152. %release = OpConstant %u32 4
  153. %acquire_release = OpConstant %u32 8
  154. %acquire_and_release = OpConstant %u32 6
  155. %sequentially_consistent = OpConstant %u32 16
  156. %acquire_release_workgroup = OpConstant %u32 264
  157. %named_barrier = OpTypeNamedBarrier
  158. %main = OpFunction %void None %func
  159. %main_entry = OpLabel
  160. )";
  161. ss << body;
  162. ss << R"(
  163. OpReturn
  164. OpFunctionEnd)";
  165. return ss.str();
  166. }
  167. TEST_F(ValidateBarriers, OpControlBarrierGLComputeSuccess) {
  168. const std::string body = R"(
  169. OpControlBarrier %device %device %none
  170. OpControlBarrier %workgroup %workgroup %acquire
  171. OpControlBarrier %workgroup %device %release
  172. OpControlBarrier %cross_device %cross_device %acquire_release
  173. OpControlBarrier %cross_device %cross_device %sequentially_consistent
  174. OpControlBarrier %cross_device %cross_device %acquire_release_uniform_workgroup
  175. )";
  176. CompileSuccessfully(GenerateShaderCode(body));
  177. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  178. }
  179. TEST_F(ValidateBarriers, OpControlBarrierKernelSuccess) {
  180. const std::string body = R"(
  181. OpControlBarrier %device %device %none
  182. OpControlBarrier %workgroup %workgroup %acquire
  183. OpControlBarrier %workgroup %device %release
  184. OpControlBarrier %cross_device %cross_device %acquire_release
  185. OpControlBarrier %cross_device %cross_device %sequentially_consistent
  186. OpControlBarrier %cross_device %cross_device %acquire_release_workgroup
  187. )";
  188. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  189. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  190. }
  191. TEST_F(ValidateBarriers, OpControlBarrierTesselationControlSuccess) {
  192. const std::string body = R"(
  193. OpControlBarrier %device %device %none
  194. OpControlBarrier %workgroup %workgroup %acquire
  195. OpControlBarrier %workgroup %device %release
  196. OpControlBarrier %cross_device %cross_device %acquire_release
  197. OpControlBarrier %cross_device %cross_device %sequentially_consistent
  198. OpControlBarrier %cross_device %cross_device %acquire_release_uniform_workgroup
  199. )";
  200. CompileSuccessfully(GenerateShaderCode(body, "OpCapability Tessellation\n",
  201. "TessellationControl"));
  202. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  203. }
  204. TEST_F(ValidateBarriers, OpControlBarrierVulkanSuccess) {
  205. const std::string body = R"(
  206. OpControlBarrier %workgroup %device %none
  207. OpControlBarrier %workgroup %workgroup %acquire_release_uniform_workgroup
  208. )";
  209. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
  210. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  211. }
  212. TEST_F(ValidateBarriers, OpControlBarrierExecutionModelFragmentSpirv12) {
  213. const std::string body = R"(
  214. OpControlBarrier %device %device %none
  215. )";
  216. CompileSuccessfully(GenerateShaderCode(body, "", "Fragment"),
  217. SPV_ENV_UNIVERSAL_1_2);
  218. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_2));
  219. EXPECT_THAT(
  220. getDiagnosticString(),
  221. HasSubstr("OpControlBarrier requires one of the following "
  222. "Execution Models: TessellationControl, GLCompute, Kernel, "
  223. "MeshNV or TaskNV"));
  224. }
  225. TEST_F(ValidateBarriers, OpControlBarrierExecutionModelFragmentSpirv13) {
  226. const std::string body = R"(
  227. OpControlBarrier %device %device %none
  228. )";
  229. CompileSuccessfully(GenerateShaderCode(body, "", "Fragment"),
  230. SPV_ENV_UNIVERSAL_1_3);
  231. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  232. }
  233. TEST_F(ValidateBarriers, OpControlBarrierFloatExecutionScope) {
  234. const std::string body = R"(
  235. OpControlBarrier %f32_1 %device %none
  236. )";
  237. CompileSuccessfully(GenerateShaderCode(body));
  238. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  239. EXPECT_THAT(getDiagnosticString(),
  240. HasSubstr("ControlBarrier: expected scope to be a 32-bit int"));
  241. }
  242. TEST_F(ValidateBarriers, OpControlBarrierU64ExecutionScope) {
  243. const std::string body = R"(
  244. OpControlBarrier %u64_1 %device %none
  245. )";
  246. CompileSuccessfully(GenerateShaderCode(body));
  247. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  248. EXPECT_THAT(getDiagnosticString(),
  249. HasSubstr("ControlBarrier: expected scope to be a 32-bit int"));
  250. }
  251. TEST_F(ValidateBarriers, OpControlBarrierFloatMemoryScope) {
  252. const std::string body = R"(
  253. OpControlBarrier %device %f32_1 %none
  254. )";
  255. CompileSuccessfully(GenerateShaderCode(body));
  256. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  257. EXPECT_THAT(getDiagnosticString(),
  258. HasSubstr("ControlBarrier: expected scope to be a 32-bit int"));
  259. }
  260. TEST_F(ValidateBarriers, OpControlBarrierU64MemoryScope) {
  261. const std::string body = R"(
  262. OpControlBarrier %device %u64_1 %none
  263. )";
  264. CompileSuccessfully(GenerateShaderCode(body));
  265. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  266. EXPECT_THAT(getDiagnosticString(),
  267. HasSubstr("ControlBarrier: expected scope to be a 32-bit int"));
  268. }
  269. TEST_F(ValidateBarriers, OpControlBarrierFloatMemorySemantics) {
  270. const std::string body = R"(
  271. OpControlBarrier %device %device %f32_0
  272. )";
  273. CompileSuccessfully(GenerateShaderCode(body));
  274. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  275. EXPECT_THAT(
  276. getDiagnosticString(),
  277. HasSubstr(
  278. "ControlBarrier: expected Memory Semantics to be a 32-bit int"));
  279. }
  280. TEST_F(ValidateBarriers, OpControlBarrierU64MemorySemantics) {
  281. const std::string body = R"(
  282. OpControlBarrier %device %device %u64_0
  283. )";
  284. CompileSuccessfully(GenerateShaderCode(body));
  285. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  286. EXPECT_THAT(
  287. getDiagnosticString(),
  288. HasSubstr(
  289. "ControlBarrier: expected Memory Semantics to be a 32-bit int"));
  290. }
  291. TEST_F(ValidateBarriers, OpControlBarrierVulkanExecutionScopeDevice) {
  292. const std::string body = R"(
  293. OpControlBarrier %device %workgroup %none
  294. )";
  295. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
  296. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  297. EXPECT_THAT(getDiagnosticString(),
  298. AnyVUID("VUID-StandaloneSpirv-None-04636"));
  299. EXPECT_THAT(getDiagnosticString(),
  300. HasSubstr("ControlBarrier: in Vulkan environment Execution Scope "
  301. "is limited to Workgroup and Subgroup"));
  302. }
  303. TEST_F(ValidateBarriers, OpControlBarrierVulkanMemoryScopeSubgroup) {
  304. const std::string body = R"(
  305. OpControlBarrier %subgroup %subgroup %none
  306. )";
  307. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
  308. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  309. EXPECT_THAT(getDiagnosticString(),
  310. AnyVUID("VUID-StandaloneSpirv-SubgroupVoteKHR-06997"));
  311. EXPECT_THAT(
  312. getDiagnosticString(),
  313. HasSubstr(
  314. "ControlBarrier: in Vulkan 1.0 environment Memory Scope is can not "
  315. "be Subgroup without SubgroupBallotKHR or SubgroupVoteKHR declared"));
  316. }
  317. TEST_F(ValidateBarriers, OpControlBarrierVulkanMemoryScopeSubgroupVoteKHR) {
  318. const std::string capabilities = R"(
  319. OpCapability SubgroupVoteKHR
  320. OpExtension "SPV_KHR_subgroup_vote"
  321. )";
  322. const std::string body = R"(
  323. OpControlBarrier %subgroup %subgroup %none
  324. )";
  325. CompileSuccessfully(GenerateShaderCode(body, capabilities),
  326. SPV_ENV_VULKAN_1_0);
  327. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  328. }
  329. TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1MemoryScopeSubgroup) {
  330. const std::string body = R"(
  331. OpControlBarrier %subgroup %subgroup %none
  332. )";
  333. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_1);
  334. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  335. }
  336. TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1MemoryScopeCrossDevice) {
  337. const std::string body = R"(
  338. OpControlBarrier %subgroup %cross_device %none
  339. )";
  340. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_1);
  341. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  342. EXPECT_THAT(getDiagnosticString(),
  343. AnyVUID("VUID-StandaloneSpirv-None-04638"));
  344. EXPECT_THAT(getDiagnosticString(),
  345. HasSubstr("ControlBarrier: in Vulkan environment Memory Scope is "
  346. "limited to Device, QueueFamily, Workgroup, "
  347. "ShaderCallKHR, Subgroup, or Invocation"));
  348. }
  349. TEST_F(ValidateBarriers,
  350. OpControlBarrierVulkan1p1WorkgroupNonComputeMemoryFailure) {
  351. const std::string body = R"(
  352. OpControlBarrier %subgroup %workgroup %acquire
  353. )";
  354. CompileSuccessfully(GenerateVulkanVertexShaderCode(body), SPV_ENV_VULKAN_1_1);
  355. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  356. EXPECT_THAT(getDiagnosticString(),
  357. AnyVUID("VUID-StandaloneSpirv-None-07321"));
  358. EXPECT_THAT(
  359. getDiagnosticString(),
  360. HasSubstr("Workgroup Memory Scope is limited to MeshNV, "
  361. "TaskNV, MeshEXT, TaskEXT, TessellationControl, and GLCompute "
  362. "execution model"));
  363. }
  364. TEST_F(ValidateBarriers,
  365. OpControlBarrierVulkan1p1WorkgroupNonComputeExecutionFailure) {
  366. const std::string body = R"(
  367. OpControlBarrier %workgroup %subgroup %acquire
  368. )";
  369. CompileSuccessfully(GenerateVulkanVertexShaderCode(body), SPV_ENV_VULKAN_1_1);
  370. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  371. EXPECT_THAT(getDiagnosticString(),
  372. AnyVUID("VUID-StandaloneSpirv-None-04637"));
  373. EXPECT_THAT(getDiagnosticString(),
  374. HasSubstr("in Vulkan environment, Workgroup execution scope is "
  375. "only for TaskNV, MeshNV, TaskEXT, MeshEXT, "
  376. "TessellationControl, and GLCompute execution models"));
  377. }
  378. TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1WorkgroupComputeSuccess) {
  379. const std::string body = R"(
  380. OpControlBarrier %workgroup %workgroup %acquire
  381. )";
  382. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_1);
  383. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  384. }
  385. TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1WorkgroupNonComputeSuccess) {
  386. const std::string body = R"(
  387. OpControlBarrier %subgroup %subgroup %acquire
  388. )";
  389. CompileSuccessfully(GenerateVulkanVertexShaderCode(body), SPV_ENV_VULKAN_1_1);
  390. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  391. }
  392. TEST_F(ValidateBarriers, OpControlBarrierVulkanInvocationSuccess) {
  393. const std::string body = R"(
  394. OpControlBarrier %workgroup %invocation %none
  395. )";
  396. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
  397. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  398. }
  399. TEST_F(ValidateBarriers, OpControlBarrierVulkanInvocationFailure) {
  400. const std::string body = R"(
  401. OpControlBarrier %workgroup %invocation %acquire
  402. )";
  403. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
  404. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  405. EXPECT_THAT(getDiagnosticString(),
  406. AnyVUID("VUID-StandaloneSpirv-None-04641"));
  407. EXPECT_THAT(
  408. getDiagnosticString(),
  409. HasSubstr("ControlBarrier: Vulkan specification requires Memory "
  410. "Semantics to be None if used with Invocation Memory Scope"));
  411. }
  412. TEST_F(ValidateBarriers, OpControlBarrierAcquireAndRelease) {
  413. const std::string body = R"(
  414. OpControlBarrier %device %device %acquire_and_release_uniform
  415. )";
  416. CompileSuccessfully(GenerateShaderCode(body));
  417. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  418. EXPECT_THAT(getDiagnosticString(),
  419. HasSubstr("ControlBarrier: Memory Semantics can have at most one "
  420. "of the following bits set: Acquire, Release, "
  421. "AcquireRelease or SequentiallyConsistent"));
  422. }
  423. // TODO([email protected]): the corresponding check fails Vulkan CTS,
  424. // reenable once fixed.
  425. TEST_F(ValidateBarriers, DISABLED_OpControlBarrierVulkanSubgroupStorageClass) {
  426. const std::string body = R"(
  427. OpControlBarrier %workgroup %device %acquire_release_subgroup
  428. )";
  429. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
  430. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  431. EXPECT_THAT(
  432. getDiagnosticString(),
  433. HasSubstr(
  434. "ControlBarrier: expected Memory Semantics to include a "
  435. "Vulkan-supported storage class if Memory Semantics is not None"));
  436. }
  437. TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionFragment1p1) {
  438. const std::string body = R"(
  439. OpControlBarrier %subgroup %subgroup %acquire_release_subgroup
  440. )";
  441. CompileSuccessfully(GenerateShaderCode(body, "", "Fragment"),
  442. SPV_ENV_VULKAN_1_1);
  443. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  444. }
  445. TEST_F(ValidateBarriers, OpControlBarrierWorkgroupExecutionFragment1p1) {
  446. const std::string body = R"(
  447. OpControlBarrier %workgroup %workgroup %acquire_release
  448. )";
  449. CompileSuccessfully(GenerateShaderCode(body, "", "Fragment"),
  450. SPV_ENV_VULKAN_1_1);
  451. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  452. EXPECT_THAT(getDiagnosticString(),
  453. AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-04682"));
  454. EXPECT_THAT(
  455. getDiagnosticString(),
  456. HasSubstr(
  457. "OpControlBarrier execution scope must be Subgroup for Fragment, "
  458. "Vertex, Geometry, TessellationEvaluation, RayGeneration, "
  459. "Intersection, AnyHit, ClosestHit, and Miss execution models"));
  460. }
  461. TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionFragment1p0) {
  462. const std::string body = R"(
  463. OpControlBarrier %subgroup %workgroup %acquire_release
  464. )";
  465. CompileSuccessfully(GenerateShaderCode(body, "", "Fragment"),
  466. SPV_ENV_VULKAN_1_0);
  467. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  468. EXPECT_THAT(getDiagnosticString(),
  469. HasSubstr("OpControlBarrier requires one of the following "
  470. "Execution "
  471. "Models: TessellationControl, GLCompute, Kernel, "
  472. "MeshNV or TaskNV"));
  473. }
  474. TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionVertex1p1) {
  475. const std::string body = R"(
  476. OpControlBarrier %subgroup %subgroup %acquire_release_subgroup
  477. )";
  478. CompileSuccessfully(GenerateShaderCode(body, "", "Vertex"),
  479. SPV_ENV_VULKAN_1_1);
  480. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  481. }
  482. TEST_F(ValidateBarriers, OpControlBarrierWorkgroupExecutionVertex1p1) {
  483. const std::string body = R"(
  484. OpControlBarrier %workgroup %workgroup %acquire_release
  485. )";
  486. CompileSuccessfully(GenerateShaderCode(body, "", "Vertex"),
  487. SPV_ENV_VULKAN_1_1);
  488. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  489. EXPECT_THAT(getDiagnosticString(),
  490. AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-04682"));
  491. EXPECT_THAT(
  492. getDiagnosticString(),
  493. HasSubstr(
  494. "OpControlBarrier execution scope must be Subgroup for Fragment, "
  495. "Vertex, Geometry, TessellationEvaluation, RayGeneration, "
  496. "Intersection, AnyHit, ClosestHit, and Miss execution models"));
  497. }
  498. TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionVertex1p0) {
  499. const std::string body = R"(
  500. OpControlBarrier %subgroup %workgroup %acquire_release
  501. )";
  502. CompileSuccessfully(GenerateShaderCode(body, "", "Vertex"),
  503. SPV_ENV_VULKAN_1_0);
  504. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  505. EXPECT_THAT(
  506. getDiagnosticString(),
  507. HasSubstr("OpControlBarrier requires one of the following "
  508. "Execution Models: TessellationControl, GLCompute, Kernel, "
  509. "MeshNV or TaskNV"));
  510. }
  511. TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionGeometry1p1) {
  512. const std::string body = R"(
  513. OpControlBarrier %subgroup %subgroup %acquire_release_subgroup
  514. )";
  515. CompileSuccessfully(
  516. GenerateShaderCode(body, "OpCapability Geometry\n", "Geometry"),
  517. SPV_ENV_VULKAN_1_1);
  518. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  519. }
  520. TEST_F(ValidateBarriers, OpControlBarrierWorkgroupExecutionGeometry1p1) {
  521. const std::string body = R"(
  522. OpControlBarrier %workgroup %workgroup %acquire_release
  523. )";
  524. CompileSuccessfully(
  525. GenerateShaderCode(body, "OpCapability Geometry\n", "Geometry"),
  526. SPV_ENV_VULKAN_1_1);
  527. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  528. EXPECT_THAT(getDiagnosticString(),
  529. AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-04682"));
  530. EXPECT_THAT(
  531. getDiagnosticString(),
  532. HasSubstr(
  533. "OpControlBarrier execution scope must be Subgroup for Fragment, "
  534. "Vertex, Geometry, TessellationEvaluation, RayGeneration, "
  535. "Intersection, AnyHit, ClosestHit, and Miss execution models"));
  536. }
  537. TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionGeometry1p0) {
  538. const std::string body = R"(
  539. OpControlBarrier %subgroup %workgroup %acquire_release
  540. )";
  541. CompileSuccessfully(
  542. GenerateShaderCode(body, "OpCapability Geometry\n", "Geometry"),
  543. SPV_ENV_VULKAN_1_0);
  544. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  545. EXPECT_THAT(getDiagnosticString(),
  546. HasSubstr("OpControlBarrier requires one of the following "
  547. "Execution "
  548. "Models: TessellationControl, GLCompute, Kernel, "
  549. "MeshNV or TaskNV"));
  550. }
  551. TEST_F(ValidateBarriers,
  552. OpControlBarrierSubgroupExecutionTessellationEvaluation1p1) {
  553. const std::string body = R"(
  554. OpControlBarrier %subgroup %subgroup %acquire_release_subgroup
  555. )";
  556. CompileSuccessfully(GenerateShaderCode(body, "OpCapability Tessellation\n",
  557. "TessellationEvaluation"),
  558. SPV_ENV_VULKAN_1_1);
  559. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  560. }
  561. TEST_F(ValidateBarriers,
  562. OpControlBarrierWorkgroupExecutionTessellationEvaluation1p1) {
  563. const std::string body = R"(
  564. OpControlBarrier %workgroup %workgroup %acquire_release
  565. )";
  566. CompileSuccessfully(GenerateShaderCode(body, "OpCapability Tessellation\n",
  567. "TessellationEvaluation"),
  568. SPV_ENV_VULKAN_1_1);
  569. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  570. EXPECT_THAT(getDiagnosticString(),
  571. AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-04682"));
  572. EXPECT_THAT(
  573. getDiagnosticString(),
  574. HasSubstr(
  575. "OpControlBarrier execution scope must be Subgroup for Fragment, "
  576. "Vertex, Geometry, TessellationEvaluation, RayGeneration, "
  577. "Intersection, AnyHit, ClosestHit, and Miss execution models"));
  578. }
  579. TEST_F(ValidateBarriers,
  580. OpControlBarrierSubgroupExecutionTessellationEvaluation1p0) {
  581. const std::string body = R"(
  582. OpControlBarrier %subgroup %workgroup %acquire_release
  583. )";
  584. CompileSuccessfully(GenerateShaderCode(body, "OpCapability Tessellation\n",
  585. "TessellationEvaluation"),
  586. SPV_ENV_VULKAN_1_0);
  587. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  588. EXPECT_THAT(getDiagnosticString(),
  589. HasSubstr("OpControlBarrier requires one of the following "
  590. "Execution "
  591. "Models: TessellationControl, GLCompute, Kernel, "
  592. "MeshNV or TaskNV"));
  593. }
  594. TEST_F(ValidateBarriers, OpMemoryBarrierSuccess) {
  595. const std::string body = R"(
  596. OpMemoryBarrier %cross_device %acquire_release_uniform_workgroup
  597. OpMemoryBarrier %device %uniform
  598. )";
  599. CompileSuccessfully(GenerateShaderCode(body));
  600. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  601. }
  602. TEST_F(ValidateBarriers, OpMemoryBarrierKernelSuccess) {
  603. const std::string body = R"(
  604. OpMemoryBarrier %cross_device %acquire_release_workgroup
  605. OpMemoryBarrier %device %none
  606. )";
  607. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  608. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  609. }
  610. TEST_F(ValidateBarriers, OpMemoryBarrierVulkanSuccess) {
  611. const std::string body = R"(
  612. OpMemoryBarrier %workgroup %acquire_release_uniform_workgroup
  613. )";
  614. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
  615. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  616. }
  617. TEST_F(ValidateBarriers, OpMemoryBarrierFloatMemoryScope) {
  618. const std::string body = R"(
  619. OpMemoryBarrier %f32_1 %acquire_release_uniform_workgroup
  620. )";
  621. CompileSuccessfully(GenerateShaderCode(body));
  622. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  623. EXPECT_THAT(getDiagnosticString(),
  624. HasSubstr("MemoryBarrier: expected scope to be a 32-bit int"));
  625. }
  626. TEST_F(ValidateBarriers, OpMemoryBarrierU64MemoryScope) {
  627. const std::string body = R"(
  628. OpMemoryBarrier %u64_1 %acquire_release_uniform_workgroup
  629. )";
  630. CompileSuccessfully(GenerateShaderCode(body));
  631. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  632. EXPECT_THAT(getDiagnosticString(),
  633. HasSubstr("MemoryBarrier: expected scope to be a 32-bit int"));
  634. }
  635. TEST_F(ValidateBarriers, OpMemoryBarrierFloatMemorySemantics) {
  636. const std::string body = R"(
  637. OpMemoryBarrier %device %f32_0
  638. )";
  639. CompileSuccessfully(GenerateShaderCode(body));
  640. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  641. EXPECT_THAT(
  642. getDiagnosticString(),
  643. HasSubstr("MemoryBarrier: expected Memory Semantics to be a 32-bit int"));
  644. }
  645. TEST_F(ValidateBarriers, OpMemoryBarrierU64MemorySemantics) {
  646. const std::string body = R"(
  647. OpMemoryBarrier %device %u64_0
  648. )";
  649. CompileSuccessfully(GenerateShaderCode(body));
  650. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  651. EXPECT_THAT(
  652. getDiagnosticString(),
  653. HasSubstr("MemoryBarrier: expected Memory Semantics to be a 32-bit int"));
  654. }
  655. TEST_F(ValidateBarriers, OpMemoryBarrierVulkanMemoryScopeSubgroup) {
  656. const std::string body = R"(
  657. OpMemoryBarrier %subgroup %acquire_release_uniform_workgroup
  658. )";
  659. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
  660. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  661. EXPECT_THAT(getDiagnosticString(),
  662. AnyVUID("VUID-StandaloneSpirv-SubgroupVoteKHR-06997"));
  663. EXPECT_THAT(
  664. getDiagnosticString(),
  665. HasSubstr(
  666. "MemoryBarrier: in Vulkan 1.0 environment Memory Scope is can not be "
  667. "Subgroup without SubgroupBallotKHR or SubgroupVoteKHR declared"));
  668. }
  669. TEST_F(ValidateBarriers, OpMemoryBarrierVulkan1p1MemoryScopeSubgroup) {
  670. const std::string body = R"(
  671. OpMemoryBarrier %subgroup %acquire_release_uniform_workgroup
  672. )";
  673. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_1);
  674. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  675. }
  676. TEST_F(ValidateBarriers, OpMemoryBarrierAcquireAndRelease) {
  677. const std::string body = R"(
  678. OpMemoryBarrier %device %acquire_and_release_uniform
  679. )";
  680. CompileSuccessfully(GenerateShaderCode(body));
  681. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  682. EXPECT_THAT(getDiagnosticString(),
  683. HasSubstr("MemoryBarrier: Memory Semantics can have at most one "
  684. "of the following bits set: Acquire, Release, "
  685. "AcquireRelease or SequentiallyConsistent"));
  686. }
  687. TEST_F(ValidateBarriers, OpMemoryBarrierVulkanMemorySemanticsNone) {
  688. const std::string body = R"(
  689. OpMemoryBarrier %device %none
  690. )";
  691. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
  692. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  693. EXPECT_THAT(getDiagnosticString(),
  694. AnyVUID("VUID-StandaloneSpirv-OpMemoryBarrier-04732"));
  695. EXPECT_THAT(
  696. getDiagnosticString(),
  697. HasSubstr("MemoryBarrier: Vulkan specification requires Memory Semantics "
  698. "to have one of the following bits set: Acquire, Release, "
  699. "AcquireRelease or SequentiallyConsistent"));
  700. }
  701. TEST_F(ValidateBarriers, OpMemoryBarrierVulkanMemorySemanticsAcquire) {
  702. const std::string body = R"(
  703. OpMemoryBarrier %device %acquire
  704. )";
  705. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
  706. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  707. EXPECT_THAT(getDiagnosticString(),
  708. AnyVUID("VUID-StandaloneSpirv-OpMemoryBarrier-04733"));
  709. EXPECT_THAT(getDiagnosticString(),
  710. HasSubstr("MemoryBarrier: expected Memory Semantics to include a "
  711. "Vulkan-supported storage class"));
  712. }
  713. TEST_F(ValidateBarriers, OpMemoryBarrierVulkanSubgroupStorageClass) {
  714. const std::string body = R"(
  715. OpMemoryBarrier %device %acquire_release_subgroup
  716. )";
  717. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
  718. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  719. EXPECT_THAT(getDiagnosticString(),
  720. AnyVUID("VUID-StandaloneSpirv-OpMemoryBarrier-04733"));
  721. EXPECT_THAT(getDiagnosticString(),
  722. HasSubstr("MemoryBarrier: expected Memory Semantics to include a "
  723. "Vulkan-supported storage class"));
  724. }
  725. TEST_F(ValidateBarriers, OpNamedBarrierInitializeSuccess) {
  726. const std::string body = R"(
  727. %barrier = OpNamedBarrierInitialize %named_barrier %u32_4
  728. )";
  729. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  730. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  731. }
  732. TEST_F(ValidateBarriers, OpNamedBarrierInitializeWrongResultType) {
  733. const std::string body = R"(
  734. %barrier = OpNamedBarrierInitialize %u32 %u32_4
  735. )";
  736. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  737. ASSERT_EQ(SPV_ERROR_INVALID_DATA,
  738. ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  739. EXPECT_THAT(getDiagnosticString(),
  740. HasSubstr("NamedBarrierInitialize: expected Result Type to be "
  741. "OpTypeNamedBarrier"));
  742. }
  743. TEST_F(ValidateBarriers, OpNamedBarrierInitializeFloatSubgroupCount) {
  744. const std::string body = R"(
  745. %barrier = OpNamedBarrierInitialize %named_barrier %f32_4
  746. )";
  747. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  748. ASSERT_EQ(SPV_ERROR_INVALID_DATA,
  749. ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  750. EXPECT_THAT(getDiagnosticString(),
  751. HasSubstr("NamedBarrierInitialize: expected Subgroup Count to be "
  752. "a 32-bit int"));
  753. }
  754. TEST_F(ValidateBarriers, OpNamedBarrierInitializeU64SubgroupCount) {
  755. const std::string body = R"(
  756. %barrier = OpNamedBarrierInitialize %named_barrier %u64_4
  757. )";
  758. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  759. ASSERT_EQ(SPV_ERROR_INVALID_DATA,
  760. ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  761. EXPECT_THAT(getDiagnosticString(),
  762. HasSubstr("NamedBarrierInitialize: expected Subgroup Count to be "
  763. "a 32-bit int"));
  764. }
  765. TEST_F(ValidateBarriers, OpMemoryNamedBarrierSuccess) {
  766. const std::string body = R"(
  767. %barrier = OpNamedBarrierInitialize %named_barrier %u32_4
  768. OpMemoryNamedBarrier %barrier %workgroup %acquire_release_workgroup
  769. )";
  770. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  771. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  772. }
  773. TEST_F(ValidateBarriers, OpMemoryNamedBarrierNotNamedBarrier) {
  774. const std::string body = R"(
  775. OpMemoryNamedBarrier %u32_1 %workgroup %acquire_release_workgroup
  776. )";
  777. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  778. ASSERT_EQ(SPV_ERROR_INVALID_DATA,
  779. ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  780. EXPECT_THAT(getDiagnosticString(),
  781. HasSubstr("MemoryNamedBarrier: expected Named Barrier to be of "
  782. "type OpTypeNamedBarrier"));
  783. }
  784. TEST_F(ValidateBarriers, OpMemoryNamedBarrierFloatMemoryScope) {
  785. const std::string body = R"(
  786. %barrier = OpNamedBarrierInitialize %named_barrier %u32_4
  787. OpMemoryNamedBarrier %barrier %f32_1 %acquire_release_workgroup
  788. )";
  789. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  790. ASSERT_EQ(SPV_ERROR_INVALID_DATA,
  791. ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  792. EXPECT_THAT(
  793. getDiagnosticString(),
  794. HasSubstr("MemoryNamedBarrier: expected scope to be a 32-bit int"));
  795. }
  796. TEST_F(ValidateBarriers, OpMemoryNamedBarrierFloatMemorySemantics) {
  797. const std::string body = R"(
  798. %barrier = OpNamedBarrierInitialize %named_barrier %u32_4
  799. OpMemoryNamedBarrier %barrier %workgroup %f32_0
  800. )";
  801. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  802. ASSERT_EQ(SPV_ERROR_INVALID_DATA,
  803. ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  804. EXPECT_THAT(
  805. getDiagnosticString(),
  806. HasSubstr(
  807. "MemoryNamedBarrier: expected Memory Semantics to be a 32-bit int"));
  808. }
  809. TEST_F(ValidateBarriers, OpMemoryNamedBarrierAcquireAndRelease) {
  810. const std::string body = R"(
  811. %barrier = OpNamedBarrierInitialize %named_barrier %u32_4
  812. OpMemoryNamedBarrier %barrier %workgroup %acquire_and_release
  813. )";
  814. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  815. ASSERT_EQ(SPV_ERROR_INVALID_DATA,
  816. ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  817. EXPECT_THAT(getDiagnosticString(),
  818. HasSubstr("MemoryNamedBarrier: Memory Semantics can have at most "
  819. "one of the following bits set: Acquire, Release, "
  820. "AcquireRelease or SequentiallyConsistent"));
  821. }
  822. TEST_F(ValidateBarriers, TypeAsMemoryScope) {
  823. const std::string body = R"(
  824. OpMemoryBarrier %u32 %u32_0
  825. )";
  826. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  827. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  828. EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand '5[%uint]' cannot be a "
  829. "type"));
  830. }
  831. TEST_F(ValidateBarriers,
  832. OpControlBarrierVulkanMemoryModelBanSequentiallyConsistent) {
  833. const std::string text = R"(
  834. OpCapability Shader
  835. OpCapability VulkanMemoryModelKHR
  836. OpExtension "SPV_KHR_vulkan_memory_model"
  837. OpMemoryModel Logical VulkanKHR
  838. OpEntryPoint Fragment %1 "func"
  839. OpExecutionMode %1 OriginUpperLeft
  840. %2 = OpTypeVoid
  841. %3 = OpTypeInt 32 0
  842. %4 = OpConstant %3 16
  843. %5 = OpTypeFunction %2
  844. %6 = OpConstant %3 5
  845. %1 = OpFunction %2 None %5
  846. %7 = OpLabel
  847. OpControlBarrier %6 %6 %4
  848. OpReturn
  849. OpFunctionEnd
  850. )";
  851. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
  852. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  853. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  854. EXPECT_THAT(getDiagnosticString(),
  855. HasSubstr("SequentiallyConsistent memory semantics cannot be "
  856. "used with the VulkanKHR memory model."));
  857. }
  858. TEST_F(ValidateBarriers,
  859. OpMemoryBarrierVulkanMemoryModelBanSequentiallyConsistent) {
  860. const std::string text = R"(
  861. OpCapability Shader
  862. OpCapability VulkanMemoryModelKHR
  863. OpExtension "SPV_KHR_vulkan_memory_model"
  864. OpMemoryModel Logical VulkanKHR
  865. OpEntryPoint Fragment %1 "func"
  866. OpExecutionMode %1 OriginUpperLeft
  867. %2 = OpTypeVoid
  868. %3 = OpTypeInt 32 0
  869. %4 = OpConstant %3 16
  870. %5 = OpTypeFunction %2
  871. %6 = OpConstant %3 5
  872. %1 = OpFunction %2 None %5
  873. %7 = OpLabel
  874. OpMemoryBarrier %6 %4
  875. OpReturn
  876. OpFunctionEnd
  877. )";
  878. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
  879. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  880. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  881. EXPECT_THAT(getDiagnosticString(),
  882. HasSubstr("SequentiallyConsistent memory semantics cannot be "
  883. "used with the VulkanKHR memory model."));
  884. }
  885. TEST_F(ValidateBarriers, OutputMemoryKHRRequireVulkanMemoryModelKHR) {
  886. const std::string text = R"(
  887. OpCapability Shader
  888. OpMemoryModel Logical GLSL450
  889. OpEntryPoint Fragment %1 "func"
  890. OpExecutionMode %1 OriginUpperLeft
  891. %2 = OpTypeVoid
  892. %3 = OpTypeInt 32 0
  893. %semantics = OpConstant %3 4104
  894. %5 = OpTypeFunction %2
  895. %device = OpConstant %3 1
  896. %1 = OpFunction %2 None %5
  897. %7 = OpLabel
  898. OpControlBarrier %device %device %semantics
  899. OpReturn
  900. OpFunctionEnd
  901. )";
  902. CompileSuccessfully(text);
  903. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  904. EXPECT_THAT(getDiagnosticString(),
  905. HasSubstr("ControlBarrier: Memory Semantics OutputMemoryKHR "
  906. "requires capability VulkanMemoryModelKHR"));
  907. }
  908. TEST_F(ValidateBarriers, MakeAvailableKHRRequireVulkanMemoryModelKHR) {
  909. const std::string text = R"(
  910. OpCapability Shader
  911. OpMemoryModel Logical GLSL450
  912. OpEntryPoint Fragment %1 "func"
  913. OpExecutionMode %1 OriginUpperLeft
  914. %2 = OpTypeVoid
  915. %3 = OpTypeInt 32 0
  916. %semantics = OpConstant %3 8264
  917. %5 = OpTypeFunction %2
  918. %device = OpConstant %3 1
  919. %1 = OpFunction %2 None %5
  920. %7 = OpLabel
  921. OpControlBarrier %device %device %semantics
  922. OpReturn
  923. OpFunctionEnd
  924. )";
  925. CompileSuccessfully(text);
  926. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  927. EXPECT_THAT(getDiagnosticString(),
  928. HasSubstr("ControlBarrier: Memory Semantics MakeAvailableKHR "
  929. "requires capability VulkanMemoryModelKHR"));
  930. }
  931. TEST_F(ValidateBarriers, MakeVisibleKHRRequireVulkanMemoryModelKHR) {
  932. const std::string text = R"(
  933. OpCapability Shader
  934. OpMemoryModel Logical GLSL450
  935. OpEntryPoint Fragment %1 "func"
  936. OpExecutionMode %1 OriginUpperLeft
  937. %2 = OpTypeVoid
  938. %3 = OpTypeInt 32 0
  939. %semantics = OpConstant %3 16456
  940. %5 = OpTypeFunction %2
  941. %device = OpConstant %3 1
  942. %1 = OpFunction %2 None %5
  943. %7 = OpLabel
  944. OpControlBarrier %device %device %semantics
  945. OpReturn
  946. OpFunctionEnd
  947. )";
  948. CompileSuccessfully(text);
  949. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  950. EXPECT_THAT(getDiagnosticString(),
  951. HasSubstr("ControlBarrier: Memory Semantics MakeVisibleKHR "
  952. "requires capability VulkanMemoryModelKHR"));
  953. }
  954. TEST_F(ValidateBarriers, MakeAvailableKHRRequiresReleaseSemantics) {
  955. const std::string text = R"(
  956. OpCapability Shader
  957. OpCapability VulkanMemoryModelKHR
  958. OpExtension "SPV_KHR_vulkan_memory_model"
  959. OpMemoryModel Logical VulkanKHR
  960. OpEntryPoint Fragment %func "func"
  961. OpExecutionMode %func OriginUpperLeft
  962. %void = OpTypeVoid
  963. %int = OpTypeInt 32 0
  964. %workgroup = OpConstant %int 2
  965. %semantics = OpConstant %int 8448
  966. %functy = OpTypeFunction %void
  967. %func = OpFunction %void None %functy
  968. %1 = OpLabel
  969. OpControlBarrier %workgroup %workgroup %semantics
  970. OpReturn
  971. OpFunctionEnd
  972. )";
  973. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
  974. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  975. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  976. EXPECT_THAT(
  977. getDiagnosticString(),
  978. HasSubstr("ControlBarrier: MakeAvailableKHR Memory Semantics also "
  979. "requires either Release or AcquireRelease Memory Semantics"));
  980. }
  981. TEST_F(ValidateBarriers, MakeVisibleKHRRequiresAcquireSemantics) {
  982. const std::string text = R"(
  983. OpCapability Shader
  984. OpCapability VulkanMemoryModelKHR
  985. OpExtension "SPV_KHR_vulkan_memory_model"
  986. OpMemoryModel Logical VulkanKHR
  987. OpEntryPoint Fragment %func "func"
  988. OpExecutionMode %func OriginUpperLeft
  989. %void = OpTypeVoid
  990. %int = OpTypeInt 32 0
  991. %workgroup = OpConstant %int 2
  992. %semantics = OpConstant %int 16640
  993. %functy = OpTypeFunction %void
  994. %func = OpFunction %void None %functy
  995. %1 = OpLabel
  996. OpControlBarrier %workgroup %workgroup %semantics
  997. OpReturn
  998. OpFunctionEnd
  999. )";
  1000. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
  1001. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1002. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1003. EXPECT_THAT(
  1004. getDiagnosticString(),
  1005. HasSubstr("ControlBarrier: MakeVisibleKHR Memory Semantics also requires "
  1006. "either Acquire or AcquireRelease Memory Semantics"));
  1007. }
  1008. TEST_F(ValidateBarriers, MakeAvailableKHRRequiresStorageSemantics) {
  1009. const std::string text = R"(
  1010. OpCapability Shader
  1011. OpCapability VulkanMemoryModelKHR
  1012. OpExtension "SPV_KHR_vulkan_memory_model"
  1013. OpMemoryModel Logical VulkanKHR
  1014. OpEntryPoint Fragment %func "func"
  1015. OpExecutionMode %func OriginUpperLeft
  1016. %void = OpTypeVoid
  1017. %int = OpTypeInt 32 0
  1018. %workgroup = OpConstant %int 2
  1019. %semantics = OpConstant %int 8196
  1020. %functy = OpTypeFunction %void
  1021. %func = OpFunction %void None %functy
  1022. %1 = OpLabel
  1023. OpMemoryBarrier %workgroup %semantics
  1024. OpReturn
  1025. OpFunctionEnd
  1026. )";
  1027. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
  1028. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1029. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1030. EXPECT_THAT(getDiagnosticString(),
  1031. HasSubstr("MemoryBarrier: expected Memory Semantics to include a "
  1032. "storage class"));
  1033. }
  1034. TEST_F(ValidateBarriers, MakeVisibleKHRRequiresStorageSemantics) {
  1035. const std::string text = R"(
  1036. OpCapability Shader
  1037. OpCapability VulkanMemoryModelKHR
  1038. OpExtension "SPV_KHR_vulkan_memory_model"
  1039. OpMemoryModel Logical VulkanKHR
  1040. OpEntryPoint Fragment %func "func"
  1041. OpExecutionMode %func OriginUpperLeft
  1042. %void = OpTypeVoid
  1043. %int = OpTypeInt 32 0
  1044. %workgroup = OpConstant %int 2
  1045. %semantics = OpConstant %int 16386
  1046. %functy = OpTypeFunction %void
  1047. %func = OpFunction %void None %functy
  1048. %1 = OpLabel
  1049. OpMemoryBarrier %workgroup %semantics
  1050. OpReturn
  1051. OpFunctionEnd
  1052. )";
  1053. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
  1054. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1055. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1056. EXPECT_THAT(getDiagnosticString(),
  1057. HasSubstr("MemoryBarrier: expected Memory Semantics to include a "
  1058. "storage class"));
  1059. }
  1060. TEST_F(ValidateBarriers, SemanticsSpecConstantShader) {
  1061. const std::string spirv = R"(
  1062. OpCapability Shader
  1063. OpMemoryModel Logical GLSL450
  1064. OpEntryPoint Fragment %func "func"
  1065. OpExecutionMode %func OriginUpperLeft
  1066. %void = OpTypeVoid
  1067. %int = OpTypeInt 32 0
  1068. %ptr_int_workgroup = OpTypePointer Workgroup %int
  1069. %var = OpVariable %ptr_int_workgroup Workgroup
  1070. %voidfn = OpTypeFunction %void
  1071. %spec_const = OpSpecConstant %int 0
  1072. %workgroup = OpConstant %int 2
  1073. %func = OpFunction %void None %voidfn
  1074. %entry = OpLabel
  1075. OpMemoryBarrier %workgroup %spec_const
  1076. OpReturn
  1077. OpFunctionEnd
  1078. )";
  1079. CompileSuccessfully(spirv);
  1080. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1081. EXPECT_THAT(getDiagnosticString(),
  1082. HasSubstr("Memory Semantics ids must be OpConstant when Shader "
  1083. "capability is present"));
  1084. }
  1085. TEST_F(ValidateBarriers, SemanticsSpecConstantKernel) {
  1086. const std::string spirv = R"(
  1087. OpCapability Kernel
  1088. OpCapability Linkage
  1089. OpMemoryModel Logical OpenCL
  1090. %void = OpTypeVoid
  1091. %int = OpTypeInt 32 0
  1092. %ptr_int_workgroup = OpTypePointer Workgroup %int
  1093. %var = OpVariable %ptr_int_workgroup Workgroup
  1094. %voidfn = OpTypeFunction %void
  1095. %spec_const = OpSpecConstant %int 0
  1096. %workgroup = OpConstant %int 2
  1097. %func = OpFunction %void None %voidfn
  1098. %entry = OpLabel
  1099. OpMemoryBarrier %workgroup %spec_const
  1100. OpReturn
  1101. OpFunctionEnd
  1102. )";
  1103. CompileSuccessfully(spirv);
  1104. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  1105. }
  1106. TEST_F(ValidateBarriers, ScopeSpecConstantShader) {
  1107. const std::string spirv = R"(
  1108. OpCapability Shader
  1109. OpMemoryModel Logical GLSL450
  1110. OpEntryPoint Fragment %func "func"
  1111. OpExecutionMode %func OriginUpperLeft
  1112. %void = OpTypeVoid
  1113. %int = OpTypeInt 32 0
  1114. %ptr_int_workgroup = OpTypePointer Workgroup %int
  1115. %var = OpVariable %ptr_int_workgroup Workgroup
  1116. %voidfn = OpTypeFunction %void
  1117. %spec_const = OpSpecConstant %int 0
  1118. %relaxed = OpConstant %int 0
  1119. %func = OpFunction %void None %voidfn
  1120. %entry = OpLabel
  1121. OpMemoryBarrier %spec_const %relaxed
  1122. OpReturn
  1123. OpFunctionEnd
  1124. )";
  1125. CompileSuccessfully(spirv);
  1126. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1127. EXPECT_THAT(getDiagnosticString(),
  1128. HasSubstr("Scope ids must be OpConstant when Shader "
  1129. "capability is present"));
  1130. }
  1131. TEST_F(ValidateBarriers, ScopeSpecConstantKernel) {
  1132. const std::string spirv = R"(
  1133. OpCapability Kernel
  1134. OpCapability Linkage
  1135. OpMemoryModel Logical OpenCL
  1136. %void = OpTypeVoid
  1137. %int = OpTypeInt 32 0
  1138. %ptr_int_workgroup = OpTypePointer Workgroup %int
  1139. %var = OpVariable %ptr_int_workgroup Workgroup
  1140. %voidfn = OpTypeFunction %void
  1141. %spec_const = OpSpecConstant %int 0
  1142. %relaxed = OpConstant %int 0
  1143. %func = OpFunction %void None %voidfn
  1144. %entry = OpLabel
  1145. OpMemoryBarrier %spec_const %relaxed
  1146. OpReturn
  1147. OpFunctionEnd
  1148. )";
  1149. CompileSuccessfully(spirv);
  1150. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  1151. }
  1152. TEST_F(ValidateBarriers, VulkanMemoryModelDeviceScopeBad) {
  1153. const std::string text = R"(
  1154. OpCapability Shader
  1155. OpCapability VulkanMemoryModelKHR
  1156. OpExtension "SPV_KHR_vulkan_memory_model"
  1157. OpMemoryModel Logical VulkanKHR
  1158. OpEntryPoint Fragment %func "func"
  1159. OpExecutionMode %func OriginUpperLeft
  1160. %void = OpTypeVoid
  1161. %int = OpTypeInt 32 0
  1162. %device = OpConstant %int 1
  1163. %semantics = OpConstant %int 0
  1164. %functy = OpTypeFunction %void
  1165. %func = OpFunction %void None %functy
  1166. %1 = OpLabel
  1167. OpMemoryBarrier %device %semantics
  1168. OpReturn
  1169. OpFunctionEnd
  1170. )";
  1171. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
  1172. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1173. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1174. EXPECT_THAT(
  1175. getDiagnosticString(),
  1176. HasSubstr("Use of device scope with VulkanKHR memory model requires the "
  1177. "VulkanMemoryModelDeviceScopeKHR capability"));
  1178. }
  1179. TEST_F(ValidateBarriers, VulkanMemoryModelDeviceScopeGood) {
  1180. const std::string text = R"(
  1181. OpCapability Shader
  1182. OpCapability VulkanMemoryModelKHR
  1183. OpCapability VulkanMemoryModelDeviceScopeKHR
  1184. OpExtension "SPV_KHR_vulkan_memory_model"
  1185. OpMemoryModel Logical VulkanKHR
  1186. OpEntryPoint Fragment %func "func"
  1187. OpExecutionMode %func OriginUpperLeft
  1188. %void = OpTypeVoid
  1189. %int = OpTypeInt 32 0
  1190. %device = OpConstant %int 1
  1191. %semantics = OpConstant %int 0
  1192. %functy = OpTypeFunction %void
  1193. %func = OpFunction %void None %functy
  1194. %1 = OpLabel
  1195. OpMemoryBarrier %device %semantics
  1196. OpReturn
  1197. OpFunctionEnd
  1198. )";
  1199. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
  1200. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1201. }
  1202. TEST_F(ValidateBarriers, VolatileMemoryBarrier) {
  1203. const std::string text = R"(
  1204. OpCapability Shader
  1205. OpCapability VulkanMemoryModelKHR
  1206. OpCapability VulkanMemoryModelDeviceScopeKHR
  1207. OpCapability Linkage
  1208. OpExtension "SPV_KHR_vulkan_memory_model"
  1209. OpMemoryModel Logical VulkanKHR
  1210. %void = OpTypeVoid
  1211. %int = OpTypeInt 32 0
  1212. %device = OpConstant %int 1
  1213. %semantics = OpConstant %int 32768
  1214. %functy = OpTypeFunction %void
  1215. %func = OpFunction %void None %functy
  1216. %1 = OpLabel
  1217. OpMemoryBarrier %device %semantics
  1218. OpReturn
  1219. OpFunctionEnd
  1220. )";
  1221. CompileSuccessfully(text);
  1222. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1223. EXPECT_THAT(getDiagnosticString(),
  1224. HasSubstr("Memory Semantics Volatile can only be used with "
  1225. "atomic instructions"));
  1226. }
  1227. TEST_F(ValidateBarriers, VolatileControlBarrier) {
  1228. const std::string text = R"(
  1229. OpCapability Shader
  1230. OpCapability VulkanMemoryModelKHR
  1231. OpCapability VulkanMemoryModelDeviceScopeKHR
  1232. OpCapability Linkage
  1233. OpExtension "SPV_KHR_vulkan_memory_model"
  1234. OpMemoryModel Logical VulkanKHR
  1235. %void = OpTypeVoid
  1236. %int = OpTypeInt 32 0
  1237. %device = OpConstant %int 1
  1238. %semantics = OpConstant %int 32768
  1239. %functy = OpTypeFunction %void
  1240. %func = OpFunction %void None %functy
  1241. %1 = OpLabel
  1242. OpControlBarrier %device %device %semantics
  1243. OpReturn
  1244. OpFunctionEnd
  1245. )";
  1246. CompileSuccessfully(text);
  1247. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1248. EXPECT_THAT(getDiagnosticString(),
  1249. HasSubstr("Memory Semantics Volatile can only be used with "
  1250. "atomic instructions"));
  1251. }
  1252. TEST_F(ValidateBarriers, CooperativeMatrixSpecConstantVolatile) {
  1253. const std::string text = R"(
  1254. OpCapability Shader
  1255. OpCapability VulkanMemoryModelKHR
  1256. OpCapability VulkanMemoryModelDeviceScopeKHR
  1257. OpCapability CooperativeMatrixNV
  1258. OpCapability Linkage
  1259. OpExtension "SPV_KHR_vulkan_memory_model"
  1260. OpExtension "SPV_NV_cooperative_matrix"
  1261. OpMemoryModel Logical VulkanKHR
  1262. %void = OpTypeVoid
  1263. %int = OpTypeInt 32 0
  1264. %device = OpConstant %int 1
  1265. %semantics = OpSpecConstant %int 32768
  1266. %functy = OpTypeFunction %void
  1267. %func = OpFunction %void None %functy
  1268. %1 = OpLabel
  1269. OpControlBarrier %device %device %semantics
  1270. OpReturn
  1271. OpFunctionEnd
  1272. )";
  1273. CompileSuccessfully(text);
  1274. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  1275. }
  1276. TEST_F(ValidateBarriers, CooperativeMatrixNonConstantSemantics) {
  1277. const std::string text = R"(
  1278. OpCapability Shader
  1279. OpCapability VulkanMemoryModelKHR
  1280. OpCapability VulkanMemoryModelDeviceScopeKHR
  1281. OpCapability CooperativeMatrixNV
  1282. OpCapability Linkage
  1283. OpExtension "SPV_KHR_vulkan_memory_model"
  1284. OpExtension "SPV_NV_cooperative_matrix"
  1285. OpMemoryModel Logical VulkanKHR
  1286. %void = OpTypeVoid
  1287. %int = OpTypeInt 32 0
  1288. %device = OpConstant %int 1
  1289. %semantics = OpUndef %int
  1290. %functy = OpTypeFunction %void
  1291. %func = OpFunction %void None %functy
  1292. %1 = OpLabel
  1293. OpControlBarrier %device %device %semantics
  1294. OpReturn
  1295. OpFunctionEnd
  1296. )";
  1297. CompileSuccessfully(text);
  1298. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1299. EXPECT_THAT(getDiagnosticString(),
  1300. HasSubstr("Memory Semantics must be a constant instruction when "
  1301. "CooperativeMatrixNV capability is present"));
  1302. }
  1303. TEST_F(ValidateBarriers, OpMemoryBarrierShaderCallRayGenSuccess) {
  1304. const std::string body =
  1305. "OpMemoryBarrier %shadercall %release_uniform_workgroup";
  1306. CompileSuccessfully(GenerateShaderCodeImpl(body,
  1307. // capabilities_and_extensions
  1308. R"(
  1309. OpCapability VulkanMemoryModelKHR
  1310. OpCapability RayTracingKHR
  1311. OpExtension "SPV_KHR_vulkan_memory_model"
  1312. OpExtension "SPV_KHR_ray_tracing"
  1313. )",
  1314. // definitions
  1315. "",
  1316. // execution_model
  1317. "RayGenerationKHR",
  1318. // memory_model
  1319. "OpMemoryModel Logical VulkanKHR"),
  1320. SPV_ENV_VULKAN_1_1);
  1321. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  1322. }
  1323. TEST_F(ValidateBarriers, OpMemoryBarrierShaderCallComputeFailure) {
  1324. const std::string body =
  1325. "OpMemoryBarrier %shadercall %release_uniform_workgroup";
  1326. CompileSuccessfully(GenerateShaderCodeImpl(body,
  1327. // capabilities_and_extensions
  1328. R"(
  1329. OpCapability VulkanMemoryModelKHR
  1330. OpExtension "SPV_KHR_vulkan_memory_model"
  1331. )",
  1332. // definitions
  1333. "",
  1334. // execution_model
  1335. "GLCompute",
  1336. // memory_model
  1337. "OpMemoryModel Logical VulkanKHR"),
  1338. SPV_ENV_VULKAN_1_1);
  1339. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  1340. EXPECT_THAT(getDiagnosticString(),
  1341. AnyVUID("VUID-StandaloneSpirv-None-04640"));
  1342. EXPECT_THAT(
  1343. getDiagnosticString(),
  1344. HasSubstr(
  1345. "ShaderCallKHR Memory Scope requires a ray tracing execution model"));
  1346. }
  1347. TEST_F(ValidateBarriers, OpControlBarrierShaderCallRayGenFailure) {
  1348. const std::string body = "OpControlBarrier %shadercall %shadercall %none";
  1349. CompileSuccessfully(GenerateShaderCodeImpl(body,
  1350. // capabilities_and_extensions
  1351. R"(
  1352. OpCapability VulkanMemoryModelKHR
  1353. OpCapability RayTracingKHR
  1354. OpExtension "SPV_KHR_vulkan_memory_model"
  1355. OpExtension "SPV_KHR_ray_tracing"
  1356. )",
  1357. // definitions
  1358. "",
  1359. // execution_model
  1360. "RayGenerationKHR",
  1361. // memory_model
  1362. "OpMemoryModel Logical VulkanKHR"),
  1363. SPV_ENV_VULKAN_1_1);
  1364. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  1365. EXPECT_THAT(getDiagnosticString(),
  1366. AnyVUID("VUID-StandaloneSpirv-None-04636"));
  1367. EXPECT_THAT(getDiagnosticString(),
  1368. HasSubstr("in Vulkan environment Execution Scope is limited to "
  1369. "Workgroup and Subgroup"));
  1370. }
  1371. } // namespace
  1372. } // namespace val
  1373. } // namespace spvtools