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 "test/opt/pass_fixture.h" 18#include "test/opt/pass_utils.h" 19 20namespace spvtools { 21namespace opt { 22namespace { 23 24struct ExecutionModelAndBuiltIn { 25 const char* execution_model; 26 const char* built_in; 27 const bool use_v4uint; 28}; 29 30using AddVolatileDecorationTest = 31 PassTest<::testing::TestWithParam<ExecutionModelAndBuiltIn>>; 32 33TEST_P(AddVolatileDecorationTest, InMain) { 34 const auto& tc = GetParam(); 35 const std::string execution_model(tc.execution_model); 36 const std::string built_in(tc.built_in); 37 const std::string var_type = 38 tc.use_v4uint ? "%_ptr_Input_v4uint" : "%_ptr_Input_uint"; 39 const std::string var_load_type = tc.use_v4uint ? "%v4uint" : "%uint"; 40 41 const std::string text = 42 std::string(R"(OpCapability RuntimeDescriptorArray 43OpCapability RayTracingKHR 44OpCapability SubgroupBallotKHR 45OpExtension "SPV_EXT_descriptor_indexing" 46OpExtension "SPV_KHR_ray_tracing" 47OpExtension "SPV_KHR_shader_ballot" 48%1 = OpExtInstImport "GLSL.std.450" 49OpMemoryModel Logical GLSL450 50OpEntryPoint )") + 51 execution_model + std::string(R"( %main "main" %var 52OpSource GLSL 460 53OpSourceExtension "GL_EXT_nonuniform_qualifier" 54OpSourceExtension "GL_KHR_ray_tracing" 55OpName %main "main" 56OpName %fn "fn" 57OpName %StorageBuffer "StorageBuffer" 58OpMemberName %StorageBuffer 0 "index" 59OpMemberName %StorageBuffer 1 "red" 60OpName %sbo "sbo" 61OpName %images "images" 62OpMemberDecorate %StorageBuffer 0 Offset 0 63OpMemberDecorate %StorageBuffer 1 Offset 4 64OpDecorate %StorageBuffer BufferBlock 65OpDecorate %sbo DescriptorSet 0 66OpDecorate %sbo Binding 0 67OpDecorate %images DescriptorSet 0 68OpDecorate %images Binding 1 69OpDecorate %images NonWritable 70)") + std::string(R"( 71; CHECK: OpDecorate [[var:%\w+]] BuiltIn )") + 72 built_in + std::string(R"( 73; CHECK: OpDecorate [[var]] Volatile 74OpDecorate %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 111OpStore %31 %29 112%32 = OpFunctionCall %void %fn 113OpReturn 114OpFunctionEnd 115%fn = OpFunction %void None %3 116%33 = OpLabel 117OpReturn 118OpFunctionEnd 119)"); 120 121 SinglePassRunAndMatch<SpreadVolatileSemantics>(text, true); 122} 123 124INSTANTIATE_TEST_SUITE_P( 125 AddVolatileDecoration, AddVolatileDecorationTest, 126 ::testing::ValuesIn(std::vector<ExecutionModelAndBuiltIn>{ 127 {"RayGenerationKHR", "SubgroupSize", false}, 128 {"RayGenerationKHR", "SubgroupLocalInvocationId", false}, 129 {"RayGenerationKHR", "SubgroupEqMask", true}, 130 {"ClosestHitKHR", "SubgroupLocalInvocationId", true}, 131 {"IntersectionKHR", "SubgroupEqMask", true}, 132 {"MissKHR", "SubgroupGeMask", true}, 133 {"CallableKHR", "SubgroupGtMask", true}, 134 {"RayGenerationKHR", "SubgroupLeMask", true}, 135 })); 136 137using SetLoadVolatileTest = 138 PassTest<::testing::TestWithParam<ExecutionModelAndBuiltIn>>; 139 140TEST_P(SetLoadVolatileTest, InMain) { 141 const auto& tc = GetParam(); 142 const std::string execution_model(tc.execution_model); 143 const std::string built_in(tc.built_in); 144 145 const std::string var_type = 146 tc.use_v4uint ? "%_ptr_Input_v4uint" : "%_ptr_Input_uint"; 147 const std::string var_value = tc.use_v4uint ? std::string(R"( 148; CHECK: [[ptr:%\w+]] = OpAccessChain %_ptr_Input_uint [[var]] %int_0 149; CHECK: OpLoad {{%\w+}} [[ptr]] Volatile 150%ptr = OpAccessChain %_ptr_Input_uint %var %int_0 151%var_value = OpLoad %uint %ptr)") 152 : std::string(R"( 153; CHECK: OpLoad {{%\w+}} [[var]] Volatile 154%var_value = OpLoad %uint %var)"); 155 156 const std::string text = std::string(R"(OpCapability RuntimeDescriptorArray 157OpCapability RayTracingKHR 158OpCapability SubgroupBallotKHR 159OpCapability VulkanMemoryModel 160OpExtension "SPV_KHR_vulkan_memory_model" 161OpExtension "SPV_EXT_descriptor_indexing" 162OpExtension "SPV_KHR_ray_tracing" 163OpExtension "SPV_KHR_shader_ballot" 164OpMemoryModel Logical Vulkan 165OpEntryPoint )") + execution_model + 166 std::string(R"( %main "main" %var 167OpName %main "main" 168OpName %StorageBuffer "StorageBuffer" 169OpMemberName %StorageBuffer 0 "index" 170OpMemberName %StorageBuffer 1 "red" 171OpName %sbo "sbo" 172OpName %images "images" 173OpMemberDecorate %StorageBuffer 0 Offset 0 174OpMemberDecorate %StorageBuffer 1 Offset 4 175OpDecorate %StorageBuffer BufferBlock 176OpDecorate %sbo DescriptorSet 0 177OpDecorate %sbo Binding 0 178OpDecorate %images DescriptorSet 0 179OpDecorate %images Binding 1 180OpDecorate %images NonWritable 181)") + std::string(R"( 182; CHECK: OpDecorate [[var:%\w+]] BuiltIn )") + 183 built_in + std::string(R"( 184OpDecorate %var BuiltIn )") + built_in + 185 std::string(R"( 186%void = OpTypeVoid 187%3 = OpTypeFunction %void 188%uint = OpTypeInt 32 0 189%float = OpTypeFloat 32 190%StorageBuffer = OpTypeStruct %uint %float 191%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer 192%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform 193%int = OpTypeInt 32 1 194%int_1 = OpConstant %int 1 195%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f 196%_runtimearr_13 = OpTypeRuntimeArray %13 197%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 198%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant 199%_ptr_Input_uint = OpTypePointer Input %uint 200%v4uint = OpTypeVector %uint 4 201%_ptr_Input_v4uint = OpTypePointer Input %v4uint 202%var = OpVariable )") + var_type + 203 std::string(R"( Input 204%int_0 = OpConstant %int 0 205%_ptr_Uniform_uint = OpTypePointer Uniform %uint 206%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 207%v2int = OpTypeVector %int 2 208%25 = OpConstantComposite %v2int %int_0 %int_0 209%v4float = OpTypeVector %float 4 210%uint_0 = OpConstant %uint 0 211%_ptr_Uniform_float = OpTypePointer Uniform %float 212%main = OpFunction %void None %3 213%5 = OpLabel 214%19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 215%20 = OpLoad %uint %19 216)") + var_value + std::string(R"( 217%test = OpIAdd %uint %var_value %20 218%22 = OpAccessChain %_ptr_UniformConstant_13 %images %test 219%23 = OpLoad %13 %22 220%27 = OpImageRead %v4float %23 %25 221%29 = OpCompositeExtract %float %27 0 222%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 223OpStore %31 %29 224OpReturn 225OpFunctionEnd 226)"); 227 228 SinglePassRunAndMatch<SpreadVolatileSemantics>(text, true); 229} 230 231INSTANTIATE_TEST_SUITE_P( 232 SetLoadVolatile, SetLoadVolatileTest, 233 ::testing::ValuesIn(std::vector<ExecutionModelAndBuiltIn>{ 234 {"RayGenerationKHR", "SubgroupSize", false}, 235 {"RayGenerationKHR", "SubgroupLocalInvocationId", false}, 236 {"RayGenerationKHR", "SubgroupEqMask", true}, 237 {"ClosestHitKHR", "SubgroupLocalInvocationId", true}, 238 {"IntersectionKHR", "SubgroupEqMask", true}, 239 {"MissKHR", "SubgroupGeMask", true}, 240 {"CallableKHR", "SubgroupGtMask", true}, 241 {"RayGenerationKHR", "SubgroupLeMask", true}, 242 })); 243 244using VolatileSpreadTest = PassTest<::testing::Test>; 245 246TEST_F(VolatileSpreadTest, SpreadVolatileForHelperInvocation) { 247 const std::string text = 248 R"( 249OpCapability Shader 250OpCapability DemoteToHelperInvocation 251OpMemoryModel Logical GLSL450 252OpEntryPoint Fragment %main "main" %var 253OpExecutionMode %main OriginUpperLeft 254 255; CHECK: OpDecorate [[var:%\w+]] BuiltIn HelperInvocation 256; CHECK: OpDecorate [[var]] Volatile 257OpDecorate %var BuiltIn HelperInvocation 258 259%bool = OpTypeBool 260%void = OpTypeVoid 261%void_fn = OpTypeFunction %void 262%_ptr_Input_bool = OpTypePointer Input %bool 263%var = OpVariable %_ptr_Input_bool Input 264%main = OpFunction %void None %void_fn 265%entry = OpLabel 266%load = OpLoad %bool %var 267OpDemoteToHelperInvocation 268OpReturn 269OpFunctionEnd 270)"; 271 272 SetTargetEnv(SPV_ENV_UNIVERSAL_1_6); 273 SinglePassRunAndMatch<SpreadVolatileSemantics>(text, true); 274} 275 276TEST_F(VolatileSpreadTest, MultipleExecutionModel) { 277 const std::string text = 278 R"( 279OpCapability RuntimeDescriptorArray 280OpCapability RayTracingKHR 281OpCapability SubgroupBallotKHR 282OpExtension "SPV_EXT_descriptor_indexing" 283OpExtension "SPV_KHR_ray_tracing" 284OpExtension "SPV_KHR_shader_ballot" 285%1 = OpExtInstImport "GLSL.std.450" 286OpMemoryModel Logical GLSL450 287OpEntryPoint RayGenerationKHR %RayGeneration "RayGeneration" %var 288OpEntryPoint GLCompute %compute "Compute" %gl_LocalInvocationIndex 289OpExecutionMode %compute LocalSize 16 16 1 290OpSource GLSL 460 291OpSourceExtension "GL_EXT_nonuniform_qualifier" 292OpSourceExtension "GL_KHR_ray_tracing" 293OpName %RayGeneration "RayGeneration" 294OpName %StorageBuffer "StorageBuffer" 295OpMemberName %StorageBuffer 0 "index" 296OpMemberName %StorageBuffer 1 "red" 297OpName %sbo "sbo" 298OpName %images "images" 299OpMemberDecorate %StorageBuffer 0 Offset 0 300OpMemberDecorate %StorageBuffer 1 Offset 4 301OpDecorate %gl_LocalInvocationIndex BuiltIn LocalInvocationIndex 302OpDecorate %StorageBuffer BufferBlock 303OpDecorate %sbo DescriptorSet 0 304OpDecorate %sbo Binding 0 305OpDecorate %images DescriptorSet 0 306OpDecorate %images Binding 1 307OpDecorate %images NonWritable 308 309; CHECK: OpEntryPoint RayGenerationNV {{%\w+}} "RayGeneration" [[var:%\w+]] 310; CHECK: OpDecorate [[var]] BuiltIn SubgroupSize 311; CHECK: OpDecorate [[var]] Volatile 312; CHECK-NOT: OpDecorate {{%\w+}} Volatile 313OpDecorate %var BuiltIn SubgroupSize 314 315%void = OpTypeVoid 316%3 = OpTypeFunction %void 317%uint = OpTypeInt 32 0 318%float = OpTypeFloat 32 319%StorageBuffer = OpTypeStruct %uint %float 320%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer 321%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform 322%int = OpTypeInt 32 1 323%int_1 = OpConstant %int 1 324%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f 325%_runtimearr_13 = OpTypeRuntimeArray %13 326%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 327%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant 328%_ptr_Input_uint = OpTypePointer Input %uint 329%var = OpVariable %_ptr_Input_uint Input 330%int_0 = OpConstant %int 0 331%_ptr_Uniform_uint = OpTypePointer Uniform %uint 332%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 333%v2int = OpTypeVector %int 2 334%25 = OpConstantComposite %v2int %int_0 %int_0 335%v4float = OpTypeVector %float 4 336%uint_0 = OpConstant %uint 0 337%uint_1 = OpConstant %uint 1 338%_ptr_Uniform_float = OpTypePointer Uniform %float 339%gl_LocalInvocationIndex = OpVariable %_ptr_Input_uint Input 340%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint 341%shared = OpVariable %_ptr_Workgroup_uint Workgroup 342 343%RayGeneration = OpFunction %void None %3 344%5 = OpLabel 345%19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 346%20 = OpLoad %uint %var 347%22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 348%23 = OpLoad %13 %22 349%27 = OpImageRead %v4float %23 %25 350%29 = OpCompositeExtract %float %27 0 351%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 352OpStore %31 %29 353OpReturn 354OpFunctionEnd 355 356%compute = OpFunction %void None %3 357%66 = OpLabel 358%62 = OpLoad %uint %gl_LocalInvocationIndex 359%61 = OpAtomicIAdd %uint %shared %uint_1 %uint_0 %62 360OpReturn 361OpFunctionEnd 362)"; 363 364 SinglePassRunAndMatch<SpreadVolatileSemantics>(text, true); 365} 366 367TEST_F(VolatileSpreadTest, VarUsedInMultipleEntryPoints) { 368 const std::string text = 369 R"( 370OpCapability RuntimeDescriptorArray 371OpCapability RayTracingKHR 372OpCapability SubgroupBallotKHR 373OpExtension "SPV_EXT_descriptor_indexing" 374OpExtension "SPV_KHR_ray_tracing" 375OpExtension "SPV_KHR_shader_ballot" 376%1 = OpExtInstImport "GLSL.std.450" 377OpMemoryModel Logical GLSL450 378OpEntryPoint RayGenerationKHR %RayGeneration "RayGeneration" %var 379OpEntryPoint ClosestHitKHR %ClosestHit "ClosestHit" %var 380OpSource GLSL 460 381OpSourceExtension "GL_EXT_nonuniform_qualifier" 382OpSourceExtension "GL_KHR_ray_tracing" 383OpName %RayGeneration "RayGeneration" 384OpName %ClosestHit "ClosestHit" 385OpName %StorageBuffer "StorageBuffer" 386OpMemberName %StorageBuffer 0 "index" 387OpMemberName %StorageBuffer 1 "red" 388OpName %sbo "sbo" 389OpName %images "images" 390OpMemberDecorate %StorageBuffer 0 Offset 0 391OpMemberDecorate %StorageBuffer 1 Offset 4 392OpDecorate %gl_LocalInvocationIndex BuiltIn LocalInvocationIndex 393OpDecorate %StorageBuffer BufferBlock 394OpDecorate %sbo DescriptorSet 0 395OpDecorate %sbo Binding 0 396OpDecorate %images DescriptorSet 0 397OpDecorate %images Binding 1 398OpDecorate %images NonWritable 399 400; CHECK: OpEntryPoint RayGenerationNV {{%\w+}} "RayGeneration" [[var:%\w+]] 401; CHECK: OpEntryPoint ClosestHitNV {{%\w+}} "ClosestHit" [[var]] 402; CHECK: OpDecorate [[var]] BuiltIn SubgroupSize 403; CHECK: OpDecorate [[var]] Volatile 404; CHECK-NOT: OpDecorate {{%\w+}} Volatile 405OpDecorate %var BuiltIn SubgroupSize 406 407%void = OpTypeVoid 408%3 = OpTypeFunction %void 409%uint = OpTypeInt 32 0 410%float = OpTypeFloat 32 411%StorageBuffer = OpTypeStruct %uint %float 412%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer 413%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform 414%int = OpTypeInt 32 1 415%int_1 = OpConstant %int 1 416%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f 417%_runtimearr_13 = OpTypeRuntimeArray %13 418%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 419%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant 420%_ptr_Input_uint = OpTypePointer Input %uint 421%var = OpVariable %_ptr_Input_uint Input 422%int_0 = OpConstant %int 0 423%_ptr_Uniform_uint = OpTypePointer Uniform %uint 424%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 425%v2int = OpTypeVector %int 2 426%25 = OpConstantComposite %v2int %int_0 %int_0 427%v4float = OpTypeVector %float 4 428%uint_0 = OpConstant %uint 0 429%uint_1 = OpConstant %uint 1 430%_ptr_Uniform_float = OpTypePointer Uniform %float 431%gl_LocalInvocationIndex = OpVariable %_ptr_Input_uint Input 432%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint 433%shared = OpVariable %_ptr_Workgroup_uint Workgroup 434 435%RayGeneration = OpFunction %void None %3 436%5 = OpLabel 437%19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 438%20 = OpLoad %uint %var 439%22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 440%23 = OpLoad %13 %22 441%27 = OpImageRead %v4float %23 %25 442%29 = OpCompositeExtract %float %27 0 443%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 444OpStore %31 %29 445OpReturn 446OpFunctionEnd 447 448%ClosestHit = OpFunction %void None %3 449%45 = OpLabel 450%49 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 451%40 = OpLoad %uint %var 452%42 = OpAccessChain %_ptr_UniformConstant_13 %images %40 453%43 = OpLoad %13 %42 454%47 = OpImageRead %v4float %43 %25 455%59 = OpCompositeExtract %float %47 0 456%51 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 457OpStore %51 %59 458OpReturn 459OpFunctionEnd 460)"; 461 462 SinglePassRunAndMatch<SpreadVolatileSemantics>(text, true); 463} 464 465class VolatileSpreadErrorTest : public PassTest<::testing::Test> { 466 public: 467 VolatileSpreadErrorTest() 468 : consumer_([this](spv_message_level_t level, const char*, 469 const spv_position_t& position, const char* message) { 470 if (!error_message_.empty()) error_message_ += "\n"; 471 switch (level) { 472 case SPV_MSG_FATAL: 473 case SPV_MSG_INTERNAL_ERROR: 474 case SPV_MSG_ERROR: 475 error_message_ += "ERROR"; 476 break; 477 case SPV_MSG_WARNING: 478 error_message_ += "WARNING"; 479 break; 480 case SPV_MSG_INFO: 481 error_message_ += "INFO"; 482 break; 483 case SPV_MSG_DEBUG: 484 error_message_ += "DEBUG"; 485 break; 486 } 487 error_message_ += 488 ": " + std::to_string(position.index) + ": " + message; 489 }) {} 490 491 Pass::Status RunPass(const std::string& text) { 492 std::unique_ptr<IRContext> context_ = 493 spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_2, consumer_, text); 494 if (!context_.get()) return Pass::Status::Failure; 495 496 PassManager manager; 497 manager.SetMessageConsumer(consumer_); 498 manager.AddPass<SpreadVolatileSemantics>(); 499 500 return manager.Run(context_.get()); 501 } 502 503 std::string GetErrorMessage() const { return error_message_; } 504 505 void TearDown() override { error_message_.clear(); } 506 507 private: 508 spvtools::MessageConsumer consumer_; 509 std::string error_message_; 510}; 511 512TEST_F(VolatileSpreadErrorTest, VarUsedInMultipleExecutionModelError) { 513 const std::string text = 514 R"( 515OpCapability RuntimeDescriptorArray 516OpCapability RayTracingKHR 517OpCapability SubgroupBallotKHR 518OpExtension "SPV_EXT_descriptor_indexing" 519OpExtension "SPV_KHR_ray_tracing" 520OpExtension "SPV_KHR_shader_ballot" 521%1 = OpExtInstImport "GLSL.std.450" 522OpMemoryModel Logical GLSL450 523OpEntryPoint RayGenerationKHR %RayGeneration "RayGeneration" %var 524OpEntryPoint GLCompute %compute "Compute" %gl_LocalInvocationIndex %var 525OpExecutionMode %compute LocalSize 16 16 1 526OpSource GLSL 460 527OpSourceExtension "GL_EXT_nonuniform_qualifier" 528OpSourceExtension "GL_KHR_ray_tracing" 529OpName %RayGeneration "RayGeneration" 530OpName %StorageBuffer "StorageBuffer" 531OpMemberName %StorageBuffer 0 "index" 532OpMemberName %StorageBuffer 1 "red" 533OpName %sbo "sbo" 534OpName %images "images" 535OpMemberDecorate %StorageBuffer 0 Offset 0 536OpMemberDecorate %StorageBuffer 1 Offset 4 537OpDecorate %gl_LocalInvocationIndex BuiltIn LocalInvocationIndex 538OpDecorate %StorageBuffer BufferBlock 539OpDecorate %sbo DescriptorSet 0 540OpDecorate %sbo Binding 0 541OpDecorate %images DescriptorSet 0 542OpDecorate %images Binding 1 543OpDecorate %images NonWritable 544OpDecorate %var BuiltIn SubgroupSize 545%void = OpTypeVoid 546%3 = OpTypeFunction %void 547%uint = OpTypeInt 32 0 548%float = OpTypeFloat 32 549%StorageBuffer = OpTypeStruct %uint %float 550%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer 551%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform 552%int = OpTypeInt 32 1 553%int_1 = OpConstant %int 1 554%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f 555%_runtimearr_13 = OpTypeRuntimeArray %13 556%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 557%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant 558%_ptr_Input_uint = OpTypePointer Input %uint 559%var = OpVariable %_ptr_Input_uint Input 560%int_0 = OpConstant %int 0 561%_ptr_Uniform_uint = OpTypePointer Uniform %uint 562%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 563%v2int = OpTypeVector %int 2 564%25 = OpConstantComposite %v2int %int_0 %int_0 565%v4float = OpTypeVector %float 4 566%uint_0 = OpConstant %uint 0 567%uint_1 = OpConstant %uint 1 568%_ptr_Uniform_float = OpTypePointer Uniform %float 569%gl_LocalInvocationIndex = OpVariable %_ptr_Input_uint Input 570%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint 571%shared = OpVariable %_ptr_Workgroup_uint Workgroup 572 573%RayGeneration = OpFunction %void None %3 574%5 = OpLabel 575%19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 576%20 = OpLoad %uint %var 577%22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 578%23 = OpLoad %13 %22 579%27 = OpImageRead %v4float %23 %25 580%29 = OpCompositeExtract %float %27 0 581%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 582OpStore %31 %29 583OpReturn 584OpFunctionEnd 585 586%compute = OpFunction %void None %3 587%66 = OpLabel 588%62 = OpLoad %uint %gl_LocalInvocationIndex 589%63 = OpLoad %uint %var 590%64 = OpIAdd %uint %62 %63 591%61 = OpAtomicIAdd %uint %shared %uint_1 %uint_0 %64 592OpReturn 593OpFunctionEnd 594)"; 595 596 EXPECT_EQ(RunPass(text), Pass::Status::Failure); 597 const char expected_error[] = 598 "ERROR: 0: Variable is a target for Volatile semantics for an entry " 599 "point, but it is not for another entry point"; 600 EXPECT_STREQ(GetErrorMessage().substr(0, sizeof(expected_error) - 1).c_str(), 601 expected_error); 602} 603 604TEST_F(VolatileSpreadErrorTest, 605 VarUsedInMultipleReverseOrderExecutionModelError) { 606 const std::string text = 607 R"( 608OpCapability RuntimeDescriptorArray 609OpCapability RayTracingKHR 610OpCapability SubgroupBallotKHR 611OpExtension "SPV_EXT_descriptor_indexing" 612OpExtension "SPV_KHR_ray_tracing" 613OpExtension "SPV_KHR_shader_ballot" 614%1 = OpExtInstImport "GLSL.std.450" 615OpMemoryModel Logical GLSL450 616OpEntryPoint GLCompute %compute "Compute" %gl_LocalInvocationIndex %var 617OpEntryPoint RayGenerationKHR %RayGeneration "RayGeneration" %var 618OpExecutionMode %compute LocalSize 16 16 1 619OpSource GLSL 460 620OpSourceExtension "GL_EXT_nonuniform_qualifier" 621OpSourceExtension "GL_KHR_ray_tracing" 622OpName %RayGeneration "RayGeneration" 623OpName %StorageBuffer "StorageBuffer" 624OpMemberName %StorageBuffer 0 "index" 625OpMemberName %StorageBuffer 1 "red" 626OpName %sbo "sbo" 627OpName %images "images" 628OpMemberDecorate %StorageBuffer 0 Offset 0 629OpMemberDecorate %StorageBuffer 1 Offset 4 630OpDecorate %gl_LocalInvocationIndex BuiltIn LocalInvocationIndex 631OpDecorate %StorageBuffer BufferBlock 632OpDecorate %sbo DescriptorSet 0 633OpDecorate %sbo Binding 0 634OpDecorate %images DescriptorSet 0 635OpDecorate %images Binding 1 636OpDecorate %images NonWritable 637OpDecorate %var BuiltIn SubgroupSize 638%void = OpTypeVoid 639%3 = OpTypeFunction %void 640%uint = OpTypeInt 32 0 641%float = OpTypeFloat 32 642%StorageBuffer = OpTypeStruct %uint %float 643%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer 644%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform 645%int = OpTypeInt 32 1 646%int_1 = OpConstant %int 1 647%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f 648%_runtimearr_13 = OpTypeRuntimeArray %13 649%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 650%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant 651%_ptr_Input_uint = OpTypePointer Input %uint 652%var = OpVariable %_ptr_Input_uint Input 653%int_0 = OpConstant %int 0 654%_ptr_Uniform_uint = OpTypePointer Uniform %uint 655%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 656%v2int = OpTypeVector %int 2 657%25 = OpConstantComposite %v2int %int_0 %int_0 658%v4float = OpTypeVector %float 4 659%uint_0 = OpConstant %uint 0 660%uint_1 = OpConstant %uint 1 661%_ptr_Uniform_float = OpTypePointer Uniform %float 662%gl_LocalInvocationIndex = OpVariable %_ptr_Input_uint Input 663%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint 664%shared = OpVariable %_ptr_Workgroup_uint Workgroup 665 666%RayGeneration = OpFunction %void None %3 667%5 = OpLabel 668%19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 669%20 = OpLoad %uint %var 670%22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 671%23 = OpLoad %13 %22 672%27 = OpImageRead %v4float %23 %25 673%29 = OpCompositeExtract %float %27 0 674%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 675OpStore %31 %29 676OpReturn 677OpFunctionEnd 678 679%compute = OpFunction %void None %3 680%66 = OpLabel 681%62 = OpLoad %uint %gl_LocalInvocationIndex 682%63 = OpLoad %uint %var 683%64 = OpIAdd %uint %62 %63 684%61 = OpAtomicIAdd %uint %shared %uint_1 %uint_0 %64 685OpReturn 686OpFunctionEnd 687)"; 688 689 EXPECT_EQ(RunPass(text), Pass::Status::Failure); 690 const char expected_error[] = 691 "ERROR: 0: Variable is a target for Volatile semantics for an entry " 692 "point, but it is not for another entry point"; 693 EXPECT_STREQ(GetErrorMessage().substr(0, sizeof(expected_error) - 1).c_str(), 694 expected_error); 695} 696 697TEST_F(VolatileSpreadErrorTest, FunctionNotInlined) { 698 const std::string text = 699 R"( 700OpCapability RuntimeDescriptorArray 701OpCapability RayTracingKHR 702OpCapability SubgroupBallotKHR 703OpExtension "SPV_EXT_descriptor_indexing" 704OpExtension "SPV_KHR_ray_tracing" 705OpExtension "SPV_KHR_shader_ballot" 706%1 = OpExtInstImport "GLSL.std.450" 707OpMemoryModel Logical GLSL450 708OpEntryPoint RayGenerationKHR %RayGeneration "RayGeneration" %var 709OpEntryPoint ClosestHitKHR %ClosestHit "ClosestHit" %var 710OpSource GLSL 460 711OpSourceExtension "GL_EXT_nonuniform_qualifier" 712OpSourceExtension "GL_KHR_ray_tracing" 713OpName %RayGeneration "RayGeneration" 714OpName %ClosestHit "ClosestHit" 715OpName %StorageBuffer "StorageBuffer" 716OpMemberName %StorageBuffer 0 "index" 717OpMemberName %StorageBuffer 1 "red" 718OpName %sbo "sbo" 719OpName %images "images" 720OpMemberDecorate %StorageBuffer 0 Offset 0 721OpMemberDecorate %StorageBuffer 1 Offset 4 722OpDecorate %gl_LocalInvocationIndex BuiltIn LocalInvocationIndex 723OpDecorate %StorageBuffer BufferBlock 724OpDecorate %sbo DescriptorSet 0 725OpDecorate %sbo Binding 0 726OpDecorate %images DescriptorSet 0 727OpDecorate %images Binding 1 728OpDecorate %images NonWritable 729OpDecorate %var BuiltIn SubgroupSize 730%void = OpTypeVoid 731%3 = OpTypeFunction %void 732%uint = OpTypeInt 32 0 733%float = OpTypeFloat 32 734%StorageBuffer = OpTypeStruct %uint %float 735%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer 736%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform 737%int = OpTypeInt 32 1 738%int_1 = OpConstant %int 1 739%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f 740%_runtimearr_13 = OpTypeRuntimeArray %13 741%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 742%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant 743%_ptr_Input_uint = OpTypePointer Input %uint 744%var = OpVariable %_ptr_Input_uint Input 745%int_0 = OpConstant %int 0 746%_ptr_Uniform_uint = OpTypePointer Uniform %uint 747%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 748%v2int = OpTypeVector %int 2 749%25 = OpConstantComposite %v2int %int_0 %int_0 750%v4float = OpTypeVector %float 4 751%uint_0 = OpConstant %uint 0 752%uint_1 = OpConstant %uint 1 753%_ptr_Uniform_float = OpTypePointer Uniform %float 754%gl_LocalInvocationIndex = OpVariable %_ptr_Input_uint Input 755%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint 756%shared = OpVariable %_ptr_Workgroup_uint Workgroup 757 758%RayGeneration = OpFunction %void None %3 759%5 = OpLabel 760%19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 761%20 = OpLoad %uint %19 762%22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 763%23 = OpLoad %13 %22 764%27 = OpImageRead %v4float %23 %25 765%29 = OpCompositeExtract %float %27 0 766%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 767OpStore %31 %29 768OpReturn 769OpFunctionEnd 770 771%NotInlined = OpFunction %void None %3 772%32 = OpLabel 773OpReturn 774OpFunctionEnd 775 776%ClosestHit = OpFunction %void None %3 777%45 = OpLabel 778%49 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 779%40 = OpLoad %uint %49 780%42 = OpAccessChain %_ptr_UniformConstant_13 %images %40 781%43 = OpLoad %13 %42 782%47 = OpImageRead %v4float %43 %25 783%59 = OpCompositeExtract %float %47 0 784%51 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 785OpStore %51 %59 786OpReturn 787OpFunctionEnd 788)"; 789 790 EXPECT_EQ(RunPass(text), Pass::Status::SuccessWithoutChange); 791} 792 793TEST_F(VolatileSpreadErrorTest, VarNotUsedInEntryPointForVolatile) { 794 const std::string text = 795 R"( 796OpCapability RuntimeDescriptorArray 797OpCapability RayTracingKHR 798OpCapability SubgroupBallotKHR 799OpExtension "SPV_EXT_descriptor_indexing" 800OpExtension "SPV_KHR_ray_tracing" 801OpExtension "SPV_KHR_shader_ballot" 802%1 = OpExtInstImport "GLSL.std.450" 803OpMemoryModel Logical GLSL450 804OpEntryPoint RayGenerationKHR %RayGeneration "RayGeneration" %var 805OpEntryPoint GLCompute %compute "Compute" %gl_LocalInvocationIndex %var 806OpExecutionMode %compute LocalSize 16 16 1 807OpSource GLSL 460 808OpSourceExtension "GL_EXT_nonuniform_qualifier" 809OpSourceExtension "GL_KHR_ray_tracing" 810OpName %RayGeneration "RayGeneration" 811OpName %StorageBuffer "StorageBuffer" 812OpMemberName %StorageBuffer 0 "index" 813OpMemberName %StorageBuffer 1 "red" 814OpName %sbo "sbo" 815OpName %images "images" 816OpMemberDecorate %StorageBuffer 0 Offset 0 817OpMemberDecorate %StorageBuffer 1 Offset 4 818OpDecorate %gl_LocalInvocationIndex BuiltIn LocalInvocationIndex 819OpDecorate %StorageBuffer BufferBlock 820OpDecorate %sbo DescriptorSet 0 821OpDecorate %sbo Binding 0 822OpDecorate %images DescriptorSet 0 823OpDecorate %images Binding 1 824OpDecorate %images NonWritable 825 826; CHECK-NOT: OpDecorate {{%\w+}} Volatile 827 828OpDecorate %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 866OpStore %31 %29 867OpReturn 868OpFunctionEnd 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 876OpReturn 877OpFunctionEnd 878)"; 879 880 SinglePassRunAndMatch<SpreadVolatileSemantics>(text, true); 881} 882 883TEST_F(VolatileSpreadTest, RecursivelySpreadVolatile) { 884 const std::string text = 885 R"( 886OpCapability RuntimeDescriptorArray 887OpCapability RayTracingKHR 888OpCapability SubgroupBallotKHR 889OpCapability VulkanMemoryModel 890OpExtension "SPV_KHR_vulkan_memory_model" 891OpExtension "SPV_EXT_descriptor_indexing" 892OpExtension "SPV_KHR_ray_tracing" 893OpExtension "SPV_KHR_shader_ballot" 894%1 = OpExtInstImport "GLSL.std.450" 895OpMemoryModel Logical Vulkan 896OpEntryPoint RayGenerationKHR %RayGeneration "RayGeneration" %var0 %var1 897OpSource GLSL 460 898OpSourceExtension "GL_EXT_nonuniform_qualifier" 899OpSourceExtension "GL_KHR_ray_tracing" 900OpName %RayGeneration "RayGeneration" 901OpName %StorageBuffer "StorageBuffer" 902OpMemberName %StorageBuffer 0 "index" 903OpMemberName %StorageBuffer 1 "red" 904OpName %sbo "sbo" 905OpName %images "images" 906OpMemberDecorate %StorageBuffer 0 Offset 0 907OpMemberDecorate %StorageBuffer 1 Offset 4 908OpDecorate %StorageBuffer BufferBlock 909OpDecorate %sbo DescriptorSet 0 910OpDecorate %sbo Binding 0 911OpDecorate %images DescriptorSet 0 912OpDecorate %images Binding 1 913OpDecorate %images NonWritable 914 915; CHECK: OpDecorate [[var0:%\w+]] BuiltIn SubgroupEqMask 916; CHECK: OpDecorate [[var1:%\w+]] BuiltIn SubgroupGeMask 917OpDecorate %var0 BuiltIn SubgroupEqMask 918OpDecorate %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 983OpStore %31 %36 984OpReturn 985OpFunctionEnd 986)"; 987 988 SinglePassRunAndMatch<SpreadVolatileSemantics>(text, true); 989} 990 991TEST_F(VolatileSpreadTest, SpreadVolatileOnlyForTargetEntryPoints) { 992 const std::string text = 993 R"( 994OpCapability RuntimeDescriptorArray 995OpCapability RayTracingKHR 996OpCapability SubgroupBallotKHR 997OpCapability VulkanMemoryModel 998OpCapability VulkanMemoryModelDeviceScopeKHR 999OpExtension "SPV_KHR_vulkan_memory_model" 1000OpExtension "SPV_EXT_descriptor_indexing" 1001OpExtension "SPV_KHR_ray_tracing" 1002OpExtension "SPV_KHR_shader_ballot" 1003%1 = OpExtInstImport "GLSL.std.450" 1004OpMemoryModel Logical Vulkan 1005OpEntryPoint RayGenerationKHR %RayGeneration "RayGeneration" %var0 %var1 1006OpEntryPoint GLCompute %compute "Compute" %var0 %var1 1007OpExecutionMode %compute LocalSize 16 16 1 1008OpSource GLSL 460 1009OpSourceExtension "GL_EXT_nonuniform_qualifier" 1010OpSourceExtension "GL_KHR_ray_tracing" 1011OpName %RayGeneration "RayGeneration" 1012OpName %StorageBuffer "StorageBuffer" 1013OpMemberName %StorageBuffer 0 "index" 1014OpMemberName %StorageBuffer 1 "red" 1015OpName %sbo "sbo" 1016OpName %images "images" 1017OpMemberDecorate %StorageBuffer 0 Offset 0 1018OpMemberDecorate %StorageBuffer 1 Offset 4 1019OpDecorate %StorageBuffer BufferBlock 1020OpDecorate %sbo DescriptorSet 0 1021OpDecorate %sbo Binding 0 1022OpDecorate %images DescriptorSet 0 1023OpDecorate %images Binding 1 1024OpDecorate %images NonWritable 1025 1026; CHECK: OpDecorate [[var0:%\w+]] BuiltIn SubgroupEqMask 1027; CHECK: OpDecorate [[var1:%\w+]] BuiltIn SubgroupGeMask 1028OpDecorate %var0 BuiltIn SubgroupEqMask 1029OpDecorate %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 1096OpStore %31 %36 1097OpReturn 1098OpFunctionEnd 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 1109OpReturn 1110OpFunctionEnd 1111)"; 1112 1113 SinglePassRunAndMatch<SpreadVolatileSemantics>(text, true); 1114} 1115 1116TEST_F(VolatileSpreadTest, SkipIfItHasNoExecutionModel) { 1117 const std::string text = R"( 1118OpCapability Shader 1119OpCapability Linkage 1120OpMemoryModel Logical GLSL450 1121%2 = OpTypeVoid 1122%3 = OpTypeFunction %2 1123%4 = OpFunction %2 None %3 1124%5 = OpLabel 1125OpReturn 1126OpFunctionEnd 1127)"; 1128 1129 Pass::Status status; 1130 std::tie(std::ignore, status) = 1131 SinglePassRunToBinary<SpreadVolatileSemantics>(text, 1132 /* skip_nop = */ false); 1133 EXPECT_EQ(status, Pass::Status::SuccessWithoutChange); 1134} 1135 1136TEST_F(VolatileSpreadTest, NoInlinedfuncCalls) { 1137 const std::string text = R"( 1138OpCapability RayTracingNV 1139OpCapability VulkanMemoryModel 1140OpCapability GroupNonUniform 1141OpExtension "SPV_NV_ray_tracing" 1142OpExtension "SPV_KHR_vulkan_memory_model" 1143OpMemoryModel Logical Vulkan 1144OpEntryPoint RayGenerationNV %main "main" %SubgroupSize 1145OpSource HLSL 630 1146OpName %main "main" 1147OpName %src_main "src.main" 1148OpName %bb_entry "bb.entry" 1149OpName %func0 "func0" 1150OpName %bb_entry_0 "bb.entry" 1151OpName %func2 "func2" 1152OpName %bb_entry_1 "bb.entry" 1153OpName %param_var_count "param.var.count" 1154OpName %func1 "func1" 1155OpName %bb_entry_2 "bb.entry" 1156OpName %func3 "func3" 1157OpName %count "count" 1158OpName %bb_entry_3 "bb.entry" 1159OpDecorate %SubgroupSize BuiltIn SubgroupSize 1160%uint = OpTypeInt 32 0 1161%_ptr_Input_uint = OpTypePointer Input %uint 1162%void = OpTypeVoid 1163%6 = OpTypeFunction %void 1164%_ptr_Function_uint = OpTypePointer Function %uint 1165%25 = OpTypeFunction %void %_ptr_Function_uint 1166%SubgroupSize = OpVariable %_ptr_Input_uint Input 1167%main = OpFunction %void None %6 1168%7 = OpLabel 1169%8 = OpFunctionCall %void %src_main 1170OpReturn 1171OpFunctionEnd 1172%src_main = OpFunction %void None %6 1173%bb_entry = OpLabel 1174%11 = OpFunctionCall %void %func0 1175OpReturn 1176OpFunctionEnd 1177%func0 = OpFunction %void DontInline %6 1178%bb_entry_0 = OpLabel 1179%14 = OpFunctionCall %void %func2 1180%16 = OpFunctionCall %void %func1 1181OpReturn 1182OpFunctionEnd 1183%func2 = OpFunction %void DontInline %6 1184%bb_entry_1 = OpLabel 1185%param_var_count = OpVariable %_ptr_Function_uint Function 1186; CHECK: {{%\w+}} = OpLoad %uint %SubgroupSize Volatile 1187%21 = OpLoad %uint %SubgroupSize 1188OpStore %param_var_count %21 1189%22 = OpFunctionCall %void %func3 %param_var_count 1190OpReturn 1191OpFunctionEnd 1192%func1 = OpFunction %void DontInline %6 1193%bb_entry_2 = OpLabel 1194OpReturn 1195OpFunctionEnd 1196%func3 = OpFunction %void DontInline %25 1197%count = OpFunctionParameter %_ptr_Function_uint 1198%bb_entry_3 = OpLabel 1199OpReturn 1200OpFunctionEnd 1201)"; 1202 SinglePassRunAndMatch<SpreadVolatileSemantics>(text, true); 1203} 1204 1205TEST_F(VolatileSpreadErrorTest, NoInlinedMultiEntryfuncCalls) { 1206 const std::string text = R"( 1207OpCapability RayTracingNV 1208OpCapability SubgroupBallotKHR 1209OpExtension "SPV_NV_ray_tracing" 1210OpExtension "SPV_KHR_shader_ballot" 1211%1 = OpExtInstImport "GLSL.std.450" 1212OpMemoryModel Logical GLSL450 1213OpEntryPoint RayGenerationNV %main "main" %SubgroupSize 1214OpEntryPoint GLCompute %main2 "main2" %gl_LocalInvocationIndex %SubgroupSize 1215OpSource HLSL 630 1216OpName %main "main" 1217OpName %bb_entry "bb.entry" 1218OpName %main2 "main2" 1219OpName %bb_entry_0 "bb.entry" 1220OpName %func "func" 1221OpName %count "count" 1222OpName %bb_entry_1 "bb.entry" 1223OpDecorate %gl_LocalInvocationIndex BuiltIn LocalInvocationIndex 1224OpDecorate %SubgroupSize BuiltIn SubgroupSize 1225%uint = OpTypeInt 32 0 1226%uint_0 = OpConstant %uint 0 1227%_ptr_Input_uint = OpTypePointer Input %uint 1228%float = OpTypeFloat 32 1229%v4float = OpTypeVector %float 4 1230%void = OpTypeVoid 1231%12 = OpTypeFunction %void 1232%_ptr_Function_uint = OpTypePointer Function %uint 1233%_ptr_Function_v4float = OpTypePointer Function %v4float 1234%29 = OpTypeFunction %void %_ptr_Function_v4float 1235%34 = OpTypeFunction %void %_ptr_Function_uint 1236%SubgroupSize = OpVariable %_ptr_Input_uint Input 1237%gl_LocalInvocationIndex = OpVariable %_ptr_Input_uint Input 1238%main = OpFunction %void None %12 1239%bb_entry = OpLabel 1240%20 = OpFunctionCall %void %func 1241OpReturn 1242OpFunctionEnd 1243%main2 = OpFunction %void None %12 1244%bb_entry_0 = OpLabel 1245%33 = OpFunctionCall %void %func 1246OpReturn 1247OpFunctionEnd 1248%func = OpFunction %void DontInline %12 1249%bb_entry_1 = OpLabel 1250%count = OpVariable %_ptr_Function_uint Function 1251%35 = OpLoad %uint %SubgroupSize 1252OpStore %count %35 1253OpReturn 1254OpFunctionEnd 1255)"; 1256 EXPECT_EQ(RunPass(text), Pass::Status::Failure); 1257 const char expected_error[] = 1258 "ERROR: 0: Variable is a target for Volatile semantics for an entry " 1259 "point, but it is not for another entry point"; 1260 EXPECT_STREQ(GetErrorMessage().substr(0, sizeof(expected_error) - 1).c_str(), 1261 expected_error); 1262} 1263 1264} // namespace 1265} // namespace opt 1266} // namespace spvtools 1267