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