val_barriers_test.cpp 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599
  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-07951"));
  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_release_workgroup
  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_release_workgroup
  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_uniform_workgroup
  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_uniform_workgroup
  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. TEST_F(ValidateBarriers, OpControlBarrierVulkanSubgroupStorageClass) {
  424. const std::string body = R"(
  425. OpControlBarrier %workgroup %device %acquire_release_subgroup
  426. )";
  427. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
  428. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  429. EXPECT_THAT(getDiagnosticString(),
  430. AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-04650"));
  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, OpControlBarrierVulkanAcquireRelease) {
  438. const std::string body = R"(
  439. OpControlBarrier %workgroup %device %acquire_release
  440. )";
  441. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
  442. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  443. EXPECT_THAT(getDiagnosticString(),
  444. AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-04650"));
  445. EXPECT_THAT(
  446. getDiagnosticString(),
  447. HasSubstr(
  448. "ControlBarrier: expected Memory Semantics to include a "
  449. "Vulkan-supported storage class if Memory Semantics is not None"));
  450. }
  451. TEST_F(ValidateBarriers, OpControlBarrierVulkanWorkgroupMemory) {
  452. const std::string body = R"(
  453. OpControlBarrier %workgroup %workgroup %workgroup_memory
  454. )";
  455. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
  456. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  457. EXPECT_THAT(getDiagnosticString(),
  458. AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-10609"));
  459. EXPECT_THAT(
  460. getDiagnosticString(),
  461. HasSubstr(
  462. "ControlBarrier: Vulkan specification requires non-zero "
  463. "Memory Semantics to have one of the following bits set: Acquire, "
  464. "Release, AcquireRelease or SequentiallyConsistent"));
  465. }
  466. TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionFragment1p1) {
  467. const std::string body = R"(
  468. OpControlBarrier %subgroup %subgroup %acquire_release_workgroup
  469. )";
  470. CompileSuccessfully(GenerateShaderCode(body, "", "Fragment"),
  471. SPV_ENV_VULKAN_1_1);
  472. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  473. }
  474. TEST_F(ValidateBarriers, OpControlBarrierWorkgroupExecutionFragment1p1) {
  475. const std::string body = R"(
  476. OpControlBarrier %workgroup %workgroup %acquire_release_workgroup
  477. )";
  478. CompileSuccessfully(GenerateShaderCode(body, "", "Fragment"),
  479. SPV_ENV_VULKAN_1_1);
  480. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  481. EXPECT_THAT(getDiagnosticString(),
  482. AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-04682"));
  483. EXPECT_THAT(
  484. getDiagnosticString(),
  485. HasSubstr(
  486. "OpControlBarrier execution scope must be Subgroup for Fragment, "
  487. "Vertex, Geometry, TessellationEvaluation, RayGeneration, "
  488. "Intersection, AnyHit, ClosestHit, and Miss execution models"));
  489. }
  490. TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionFragment1p0) {
  491. const std::string body = R"(
  492. OpControlBarrier %subgroup %workgroup %acquire_release_workgroup
  493. )";
  494. CompileSuccessfully(GenerateShaderCode(body, "", "Fragment"),
  495. SPV_ENV_VULKAN_1_0);
  496. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  497. EXPECT_THAT(getDiagnosticString(),
  498. HasSubstr("OpControlBarrier requires one of the following "
  499. "Execution "
  500. "Models: TessellationControl, GLCompute, Kernel, "
  501. "MeshNV or TaskNV"));
  502. }
  503. TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionVertex1p1) {
  504. const std::string body = R"(
  505. OpControlBarrier %subgroup %subgroup %acquire_release_workgroup
  506. )";
  507. CompileSuccessfully(GenerateShaderCode(body, "", "Vertex"),
  508. SPV_ENV_VULKAN_1_1);
  509. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  510. }
  511. TEST_F(ValidateBarriers, OpControlBarrierWorkgroupExecutionVertex1p1) {
  512. const std::string body = R"(
  513. OpControlBarrier %workgroup %workgroup %acquire_release_workgroup
  514. )";
  515. CompileSuccessfully(GenerateShaderCode(body, "", "Vertex"),
  516. SPV_ENV_VULKAN_1_1);
  517. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  518. EXPECT_THAT(getDiagnosticString(),
  519. AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-04682"));
  520. EXPECT_THAT(
  521. getDiagnosticString(),
  522. HasSubstr(
  523. "OpControlBarrier execution scope must be Subgroup for Fragment, "
  524. "Vertex, Geometry, TessellationEvaluation, RayGeneration, "
  525. "Intersection, AnyHit, ClosestHit, and Miss execution models"));
  526. }
  527. TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionVertex1p0) {
  528. const std::string body = R"(
  529. OpControlBarrier %subgroup %workgroup %acquire_release_workgroup
  530. )";
  531. CompileSuccessfully(GenerateShaderCode(body, "", "Vertex"),
  532. SPV_ENV_VULKAN_1_0);
  533. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  534. EXPECT_THAT(
  535. getDiagnosticString(),
  536. HasSubstr("OpControlBarrier requires one of the following "
  537. "Execution Models: TessellationControl, GLCompute, Kernel, "
  538. "MeshNV or TaskNV"));
  539. }
  540. TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionGeometry1p1) {
  541. const std::string body = R"(
  542. OpControlBarrier %subgroup %subgroup %acquire_release_workgroup
  543. )";
  544. CompileSuccessfully(
  545. GenerateShaderCode(body, "OpCapability Geometry\n", "Geometry"),
  546. SPV_ENV_VULKAN_1_1);
  547. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  548. }
  549. TEST_F(ValidateBarriers, OpControlBarrierWorkgroupExecutionGeometry1p1) {
  550. const std::string body = R"(
  551. OpControlBarrier %workgroup %workgroup %acquire_release_workgroup
  552. )";
  553. CompileSuccessfully(
  554. GenerateShaderCode(body, "OpCapability Geometry\n", "Geometry"),
  555. SPV_ENV_VULKAN_1_1);
  556. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  557. EXPECT_THAT(getDiagnosticString(),
  558. AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-04682"));
  559. EXPECT_THAT(
  560. getDiagnosticString(),
  561. HasSubstr(
  562. "OpControlBarrier execution scope must be Subgroup for Fragment, "
  563. "Vertex, Geometry, TessellationEvaluation, RayGeneration, "
  564. "Intersection, AnyHit, ClosestHit, and Miss execution models"));
  565. }
  566. TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionGeometry1p0) {
  567. const std::string body = R"(
  568. OpControlBarrier %subgroup %workgroup %acquire_release_workgroup
  569. )";
  570. CompileSuccessfully(
  571. GenerateShaderCode(body, "OpCapability Geometry\n", "Geometry"),
  572. SPV_ENV_VULKAN_1_0);
  573. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  574. EXPECT_THAT(getDiagnosticString(),
  575. HasSubstr("OpControlBarrier requires one of the following "
  576. "Execution "
  577. "Models: TessellationControl, GLCompute, Kernel, "
  578. "MeshNV or TaskNV"));
  579. }
  580. TEST_F(ValidateBarriers,
  581. OpControlBarrierSubgroupExecutionTessellationEvaluation1p1) {
  582. const std::string body = R"(
  583. OpControlBarrier %subgroup %subgroup %acquire_release_workgroup
  584. )";
  585. CompileSuccessfully(GenerateShaderCode(body, "OpCapability Tessellation\n",
  586. "TessellationEvaluation"),
  587. SPV_ENV_VULKAN_1_1);
  588. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  589. }
  590. TEST_F(ValidateBarriers,
  591. OpControlBarrierWorkgroupExecutionTessellationEvaluation1p1) {
  592. const std::string body = R"(
  593. OpControlBarrier %workgroup %workgroup %acquire_release_workgroup
  594. )";
  595. CompileSuccessfully(GenerateShaderCode(body, "OpCapability Tessellation\n",
  596. "TessellationEvaluation"),
  597. SPV_ENV_VULKAN_1_1);
  598. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  599. EXPECT_THAT(getDiagnosticString(),
  600. AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-04682"));
  601. EXPECT_THAT(
  602. getDiagnosticString(),
  603. HasSubstr(
  604. "OpControlBarrier execution scope must be Subgroup for Fragment, "
  605. "Vertex, Geometry, TessellationEvaluation, RayGeneration, "
  606. "Intersection, AnyHit, ClosestHit, and Miss execution models"));
  607. }
  608. TEST_F(ValidateBarriers,
  609. OpControlBarrierSubgroupExecutionTessellationEvaluation1p0) {
  610. const std::string body = R"(
  611. OpControlBarrier %subgroup %workgroup %acquire_release_workgroup
  612. )";
  613. CompileSuccessfully(GenerateShaderCode(body, "OpCapability Tessellation\n",
  614. "TessellationEvaluation"),
  615. SPV_ENV_VULKAN_1_0);
  616. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  617. EXPECT_THAT(getDiagnosticString(),
  618. HasSubstr("OpControlBarrier requires one of the following "
  619. "Execution Models: TessellationControl, GLCompute, "
  620. "Kernel, MeshNV or TaskNV"));
  621. }
  622. TEST_F(ValidateBarriers, OpMemoryBarrierSuccess) {
  623. const std::string body = R"(
  624. OpMemoryBarrier %cross_device %acquire_release_uniform_workgroup
  625. OpMemoryBarrier %device %uniform
  626. )";
  627. CompileSuccessfully(GenerateShaderCode(body));
  628. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  629. }
  630. TEST_F(ValidateBarriers, OpMemoryBarrierKernelSuccess) {
  631. const std::string body = R"(
  632. OpMemoryBarrier %cross_device %acquire_release_workgroup
  633. OpMemoryBarrier %device %none
  634. )";
  635. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  636. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  637. }
  638. TEST_F(ValidateBarriers, OpMemoryBarrierVulkanSuccess) {
  639. const std::string body = R"(
  640. OpMemoryBarrier %workgroup %acquire_release_uniform_workgroup
  641. )";
  642. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
  643. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  644. }
  645. TEST_F(ValidateBarriers, OpMemoryBarrierFloatMemoryScope) {
  646. const std::string body = R"(
  647. OpMemoryBarrier %f32_1 %acquire_release_uniform_workgroup
  648. )";
  649. CompileSuccessfully(GenerateShaderCode(body));
  650. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  651. EXPECT_THAT(getDiagnosticString(),
  652. HasSubstr("MemoryBarrier: expected scope to be a 32-bit int"));
  653. }
  654. TEST_F(ValidateBarriers, OpMemoryBarrierU64MemoryScope) {
  655. const std::string body = R"(
  656. OpMemoryBarrier %u64_1 %acquire_release_uniform_workgroup
  657. )";
  658. CompileSuccessfully(GenerateShaderCode(body));
  659. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  660. EXPECT_THAT(getDiagnosticString(),
  661. HasSubstr("MemoryBarrier: expected scope to be a 32-bit int"));
  662. }
  663. TEST_F(ValidateBarriers, OpMemoryBarrierFloatMemorySemantics) {
  664. const std::string body = R"(
  665. OpMemoryBarrier %device %f32_0
  666. )";
  667. CompileSuccessfully(GenerateShaderCode(body));
  668. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  669. EXPECT_THAT(
  670. getDiagnosticString(),
  671. HasSubstr("MemoryBarrier: expected Memory Semantics to be a 32-bit int"));
  672. }
  673. TEST_F(ValidateBarriers, OpMemoryBarrierU64MemorySemantics) {
  674. const std::string body = R"(
  675. OpMemoryBarrier %device %u64_0
  676. )";
  677. CompileSuccessfully(GenerateShaderCode(body));
  678. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  679. EXPECT_THAT(
  680. getDiagnosticString(),
  681. HasSubstr("MemoryBarrier: expected Memory Semantics to be a 32-bit int"));
  682. }
  683. TEST_F(ValidateBarriers, OpMemoryBarrierVulkanMemoryScopeSubgroup) {
  684. const std::string body = R"(
  685. OpMemoryBarrier %subgroup %acquire_release_uniform_workgroup
  686. )";
  687. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
  688. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  689. EXPECT_THAT(getDiagnosticString(),
  690. AnyVUID("VUID-StandaloneSpirv-SubgroupVoteKHR-07951"));
  691. EXPECT_THAT(
  692. getDiagnosticString(),
  693. HasSubstr(
  694. "MemoryBarrier: in Vulkan 1.0 environment Memory Scope is can not be "
  695. "Subgroup without SubgroupBallotKHR or SubgroupVoteKHR declared"));
  696. }
  697. TEST_F(ValidateBarriers, OpMemoryBarrierVulkan1p1MemoryScopeSubgroup) {
  698. const std::string body = R"(
  699. OpMemoryBarrier %subgroup %acquire_release_uniform_workgroup
  700. )";
  701. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_1);
  702. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  703. }
  704. TEST_F(ValidateBarriers, OpMemoryBarrierAcquireAndRelease) {
  705. const std::string body = R"(
  706. OpMemoryBarrier %device %acquire_and_release_uniform
  707. )";
  708. CompileSuccessfully(GenerateShaderCode(body));
  709. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  710. EXPECT_THAT(getDiagnosticString(),
  711. HasSubstr("MemoryBarrier: Memory Semantics can have at most one "
  712. "of the following bits set: Acquire, Release, "
  713. "AcquireRelease or SequentiallyConsistent"));
  714. }
  715. TEST_F(ValidateBarriers, OpMemoryBarrierVulkanMemorySemanticsNone) {
  716. const std::string body = R"(
  717. OpMemoryBarrier %device %none
  718. )";
  719. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
  720. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  721. EXPECT_THAT(getDiagnosticString(),
  722. AnyVUID("VUID-StandaloneSpirv-OpMemoryBarrier-04732"));
  723. EXPECT_THAT(
  724. getDiagnosticString(),
  725. HasSubstr("MemoryBarrier: Vulkan specification requires Memory Semantics "
  726. "to have one of the following bits set: Acquire, Release, "
  727. "AcquireRelease or SequentiallyConsistent"));
  728. }
  729. TEST_F(ValidateBarriers, OpMemoryBarrierVulkanMemorySemanticsAcquire) {
  730. const std::string body = R"(
  731. OpMemoryBarrier %device %acquire
  732. )";
  733. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
  734. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  735. EXPECT_THAT(getDiagnosticString(),
  736. AnyVUID("VUID-StandaloneSpirv-OpMemoryBarrier-04733"));
  737. EXPECT_THAT(getDiagnosticString(),
  738. HasSubstr("MemoryBarrier: expected Memory Semantics to include a "
  739. "Vulkan-supported storage class"));
  740. }
  741. TEST_F(ValidateBarriers, OpMemoryBarrierVulkanSubgroupStorageClass) {
  742. const std::string body = R"(
  743. OpMemoryBarrier %device %acquire_release_subgroup
  744. )";
  745. CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
  746. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  747. EXPECT_THAT(getDiagnosticString(),
  748. AnyVUID("VUID-StandaloneSpirv-OpMemoryBarrier-04733"));
  749. EXPECT_THAT(getDiagnosticString(),
  750. HasSubstr("MemoryBarrier: expected Memory Semantics to include a "
  751. "Vulkan-supported storage class"));
  752. }
  753. TEST_F(ValidateBarriers, OpNamedBarrierInitializeSuccess) {
  754. const std::string body = R"(
  755. %barrier = OpNamedBarrierInitialize %named_barrier %u32_4
  756. )";
  757. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  758. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  759. }
  760. TEST_F(ValidateBarriers, OpNamedBarrierInitializeWrongResultType) {
  761. const std::string body = R"(
  762. %barrier = OpNamedBarrierInitialize %u32 %u32_4
  763. )";
  764. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  765. ASSERT_EQ(SPV_ERROR_INVALID_DATA,
  766. ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  767. EXPECT_THAT(getDiagnosticString(),
  768. HasSubstr("NamedBarrierInitialize: expected Result Type to be "
  769. "OpTypeNamedBarrier"));
  770. }
  771. TEST_F(ValidateBarriers, OpNamedBarrierInitializeFloatSubgroupCount) {
  772. const std::string body = R"(
  773. %barrier = OpNamedBarrierInitialize %named_barrier %f32_4
  774. )";
  775. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  776. ASSERT_EQ(SPV_ERROR_INVALID_DATA,
  777. ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  778. EXPECT_THAT(getDiagnosticString(),
  779. HasSubstr("NamedBarrierInitialize: expected Subgroup Count to be "
  780. "a 32-bit int"));
  781. }
  782. TEST_F(ValidateBarriers, OpNamedBarrierInitializeU64SubgroupCount) {
  783. const std::string body = R"(
  784. %barrier = OpNamedBarrierInitialize %named_barrier %u64_4
  785. )";
  786. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  787. ASSERT_EQ(SPV_ERROR_INVALID_DATA,
  788. ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  789. EXPECT_THAT(getDiagnosticString(),
  790. HasSubstr("NamedBarrierInitialize: expected Subgroup Count to be "
  791. "a 32-bit int"));
  792. }
  793. TEST_F(ValidateBarriers, OpMemoryNamedBarrierSuccess) {
  794. const std::string body = R"(
  795. %barrier = OpNamedBarrierInitialize %named_barrier %u32_4
  796. OpMemoryNamedBarrier %barrier %workgroup %acquire_release_workgroup
  797. )";
  798. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  799. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  800. }
  801. TEST_F(ValidateBarriers, OpMemoryNamedBarrierNotNamedBarrier) {
  802. const std::string body = R"(
  803. OpMemoryNamedBarrier %u32_1 %workgroup %acquire_release_workgroup
  804. )";
  805. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  806. ASSERT_EQ(SPV_ERROR_INVALID_DATA,
  807. ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  808. EXPECT_THAT(getDiagnosticString(),
  809. HasSubstr("MemoryNamedBarrier: expected Named Barrier to be of "
  810. "type OpTypeNamedBarrier"));
  811. }
  812. TEST_F(ValidateBarriers, OpMemoryNamedBarrierFloatMemoryScope) {
  813. const std::string body = R"(
  814. %barrier = OpNamedBarrierInitialize %named_barrier %u32_4
  815. OpMemoryNamedBarrier %barrier %f32_1 %acquire_release_workgroup
  816. )";
  817. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  818. ASSERT_EQ(SPV_ERROR_INVALID_DATA,
  819. ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  820. EXPECT_THAT(
  821. getDiagnosticString(),
  822. HasSubstr("MemoryNamedBarrier: expected scope to be a 32-bit int"));
  823. }
  824. TEST_F(ValidateBarriers, OpMemoryNamedBarrierFloatMemorySemantics) {
  825. const std::string body = R"(
  826. %barrier = OpNamedBarrierInitialize %named_barrier %u32_4
  827. OpMemoryNamedBarrier %barrier %workgroup %f32_0
  828. )";
  829. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  830. ASSERT_EQ(SPV_ERROR_INVALID_DATA,
  831. ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  832. EXPECT_THAT(
  833. getDiagnosticString(),
  834. HasSubstr(
  835. "MemoryNamedBarrier: expected Memory Semantics to be a 32-bit int"));
  836. }
  837. TEST_F(ValidateBarriers, OpMemoryNamedBarrierAcquireAndRelease) {
  838. const std::string body = R"(
  839. %barrier = OpNamedBarrierInitialize %named_barrier %u32_4
  840. OpMemoryNamedBarrier %barrier %workgroup %acquire_and_release
  841. )";
  842. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  843. ASSERT_EQ(SPV_ERROR_INVALID_DATA,
  844. ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  845. EXPECT_THAT(getDiagnosticString(),
  846. HasSubstr("MemoryNamedBarrier: Memory Semantics can have at most "
  847. "one of the following bits set: Acquire, Release, "
  848. "AcquireRelease or SequentiallyConsistent"));
  849. }
  850. TEST_F(ValidateBarriers, TypeAsMemoryScope) {
  851. const std::string body = R"(
  852. OpMemoryBarrier %u32 %u32_0
  853. )";
  854. CompileSuccessfully(GenerateKernelCode(body), SPV_ENV_UNIVERSAL_1_1);
  855. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
  856. EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand '5[%uint]' cannot be a "
  857. "type"));
  858. }
  859. TEST_F(ValidateBarriers,
  860. OpControlBarrierVulkanMemoryModelBanSequentiallyConsistent) {
  861. const std::string text = R"(
  862. OpCapability Shader
  863. OpCapability VulkanMemoryModelKHR
  864. OpExtension "SPV_KHR_vulkan_memory_model"
  865. OpMemoryModel Logical VulkanKHR
  866. OpEntryPoint Fragment %1 "func"
  867. OpExecutionMode %1 OriginUpperLeft
  868. %2 = OpTypeVoid
  869. %3 = OpTypeInt 32 0
  870. %4 = OpConstant %3 16
  871. %5 = OpTypeFunction %2
  872. %6 = OpConstant %3 5
  873. %1 = OpFunction %2 None %5
  874. %7 = OpLabel
  875. OpControlBarrier %6 %6 %4
  876. OpReturn
  877. OpFunctionEnd
  878. )";
  879. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
  880. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  881. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  882. EXPECT_THAT(getDiagnosticString(),
  883. HasSubstr("SequentiallyConsistent memory semantics cannot be "
  884. "used with the VulkanKHR memory model."));
  885. }
  886. TEST_F(ValidateBarriers,
  887. OpMemoryBarrierVulkanMemoryModelBanSequentiallyConsistent) {
  888. const std::string text = R"(
  889. OpCapability Shader
  890. OpCapability VulkanMemoryModelKHR
  891. OpExtension "SPV_KHR_vulkan_memory_model"
  892. OpMemoryModel Logical VulkanKHR
  893. OpEntryPoint Fragment %1 "func"
  894. OpExecutionMode %1 OriginUpperLeft
  895. %2 = OpTypeVoid
  896. %3 = OpTypeInt 32 0
  897. %4 = OpConstant %3 16
  898. %5 = OpTypeFunction %2
  899. %6 = OpConstant %3 5
  900. %1 = OpFunction %2 None %5
  901. %7 = OpLabel
  902. OpMemoryBarrier %6 %4
  903. OpReturn
  904. OpFunctionEnd
  905. )";
  906. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
  907. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  908. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  909. EXPECT_THAT(getDiagnosticString(),
  910. HasSubstr("SequentiallyConsistent memory semantics cannot be "
  911. "used with the VulkanKHR memory model."));
  912. }
  913. TEST_F(ValidateBarriers, OutputMemoryKHRRequireVulkanMemoryModelKHR) {
  914. const std::string text = R"(
  915. OpCapability Shader
  916. OpMemoryModel Logical GLSL450
  917. OpEntryPoint Fragment %1 "func"
  918. OpExecutionMode %1 OriginUpperLeft
  919. %2 = OpTypeVoid
  920. %3 = OpTypeInt 32 0
  921. %semantics = OpConstant %3 4104
  922. %5 = OpTypeFunction %2
  923. %device = OpConstant %3 1
  924. %1 = OpFunction %2 None %5
  925. %7 = OpLabel
  926. OpControlBarrier %device %device %semantics
  927. OpReturn
  928. OpFunctionEnd
  929. )";
  930. CompileSuccessfully(text);
  931. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  932. EXPECT_THAT(getDiagnosticString(),
  933. HasSubstr("ControlBarrier: Memory Semantics OutputMemoryKHR "
  934. "requires capability VulkanMemoryModelKHR"));
  935. }
  936. TEST_F(ValidateBarriers, MakeAvailableKHRRequireVulkanMemoryModelKHR) {
  937. const std::string text = R"(
  938. OpCapability Shader
  939. OpMemoryModel Logical GLSL450
  940. OpEntryPoint Fragment %1 "func"
  941. OpExecutionMode %1 OriginUpperLeft
  942. %2 = OpTypeVoid
  943. %3 = OpTypeInt 32 0
  944. %semantics = OpConstant %3 8264
  945. %5 = OpTypeFunction %2
  946. %device = OpConstant %3 1
  947. %1 = OpFunction %2 None %5
  948. %7 = OpLabel
  949. OpControlBarrier %device %device %semantics
  950. OpReturn
  951. OpFunctionEnd
  952. )";
  953. CompileSuccessfully(text);
  954. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  955. EXPECT_THAT(getDiagnosticString(),
  956. HasSubstr("ControlBarrier: Memory Semantics MakeAvailableKHR "
  957. "requires capability VulkanMemoryModelKHR"));
  958. }
  959. TEST_F(ValidateBarriers, MakeVisibleKHRRequireVulkanMemoryModelKHR) {
  960. const std::string text = R"(
  961. OpCapability Shader
  962. OpMemoryModel Logical GLSL450
  963. OpEntryPoint Fragment %1 "func"
  964. OpExecutionMode %1 OriginUpperLeft
  965. %2 = OpTypeVoid
  966. %3 = OpTypeInt 32 0
  967. %semantics = OpConstant %3 16456
  968. %5 = OpTypeFunction %2
  969. %device = OpConstant %3 1
  970. %1 = OpFunction %2 None %5
  971. %7 = OpLabel
  972. OpControlBarrier %device %device %semantics
  973. OpReturn
  974. OpFunctionEnd
  975. )";
  976. CompileSuccessfully(text);
  977. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  978. EXPECT_THAT(getDiagnosticString(),
  979. HasSubstr("ControlBarrier: Memory Semantics MakeVisibleKHR "
  980. "requires capability VulkanMemoryModelKHR"));
  981. }
  982. TEST_F(ValidateBarriers, MakeAvailableKHRRequiresReleaseSemantics) {
  983. const std::string text = R"(
  984. OpCapability Shader
  985. OpCapability VulkanMemoryModelKHR
  986. OpExtension "SPV_KHR_vulkan_memory_model"
  987. OpMemoryModel Logical VulkanKHR
  988. OpEntryPoint Fragment %func "func"
  989. OpExecutionMode %func OriginUpperLeft
  990. %void = OpTypeVoid
  991. %int = OpTypeInt 32 0
  992. %workgroup = OpConstant %int 2
  993. %semantics = OpConstant %int 8448
  994. %functy = OpTypeFunction %void
  995. %func = OpFunction %void None %functy
  996. %1 = OpLabel
  997. OpControlBarrier %workgroup %workgroup %semantics
  998. OpReturn
  999. OpFunctionEnd
  1000. )";
  1001. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
  1002. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1003. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1004. EXPECT_THAT(
  1005. getDiagnosticString(),
  1006. HasSubstr("ControlBarrier: MakeAvailableKHR Memory Semantics also "
  1007. "requires either Release or AcquireRelease Memory Semantics"));
  1008. }
  1009. TEST_F(ValidateBarriers, MakeVisibleKHRRequiresAcquireSemantics) {
  1010. const std::string text = R"(
  1011. OpCapability Shader
  1012. OpCapability VulkanMemoryModelKHR
  1013. OpExtension "SPV_KHR_vulkan_memory_model"
  1014. OpMemoryModel Logical VulkanKHR
  1015. OpEntryPoint Fragment %func "func"
  1016. OpExecutionMode %func OriginUpperLeft
  1017. %void = OpTypeVoid
  1018. %int = OpTypeInt 32 0
  1019. %workgroup = OpConstant %int 2
  1020. %semantics = OpConstant %int 16640
  1021. %functy = OpTypeFunction %void
  1022. %func = OpFunction %void None %functy
  1023. %1 = OpLabel
  1024. OpControlBarrier %workgroup %workgroup %semantics
  1025. OpReturn
  1026. OpFunctionEnd
  1027. )";
  1028. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
  1029. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1030. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1031. EXPECT_THAT(
  1032. getDiagnosticString(),
  1033. HasSubstr("ControlBarrier: MakeVisibleKHR Memory Semantics also requires "
  1034. "either Acquire or AcquireRelease Memory Semantics"));
  1035. }
  1036. TEST_F(ValidateBarriers, MakeAvailableKHRRequiresStorageSemantics) {
  1037. const std::string text = R"(
  1038. OpCapability Shader
  1039. OpCapability VulkanMemoryModelKHR
  1040. OpExtension "SPV_KHR_vulkan_memory_model"
  1041. OpMemoryModel Logical VulkanKHR
  1042. OpEntryPoint Fragment %func "func"
  1043. OpExecutionMode %func OriginUpperLeft
  1044. %void = OpTypeVoid
  1045. %int = OpTypeInt 32 0
  1046. %workgroup = OpConstant %int 2
  1047. %semantics = OpConstant %int 8196
  1048. %functy = OpTypeFunction %void
  1049. %func = OpFunction %void None %functy
  1050. %1 = OpLabel
  1051. OpMemoryBarrier %workgroup %semantics
  1052. OpReturn
  1053. OpFunctionEnd
  1054. )";
  1055. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
  1056. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1057. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1058. EXPECT_THAT(getDiagnosticString(),
  1059. HasSubstr("MemoryBarrier: expected Memory Semantics to include a "
  1060. "storage class"));
  1061. }
  1062. TEST_F(ValidateBarriers, MakeVisibleKHRRequiresStorageSemantics) {
  1063. const std::string text = R"(
  1064. OpCapability Shader
  1065. OpCapability VulkanMemoryModelKHR
  1066. OpExtension "SPV_KHR_vulkan_memory_model"
  1067. OpMemoryModel Logical VulkanKHR
  1068. OpEntryPoint Fragment %func "func"
  1069. OpExecutionMode %func OriginUpperLeft
  1070. %void = OpTypeVoid
  1071. %int = OpTypeInt 32 0
  1072. %workgroup = OpConstant %int 2
  1073. %semantics = OpConstant %int 16386
  1074. %functy = OpTypeFunction %void
  1075. %func = OpFunction %void None %functy
  1076. %1 = OpLabel
  1077. OpMemoryBarrier %workgroup %semantics
  1078. OpReturn
  1079. OpFunctionEnd
  1080. )";
  1081. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
  1082. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1083. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1084. EXPECT_THAT(getDiagnosticString(),
  1085. HasSubstr("MemoryBarrier: expected Memory Semantics to include a "
  1086. "storage class"));
  1087. }
  1088. TEST_F(ValidateBarriers, SemanticsSpecConstantShader) {
  1089. const std::string spirv = R"(
  1090. OpCapability Shader
  1091. OpMemoryModel Logical GLSL450
  1092. OpEntryPoint Fragment %func "func"
  1093. OpExecutionMode %func OriginUpperLeft
  1094. %void = OpTypeVoid
  1095. %int = OpTypeInt 32 0
  1096. %ptr_int_workgroup = OpTypePointer Workgroup %int
  1097. %var = OpVariable %ptr_int_workgroup Workgroup
  1098. %voidfn = OpTypeFunction %void
  1099. %spec_const = OpSpecConstant %int 0
  1100. %workgroup = OpConstant %int 2
  1101. %func = OpFunction %void None %voidfn
  1102. %entry = OpLabel
  1103. OpMemoryBarrier %workgroup %spec_const
  1104. OpReturn
  1105. OpFunctionEnd
  1106. )";
  1107. CompileSuccessfully(spirv);
  1108. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1109. EXPECT_THAT(getDiagnosticString(),
  1110. HasSubstr("Memory Semantics ids must be OpConstant when Shader "
  1111. "capability is present"));
  1112. }
  1113. TEST_F(ValidateBarriers, SemanticsSpecConstantKernel) {
  1114. const std::string spirv = R"(
  1115. OpCapability Kernel
  1116. OpCapability Linkage
  1117. OpMemoryModel Logical OpenCL
  1118. %void = OpTypeVoid
  1119. %int = OpTypeInt 32 0
  1120. %ptr_int_workgroup = OpTypePointer Workgroup %int
  1121. %var = OpVariable %ptr_int_workgroup Workgroup
  1122. %voidfn = OpTypeFunction %void
  1123. %spec_const = OpSpecConstant %int 0
  1124. %workgroup = OpConstant %int 2
  1125. %func = OpFunction %void None %voidfn
  1126. %entry = OpLabel
  1127. OpMemoryBarrier %workgroup %spec_const
  1128. OpReturn
  1129. OpFunctionEnd
  1130. )";
  1131. CompileSuccessfully(spirv);
  1132. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  1133. }
  1134. TEST_F(ValidateBarriers, ScopeSpecConstantShader) {
  1135. const std::string spirv = R"(
  1136. OpCapability Shader
  1137. OpMemoryModel Logical GLSL450
  1138. OpEntryPoint Fragment %func "func"
  1139. OpExecutionMode %func OriginUpperLeft
  1140. %void = OpTypeVoid
  1141. %int = OpTypeInt 32 0
  1142. %ptr_int_workgroup = OpTypePointer Workgroup %int
  1143. %var = OpVariable %ptr_int_workgroup Workgroup
  1144. %voidfn = OpTypeFunction %void
  1145. %spec_const = OpSpecConstant %int 0
  1146. %relaxed = OpConstant %int 0
  1147. %func = OpFunction %void None %voidfn
  1148. %entry = OpLabel
  1149. OpMemoryBarrier %spec_const %relaxed
  1150. OpReturn
  1151. OpFunctionEnd
  1152. )";
  1153. CompileSuccessfully(spirv);
  1154. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1155. EXPECT_THAT(getDiagnosticString(),
  1156. HasSubstr("Scope ids must be OpConstant when Shader "
  1157. "capability is present"));
  1158. }
  1159. TEST_F(ValidateBarriers, ScopeSpecConstantKernel) {
  1160. const std::string spirv = R"(
  1161. OpCapability Kernel
  1162. OpCapability Linkage
  1163. OpMemoryModel Logical OpenCL
  1164. %void = OpTypeVoid
  1165. %int = OpTypeInt 32 0
  1166. %ptr_int_workgroup = OpTypePointer Workgroup %int
  1167. %var = OpVariable %ptr_int_workgroup Workgroup
  1168. %voidfn = OpTypeFunction %void
  1169. %spec_const = OpSpecConstant %int 0
  1170. %relaxed = OpConstant %int 0
  1171. %func = OpFunction %void None %voidfn
  1172. %entry = OpLabel
  1173. OpMemoryBarrier %spec_const %relaxed
  1174. OpReturn
  1175. OpFunctionEnd
  1176. )";
  1177. CompileSuccessfully(spirv);
  1178. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  1179. }
  1180. TEST_F(ValidateBarriers, VulkanMemoryModelDeviceScopeBad) {
  1181. const std::string text = R"(
  1182. OpCapability Shader
  1183. OpCapability VulkanMemoryModelKHR
  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_ERROR_INVALID_DATA,
  1201. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1202. EXPECT_THAT(
  1203. getDiagnosticString(),
  1204. HasSubstr("Use of device scope with VulkanKHR memory model requires the "
  1205. "VulkanMemoryModelDeviceScopeKHR capability"));
  1206. }
  1207. TEST_F(ValidateBarriers, VulkanMemoryModelDeviceScopeGood) {
  1208. const std::string text = R"(
  1209. OpCapability Shader
  1210. OpCapability VulkanMemoryModelKHR
  1211. OpCapability VulkanMemoryModelDeviceScopeKHR
  1212. OpExtension "SPV_KHR_vulkan_memory_model"
  1213. OpMemoryModel Logical VulkanKHR
  1214. OpEntryPoint Fragment %func "func"
  1215. OpExecutionMode %func OriginUpperLeft
  1216. %void = OpTypeVoid
  1217. %int = OpTypeInt 32 0
  1218. %device = OpConstant %int 1
  1219. %semantics = OpConstant %int 0
  1220. %functy = OpTypeFunction %void
  1221. %func = OpFunction %void None %functy
  1222. %1 = OpLabel
  1223. OpMemoryBarrier %device %semantics
  1224. OpReturn
  1225. OpFunctionEnd
  1226. )";
  1227. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
  1228. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1229. }
  1230. TEST_F(ValidateBarriers, VolatileMemoryBarrier) {
  1231. const std::string text = R"(
  1232. OpCapability Shader
  1233. OpCapability VulkanMemoryModelKHR
  1234. OpCapability VulkanMemoryModelDeviceScopeKHR
  1235. OpCapability Linkage
  1236. OpExtension "SPV_KHR_vulkan_memory_model"
  1237. OpMemoryModel Logical VulkanKHR
  1238. %void = OpTypeVoid
  1239. %int = OpTypeInt 32 0
  1240. %device = OpConstant %int 1
  1241. %semantics = OpConstant %int 32768
  1242. %functy = OpTypeFunction %void
  1243. %func = OpFunction %void None %functy
  1244. %1 = OpLabel
  1245. OpMemoryBarrier %device %semantics
  1246. OpReturn
  1247. OpFunctionEnd
  1248. )";
  1249. CompileSuccessfully(text);
  1250. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1251. EXPECT_THAT(getDiagnosticString(),
  1252. HasSubstr("Memory Semantics Volatile can only be used with "
  1253. "atomic instructions"));
  1254. }
  1255. TEST_F(ValidateBarriers, VolatileControlBarrier) {
  1256. const std::string text = R"(
  1257. OpCapability Shader
  1258. OpCapability VulkanMemoryModelKHR
  1259. OpCapability VulkanMemoryModelDeviceScopeKHR
  1260. OpCapability Linkage
  1261. OpExtension "SPV_KHR_vulkan_memory_model"
  1262. OpMemoryModel Logical VulkanKHR
  1263. %void = OpTypeVoid
  1264. %int = OpTypeInt 32 0
  1265. %device = OpConstant %int 1
  1266. %semantics = OpConstant %int 32768
  1267. %functy = OpTypeFunction %void
  1268. %func = OpFunction %void None %functy
  1269. %1 = OpLabel
  1270. OpControlBarrier %device %device %semantics
  1271. OpReturn
  1272. OpFunctionEnd
  1273. )";
  1274. CompileSuccessfully(text);
  1275. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1276. EXPECT_THAT(getDiagnosticString(),
  1277. HasSubstr("Memory Semantics Volatile can only be used with "
  1278. "atomic instructions"));
  1279. }
  1280. TEST_F(ValidateBarriers, CooperativeMatrixSpecConstantVolatile) {
  1281. const std::string text = R"(
  1282. OpCapability Shader
  1283. OpCapability VulkanMemoryModelKHR
  1284. OpCapability VulkanMemoryModelDeviceScopeKHR
  1285. OpCapability CooperativeMatrixNV
  1286. OpCapability Linkage
  1287. OpExtension "SPV_KHR_vulkan_memory_model"
  1288. OpExtension "SPV_NV_cooperative_matrix"
  1289. OpMemoryModel Logical VulkanKHR
  1290. %void = OpTypeVoid
  1291. %int = OpTypeInt 32 0
  1292. %device = OpConstant %int 1
  1293. %semantics = OpSpecConstant %int 32768
  1294. %functy = OpTypeFunction %void
  1295. %func = OpFunction %void None %functy
  1296. %1 = OpLabel
  1297. OpControlBarrier %device %device %semantics
  1298. OpReturn
  1299. OpFunctionEnd
  1300. )";
  1301. CompileSuccessfully(text);
  1302. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  1303. }
  1304. TEST_F(ValidateBarriers, CooperativeMatrixNonConstantSemantics) {
  1305. const std::string text = R"(
  1306. OpCapability Shader
  1307. OpCapability VulkanMemoryModelKHR
  1308. OpCapability VulkanMemoryModelDeviceScopeKHR
  1309. OpCapability CooperativeMatrixNV
  1310. OpCapability Linkage
  1311. OpExtension "SPV_KHR_vulkan_memory_model"
  1312. OpExtension "SPV_NV_cooperative_matrix"
  1313. OpMemoryModel Logical VulkanKHR
  1314. %void = OpTypeVoid
  1315. %int = OpTypeInt 32 0
  1316. %device = OpConstant %int 1
  1317. %semantics = OpUndef %int
  1318. %functy = OpTypeFunction %void
  1319. %func = OpFunction %void None %functy
  1320. %1 = OpLabel
  1321. OpControlBarrier %device %device %semantics
  1322. OpReturn
  1323. OpFunctionEnd
  1324. )";
  1325. CompileSuccessfully(text);
  1326. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1327. EXPECT_THAT(getDiagnosticString(),
  1328. HasSubstr("Memory Semantics must be a constant instruction when "
  1329. "CooperativeMatrixNV capability is present"));
  1330. }
  1331. TEST_F(ValidateBarriers, OpMemoryBarrierShaderCallRayGenSuccess) {
  1332. const std::string body =
  1333. "OpMemoryBarrier %shadercall %release_uniform_workgroup";
  1334. CompileSuccessfully(GenerateShaderCodeImpl(body,
  1335. // capabilities_and_extensions
  1336. R"(
  1337. OpCapability VulkanMemoryModelKHR
  1338. OpCapability RayTracingKHR
  1339. OpExtension "SPV_KHR_vulkan_memory_model"
  1340. OpExtension "SPV_KHR_ray_tracing"
  1341. )",
  1342. // definitions
  1343. "",
  1344. // execution_model
  1345. "RayGenerationKHR",
  1346. // memory_model
  1347. "OpMemoryModel Logical VulkanKHR"),
  1348. SPV_ENV_VULKAN_1_1);
  1349. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  1350. }
  1351. TEST_F(ValidateBarriers, OpMemoryBarrierShaderCallComputeFailure) {
  1352. const std::string body =
  1353. "OpMemoryBarrier %shadercall %release_uniform_workgroup";
  1354. CompileSuccessfully(GenerateShaderCodeImpl(body,
  1355. // capabilities_and_extensions
  1356. R"(
  1357. OpCapability VulkanMemoryModelKHR
  1358. OpExtension "SPV_KHR_vulkan_memory_model"
  1359. )",
  1360. // definitions
  1361. "",
  1362. // execution_model
  1363. "GLCompute",
  1364. // memory_model
  1365. "OpMemoryModel Logical VulkanKHR"),
  1366. SPV_ENV_VULKAN_1_1);
  1367. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  1368. EXPECT_THAT(getDiagnosticString(),
  1369. AnyVUID("VUID-StandaloneSpirv-None-04640"));
  1370. EXPECT_THAT(
  1371. getDiagnosticString(),
  1372. HasSubstr(
  1373. "ShaderCallKHR Memory Scope requires a ray tracing execution model"));
  1374. }
  1375. TEST_F(ValidateBarriers, OpControlBarrierShaderCallRayGenFailure) {
  1376. const std::string body = "OpControlBarrier %shadercall %shadercall %none";
  1377. CompileSuccessfully(GenerateShaderCodeImpl(body,
  1378. // capabilities_and_extensions
  1379. R"(
  1380. OpCapability VulkanMemoryModelKHR
  1381. OpCapability RayTracingKHR
  1382. OpExtension "SPV_KHR_vulkan_memory_model"
  1383. OpExtension "SPV_KHR_ray_tracing"
  1384. )",
  1385. // definitions
  1386. "",
  1387. // execution_model
  1388. "RayGenerationKHR",
  1389. // memory_model
  1390. "OpMemoryModel Logical VulkanKHR"),
  1391. SPV_ENV_VULKAN_1_1);
  1392. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  1393. EXPECT_THAT(getDiagnosticString(),
  1394. AnyVUID("VUID-StandaloneSpirv-None-04636"));
  1395. EXPECT_THAT(getDiagnosticString(),
  1396. HasSubstr("in Vulkan environment Execution Scope is limited to "
  1397. "Workgroup and Subgroup"));
  1398. }
  1399. } // namespace
  1400. } // namespace val
  1401. } // namespace spvtools