spread_volatile_semantics_test.cpp 42 KB

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