spread_volatile_semantics_test.cpp 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267
  1. // Copyright (c) 2022 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 <string>
  15. #include "gmock/gmock.h"
  16. #include "test/opt/pass_fixture.h"
  17. #include "test/opt/pass_utils.h"
  18. namespace spvtools {
  19. namespace opt {
  20. namespace {
  21. struct ExecutionModelAndBuiltIn {
  22. const char* execution_model;
  23. const char* built_in;
  24. const bool use_v4uint;
  25. };
  26. using AddVolatileDecorationTest =
  27. PassTest<::testing::TestWithParam<ExecutionModelAndBuiltIn>>;
  28. TEST_P(AddVolatileDecorationTest, InMain) {
  29. const auto& tc = GetParam();
  30. const std::string execution_model(tc.execution_model);
  31. const std::string built_in(tc.built_in);
  32. const std::string var_type =
  33. tc.use_v4uint ? "%_ptr_Input_v4uint" : "%_ptr_Input_uint";
  34. const std::string var_load_type = tc.use_v4uint ? "%v4uint" : "%uint";
  35. const std::string text =
  36. std::string(R"(OpCapability RuntimeDescriptorArray
  37. OpCapability RayTracingKHR
  38. OpCapability SubgroupBallotKHR
  39. OpExtension "SPV_EXT_descriptor_indexing"
  40. OpExtension "SPV_KHR_ray_tracing"
  41. OpExtension "SPV_KHR_shader_ballot"
  42. %1 = OpExtInstImport "GLSL.std.450"
  43. OpMemoryModel Logical GLSL450
  44. OpEntryPoint )") +
  45. execution_model + std::string(R"( %main "main" %var
  46. OpSource GLSL 460
  47. OpSourceExtension "GL_EXT_nonuniform_qualifier"
  48. OpSourceExtension "GL_KHR_ray_tracing"
  49. OpName %main "main"
  50. OpName %fn "fn"
  51. OpName %StorageBuffer "StorageBuffer"
  52. OpMemberName %StorageBuffer 0 "index"
  53. OpMemberName %StorageBuffer 1 "red"
  54. OpName %sbo "sbo"
  55. OpName %images "images"
  56. OpMemberDecorate %StorageBuffer 0 Offset 0
  57. OpMemberDecorate %StorageBuffer 1 Offset 4
  58. OpDecorate %StorageBuffer BufferBlock
  59. OpDecorate %sbo DescriptorSet 0
  60. OpDecorate %sbo Binding 0
  61. OpDecorate %images DescriptorSet 0
  62. OpDecorate %images Binding 1
  63. OpDecorate %images NonWritable
  64. )") + std::string(R"(
  65. ; CHECK: OpDecorate [[var:%\w+]] BuiltIn )") +
  66. built_in + std::string(R"(
  67. ; CHECK: OpDecorate [[var]] Volatile
  68. OpDecorate %var BuiltIn )") + built_in + std::string(R"(
  69. %void = OpTypeVoid
  70. %3 = OpTypeFunction %void
  71. %uint = OpTypeInt 32 0
  72. %float = OpTypeFloat 32
  73. %StorageBuffer = OpTypeStruct %uint %float
  74. %_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer
  75. %sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform
  76. %int = OpTypeInt 32 1
  77. %int_1 = OpConstant %int 1
  78. %13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
  79. %_runtimearr_13 = OpTypeRuntimeArray %13
  80. %_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
  81. %images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
  82. %_ptr_Input_uint = OpTypePointer Input %uint
  83. %v4uint = OpTypeVector %uint 4
  84. %_ptr_Input_v4uint = OpTypePointer Input %v4uint
  85. %var = OpVariable )") +
  86. var_type + std::string(R"( Input
  87. %int_0 = OpConstant %int 0
  88. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  89. %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
  90. %v2int = OpTypeVector %int 2
  91. %25 = OpConstantComposite %v2int %int_0 %int_0
  92. %v4float = OpTypeVector %float 4
  93. %uint_0 = OpConstant %uint 0
  94. %_ptr_Uniform_float = OpTypePointer Uniform %float
  95. %main = OpFunction %void None %3
  96. %5 = OpLabel
  97. %19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
  98. %20 = OpLoad %uint %19
  99. %load = OpLoad )") + var_load_type + std::string(R"( %var
  100. %22 = OpAccessChain %_ptr_UniformConstant_13 %images %20
  101. %23 = OpLoad %13 %22
  102. %27 = OpImageRead %v4float %23 %25
  103. %29 = OpCompositeExtract %float %27 0
  104. %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
  105. OpStore %31 %29
  106. %32 = OpFunctionCall %void %fn
  107. OpReturn
  108. OpFunctionEnd
  109. %fn = OpFunction %void None %3
  110. %33 = OpLabel
  111. OpReturn
  112. OpFunctionEnd
  113. )");
  114. SinglePassRunAndMatch<SpreadVolatileSemantics>(text, true);
  115. }
  116. INSTANTIATE_TEST_SUITE_P(
  117. AddVolatileDecoration, AddVolatileDecorationTest,
  118. ::testing::ValuesIn(std::vector<ExecutionModelAndBuiltIn>{
  119. {"RayGenerationKHR", "SubgroupSize", false},
  120. {"RayGenerationKHR", "SubgroupLocalInvocationId", false},
  121. {"RayGenerationKHR", "SubgroupEqMask", true},
  122. {"ClosestHitKHR", "SubgroupLocalInvocationId", true},
  123. {"IntersectionKHR", "SubgroupEqMask", true},
  124. {"MissKHR", "SubgroupGeMask", true},
  125. {"CallableKHR", "SubgroupGtMask", true},
  126. {"RayGenerationKHR", "SubgroupLeMask", true},
  127. }));
  128. using SetLoadVolatileTest =
  129. PassTest<::testing::TestWithParam<ExecutionModelAndBuiltIn>>;
  130. TEST_P(SetLoadVolatileTest, InMain) {
  131. const auto& tc = GetParam();
  132. const std::string execution_model(tc.execution_model);
  133. const std::string built_in(tc.built_in);
  134. const std::string var_type =
  135. tc.use_v4uint ? "%_ptr_Input_v4uint" : "%_ptr_Input_uint";
  136. const std::string var_value = tc.use_v4uint ? std::string(R"(
  137. ; CHECK: [[ptr:%\w+]] = OpAccessChain %_ptr_Input_uint [[var]] %int_0
  138. ; CHECK: OpLoad {{%\w+}} [[ptr]] Volatile
  139. %ptr = OpAccessChain %_ptr_Input_uint %var %int_0
  140. %var_value = OpLoad %uint %ptr)")
  141. : std::string(R"(
  142. ; CHECK: OpLoad {{%\w+}} [[var]] Volatile
  143. %var_value = OpLoad %uint %var)");
  144. const std::string text = std::string(R"(OpCapability RuntimeDescriptorArray
  145. OpCapability RayTracingKHR
  146. OpCapability SubgroupBallotKHR
  147. OpCapability VulkanMemoryModel
  148. OpExtension "SPV_KHR_vulkan_memory_model"
  149. OpExtension "SPV_EXT_descriptor_indexing"
  150. OpExtension "SPV_KHR_ray_tracing"
  151. OpExtension "SPV_KHR_shader_ballot"
  152. OpMemoryModel Logical Vulkan
  153. OpEntryPoint )") + execution_model +
  154. std::string(R"( %main "main" %var
  155. OpName %main "main"
  156. OpName %StorageBuffer "StorageBuffer"
  157. OpMemberName %StorageBuffer 0 "index"
  158. OpMemberName %StorageBuffer 1 "red"
  159. OpName %sbo "sbo"
  160. OpName %images "images"
  161. OpMemberDecorate %StorageBuffer 0 Offset 0
  162. OpMemberDecorate %StorageBuffer 1 Offset 4
  163. OpDecorate %StorageBuffer BufferBlock
  164. OpDecorate %sbo DescriptorSet 0
  165. OpDecorate %sbo Binding 0
  166. OpDecorate %images DescriptorSet 0
  167. OpDecorate %images Binding 1
  168. OpDecorate %images NonWritable
  169. )") + std::string(R"(
  170. ; CHECK: OpDecorate [[var:%\w+]] BuiltIn )") +
  171. built_in + std::string(R"(
  172. OpDecorate %var BuiltIn )") + built_in +
  173. std::string(R"(
  174. %void = OpTypeVoid
  175. %3 = OpTypeFunction %void
  176. %uint = OpTypeInt 32 0
  177. %float = OpTypeFloat 32
  178. %StorageBuffer = OpTypeStruct %uint %float
  179. %_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer
  180. %sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform
  181. %int = OpTypeInt 32 1
  182. %int_1 = OpConstant %int 1
  183. %13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
  184. %_runtimearr_13 = OpTypeRuntimeArray %13
  185. %_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
  186. %images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
  187. %_ptr_Input_uint = OpTypePointer Input %uint
  188. %v4uint = OpTypeVector %uint 4
  189. %_ptr_Input_v4uint = OpTypePointer Input %v4uint
  190. %var = OpVariable )") + var_type +
  191. std::string(R"( Input
  192. %int_0 = OpConstant %int 0
  193. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  194. %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
  195. %v2int = OpTypeVector %int 2
  196. %25 = OpConstantComposite %v2int %int_0 %int_0
  197. %v4float = OpTypeVector %float 4
  198. %uint_0 = OpConstant %uint 0
  199. %_ptr_Uniform_float = OpTypePointer Uniform %float
  200. %main = OpFunction %void None %3
  201. %5 = OpLabel
  202. %19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
  203. %20 = OpLoad %uint %19
  204. )") + var_value + std::string(R"(
  205. %test = OpIAdd %uint %var_value %20
  206. %22 = OpAccessChain %_ptr_UniformConstant_13 %images %test
  207. %23 = OpLoad %13 %22
  208. %27 = OpImageRead %v4float %23 %25
  209. %29 = OpCompositeExtract %float %27 0
  210. %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
  211. OpStore %31 %29
  212. OpReturn
  213. OpFunctionEnd
  214. )");
  215. SinglePassRunAndMatch<SpreadVolatileSemantics>(text, true);
  216. }
  217. INSTANTIATE_TEST_SUITE_P(
  218. SetLoadVolatile, SetLoadVolatileTest,
  219. ::testing::ValuesIn(std::vector<ExecutionModelAndBuiltIn>{
  220. {"RayGenerationKHR", "SubgroupSize", false},
  221. {"RayGenerationKHR", "SubgroupLocalInvocationId", false},
  222. {"RayGenerationKHR", "SubgroupEqMask", true},
  223. {"ClosestHitKHR", "SubgroupLocalInvocationId", true},
  224. {"IntersectionKHR", "SubgroupEqMask", true},
  225. {"MissKHR", "SubgroupGeMask", true},
  226. {"CallableKHR", "SubgroupGtMask", true},
  227. {"RayGenerationKHR", "SubgroupLeMask", true},
  228. }));
  229. using VolatileSpreadTest = PassTest<::testing::Test>;
  230. TEST_F(VolatileSpreadTest, SpreadVolatileForHelperInvocation) {
  231. const std::string text =
  232. R"(
  233. OpCapability Shader
  234. OpCapability DemoteToHelperInvocation
  235. OpMemoryModel Logical GLSL450
  236. OpEntryPoint Fragment %main "main" %var
  237. OpExecutionMode %main OriginUpperLeft
  238. ; CHECK: OpDecorate [[var:%\w+]] BuiltIn HelperInvocation
  239. ; CHECK: OpDecorate [[var]] Volatile
  240. OpDecorate %var BuiltIn HelperInvocation
  241. %bool = OpTypeBool
  242. %void = OpTypeVoid
  243. %void_fn = OpTypeFunction %void
  244. %_ptr_Input_bool = OpTypePointer Input %bool
  245. %var = OpVariable %_ptr_Input_bool Input
  246. %main = OpFunction %void None %void_fn
  247. %entry = OpLabel
  248. %load = OpLoad %bool %var
  249. OpDemoteToHelperInvocation
  250. OpReturn
  251. OpFunctionEnd
  252. )";
  253. SetTargetEnv(SPV_ENV_UNIVERSAL_1_6);
  254. SinglePassRunAndMatch<SpreadVolatileSemantics>(text, true);
  255. }
  256. TEST_F(VolatileSpreadTest, MultipleExecutionModel) {
  257. const std::string text =
  258. R"(
  259. OpCapability RuntimeDescriptorArray
  260. OpCapability RayTracingKHR
  261. OpCapability SubgroupBallotKHR
  262. OpExtension "SPV_EXT_descriptor_indexing"
  263. OpExtension "SPV_KHR_ray_tracing"
  264. OpExtension "SPV_KHR_shader_ballot"
  265. %1 = OpExtInstImport "GLSL.std.450"
  266. OpMemoryModel Logical GLSL450
  267. OpEntryPoint RayGenerationKHR %RayGeneration "RayGeneration" %var
  268. OpEntryPoint GLCompute %compute "Compute" %gl_LocalInvocationIndex
  269. OpExecutionMode %compute LocalSize 16 16 1
  270. OpSource GLSL 460
  271. OpSourceExtension "GL_EXT_nonuniform_qualifier"
  272. OpSourceExtension "GL_KHR_ray_tracing"
  273. OpName %RayGeneration "RayGeneration"
  274. OpName %StorageBuffer "StorageBuffer"
  275. OpMemberName %StorageBuffer 0 "index"
  276. OpMemberName %StorageBuffer 1 "red"
  277. OpName %sbo "sbo"
  278. OpName %images "images"
  279. OpMemberDecorate %StorageBuffer 0 Offset 0
  280. OpMemberDecorate %StorageBuffer 1 Offset 4
  281. OpDecorate %gl_LocalInvocationIndex BuiltIn LocalInvocationIndex
  282. OpDecorate %StorageBuffer BufferBlock
  283. OpDecorate %sbo DescriptorSet 0
  284. OpDecorate %sbo Binding 0
  285. OpDecorate %images DescriptorSet 0
  286. OpDecorate %images Binding 1
  287. OpDecorate %images NonWritable
  288. ; CHECK: OpEntryPoint RayGenerationNV {{%\w+}} "RayGeneration" [[var:%\w+]]
  289. ; CHECK: OpDecorate [[var]] BuiltIn SubgroupSize
  290. ; CHECK: OpDecorate [[var]] Volatile
  291. ; CHECK-NOT: OpDecorate {{%\w+}} Volatile
  292. OpDecorate %var BuiltIn SubgroupSize
  293. %void = OpTypeVoid
  294. %3 = OpTypeFunction %void
  295. %uint = OpTypeInt 32 0
  296. %float = OpTypeFloat 32
  297. %StorageBuffer = OpTypeStruct %uint %float
  298. %_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer
  299. %sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform
  300. %int = OpTypeInt 32 1
  301. %int_1 = OpConstant %int 1
  302. %13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
  303. %_runtimearr_13 = OpTypeRuntimeArray %13
  304. %_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
  305. %images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
  306. %_ptr_Input_uint = OpTypePointer Input %uint
  307. %var = OpVariable %_ptr_Input_uint Input
  308. %int_0 = OpConstant %int 0
  309. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  310. %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
  311. %v2int = OpTypeVector %int 2
  312. %25 = OpConstantComposite %v2int %int_0 %int_0
  313. %v4float = OpTypeVector %float 4
  314. %uint_0 = OpConstant %uint 0
  315. %uint_1 = OpConstant %uint 1
  316. %_ptr_Uniform_float = OpTypePointer Uniform %float
  317. %gl_LocalInvocationIndex = OpVariable %_ptr_Input_uint Input
  318. %_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
  319. %shared = OpVariable %_ptr_Workgroup_uint Workgroup
  320. %RayGeneration = OpFunction %void None %3
  321. %5 = OpLabel
  322. %19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
  323. %20 = OpLoad %uint %var
  324. %22 = OpAccessChain %_ptr_UniformConstant_13 %images %20
  325. %23 = OpLoad %13 %22
  326. %27 = OpImageRead %v4float %23 %25
  327. %29 = OpCompositeExtract %float %27 0
  328. %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
  329. OpStore %31 %29
  330. OpReturn
  331. OpFunctionEnd
  332. %compute = OpFunction %void None %3
  333. %66 = OpLabel
  334. %62 = OpLoad %uint %gl_LocalInvocationIndex
  335. %61 = OpAtomicIAdd %uint %shared %uint_1 %uint_0 %62
  336. OpReturn
  337. OpFunctionEnd
  338. )";
  339. SinglePassRunAndMatch<SpreadVolatileSemantics>(text, true);
  340. }
  341. TEST_F(VolatileSpreadTest, VarUsedInMultipleEntryPoints) {
  342. const std::string text =
  343. R"(
  344. OpCapability RuntimeDescriptorArray
  345. OpCapability RayTracingKHR
  346. OpCapability SubgroupBallotKHR
  347. OpExtension "SPV_EXT_descriptor_indexing"
  348. OpExtension "SPV_KHR_ray_tracing"
  349. OpExtension "SPV_KHR_shader_ballot"
  350. %1 = OpExtInstImport "GLSL.std.450"
  351. OpMemoryModel Logical GLSL450
  352. OpEntryPoint RayGenerationKHR %RayGeneration "RayGeneration" %var
  353. OpEntryPoint ClosestHitKHR %ClosestHit "ClosestHit" %var
  354. OpSource GLSL 460
  355. OpSourceExtension "GL_EXT_nonuniform_qualifier"
  356. OpSourceExtension "GL_KHR_ray_tracing"
  357. OpName %RayGeneration "RayGeneration"
  358. OpName %ClosestHit "ClosestHit"
  359. OpName %StorageBuffer "StorageBuffer"
  360. OpMemberName %StorageBuffer 0 "index"
  361. OpMemberName %StorageBuffer 1 "red"
  362. OpName %sbo "sbo"
  363. OpName %images "images"
  364. OpMemberDecorate %StorageBuffer 0 Offset 0
  365. OpMemberDecorate %StorageBuffer 1 Offset 4
  366. OpDecorate %gl_LocalInvocationIndex BuiltIn LocalInvocationIndex
  367. OpDecorate %StorageBuffer BufferBlock
  368. OpDecorate %sbo DescriptorSet 0
  369. OpDecorate %sbo Binding 0
  370. OpDecorate %images DescriptorSet 0
  371. OpDecorate %images Binding 1
  372. OpDecorate %images NonWritable
  373. ; CHECK: OpEntryPoint RayGenerationNV {{%\w+}} "RayGeneration" [[var:%\w+]]
  374. ; CHECK: OpEntryPoint ClosestHitNV {{%\w+}} "ClosestHit" [[var]]
  375. ; CHECK: OpDecorate [[var]] BuiltIn SubgroupSize
  376. ; CHECK: OpDecorate [[var]] Volatile
  377. ; CHECK-NOT: OpDecorate {{%\w+}} Volatile
  378. OpDecorate %var BuiltIn SubgroupSize
  379. %void = OpTypeVoid
  380. %3 = OpTypeFunction %void
  381. %uint = OpTypeInt 32 0
  382. %float = OpTypeFloat 32
  383. %StorageBuffer = OpTypeStruct %uint %float
  384. %_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer
  385. %sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform
  386. %int = OpTypeInt 32 1
  387. %int_1 = OpConstant %int 1
  388. %13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
  389. %_runtimearr_13 = OpTypeRuntimeArray %13
  390. %_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
  391. %images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
  392. %_ptr_Input_uint = OpTypePointer Input %uint
  393. %var = OpVariable %_ptr_Input_uint Input
  394. %int_0 = OpConstant %int 0
  395. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  396. %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
  397. %v2int = OpTypeVector %int 2
  398. %25 = OpConstantComposite %v2int %int_0 %int_0
  399. %v4float = OpTypeVector %float 4
  400. %uint_0 = OpConstant %uint 0
  401. %uint_1 = OpConstant %uint 1
  402. %_ptr_Uniform_float = OpTypePointer Uniform %float
  403. %gl_LocalInvocationIndex = OpVariable %_ptr_Input_uint Input
  404. %_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
  405. %shared = OpVariable %_ptr_Workgroup_uint Workgroup
  406. %RayGeneration = OpFunction %void None %3
  407. %5 = OpLabel
  408. %19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
  409. %20 = OpLoad %uint %var
  410. %22 = OpAccessChain %_ptr_UniformConstant_13 %images %20
  411. %23 = OpLoad %13 %22
  412. %27 = OpImageRead %v4float %23 %25
  413. %29 = OpCompositeExtract %float %27 0
  414. %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
  415. OpStore %31 %29
  416. OpReturn
  417. OpFunctionEnd
  418. %ClosestHit = OpFunction %void None %3
  419. %45 = OpLabel
  420. %49 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
  421. %40 = OpLoad %uint %var
  422. %42 = OpAccessChain %_ptr_UniformConstant_13 %images %40
  423. %43 = OpLoad %13 %42
  424. %47 = OpImageRead %v4float %43 %25
  425. %59 = OpCompositeExtract %float %47 0
  426. %51 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
  427. OpStore %51 %59
  428. OpReturn
  429. OpFunctionEnd
  430. )";
  431. SinglePassRunAndMatch<SpreadVolatileSemantics>(text, true);
  432. }
  433. class VolatileSpreadErrorTest : public PassTest<::testing::Test> {
  434. public:
  435. VolatileSpreadErrorTest()
  436. : consumer_([this](spv_message_level_t level, const char*,
  437. const spv_position_t& position, const char* message) {
  438. if (!error_message_.empty()) error_message_ += "\n";
  439. switch (level) {
  440. case SPV_MSG_FATAL:
  441. case SPV_MSG_INTERNAL_ERROR:
  442. case SPV_MSG_ERROR:
  443. error_message_ += "ERROR";
  444. break;
  445. case SPV_MSG_WARNING:
  446. error_message_ += "WARNING";
  447. break;
  448. case SPV_MSG_INFO:
  449. error_message_ += "INFO";
  450. break;
  451. case SPV_MSG_DEBUG:
  452. error_message_ += "DEBUG";
  453. break;
  454. }
  455. error_message_ +=
  456. ": " + std::to_string(position.index) + ": " + message;
  457. }) {}
  458. Pass::Status RunPass(const std::string& text) {
  459. std::unique_ptr<IRContext> context_ =
  460. spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_2, consumer_, text);
  461. if (!context_.get()) return Pass::Status::Failure;
  462. PassManager manager;
  463. manager.SetMessageConsumer(consumer_);
  464. manager.AddPass<SpreadVolatileSemantics>();
  465. return manager.Run(context_.get());
  466. }
  467. std::string GetErrorMessage() const { return error_message_; }
  468. void TearDown() override { error_message_.clear(); }
  469. private:
  470. spvtools::MessageConsumer consumer_;
  471. std::string error_message_;
  472. };
  473. TEST_F(VolatileSpreadErrorTest, VarUsedInMultipleExecutionModelError) {
  474. const std::string text =
  475. R"(
  476. OpCapability RuntimeDescriptorArray
  477. OpCapability RayTracingKHR
  478. OpCapability SubgroupBallotKHR
  479. OpExtension "SPV_EXT_descriptor_indexing"
  480. OpExtension "SPV_KHR_ray_tracing"
  481. OpExtension "SPV_KHR_shader_ballot"
  482. %1 = OpExtInstImport "GLSL.std.450"
  483. OpMemoryModel Logical GLSL450
  484. OpEntryPoint RayGenerationKHR %RayGeneration "RayGeneration" %var
  485. OpEntryPoint GLCompute %compute "Compute" %gl_LocalInvocationIndex %var
  486. OpExecutionMode %compute LocalSize 16 16 1
  487. OpSource GLSL 460
  488. OpSourceExtension "GL_EXT_nonuniform_qualifier"
  489. OpSourceExtension "GL_KHR_ray_tracing"
  490. OpName %RayGeneration "RayGeneration"
  491. OpName %StorageBuffer "StorageBuffer"
  492. OpMemberName %StorageBuffer 0 "index"
  493. OpMemberName %StorageBuffer 1 "red"
  494. OpName %sbo "sbo"
  495. OpName %images "images"
  496. OpMemberDecorate %StorageBuffer 0 Offset 0
  497. OpMemberDecorate %StorageBuffer 1 Offset 4
  498. OpDecorate %gl_LocalInvocationIndex BuiltIn LocalInvocationIndex
  499. OpDecorate %StorageBuffer BufferBlock
  500. OpDecorate %sbo DescriptorSet 0
  501. OpDecorate %sbo Binding 0
  502. OpDecorate %images DescriptorSet 0
  503. OpDecorate %images Binding 1
  504. OpDecorate %images NonWritable
  505. OpDecorate %var BuiltIn SubgroupSize
  506. %void = OpTypeVoid
  507. %3 = OpTypeFunction %void
  508. %uint = OpTypeInt 32 0
  509. %float = OpTypeFloat 32
  510. %StorageBuffer = OpTypeStruct %uint %float
  511. %_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer
  512. %sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform
  513. %int = OpTypeInt 32 1
  514. %int_1 = OpConstant %int 1
  515. %13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
  516. %_runtimearr_13 = OpTypeRuntimeArray %13
  517. %_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
  518. %images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
  519. %_ptr_Input_uint = OpTypePointer Input %uint
  520. %var = OpVariable %_ptr_Input_uint Input
  521. %int_0 = OpConstant %int 0
  522. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  523. %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
  524. %v2int = OpTypeVector %int 2
  525. %25 = OpConstantComposite %v2int %int_0 %int_0
  526. %v4float = OpTypeVector %float 4
  527. %uint_0 = OpConstant %uint 0
  528. %uint_1 = OpConstant %uint 1
  529. %_ptr_Uniform_float = OpTypePointer Uniform %float
  530. %gl_LocalInvocationIndex = OpVariable %_ptr_Input_uint Input
  531. %_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
  532. %shared = OpVariable %_ptr_Workgroup_uint Workgroup
  533. %RayGeneration = OpFunction %void None %3
  534. %5 = OpLabel
  535. %19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
  536. %20 = OpLoad %uint %var
  537. %22 = OpAccessChain %_ptr_UniformConstant_13 %images %20
  538. %23 = OpLoad %13 %22
  539. %27 = OpImageRead %v4float %23 %25
  540. %29 = OpCompositeExtract %float %27 0
  541. %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
  542. OpStore %31 %29
  543. OpReturn
  544. OpFunctionEnd
  545. %compute = OpFunction %void None %3
  546. %66 = OpLabel
  547. %62 = OpLoad %uint %gl_LocalInvocationIndex
  548. %63 = OpLoad %uint %var
  549. %64 = OpIAdd %uint %62 %63
  550. %61 = OpAtomicIAdd %uint %shared %uint_1 %uint_0 %64
  551. OpReturn
  552. OpFunctionEnd
  553. )";
  554. EXPECT_EQ(RunPass(text), Pass::Status::Failure);
  555. const char expected_error[] =
  556. "ERROR: 0: Variable is a target for Volatile semantics for an entry "
  557. "point, but it is not for another entry point";
  558. EXPECT_STREQ(GetErrorMessage().substr(0, sizeof(expected_error) - 1).c_str(),
  559. expected_error);
  560. }
  561. TEST_F(VolatileSpreadErrorTest,
  562. VarUsedInMultipleReverseOrderExecutionModelError) {
  563. const std::string text =
  564. R"(
  565. OpCapability RuntimeDescriptorArray
  566. OpCapability RayTracingKHR
  567. OpCapability SubgroupBallotKHR
  568. OpExtension "SPV_EXT_descriptor_indexing"
  569. OpExtension "SPV_KHR_ray_tracing"
  570. OpExtension "SPV_KHR_shader_ballot"
  571. %1 = OpExtInstImport "GLSL.std.450"
  572. OpMemoryModel Logical GLSL450
  573. OpEntryPoint GLCompute %compute "Compute" %gl_LocalInvocationIndex %var
  574. OpEntryPoint RayGenerationKHR %RayGeneration "RayGeneration" %var
  575. OpExecutionMode %compute LocalSize 16 16 1
  576. OpSource GLSL 460
  577. OpSourceExtension "GL_EXT_nonuniform_qualifier"
  578. OpSourceExtension "GL_KHR_ray_tracing"
  579. OpName %RayGeneration "RayGeneration"
  580. OpName %StorageBuffer "StorageBuffer"
  581. OpMemberName %StorageBuffer 0 "index"
  582. OpMemberName %StorageBuffer 1 "red"
  583. OpName %sbo "sbo"
  584. OpName %images "images"
  585. OpMemberDecorate %StorageBuffer 0 Offset 0
  586. OpMemberDecorate %StorageBuffer 1 Offset 4
  587. OpDecorate %gl_LocalInvocationIndex BuiltIn LocalInvocationIndex
  588. OpDecorate %StorageBuffer BufferBlock
  589. OpDecorate %sbo DescriptorSet 0
  590. OpDecorate %sbo Binding 0
  591. OpDecorate %images DescriptorSet 0
  592. OpDecorate %images Binding 1
  593. OpDecorate %images NonWritable
  594. OpDecorate %var BuiltIn SubgroupSize
  595. %void = OpTypeVoid
  596. %3 = OpTypeFunction %void
  597. %uint = OpTypeInt 32 0
  598. %float = OpTypeFloat 32
  599. %StorageBuffer = OpTypeStruct %uint %float
  600. %_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer
  601. %sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform
  602. %int = OpTypeInt 32 1
  603. %int_1 = OpConstant %int 1
  604. %13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
  605. %_runtimearr_13 = OpTypeRuntimeArray %13
  606. %_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
  607. %images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
  608. %_ptr_Input_uint = OpTypePointer Input %uint
  609. %var = OpVariable %_ptr_Input_uint Input
  610. %int_0 = OpConstant %int 0
  611. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  612. %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
  613. %v2int = OpTypeVector %int 2
  614. %25 = OpConstantComposite %v2int %int_0 %int_0
  615. %v4float = OpTypeVector %float 4
  616. %uint_0 = OpConstant %uint 0
  617. %uint_1 = OpConstant %uint 1
  618. %_ptr_Uniform_float = OpTypePointer Uniform %float
  619. %gl_LocalInvocationIndex = OpVariable %_ptr_Input_uint Input
  620. %_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
  621. %shared = OpVariable %_ptr_Workgroup_uint Workgroup
  622. %RayGeneration = OpFunction %void None %3
  623. %5 = OpLabel
  624. %19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
  625. %20 = OpLoad %uint %var
  626. %22 = OpAccessChain %_ptr_UniformConstant_13 %images %20
  627. %23 = OpLoad %13 %22
  628. %27 = OpImageRead %v4float %23 %25
  629. %29 = OpCompositeExtract %float %27 0
  630. %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
  631. OpStore %31 %29
  632. OpReturn
  633. OpFunctionEnd
  634. %compute = OpFunction %void None %3
  635. %66 = OpLabel
  636. %62 = OpLoad %uint %gl_LocalInvocationIndex
  637. %63 = OpLoad %uint %var
  638. %64 = OpIAdd %uint %62 %63
  639. %61 = OpAtomicIAdd %uint %shared %uint_1 %uint_0 %64
  640. OpReturn
  641. OpFunctionEnd
  642. )";
  643. EXPECT_EQ(RunPass(text), Pass::Status::Failure);
  644. const char expected_error[] =
  645. "ERROR: 0: Variable is a target for Volatile semantics for an entry "
  646. "point, but it is not for another entry point";
  647. EXPECT_STREQ(GetErrorMessage().substr(0, sizeof(expected_error) - 1).c_str(),
  648. expected_error);
  649. }
  650. TEST_F(VolatileSpreadErrorTest, FunctionNotInlined) {
  651. const std::string text =
  652. R"(
  653. OpCapability RuntimeDescriptorArray
  654. OpCapability RayTracingKHR
  655. OpCapability SubgroupBallotKHR
  656. OpExtension "SPV_EXT_descriptor_indexing"
  657. OpExtension "SPV_KHR_ray_tracing"
  658. OpExtension "SPV_KHR_shader_ballot"
  659. %1 = OpExtInstImport "GLSL.std.450"
  660. OpMemoryModel Logical GLSL450
  661. OpEntryPoint RayGenerationKHR %RayGeneration "RayGeneration" %var
  662. OpEntryPoint ClosestHitKHR %ClosestHit "ClosestHit" %var
  663. OpSource GLSL 460
  664. OpSourceExtension "GL_EXT_nonuniform_qualifier"
  665. OpSourceExtension "GL_KHR_ray_tracing"
  666. OpName %RayGeneration "RayGeneration"
  667. OpName %ClosestHit "ClosestHit"
  668. OpName %StorageBuffer "StorageBuffer"
  669. OpMemberName %StorageBuffer 0 "index"
  670. OpMemberName %StorageBuffer 1 "red"
  671. OpName %sbo "sbo"
  672. OpName %images "images"
  673. OpMemberDecorate %StorageBuffer 0 Offset 0
  674. OpMemberDecorate %StorageBuffer 1 Offset 4
  675. OpDecorate %gl_LocalInvocationIndex BuiltIn LocalInvocationIndex
  676. OpDecorate %StorageBuffer BufferBlock
  677. OpDecorate %sbo DescriptorSet 0
  678. OpDecorate %sbo Binding 0
  679. OpDecorate %images DescriptorSet 0
  680. OpDecorate %images Binding 1
  681. OpDecorate %images NonWritable
  682. OpDecorate %var BuiltIn SubgroupSize
  683. %void = OpTypeVoid
  684. %3 = OpTypeFunction %void
  685. %uint = OpTypeInt 32 0
  686. %float = OpTypeFloat 32
  687. %StorageBuffer = OpTypeStruct %uint %float
  688. %_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer
  689. %sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform
  690. %int = OpTypeInt 32 1
  691. %int_1 = OpConstant %int 1
  692. %13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
  693. %_runtimearr_13 = OpTypeRuntimeArray %13
  694. %_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
  695. %images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
  696. %_ptr_Input_uint = OpTypePointer Input %uint
  697. %var = OpVariable %_ptr_Input_uint Input
  698. %int_0 = OpConstant %int 0
  699. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  700. %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
  701. %v2int = OpTypeVector %int 2
  702. %25 = OpConstantComposite %v2int %int_0 %int_0
  703. %v4float = OpTypeVector %float 4
  704. %uint_0 = OpConstant %uint 0
  705. %uint_1 = OpConstant %uint 1
  706. %_ptr_Uniform_float = OpTypePointer Uniform %float
  707. %gl_LocalInvocationIndex = OpVariable %_ptr_Input_uint Input
  708. %_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
  709. %shared = OpVariable %_ptr_Workgroup_uint Workgroup
  710. %RayGeneration = OpFunction %void None %3
  711. %5 = OpLabel
  712. %19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
  713. %20 = OpLoad %uint %19
  714. %22 = OpAccessChain %_ptr_UniformConstant_13 %images %20
  715. %23 = OpLoad %13 %22
  716. %27 = OpImageRead %v4float %23 %25
  717. %29 = OpCompositeExtract %float %27 0
  718. %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
  719. OpStore %31 %29
  720. OpReturn
  721. OpFunctionEnd
  722. %NotInlined = OpFunction %void None %3
  723. %32 = OpLabel
  724. OpReturn
  725. OpFunctionEnd
  726. %ClosestHit = OpFunction %void None %3
  727. %45 = OpLabel
  728. %49 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
  729. %40 = OpLoad %uint %49
  730. %42 = OpAccessChain %_ptr_UniformConstant_13 %images %40
  731. %43 = OpLoad %13 %42
  732. %47 = OpImageRead %v4float %43 %25
  733. %59 = OpCompositeExtract %float %47 0
  734. %51 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
  735. OpStore %51 %59
  736. OpReturn
  737. OpFunctionEnd
  738. )";
  739. EXPECT_EQ(RunPass(text), Pass::Status::SuccessWithoutChange);
  740. }
  741. TEST_F(VolatileSpreadErrorTest, VarNotUsedInEntryPointForVolatile) {
  742. const std::string text =
  743. R"(
  744. OpCapability RuntimeDescriptorArray
  745. OpCapability RayTracingKHR
  746. OpCapability SubgroupBallotKHR
  747. OpExtension "SPV_EXT_descriptor_indexing"
  748. OpExtension "SPV_KHR_ray_tracing"
  749. OpExtension "SPV_KHR_shader_ballot"
  750. %1 = OpExtInstImport "GLSL.std.450"
  751. OpMemoryModel Logical GLSL450
  752. OpEntryPoint RayGenerationKHR %RayGeneration "RayGeneration" %var
  753. OpEntryPoint GLCompute %compute "Compute" %gl_LocalInvocationIndex %var
  754. OpExecutionMode %compute LocalSize 16 16 1
  755. OpSource GLSL 460
  756. OpSourceExtension "GL_EXT_nonuniform_qualifier"
  757. OpSourceExtension "GL_KHR_ray_tracing"
  758. OpName %RayGeneration "RayGeneration"
  759. OpName %StorageBuffer "StorageBuffer"
  760. OpMemberName %StorageBuffer 0 "index"
  761. OpMemberName %StorageBuffer 1 "red"
  762. OpName %sbo "sbo"
  763. OpName %images "images"
  764. OpMemberDecorate %StorageBuffer 0 Offset 0
  765. OpMemberDecorate %StorageBuffer 1 Offset 4
  766. OpDecorate %gl_LocalInvocationIndex BuiltIn LocalInvocationIndex
  767. OpDecorate %StorageBuffer BufferBlock
  768. OpDecorate %sbo DescriptorSet 0
  769. OpDecorate %sbo Binding 0
  770. OpDecorate %images DescriptorSet 0
  771. OpDecorate %images Binding 1
  772. OpDecorate %images NonWritable
  773. ; CHECK-NOT: OpDecorate {{%\w+}} Volatile
  774. OpDecorate %var BuiltIn SubgroupSize
  775. %void = OpTypeVoid
  776. %3 = OpTypeFunction %void
  777. %uint = OpTypeInt 32 0
  778. %float = OpTypeFloat 32
  779. %StorageBuffer = OpTypeStruct %uint %float
  780. %_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer
  781. %sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform
  782. %int = OpTypeInt 32 1
  783. %int_1 = OpConstant %int 1
  784. %13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
  785. %_runtimearr_13 = OpTypeRuntimeArray %13
  786. %_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
  787. %images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
  788. %_ptr_Input_uint = OpTypePointer Input %uint
  789. %var = OpVariable %_ptr_Input_uint Input
  790. %int_0 = OpConstant %int 0
  791. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  792. %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
  793. %v2int = OpTypeVector %int 2
  794. %25 = OpConstantComposite %v2int %int_0 %int_0
  795. %v4float = OpTypeVector %float 4
  796. %uint_0 = OpConstant %uint 0
  797. %uint_1 = OpConstant %uint 1
  798. %_ptr_Uniform_float = OpTypePointer Uniform %float
  799. %gl_LocalInvocationIndex = OpVariable %_ptr_Input_uint Input
  800. %_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
  801. %shared = OpVariable %_ptr_Workgroup_uint Workgroup
  802. %RayGeneration = OpFunction %void None %3
  803. %5 = OpLabel
  804. %19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
  805. %20 = OpLoad %uint %19
  806. %22 = OpAccessChain %_ptr_UniformConstant_13 %images %20
  807. %23 = OpLoad %13 %22
  808. %27 = OpImageRead %v4float %23 %25
  809. %29 = OpCompositeExtract %float %27 0
  810. %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
  811. OpStore %31 %29
  812. OpReturn
  813. OpFunctionEnd
  814. %compute = OpFunction %void None %3
  815. %66 = OpLabel
  816. %62 = OpLoad %uint %gl_LocalInvocationIndex
  817. %63 = OpLoad %uint %var
  818. %64 = OpIAdd %uint %62 %63
  819. %61 = OpAtomicIAdd %uint %shared %uint_1 %uint_0 %64
  820. OpReturn
  821. OpFunctionEnd
  822. )";
  823. SinglePassRunAndMatch<SpreadVolatileSemantics>(text, true);
  824. }
  825. TEST_F(VolatileSpreadTest, RecursivelySpreadVolatile) {
  826. const std::string text =
  827. R"(
  828. OpCapability RuntimeDescriptorArray
  829. OpCapability RayTracingKHR
  830. OpCapability SubgroupBallotKHR
  831. OpCapability VulkanMemoryModel
  832. OpExtension "SPV_KHR_vulkan_memory_model"
  833. OpExtension "SPV_EXT_descriptor_indexing"
  834. OpExtension "SPV_KHR_ray_tracing"
  835. OpExtension "SPV_KHR_shader_ballot"
  836. %1 = OpExtInstImport "GLSL.std.450"
  837. OpMemoryModel Logical Vulkan
  838. OpEntryPoint RayGenerationKHR %RayGeneration "RayGeneration" %var0 %var1
  839. OpSource GLSL 460
  840. OpSourceExtension "GL_EXT_nonuniform_qualifier"
  841. OpSourceExtension "GL_KHR_ray_tracing"
  842. OpName %RayGeneration "RayGeneration"
  843. OpName %StorageBuffer "StorageBuffer"
  844. OpMemberName %StorageBuffer 0 "index"
  845. OpMemberName %StorageBuffer 1 "red"
  846. OpName %sbo "sbo"
  847. OpName %images "images"
  848. OpMemberDecorate %StorageBuffer 0 Offset 0
  849. OpMemberDecorate %StorageBuffer 1 Offset 4
  850. OpDecorate %StorageBuffer BufferBlock
  851. OpDecorate %sbo DescriptorSet 0
  852. OpDecorate %sbo Binding 0
  853. OpDecorate %images DescriptorSet 0
  854. OpDecorate %images Binding 1
  855. OpDecorate %images NonWritable
  856. ; CHECK: OpDecorate [[var0:%\w+]] BuiltIn SubgroupEqMask
  857. ; CHECK: OpDecorate [[var1:%\w+]] BuiltIn SubgroupGeMask
  858. OpDecorate %var0 BuiltIn SubgroupEqMask
  859. OpDecorate %var1 BuiltIn SubgroupGeMask
  860. %void = OpTypeVoid
  861. %3 = OpTypeFunction %void
  862. %uint = OpTypeInt 32 0
  863. %float = OpTypeFloat 32
  864. %StorageBuffer = OpTypeStruct %uint %float
  865. %_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer
  866. %sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform
  867. %int = OpTypeInt 32 1
  868. %int_1 = OpConstant %int 1
  869. %13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
  870. %_runtimearr_13 = OpTypeRuntimeArray %13
  871. %_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
  872. %images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
  873. %v4uint = OpTypeVector %uint 4
  874. %_ptr_Input_v4uint = OpTypePointer Input %v4uint
  875. %_ptr_Input_uint = OpTypePointer Input %uint
  876. %var0 = OpVariable %_ptr_Input_v4uint Input
  877. %var1 = OpVariable %_ptr_Input_v4uint Input
  878. %int_0 = OpConstant %int 0
  879. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  880. %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
  881. %v2int = OpTypeVector %int 2
  882. %25 = OpConstantComposite %v2int %int_0 %int_0
  883. %v4float = OpTypeVector %float 4
  884. %uint_0 = OpConstant %uint 0
  885. %uint_1 = OpConstant %uint 1
  886. %_ptr_Uniform_float = OpTypePointer Uniform %float
  887. %RayGeneration = OpFunction %void None %3
  888. %5 = OpLabel
  889. ; CHECK: [[ptr0:%\w+]] = OpAccessChain %_ptr_Input_uint [[var0]] %int_0
  890. ; CHECK: OpLoad {{%\w+}} [[ptr0]] Volatile
  891. %19 = OpAccessChain %_ptr_Input_uint %var0 %int_0
  892. %20 = OpLoad %uint %19
  893. %22 = OpAccessChain %_ptr_UniformConstant_13 %images %20
  894. %23 = OpLoad %13 %22
  895. %27 = OpImageRead %v4float %23 %25
  896. %29 = OpCompositeExtract %float %27 0
  897. %31 = OpAccessChain %_ptr_Uniform_float %sbo %uint_1
  898. ; CHECK: OpLoad {{%\w+}} [[ptr0]] Volatile
  899. %24 = OpLoad %uint %19
  900. ; CHECK: [[var2:%\w+]] = OpCopyObject %_ptr_Input_v4uint [[var0]]
  901. ; CHECK: [[ptr2:%\w+]] = OpAccessChain %_ptr_Input_uint [[var2]] %int_1
  902. ; CHECK: OpLoad {{%\w+}} [[ptr2]] Volatile
  903. %18 = OpCopyObject %_ptr_Input_v4uint %var0
  904. %21 = OpAccessChain %_ptr_Input_uint %18 %int_1
  905. %26 = OpLoad %uint %21
  906. %28 = OpIAdd %uint %24 %26
  907. %30 = OpConvertUToF %float %28
  908. ; CHECK: [[ptr1:%\w+]] = OpAccessChain %_ptr_Input_uint [[var1]] %int_1
  909. ; CHECK: OpLoad {{%\w+}} [[ptr1]] Volatile
  910. %32 = OpAccessChain %_ptr_Input_uint %var1 %int_1
  911. %33 = OpLoad %uint %32
  912. %34 = OpConvertUToF %float %33
  913. %35 = OpFAdd %float %34 %30
  914. %36 = OpFAdd %float %35 %29
  915. OpStore %31 %36
  916. OpReturn
  917. OpFunctionEnd
  918. )";
  919. SinglePassRunAndMatch<SpreadVolatileSemantics>(text, true);
  920. }
  921. TEST_F(VolatileSpreadTest, SpreadVolatileOnlyForTargetEntryPoints) {
  922. const std::string text =
  923. R"(
  924. OpCapability RuntimeDescriptorArray
  925. OpCapability RayTracingKHR
  926. OpCapability SubgroupBallotKHR
  927. OpCapability VulkanMemoryModel
  928. OpCapability VulkanMemoryModelDeviceScopeKHR
  929. OpExtension "SPV_KHR_vulkan_memory_model"
  930. OpExtension "SPV_EXT_descriptor_indexing"
  931. OpExtension "SPV_KHR_ray_tracing"
  932. OpExtension "SPV_KHR_shader_ballot"
  933. %1 = OpExtInstImport "GLSL.std.450"
  934. OpMemoryModel Logical Vulkan
  935. OpEntryPoint RayGenerationKHR %RayGeneration "RayGeneration" %var0 %var1
  936. OpEntryPoint GLCompute %compute "Compute" %var0 %var1
  937. OpExecutionMode %compute LocalSize 16 16 1
  938. OpSource GLSL 460
  939. OpSourceExtension "GL_EXT_nonuniform_qualifier"
  940. OpSourceExtension "GL_KHR_ray_tracing"
  941. OpName %RayGeneration "RayGeneration"
  942. OpName %StorageBuffer "StorageBuffer"
  943. OpMemberName %StorageBuffer 0 "index"
  944. OpMemberName %StorageBuffer 1 "red"
  945. OpName %sbo "sbo"
  946. OpName %images "images"
  947. OpMemberDecorate %StorageBuffer 0 Offset 0
  948. OpMemberDecorate %StorageBuffer 1 Offset 4
  949. OpDecorate %StorageBuffer BufferBlock
  950. OpDecorate %sbo DescriptorSet 0
  951. OpDecorate %sbo Binding 0
  952. OpDecorate %images DescriptorSet 0
  953. OpDecorate %images Binding 1
  954. OpDecorate %images NonWritable
  955. ; CHECK: OpDecorate [[var0:%\w+]] BuiltIn SubgroupEqMask
  956. ; CHECK: OpDecorate [[var1:%\w+]] BuiltIn SubgroupGeMask
  957. OpDecorate %var0 BuiltIn SubgroupEqMask
  958. OpDecorate %var1 BuiltIn SubgroupGeMask
  959. %void = OpTypeVoid
  960. %3 = OpTypeFunction %void
  961. %uint = OpTypeInt 32 0
  962. %float = OpTypeFloat 32
  963. %StorageBuffer = OpTypeStruct %uint %float
  964. %_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer
  965. %sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform
  966. %int = OpTypeInt 32 1
  967. %int_1 = OpConstant %int 1
  968. %13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
  969. %_runtimearr_13 = OpTypeRuntimeArray %13
  970. %_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
  971. %images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
  972. %v4uint = OpTypeVector %uint 4
  973. %_ptr_Input_v4uint = OpTypePointer Input %v4uint
  974. %_ptr_Input_uint = OpTypePointer Input %uint
  975. %var0 = OpVariable %_ptr_Input_v4uint Input
  976. %var1 = OpVariable %_ptr_Input_v4uint Input
  977. %int_0 = OpConstant %int 0
  978. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  979. %_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
  980. %v2int = OpTypeVector %int 2
  981. %25 = OpConstantComposite %v2int %int_0 %int_0
  982. %v4float = OpTypeVector %float 4
  983. %uint_0 = OpConstant %uint 0
  984. %uint_1 = OpConstant %uint 1
  985. %_ptr_Uniform_float = OpTypePointer Uniform %float
  986. %_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
  987. %shared = OpVariable %_ptr_Workgroup_uint Workgroup
  988. %RayGeneration = OpFunction %void None %3
  989. %5 = OpLabel
  990. ; CHECK: [[ptr0:%\w+]] = OpAccessChain %_ptr_Input_uint [[var0]] %int_0
  991. ; CHECK: OpLoad {{%\w+}} [[ptr0]] Volatile
  992. %19 = OpAccessChain %_ptr_Input_uint %var0 %int_0
  993. %20 = OpLoad %uint %19
  994. %22 = OpAccessChain %_ptr_UniformConstant_13 %images %20
  995. %23 = OpLoad %13 %22
  996. %27 = OpImageRead %v4float %23 %25
  997. %29 = OpCompositeExtract %float %27 0
  998. %31 = OpAccessChain %_ptr_Uniform_float %sbo %uint_1
  999. ; CHECK: OpLoad {{%\w+}} [[ptr0]] Volatile
  1000. %24 = OpLoad %uint %19
  1001. ; CHECK: [[var2:%\w+]] = OpCopyObject %_ptr_Input_v4uint [[var0]]
  1002. ; CHECK: [[ptr2:%\w+]] = OpAccessChain %_ptr_Input_uint [[var2]] %int_1
  1003. ; CHECK: OpLoad {{%\w+}} [[ptr2]] Volatile
  1004. %18 = OpCopyObject %_ptr_Input_v4uint %var0
  1005. %21 = OpAccessChain %_ptr_Input_uint %18 %int_1
  1006. %26 = OpLoad %uint %21
  1007. %28 = OpIAdd %uint %24 %26
  1008. %30 = OpConvertUToF %float %28
  1009. ; CHECK: [[ptr1:%\w+]] = OpAccessChain %_ptr_Input_uint [[var1]] %int_1
  1010. ; CHECK: OpLoad {{%\w+}} [[ptr1]] Volatile
  1011. %32 = OpAccessChain %_ptr_Input_uint %var1 %int_1
  1012. %33 = OpLoad %uint %32
  1013. %34 = OpConvertUToF %float %33
  1014. %35 = OpFAdd %float %34 %30
  1015. %36 = OpFAdd %float %35 %29
  1016. OpStore %31 %36
  1017. OpReturn
  1018. OpFunctionEnd
  1019. %compute = OpFunction %void None %3
  1020. %66 = OpLabel
  1021. ; CHECK-NOT: OpLoad {{%\w+}} {{%\w+}} Volatile
  1022. %62 = OpLoad %v4uint %var0
  1023. %63 = OpLoad %v4uint %var1
  1024. %64 = OpIAdd %v4uint %62 %63
  1025. %65 = OpCompositeExtract %uint %64 0
  1026. %61 = OpAtomicIAdd %uint %shared %uint_1 %uint_0 %65
  1027. OpReturn
  1028. OpFunctionEnd
  1029. )";
  1030. SinglePassRunAndMatch<SpreadVolatileSemantics>(text, true);
  1031. }
  1032. TEST_F(VolatileSpreadTest, SkipIfItHasNoExecutionModel) {
  1033. const std::string text = R"(
  1034. OpCapability Shader
  1035. OpCapability Linkage
  1036. OpMemoryModel Logical GLSL450
  1037. %2 = OpTypeVoid
  1038. %3 = OpTypeFunction %2
  1039. %4 = OpFunction %2 None %3
  1040. %5 = OpLabel
  1041. OpReturn
  1042. OpFunctionEnd
  1043. )";
  1044. Pass::Status status;
  1045. std::tie(std::ignore, status) =
  1046. SinglePassRunToBinary<SpreadVolatileSemantics>(text,
  1047. /* skip_nop = */ false);
  1048. EXPECT_EQ(status, Pass::Status::SuccessWithoutChange);
  1049. }
  1050. TEST_F(VolatileSpreadTest, NoInlinedfuncCalls) {
  1051. const std::string text = R"(
  1052. OpCapability RayTracingNV
  1053. OpCapability VulkanMemoryModel
  1054. OpCapability GroupNonUniform
  1055. OpExtension "SPV_NV_ray_tracing"
  1056. OpExtension "SPV_KHR_vulkan_memory_model"
  1057. OpMemoryModel Logical Vulkan
  1058. OpEntryPoint RayGenerationNV %main "main" %SubgroupSize
  1059. OpSource HLSL 630
  1060. OpName %main "main"
  1061. OpName %src_main "src.main"
  1062. OpName %bb_entry "bb.entry"
  1063. OpName %func0 "func0"
  1064. OpName %bb_entry_0 "bb.entry"
  1065. OpName %func2 "func2"
  1066. OpName %bb_entry_1 "bb.entry"
  1067. OpName %param_var_count "param.var.count"
  1068. OpName %func1 "func1"
  1069. OpName %bb_entry_2 "bb.entry"
  1070. OpName %func3 "func3"
  1071. OpName %count "count"
  1072. OpName %bb_entry_3 "bb.entry"
  1073. OpDecorate %SubgroupSize BuiltIn SubgroupSize
  1074. %uint = OpTypeInt 32 0
  1075. %_ptr_Input_uint = OpTypePointer Input %uint
  1076. %void = OpTypeVoid
  1077. %6 = OpTypeFunction %void
  1078. %_ptr_Function_uint = OpTypePointer Function %uint
  1079. %25 = OpTypeFunction %void %_ptr_Function_uint
  1080. %SubgroupSize = OpVariable %_ptr_Input_uint Input
  1081. %main = OpFunction %void None %6
  1082. %7 = OpLabel
  1083. %8 = OpFunctionCall %void %src_main
  1084. OpReturn
  1085. OpFunctionEnd
  1086. %src_main = OpFunction %void None %6
  1087. %bb_entry = OpLabel
  1088. %11 = OpFunctionCall %void %func0
  1089. OpReturn
  1090. OpFunctionEnd
  1091. %func0 = OpFunction %void DontInline %6
  1092. %bb_entry_0 = OpLabel
  1093. %14 = OpFunctionCall %void %func2
  1094. %16 = OpFunctionCall %void %func1
  1095. OpReturn
  1096. OpFunctionEnd
  1097. %func2 = OpFunction %void DontInline %6
  1098. %bb_entry_1 = OpLabel
  1099. %param_var_count = OpVariable %_ptr_Function_uint Function
  1100. ; CHECK: {{%\w+}} = OpLoad %uint %SubgroupSize Volatile
  1101. %21 = OpLoad %uint %SubgroupSize
  1102. OpStore %param_var_count %21
  1103. %22 = OpFunctionCall %void %func3 %param_var_count
  1104. OpReturn
  1105. OpFunctionEnd
  1106. %func1 = OpFunction %void DontInline %6
  1107. %bb_entry_2 = OpLabel
  1108. OpReturn
  1109. OpFunctionEnd
  1110. %func3 = OpFunction %void DontInline %25
  1111. %count = OpFunctionParameter %_ptr_Function_uint
  1112. %bb_entry_3 = OpLabel
  1113. OpReturn
  1114. OpFunctionEnd
  1115. )";
  1116. SinglePassRunAndMatch<SpreadVolatileSemantics>(text, true);
  1117. }
  1118. TEST_F(VolatileSpreadErrorTest, NoInlinedMultiEntryfuncCalls) {
  1119. const std::string text = R"(
  1120. OpCapability RayTracingNV
  1121. OpCapability SubgroupBallotKHR
  1122. OpExtension "SPV_NV_ray_tracing"
  1123. OpExtension "SPV_KHR_shader_ballot"
  1124. %1 = OpExtInstImport "GLSL.std.450"
  1125. OpMemoryModel Logical GLSL450
  1126. OpEntryPoint RayGenerationNV %main "main" %SubgroupSize
  1127. OpEntryPoint GLCompute %main2 "main2" %gl_LocalInvocationIndex %SubgroupSize
  1128. OpSource HLSL 630
  1129. OpName %main "main"
  1130. OpName %bb_entry "bb.entry"
  1131. OpName %main2 "main2"
  1132. OpName %bb_entry_0 "bb.entry"
  1133. OpName %func "func"
  1134. OpName %count "count"
  1135. OpName %bb_entry_1 "bb.entry"
  1136. OpDecorate %gl_LocalInvocationIndex BuiltIn LocalInvocationIndex
  1137. OpDecorate %SubgroupSize BuiltIn SubgroupSize
  1138. %uint = OpTypeInt 32 0
  1139. %uint_0 = OpConstant %uint 0
  1140. %_ptr_Input_uint = OpTypePointer Input %uint
  1141. %float = OpTypeFloat 32
  1142. %v4float = OpTypeVector %float 4
  1143. %void = OpTypeVoid
  1144. %12 = OpTypeFunction %void
  1145. %_ptr_Function_uint = OpTypePointer Function %uint
  1146. %_ptr_Function_v4float = OpTypePointer Function %v4float
  1147. %29 = OpTypeFunction %void %_ptr_Function_v4float
  1148. %34 = OpTypeFunction %void %_ptr_Function_uint
  1149. %SubgroupSize = OpVariable %_ptr_Input_uint Input
  1150. %gl_LocalInvocationIndex = OpVariable %_ptr_Input_uint Input
  1151. %main = OpFunction %void None %12
  1152. %bb_entry = OpLabel
  1153. %20 = OpFunctionCall %void %func
  1154. OpReturn
  1155. OpFunctionEnd
  1156. %main2 = OpFunction %void None %12
  1157. %bb_entry_0 = OpLabel
  1158. %33 = OpFunctionCall %void %func
  1159. OpReturn
  1160. OpFunctionEnd
  1161. %func = OpFunction %void DontInline %12
  1162. %bb_entry_1 = OpLabel
  1163. %count = OpVariable %_ptr_Function_uint Function
  1164. %35 = OpLoad %uint %SubgroupSize
  1165. OpStore %count %35
  1166. OpReturn
  1167. OpFunctionEnd
  1168. )";
  1169. EXPECT_EQ(RunPass(text), Pass::Status::Failure);
  1170. const char expected_error[] =
  1171. "ERROR: 0: Variable is a target for Volatile semantics for an entry "
  1172. "point, but it is not for another entry point";
  1173. EXPECT_STREQ(GetErrorMessage().substr(0, sizeof(expected_error) - 1).c_str(),
  1174. expected_error);
  1175. }
  1176. } // namespace
  1177. } // namespace opt
  1178. } // namespace spvtools