1// Copyright (c) 2017-2022 Valve Corporation 2// Copyright (c) 2017-2022 LunarG Inc. 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// http://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15 16// Bindless Check Instrumentation Tests. 17 18#include <string> 19#include <vector> 20 21#include "test/opt/pass_fixture.h" 22#include "test/opt/pass_utils.h" 23 24namespace spvtools { 25namespace opt { 26namespace { 27 28using InstBindlessTest = PassTest<::testing::Test>; 29 30static const std::string kFuncName = "inst_bindless_check_desc"; 31 32static const std::string kImportDeco = R"( 33;CHECK: OpDecorate %)" + kFuncName + R"( LinkageAttributes ")" + 34 kFuncName + R"(" Import 35)"; 36 37static const std::string kImportStub = R"( 38;CHECK: %)" + kFuncName + R"( = OpFunction %bool None {{%\w+}} 39;CHECK: OpFunctionEnd 40)"; 41 42TEST_F(InstBindlessTest, Simple) { 43 // Texture2D g_tColor[128]; 44 // 45 // layout(push_constant) cbuffer PerViewConstantBuffer_t 46 // { 47 // uint g_nDataIdx; 48 // }; 49 // 50 // SamplerState g_sAniso; 51 // 52 // struct PS_INPUT 53 // { 54 // float2 vTextureCoords : TEXCOORD2; 55 // }; 56 // 57 // struct PS_OUTPUT 58 // { 59 // float4 vColor : SV_Target0; 60 // }; 61 // 62 // PS_OUTPUT MainPs(PS_INPUT i) 63 // { 64 // PS_OUTPUT ps_output; 65 // ps_output.vColor = 66 // g_tColor[ g_nDataIdx ].Sample(g_sAniso, i.vTextureCoords.xy); 67 // return ps_output; 68 // } 69 70 const std::string entry = R"( 71OpCapability Shader 72;CHECK: OpCapability Linkage 73%1 = OpExtInstImport "GLSL.std.450" 74OpMemoryModel Logical GLSL450 75OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor 76;CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord 77OpExecutionMode %MainPs OriginUpperLeft 78OpSource HLSL 500 79)"; 80 81 // clang-format off 82 const std::string names_annots = R"( 83OpName %MainPs "MainPs" 84OpName %g_tColor "g_tColor" 85OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" 86OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" 87OpName %_ "" 88OpName %g_sAniso "g_sAniso" 89OpName %i_vTextureCoords "i.vTextureCoords" 90OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" 91OpDecorate %g_tColor DescriptorSet 3 92OpDecorate %g_tColor Binding 0 93OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 94OpDecorate %PerViewConstantBuffer_t Block 95OpDecorate %g_sAniso DescriptorSet 0 96OpDecorate %i_vTextureCoords Location 0 97OpDecorate %_entryPointOutput_vColor Location 0)" 98+ kImportDeco + 99R"( 100;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 101)"; 102 103 const std::string consts_types_vars = R"( 104%void = OpTypeVoid 105%10 = OpTypeFunction %void 106%float = OpTypeFloat 32 107%v2float = OpTypeVector %float 2 108%v4float = OpTypeVector %float 4 109%int = OpTypeInt 32 1 110%int_0 = OpConstant %int 0 111%16 = OpTypeImage %float 2D 0 0 0 1 Unknown 112%uint = OpTypeInt 32 0 113%uint_128 = OpConstant %uint 128 114%_arr_16_uint_128 = OpTypeArray %16 %uint_128 115%_ptr_UniformConstant__arr_16_uint_128 = OpTypePointer UniformConstant %_arr_16_uint_128 116%g_tColor = OpVariable %_ptr_UniformConstant__arr_16_uint_128 UniformConstant 117%PerViewConstantBuffer_t = OpTypeStruct %uint 118%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t 119%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant 120%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint 121%_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16 122%24 = OpTypeSampler 123%_ptr_UniformConstant_24 = OpTypePointer UniformConstant %24 124%g_sAniso = OpVariable %_ptr_UniformConstant_24 UniformConstant 125%26 = OpTypeSampledImage %16 126%_ptr_Input_v2float = OpTypePointer Input %v2float 127%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input 128%_ptr_Output_v4float = OpTypePointer Output %v4float 129%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output 130;CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float 131;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 132;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 133)"; 134 135 const std::string main_func = R"( 136%MainPs = OpFunction %void None %10 137%29 = OpLabel 138%30 = OpLoad %v2float %i_vTextureCoords 139%31 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 140%32 = OpLoad %uint %31 141%33 = OpAccessChain %_ptr_UniformConstant_16 %g_tColor %32 142%34 = OpLoad %16 %33 143%35 = OpLoad %24 %g_sAniso 144%36 = OpSampledImage %26 %34 %35 145%37 = OpImageSampleImplicitLod %v4float %36 %30 146OpStore %_entryPointOutput_vColor %37 147;CHECK-NOT: %37 = OpImageSampleImplicitLod %v4float %36 %30 148;CHECK-NOT: OpStore %_entryPointOutput_vColor %37 149;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_57 {{%\w+}} %uint_3 %uint_0 %32 %uint_0 150;CHECK: OpSelectionMerge {{%\w+}} None 151;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 152;CHECK: {{%\w+}} = OpLabel 153;CHECK: {{%\w+}} = OpLoad %16 %33 154;CHECK: {{%\w+}} = OpSampledImage %26 {{%\w+}} %35 155;CHECK: {{%\w+}} = OpImageSampleImplicitLod %v4float {{%\w+}} %30 156;CHECK: OpBranch {{%\w+}} 157;CHECK: {{%\w+}} = OpLabel 158;CHECK: OpBranch {{%\w+}} 159;CHECK: {{%\w+}} = OpLabel 160;CHECK: [[phi_result:%\w+]] = OpPhi %v4float {{%\w+}} {{%\w+}} [[null_v4float]] {{%\w+}} 161;CHECK: OpStore %_entryPointOutput_vColor [[phi_result]] 162OpReturn 163OpFunctionEnd 164)"; 165 // clang-format on 166 167 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 168 SinglePassRunAndMatch<InstBindlessCheckPass>( 169 entry + names_annots + consts_types_vars + kImportStub + main_func, true, 170 23u); 171} 172 173TEST_F(InstBindlessTest, InstrumentMultipleInstructions) { 174 // Texture2D g_tColor[128]; 175 // 176 // layout(push_constant) cbuffer PerViewConstantBuffer_t 177 // { 178 // uint g_nDataIdx; 179 // uint g_nDataIdx2; 180 // }; 181 // 182 // SamplerState g_sAniso; 183 // 184 // struct PS_INPUT 185 // { 186 // float2 vTextureCoords : TEXCOORD2; 187 // }; 188 // 189 // struct PS_OUTPUT 190 // { 191 // float4 vColor : SV_Target0; 192 // }; 193 // 194 // PS_OUTPUT MainPs(PS_INPUT i) 195 // { 196 // PS_OUTPUT ps_output; 197 // 198 // float t = g_tColor[g_nDataIdx ].Sample(g_sAniso, i.vTextureCoords.xy); 199 // float t2 = g_tColor[g_nDataIdx2].Sample(g_sAniso, i.vTextureCoords.xy); 200 // ps_output.vColor = t + t2; 201 // return ps_output; 202 // } 203 204 // clang-format off 205 const std::string defs = R"( 206OpCapability Shader 207OpCapability Linkage 208%1 = OpExtInstImport "GLSL.std.450" 209OpMemoryModel Logical GLSL450 210OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor 211;CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord 212OpExecutionMode %MainPs OriginUpperLeft 213OpSource HLSL 500 214OpName %MainPs "MainPs" 215OpName %g_tColor "g_tColor" 216OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" 217OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" 218OpName %_ "" 219OpName %g_sAniso "g_sAniso" 220OpName %i_vTextureCoords "i.vTextureCoords" 221OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" 222OpDecorate %g_tColor DescriptorSet 3 223OpDecorate %g_tColor Binding 4 224OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 225OpMemberDecorate %PerViewConstantBuffer_t 1 Offset 4 226OpDecorate %PerViewConstantBuffer_t Block 227OpDecorate %g_sAniso DescriptorSet 3 228OpDecorate %i_vTextureCoords Location 0 229OpDecorate %_entryPointOutput_vColor Location 0 230)" + kImportDeco + R"( 231;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 232%void = OpTypeVoid 233%10 = OpTypeFunction %void 234%float = OpTypeFloat 32 235%v2float = OpTypeVector %float 2 236%v4float = OpTypeVector %float 4 237%int = OpTypeInt 32 1 238%int_0 = OpConstant %int 0 239%int_1 = OpConstant %int 1 240%17 = OpTypeImage %float 2D 0 0 0 1 Unknown 241%uint = OpTypeInt 32 0 242%uint_128 = OpConstant %uint 128 243%_arr_17_uint_128 = OpTypeArray %17 %uint_128 244%_ptr_UniformConstant__arr_17_uint_128 = OpTypePointer UniformConstant %_arr_17_uint_128 245%g_tColor = OpVariable %_ptr_UniformConstant__arr_17_uint_128 UniformConstant 246%PerViewConstantBuffer_t = OpTypeStruct %uint %uint 247%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t 248%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant 249%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint 250%_ptr_UniformConstant_17 = OpTypePointer UniformConstant %17 251%25 = OpTypeSampler 252%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %25 253%g_sAniso = OpVariable %_ptr_UniformConstant_25 UniformConstant 254%27 = OpTypeSampledImage %17 255%_ptr_Input_v2float = OpTypePointer Input %v2float 256%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input 257%_ptr_Output_v4float = OpTypePointer Output %v4float 258%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output 259;CHECK: %v4uint = OpTypeVector %uint 4 260;CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float 261;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 262;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 263)"; 264 265 const std::string main_func = R"( 266%MainPs = OpFunction %void None %10 267%30 = OpLabel 268%31 = OpLoad %v2float %i_vTextureCoords 269%32 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 270%33 = OpLoad %uint %32 271%34 = OpAccessChain %_ptr_UniformConstant_17 %g_tColor %33 272%35 = OpLoad %17 %34 273%36 = OpLoad %25 %g_sAniso 274%37 = OpSampledImage %27 %35 %36 275%38 = OpImageSampleImplicitLod %v4float %37 %31 276;CHECK-NOT: %38 = OpImageSampleImplicitLod %v4float %37 %31 277;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 278;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 279;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 280;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 281;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 282;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_60 {{%\w+}} %uint_3 %uint_4 %33 %uint_0 283;CHECK: OpSelectionMerge {{%\w+}} None 284;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 285;CHECK: {{%\w+}} = OpLabel 286;CHECK: {{%\w+}} = OpLoad %17 %34 287;CHECK: {{%\w+}} = OpSampledImage %27 {{%\w+}} %36 288;CHECK: {{%\w+}} = OpImageSampleImplicitLod %v4float {{%\w+}} %31 289;CHECK: OpBranch {{%\w+}} 290;CHECK: {{%\w+}} = OpLabel 291;CHECK: OpBranch {{%\w+}} 292;CHECK: {{%\w+}} = OpLabel 293;CHECK: {{%\w+}} = OpPhi %v4float {{%\w+}} {{%\w+}} [[null_v4float]] {{%\w+}} 294%39 = OpAccessChain %_ptr_PushConstant_uint %_ %int_1 295%40 = OpLoad %uint %39 296%41 = OpAccessChain %_ptr_UniformConstant_17 %g_tColor %40 297%42 = OpLoad %17 %41 298%43 = OpSampledImage %27 %42 %36 299%44 = OpImageSampleImplicitLod %v4float %43 %31 300%45 = OpFAdd %v4float %38 %44 301;CHECK-NOT: %44 = OpImageSampleImplicitLod %v4float %43 %31 302;CHECK-NOT: %45 = OpFAdd %v4float %38 %44 303;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 304;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 305;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 306;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 307;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 308;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_66 {{%\w+}} %uint_3 %uint_4 %40 %uint_0 309;CHECK: OpSelectionMerge {{%\w+}} None 310;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 311;CHECK: {{%\w+}} = OpLabel 312;CHECK: {{%\w+}} = OpLoad %17 %41 313;CHECK: {{%\w+}} = OpSampledImage %27 {{%\w+}} %36 314;CHECK: {{%\w+}} = OpImageSampleImplicitLod %v4float {{%\w+}} %31 315;CHECK: OpBranch {{%\w+}} 316;CHECK: {{%\w+}} = OpLabel 317;CHECK: OpBranch {{%\w+}} 318;CHECK: {{%\w+}} = OpLabel 319;CHECK: {{%\w+}} = OpPhi %v4float {{%\w+}} {{%\w+}} [[null_v4float]] {{%\w+}} 320;CHECK: %45 = OpFAdd %v4float {{%\w+}} {{%\w+}} 321OpStore %_entryPointOutput_vColor %45 322OpReturn 323OpFunctionEnd 324)"; 325 // clang-format on 326 327 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 328 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 329 true, 23u); 330} 331 332TEST_F(InstBindlessTest, InstrumentOpImage) { 333 // This test verifies that the pass will correctly instrument shader 334 // using OpImage. This test was created by editing the SPIR-V 335 // from the Simple test. 336 337 // clang-format off 338 const std::string defs = R"( 339OpCapability Shader 340OpCapability StorageImageReadWithoutFormat 341;CHECK: OpCapability Linkage 342%1 = OpExtInstImport "GLSL.std.450" 343OpMemoryModel Logical GLSL450 344OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor 345;CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord 346OpExecutionMode %MainPs OriginUpperLeft 347OpSource HLSL 500 348OpName %MainPs "MainPs" 349OpName %g_tColor "g_tColor" 350OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" 351OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" 352OpName %_ "" 353OpName %i_vTextureCoords "i.vTextureCoords" 354OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" 355OpDecorate %g_tColor DescriptorSet 3 356OpDecorate %g_tColor Binding 9 357OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 358OpDecorate %PerViewConstantBuffer_t Block 359OpDecorate %i_vTextureCoords Location 0 360OpDecorate %_entryPointOutput_vColor Location 0 361)" + kImportDeco + R"( 362;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 363%void = OpTypeVoid 364%3 = OpTypeFunction %void 365%float = OpTypeFloat 32 366%v4float = OpTypeVector %float 4 367%int = OpTypeInt 32 1 368%v2int = OpTypeVector %int 2 369%int_0 = OpConstant %int 0 370%20 = OpTypeImage %float 2D 0 0 0 0 Unknown 371%uint = OpTypeInt 32 0 372%uint_128 = OpConstant %uint 128 373%39 = OpTypeSampledImage %20 374%_arr_39_uint_128 = OpTypeArray %39 %uint_128 375%_ptr_UniformConstant__arr_39_uint_128 = OpTypePointer UniformConstant %_arr_39_uint_128 376%g_tColor = OpVariable %_ptr_UniformConstant__arr_39_uint_128 UniformConstant 377%PerViewConstantBuffer_t = OpTypeStruct %uint 378%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t 379%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant 380%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint 381%_ptr_UniformConstant_39 = OpTypePointer UniformConstant %39 382%_ptr_Input_v2int = OpTypePointer Input %v2int 383%i_vTextureCoords = OpVariable %_ptr_Input_v2int Input 384%_ptr_Output_v4float = OpTypePointer Output %v4float 385%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output 386;CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float 387;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 388;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 389)"; 390 391 const std::string main_func = R"( 392%MainPs = OpFunction %void None %3 393%5 = OpLabel 394%53 = OpLoad %v2int %i_vTextureCoords 395%63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 396%64 = OpLoad %uint %63 397%65 = OpAccessChain %_ptr_UniformConstant_39 %g_tColor %64 398%66 = OpLoad %39 %65 399%75 = OpImage %20 %66 400%71 = OpImageRead %v4float %75 %53 401OpStore %_entryPointOutput_vColor %71 402;CHECK-NOT: %71 = OpImageRead %v4float %75 %53 403;CHECK-NOT: OpStore %_entryPointOutput_vColor %71 404;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 405;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 406;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 407;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 408;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 409;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_52 {{%\w+}} %uint_3 %uint_9 %64 %uint_0 410;CHECK: OpSelectionMerge {{%\w+}} None 411;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 412;CHECK: {{%\w+}} = OpLabel 413;CHECK: {{%\w+}} = OpLoad %39 %65 414;CHECK: {{%\w+}} = OpImage %20 {{%\w+}} 415;CHECK: {{%\w+}} = OpImageRead %v4float {{%\w+}} %53 416;CHECK: OpBranch {{%\w+}} 417;CHECK: {{%\w+}} = OpLabel 418;CHECK: OpBranch {{%\w+}} 419;CHECK: {{%\w+}} = OpLabel 420;CHECK: {{%\w+}} = OpPhi %v4float {{%\w+}} {{%\w+}} [[null_v4float]] {{%\w+}} 421;CHECK: OpStore %_entryPointOutput_vColor {{%\w+}} 422OpReturn 423OpFunctionEnd 424)"; 425 // clang-format on 426 427 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 428 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 429 true, 23u); 430} 431 432TEST_F(InstBindlessTest, InstrumentSampledImage) { 433 // This test verifies that the pass will correctly instrument shader 434 // using sampled image. This test was created by editing the SPIR-V 435 // from the Simple test. 436 437 // clang-format off 438 const std::string defs = R"( 439OpCapability Shader 440;CHECK: OpCapability Linkage 441%1 = OpExtInstImport "GLSL.std.450" 442OpMemoryModel Logical GLSL450 443OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor 444;CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord 445OpExecutionMode %MainPs OriginUpperLeft 446OpSource HLSL 500 447OpName %MainPs "MainPs" 448OpName %g_tColor "g_tColor" 449OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" 450OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" 451OpName %_ "" 452OpName %i_vTextureCoords "i.vTextureCoords" 453OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" 454OpDecorate %g_tColor DescriptorSet 4 455OpDecorate %g_tColor Binding 11 456OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 457OpDecorate %PerViewConstantBuffer_t Block 458OpDecorate %i_vTextureCoords Location 0 459OpDecorate %_entryPointOutput_vColor Location 0 460)" + kImportDeco + R"( 461;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 462%void = OpTypeVoid 463%3 = OpTypeFunction %void 464%float = OpTypeFloat 32 465%v2float = OpTypeVector %float 2 466%v4float = OpTypeVector %float 4 467%int = OpTypeInt 32 1 468%int_0 = OpConstant %int 0 469%20 = OpTypeImage %float 2D 0 0 0 1 Unknown 470%uint = OpTypeInt 32 0 471%uint_128 = OpConstant %uint 128 472%39 = OpTypeSampledImage %20 473%_arr_39_uint_128 = OpTypeArray %39 %uint_128 474%_ptr_UniformConstant__arr_39_uint_128 = OpTypePointer UniformConstant %_arr_39_uint_128 475%g_tColor = OpVariable %_ptr_UniformConstant__arr_39_uint_128 UniformConstant 476%PerViewConstantBuffer_t = OpTypeStruct %uint 477%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t 478%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant 479%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint 480%_ptr_UniformConstant_39 = OpTypePointer UniformConstant %39 481%_ptr_Input_v2float = OpTypePointer Input %v2float 482%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input 483%_ptr_Output_v4float = OpTypePointer Output %v4float 484%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output 485;CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float 486;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 487;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 488)"; 489 490 const std::string main_func = R"( 491%MainPs = OpFunction %void None %3 492%5 = OpLabel 493%53 = OpLoad %v2float %i_vTextureCoords 494%63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 495%64 = OpLoad %uint %63 496%65 = OpAccessChain %_ptr_UniformConstant_39 %g_tColor %64 497%66 = OpLoad %39 %65 498%71 = OpImageSampleImplicitLod %v4float %66 %53 499OpStore %_entryPointOutput_vColor %71 500;CHECK-NOT: %71 = OpImageSampleImplicitLod %v4float %66 %53 501;CHECK-NOT: OpStore %_entryPointOutput_vColor %71 502;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 503;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 504;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 505;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 506;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 507;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_50 {{%\w+}} %uint_4 %uint_11 %64 %uint_0 508;CHECK: OpSelectionMerge {{%\w+}} None 509;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 510;CHECK: {{%\w+}} = OpLabel 511;CHECK: {{%\w+}} = OpLoad %39 %65 512;CHECK: {{%\w+}} = OpImageSampleImplicitLod %v4float {{%\w+}} %53 513;CHECK: OpBranch {{%\w+}} 514;CHECK: {{%\w+}} = OpLabel 515;CHECK: OpBranch {{%\w+}} 516;CHECK: {{%\w+}} = OpLabel 517;CHECK: {{%\w+}} = OpPhi %v4float {{%\w+}} {{%\w+}} [[null_v4float]] {{%\w+}} 518;CHECK: OpStore %_entryPointOutput_vColor {{%\w+}} 519OpReturn 520OpFunctionEnd 521)"; 522 // clang-format on 523 524 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 525 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 526 true, 23u); 527} 528 529TEST_F(InstBindlessTest, InstrumentImageWrite) { 530 // This test verifies that the pass will correctly instrument shader 531 // doing bindless image write. This test was created by editing the SPIR-V 532 // from the Simple test. 533 534 // clang-format off 535 const std::string defs = R"( 536OpCapability Shader 537OpCapability StorageImageWriteWithoutFormat 538;CHECK: OpCapability Linkage 539%1 = OpExtInstImport "GLSL.std.450" 540OpMemoryModel Logical GLSL450 541OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor 542;CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord 543OpExecutionMode %MainPs OriginUpperLeft 544OpSource HLSL 500 545OpName %MainPs "MainPs" 546OpName %g_tColor "g_tColor" 547OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" 548OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" 549OpName %_ "" 550OpName %i_vTextureCoords "i.vTextureCoords" 551OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" 552OpDecorate %g_tColor DescriptorSet 30 553OpDecorate %g_tColor Binding 2 554OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 555OpDecorate %PerViewConstantBuffer_t Block 556OpDecorate %i_vTextureCoords Location 0 557OpDecorate %_entryPointOutput_vColor Location 0 558)" + kImportDeco + R"( 559;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 560%void = OpTypeVoid 561%3 = OpTypeFunction %void 562%float = OpTypeFloat 32 563%v2float = OpTypeVector %float 2 564%v4float = OpTypeVector %float 4 565%int = OpTypeInt 32 1 566%v2int = OpTypeVector %int 2 567%int_0 = OpConstant %int 0 568%20 = OpTypeImage %float 2D 0 0 0 0 Unknown 569%uint = OpTypeInt 32 0 570%uint_128 = OpConstant %uint 128 571%80 = OpConstantNull %v4float 572%_arr_20_uint_128 = OpTypeArray %20 %uint_128 573%_ptr_UniformConstant__arr_20_uint_128 = OpTypePointer UniformConstant %_arr_20_uint_128 574%g_tColor = OpVariable %_ptr_UniformConstant__arr_20_uint_128 UniformConstant 575%PerViewConstantBuffer_t = OpTypeStruct %uint 576%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t 577%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant 578%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint 579%_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20 580%_ptr_Input_v2int = OpTypePointer Input %v2int 581%i_vTextureCoords = OpVariable %_ptr_Input_v2int Input 582%_ptr_Output_v4float = OpTypePointer Output %v4float 583%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output 584;CHECK: %v4uint = OpTypeVector %uint 4 585;CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float 586;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 587)"; 588 589 const std::string main_func = R"( 590%MainPs = OpFunction %void None %3 591%5 = OpLabel 592%53 = OpLoad %v2int %i_vTextureCoords 593%63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 594%64 = OpLoad %uint %63 595%65 = OpAccessChain %_ptr_UniformConstant_20 %g_tColor %64 596%66 = OpLoad %20 %65 597OpImageWrite %66 %53 %80 598OpStore %_entryPointOutput_vColor %80 599;CHECK-NOT: OpImageWrite %66 %53 %80 600;CHECK-NOT: OpStore %_entryPointOutput_vColor %80 601;CHECK: %32 = OpLoad %16 %31 602;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 603;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 604;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 605;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 606;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 607;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_52 {{%\w+}} %uint_30 %uint_2 %30 %uint_0 608;CHECK: OpSelectionMerge {{%\w+}} None 609;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 610;CHECK: {{%\w+}} = OpLabel 611;CHECK: {{%\w+}} = OpLoad %16 %31 612;CHECK: OpImageWrite {{%\w+}} %28 %19 613;CHECK: OpBranch {{%\w+}} 614;CHECK: {{%\w+}} = OpLabel 615;CHECK: OpBranch {{%\w+}} 616;CHECK: {{%\w+}} = OpLabel 617;CHECK: OpStore %_entryPointOutput_vColor %19 618OpReturn 619OpFunctionEnd 620)"; 621 // clang-format on 622 623 // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 624 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 625 true, 23u); 626} 627 628TEST_F(InstBindlessTest, InstrumentVertexSimple) { 629 // This test verifies that the pass will correctly instrument shader 630 // doing bindless image write. This test was created by editing the SPIR-V 631 // from the Simple test. 632 633 // clang-format off 634 const std::string defs = R"( 635OpCapability Shader 636OpCapability Sampled1D 637;CHECK: OpCapability Linkage 638%1 = OpExtInstImport "GLSL.std.450" 639OpMemoryModel Logical GLSL450 640OpEntryPoint Vertex %main "main" %_ %coords2D 641OpSource GLSL 450 642OpName %main "main" 643OpName %lod "lod" 644OpName %coords1D "coords1D" 645OpName %gl_PerVertex "gl_PerVertex" 646OpMemberName %gl_PerVertex 0 "gl_Position" 647OpMemberName %gl_PerVertex 1 "gl_PointSize" 648OpMemberName %gl_PerVertex 2 "gl_ClipDistance" 649OpMemberName %gl_PerVertex 3 "gl_CullDistance" 650OpName %_ "" 651OpName %texSampler1D "texSampler1D" 652OpName %foo "foo" 653OpMemberName %foo 0 "g_idx" 654OpName %__0 "" 655OpName %coords2D "coords2D" 656)" + kImportDeco + R"( 657;CHECK: OpDecorate %gl_VertexIndex BuiltIn VertexIndex 658;CHECK: OpDecorate %gl_InstanceIndex BuiltIn InstanceIndex 659OpMemberDecorate %gl_PerVertex 0 BuiltIn Position 660OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize 661OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance 662OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance 663OpDecorate %gl_PerVertex Block 664OpDecorate %texSampler1D DescriptorSet 2 665OpDecorate %texSampler1D Binding 13 666OpMemberDecorate %foo 0 Offset 0 667OpDecorate %foo Block 668OpDecorate %__0 DescriptorSet 7 669OpDecorate %__0 Binding 5 670OpDecorate %coords2D Location 0 671%void = OpTypeVoid 672%3 = OpTypeFunction %void 673%float = OpTypeFloat 32 674%_ptr_Function_float = OpTypePointer Function %float 675%float_3 = OpConstant %float 3 676%float_1_78900003 = OpConstant %float 1.78900003 677%v4float = OpTypeVector %float 4 678%uint = OpTypeInt 32 0 679%uint_1 = OpConstant %uint 1 680%_arr_float_uint_1 = OpTypeArray %float %uint_1 681%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1 682%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex 683%_ = OpVariable %_ptr_Output_gl_PerVertex Output 684%int = OpTypeInt 32 1 685%int_0 = OpConstant %int 0 686%21 = OpTypeImage %float 1D 0 0 0 1 Unknown 687%22 = OpTypeSampledImage %21 688%uint_128 = OpConstant %uint 128 689%_arr_22_uint_128 = OpTypeArray %22 %uint_128 690%_ptr_UniformConstant__arr_22_uint_128 = OpTypePointer UniformConstant %_arr_22_uint_128 691%texSampler1D = OpVariable %_ptr_UniformConstant__arr_22_uint_128 UniformConstant 692%foo = OpTypeStruct %int 693%_ptr_Uniform_foo = OpTypePointer Uniform %foo 694%__0 = OpVariable %_ptr_Uniform_foo Uniform 695%_ptr_Uniform_int = OpTypePointer Uniform %int 696%_ptr_UniformConstant_22 = OpTypePointer UniformConstant %22 697%_ptr_Output_v4float = OpTypePointer Output %v4float 698%v2float = OpTypeVector %float 2 699%_ptr_Input_v2float = OpTypePointer Input %v2float 700%coords2D = OpVariable %_ptr_Input_v2float Input 701;CHECK: %_ptr_Input_uint = OpTypePointer Input %uint 702;CHECK: %gl_VertexIndex = OpVariable %_ptr_Input_uint Input 703;CHECK: %gl_InstanceIndex = OpVariable %_ptr_Input_uint Input 704;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 705)"; 706 707 const std::string main_func = R"( 708%main = OpFunction %void None %3 709%5 = OpLabel 710%lod = OpVariable %_ptr_Function_float Function 711%coords1D = OpVariable %_ptr_Function_float Function 712OpStore %lod %float_3 713OpStore %coords1D %float_1_78900003 714%31 = OpAccessChain %_ptr_Uniform_int %__0 %int_0 715%32 = OpLoad %int %31 716%34 = OpAccessChain %_ptr_UniformConstant_22 %texSampler1D %32 717%35 = OpLoad %22 %34 718%36 = OpLoad %float %coords1D 719%37 = OpLoad %float %lod 720%38 = OpImageSampleExplicitLod %v4float %35 %36 Lod %37 721%40 = OpAccessChain %_ptr_Output_v4float %_ %int_0 722OpStore %40 %38 723;CHECK-NOT: %38 = OpImageSampleExplicitLod %v4float %35 %36 Lod %37 724;CHECK-NOT: %40 = OpAccessChain %_ptr_Output_v4float %_ %int_0 725;CHECK-NOT: OpStore %40 %38 726;CHECK: {{%\w+}} = OpLoad %uint %gl_VertexIndex 727;CHECK: {{%\w+}} = OpLoad %uint %gl_InstanceIndex 728;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_0 {{%\w+}} {{%\w+}} %uint_0 729;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_70 {{%\w+}} %uint_7 %uint_5 %uint_0 {{%\w+}} 730;CHECK: OpSelectionMerge {{%\w+}} None 731;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 732;CHECK: {{%\w+}} = OpLabel 733;CHECK: {{%\w+}} = OpLoad %int {{%\w+}} 734;CHECK: OpBranch {{%\w+}} 735;CHECK: {{%\w+}} = OpLabel 736;CHECK: OpBranch {{%\w+}} 737;CHECK: {{%\w+}} = OpLabel 738;CHECK: {{%\w+}} = OpPhi %int {{%\w+}} {{%\w+}} {{%\w+}} {{%\w+}} 739;CHECK: {{%\w+}} = OpAccessChain %_ptr_UniformConstant_25 %texSampler1D {{%\w+}} 740;CHECK: {{%\w+}} = OpLoad {{%\w+}} {{%\w+}} 741;CHECK: {{%\w+}} = OpLoad %float %coords1D 742;CHECK: {{%\w+}} = OpLoad %float %lod 743;CHECK: {{%\w+}} = OpLoad %uint %gl_VertexIndex 744;CHECK: {{%\w+}} = OpLoad %uint %gl_InstanceIndex 745;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_0 {{%\w+}} {{%\w+}} %uint_0 746;CHECK: {{%\w+}} = OpBitcast %uint {{%\w+}} 747;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_75 {{%\w+}} %uint_2 %uint_13 {{%\w+}} %uint_0 748;CHECK: OpSelectionMerge {{%\w+}} None 749;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 750;CHECK: {{%\w+}} = OpLabel 751;CHECK: {{%\w+}} = OpLoad %25 %38 752;CHECK: {{%\w+}} = OpImageSampleExplicitLod %v4float {{%\w+}} %40 Lod %41 753;CHECK: OpBranch {{%\w+}} 754;CHECK: {{%\w+}} = OpLabel 755;CHECK: OpBranch {{%\w+}} 756;CHECK: {{%\w+}} = OpLabel 757;CHECK: {{%\w+}} = OpPhi %v4float {{%\w+}} {{%\w+}} {{%\w+}} {{%\w+}} 758;CHECK: %43 = OpAccessChain %_ptr_Output_v4float %_ %int_0 759;CHECK: OpStore %43 {{%\w+}} 760OpReturn 761OpFunctionEnd 762)"; 763 // clang-format on 764 765 // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 766 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 767 true, 23u); 768} 769 770TEST_F(InstBindlessTest, InstrumentTeseSimple) { 771 // This test verifies that the pass will correctly instrument tessellation 772 // evaluation shader doing bindless buffer load. 773 // 774 // clang-format off 775 // 776 // #version 450 777 // #extension GL_EXT_nonuniform_qualifier : enable 778 // 779 // layout(std140, set = 9, binding = 1) uniform ufoo { uint index; } uniform_index_buffer; 780 // 781 // layout(set = 9, binding = 2) buffer bfoo { vec4 val; } adds[11]; 782 // 783 // layout(triangles, equal_spacing, cw) in; 784 // 785 // void main() { 786 // gl_Position = adds[uniform_index_buffer.index].val; 787 // } 788 // 789 790 const std::string defs = R"( 791OpCapability Tessellation 792;CHECK: OpCapability Linkage 793%1 = OpExtInstImport "GLSL.std.450" 794OpMemoryModel Logical GLSL450 795OpEntryPoint TessellationEvaluation %main "main" %_ 796;CHECK: OpEntryPoint TessellationEvaluation %main "main" %_ %gl_PrimitiveID %gl_TessCoord 797OpExecutionMode %main Triangles 798OpExecutionMode %main SpacingEqual 799OpExecutionMode %main VertexOrderCw 800OpSource GLSL 450 801OpSourceExtension "GL_EXT_nonuniform_qualifier" 802OpName %main "main" 803OpName %gl_PerVertex "gl_PerVertex" 804OpMemberName %gl_PerVertex 0 "gl_Position" 805OpMemberName %gl_PerVertex 1 "gl_PointSize" 806OpMemberName %gl_PerVertex 2 "gl_ClipDistance" 807OpMemberName %gl_PerVertex 3 "gl_CullDistance" 808OpName %_ "" 809OpName %bfoo "bfoo" 810OpMemberName %bfoo 0 "val" 811OpName %adds "adds" 812OpName %ufoo "ufoo" 813OpMemberName %ufoo 0 "index" 814OpName %uniform_index_buffer "uniform_index_buffer" 815OpMemberDecorate %gl_PerVertex 0 BuiltIn Position 816OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize 817OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance 818OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance 819OpDecorate %gl_PerVertex Block 820OpMemberDecorate %bfoo 0 Offset 0 821OpDecorate %bfoo Block 822OpDecorate %adds DescriptorSet 9 823OpDecorate %adds Binding 1 824OpMemberDecorate %ufoo 0 Offset 0 825OpDecorate %ufoo Block 826OpDecorate %uniform_index_buffer DescriptorSet 9 827OpDecorate %uniform_index_buffer Binding 2 828)" + kImportDeco + R"( 829;CHECK: OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId 830;CHECK: OpDecorate %gl_TessCoord BuiltIn TessCoord 831%void = OpTypeVoid 832%3 = OpTypeFunction %void 833%float = OpTypeFloat 32 834%v4float = OpTypeVector %float 4 835%uint = OpTypeInt 32 0 836%uint_1 = OpConstant %uint 1 837%_arr_float_uint_1 = OpTypeArray %float %uint_1 838%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1 839%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex 840%_ = OpVariable %_ptr_Output_gl_PerVertex Output 841%int = OpTypeInt 32 1 842%int_0 = OpConstant %int 0 843%bfoo = OpTypeStruct %v4float 844%uint_11 = OpConstant %uint 11 845%_arr_bfoo_uint_11 = OpTypeArray %bfoo %uint_11 846%_ptr_StorageBuffer__arr_bfoo_uint_11 = OpTypePointer StorageBuffer %_arr_bfoo_uint_11 847%adds = OpVariable %_ptr_StorageBuffer__arr_bfoo_uint_11 StorageBuffer 848%ufoo = OpTypeStruct %uint 849%_ptr_Uniform_ufoo = OpTypePointer Uniform %ufoo 850%uniform_index_buffer = OpVariable %_ptr_Uniform_ufoo Uniform 851%_ptr_Uniform_uint = OpTypePointer Uniform %uint 852%_ptr_StorageBuffer_v4float = OpTypePointer StorageBuffer %v4float 853%_ptr_Output_v4float = OpTypePointer Output %v4float 854;CHECK: %_ptr_Input_uint = OpTypePointer Input %uint 855;CHECK: %gl_PrimitiveID = OpVariable %_ptr_Input_uint Input 856;CHECK: %v3float = OpTypeVector %float 3 857;CHECK: %_ptr_Input_v3float = OpTypePointer Input %v3float 858;CHECK: %gl_TessCoord = OpVariable %_ptr_Input_v3float Input 859;CHECK: %v3uint = OpTypeVector %uint 3 860;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 861)"; 862 863 const std::string main_func = 864 R"( 865%main = OpFunction %void None %3 866%5 = OpLabel 867%25 = OpAccessChain %_ptr_Uniform_uint %uniform_index_buffer %int_0 868%26 = OpLoad %uint %25 869%28 = OpAccessChain %_ptr_StorageBuffer_v4float %adds %26 %int_0 870%29 = OpLoad %v4float %28 871;CHECK-NOT: %29 = OpLoad %v4float %28 872;CHECK: {{%\w+}} = OpLoad %uint %gl_PrimitiveID 873;CHECK: {{%\w+}} = OpLoad %v3float %gl_TessCoord 874;CHECK: {{%\w+}} = OpBitcast %v3uint {{%\w+}} 875;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 876;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 877;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_2 {{%\w+}} {{%\w+}} {{%\w+}} 878;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_62 {{%\w+}} %uint_9 %uint_2 %uint_0 {{%\w+}} 879;CHECK: OpSelectionMerge {{%\w+}} None 880;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 881;CHECK: {{%\w+}} = OpLabel 882;CHECK: {{%\w+}} = OpLoad %uint %27 883;CHECK: OpBranch {{%\w+}} 884;CHECK: {{%\w+}} = OpLabel 885;CHECK: OpBranch {{%\w+}} 886;CHECK: {{%\w+}} = OpLabel 887;CHECK: {{%\w+}} = OpPhi %uint {{%\w+}} {{%\w+}} {{%\w+}} {{%\w+}} 888%31 = OpAccessChain %_ptr_Output_v4float %_ %int_0 889OpStore %31 %29 890;CHECK-NOT: OpStore %31 %29 891;CHECK: {{%\w+}} = OpLoad %uint %gl_PrimitiveID 892;CHECK: {{%\w+}} = OpLoad %v3float %gl_TessCoord 893;CHECK: {{%\w+}} = OpBitcast %v3uint {{%\w+}} 894;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 895;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 896;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_2 {{%\w+}} {{%\w+}} {{%\w+}} 897;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_64 {{%\w+}} %uint_9 %uint_1 {{%\w+}} {{%\w+}} 898;CHECK: OpSelectionMerge {{%\w+}} None 899;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 900;CHECK: {{%\w+}} = OpLabel 901;CHECK: {{%\w+}} = OpLoad %v4float %29 902;CHECK: OpBranch {{%\w+}} 903;CHECK: {{%\w+}} = OpLabel 904;CHECK: OpBranch {{%\w+}} 905;CHECK: {{%\w+}} = OpLabel 906;CHECK: [[phi_result:%\w+]] = OpPhi {{%\w+}} {{%\w+}} {{%\w+}} {{%\w+}} {{%\w+}} 907;CHECK: %31 = OpAccessChain %_ptr_Output_v4float %_ %int_0 908;CHECK: OpStore %31 [[phi_result]] 909OpReturn 910OpFunctionEnd 911)"; 912 // clang-format on 913 914 // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 915 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 916 true, 23u); 917} 918 919TEST_F(InstBindlessTest, InstrumentTesc) { 920 // This test verifies that the pass will correctly instrument tessellation 921 // control shader 922 // 923 // clang-format off 924 // 925 // #version 450 926 // layout(vertices = 3) out; 927 // layout(set = 0, binding = 0) uniform texture1D _77; 928 // layout(set = 0, binding = 1) uniform sampler _78; 929 930 // layout(location = 1) flat in int _3[]; 931 // layout(location = 0) out vec4 _5[3]; 932 933 // void main() 934 // { 935 // float param; 936 // if (_3[gl_InvocationID] == 0) 937 // { 938 // param = 0.0234375; 939 // } 940 // else 941 // { 942 // param = 1.0156199932098388671875; 943 // } 944 // _5[gl_InvocationID] = textureLod(sampler1D(_77, _78), param, 0.0); 945 // vec4 _203; 946 // if (gl_InvocationID == 0) 947 // { 948 // _203 = gl_in[0].gl_Position; 949 // } 950 // else 951 // { 952 // _203 = gl_in[2].gl_Position; 953 // } 954 // gl_out[gl_InvocationID].gl_Position = _203; 955 // gl_TessLevelInner[0] = 2.7999999523162841796875; 956 // gl_TessLevelInner[1] = 2.7999999523162841796875; 957 // gl_TessLevelOuter[0] = 2.7999999523162841796875; 958 // gl_TessLevelOuter[1] = 2.7999999523162841796875; 959 // gl_TessLevelOuter[2] = 2.7999999523162841796875; 960 // gl_TessLevelOuter[3] = 2.7999999523162841796875; 961 // } 962 // 963 // clang-format on 964 // 965 // 966 967 // clang-format off 968 const std::string defs = R"( 969OpCapability Tessellation 970OpCapability Sampled1D 971;CHECK: OpCapability Linkage 972;CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class" 973;CHECK: OpExtension "SPV_KHR_physical_storage_buffer" 974%1 = OpExtInstImport "GLSL.std.450" 975OpMemoryModel Logical GLSL450 976;CHECK: OpMemoryModel PhysicalStorageBuffer64 GLSL450 977OpEntryPoint TessellationControl %main "main" %_3 %gl_InvocationID %_5 %gl_in %gl_out %gl_TessLevelInner %gl_TessLevelOuter 978;CHECK: OpEntryPoint TessellationControl %main "main" %_3 %gl_InvocationID %_5 %gl_in %gl_out %gl_TessLevelInner %gl_TessLevelOuter %gl_PrimitiveID 979OpExecutionMode %main OutputVertices 3 980OpSource GLSL 450 981OpName %main "main" 982OpName %_3 "_3" 983OpName %gl_InvocationID "gl_InvocationID" 984OpName %param "param" 985OpName %_5 "_5" 986OpName %_77 "_77" 987OpName %_78 "_78" 988OpName %_203 "_203" 989OpName %gl_PerVertex "gl_PerVertex" 990OpMemberName %gl_PerVertex 0 "gl_Position" 991OpMemberName %gl_PerVertex 1 "gl_PointSize" 992OpMemberName %gl_PerVertex 2 "gl_ClipDistance" 993OpMemberName %gl_PerVertex 3 "gl_CullDistance" 994OpName %gl_in "gl_in" 995OpName %gl_PerVertex_0 "gl_PerVertex" 996OpMemberName %gl_PerVertex_0 0 "gl_Position" 997OpMemberName %gl_PerVertex_0 1 "gl_PointSize" 998OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance" 999OpMemberName %gl_PerVertex_0 3 "gl_CullDistance" 1000OpName %gl_out "gl_out" 1001OpName %gl_TessLevelInner "gl_TessLevelInner" 1002OpName %gl_TessLevelOuter "gl_TessLevelOuter" 1003OpDecorate %_3 Flat 1004OpDecorate %_3 Location 1 1005OpDecorate %gl_InvocationID BuiltIn InvocationId 1006OpDecorate %_5 Location 0 1007OpDecorate %_77 DescriptorSet 0 1008OpDecorate %_77 Binding 0 1009OpDecorate %_78 DescriptorSet 0 1010OpDecorate %_78 Binding 1 1011OpMemberDecorate %gl_PerVertex 0 BuiltIn Position 1012OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize 1013OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance 1014OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance 1015OpDecorate %gl_PerVertex Block 1016OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position 1017OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize 1018OpMemberDecorate %gl_PerVertex_0 2 BuiltIn ClipDistance 1019OpMemberDecorate %gl_PerVertex_0 3 BuiltIn CullDistance 1020OpDecorate %gl_PerVertex_0 Block 1021OpDecorate %gl_TessLevelInner Patch 1022OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner 1023OpDecorate %gl_TessLevelOuter Patch 1024OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter 1025%void = OpTypeVoid 1026%3 = OpTypeFunction %void 1027%int = OpTypeInt 32 1 1028%uint = OpTypeInt 32 0 1029%uint_32 = OpConstant %uint 32 1030%_arr_int_uint_32 = OpTypeArray %int %uint_32 1031%_ptr_Input__arr_int_uint_32 = OpTypePointer Input %_arr_int_uint_32 1032%_3 = OpVariable %_ptr_Input__arr_int_uint_32 Input 1033%_ptr_Input_int = OpTypePointer Input %int 1034%gl_InvocationID = OpVariable %_ptr_Input_int Input 1035%int_0 = OpConstant %int 0 1036%bool = OpTypeBool 1037%float = OpTypeFloat 32 1038%_ptr_Function_float = OpTypePointer Function %float 1039%float_0_0234375 = OpConstant %float 0.0234375 1040%float_1_01561999 = OpConstant %float 1.01561999 1041%v4float = OpTypeVector %float 4 1042%uint_3 = OpConstant %uint 3 1043%_arr_v4float_uint_3 = OpTypeArray %v4float %uint_3 1044%_ptr_Output__arr_v4float_uint_3 = OpTypePointer Output %_arr_v4float_uint_3 1045%_5 = OpVariable %_ptr_Output__arr_v4float_uint_3 Output 1046%34 = OpTypeImage %float 1D 0 0 0 1 Unknown 1047%_ptr_UniformConstant_34 = OpTypePointer UniformConstant %34 1048%_77 = OpVariable %_ptr_UniformConstant_34 UniformConstant 1049%38 = OpTypeSampler 1050%_ptr_UniformConstant_38 = OpTypePointer UniformConstant %38 1051%_78 = OpVariable %_ptr_UniformConstant_38 UniformConstant 1052%42 = OpTypeSampledImage %34 1053%float_0 = OpConstant %float 0 1054%_ptr_Output_v4float = OpTypePointer Output %v4float 1055%_ptr_Function_v4float = OpTypePointer Function %v4float 1056%uint_1 = OpConstant %uint 1 1057%_arr_float_uint_1 = OpTypeArray %float %uint_1 1058%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1 1059%_arr_gl_PerVertex_uint_32 = OpTypeArray %gl_PerVertex %uint_32 1060%_ptr_Input__arr_gl_PerVertex_uint_32 = OpTypePointer Input %_arr_gl_PerVertex_uint_32 1061%gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_32 Input 1062%_ptr_Input_v4float = OpTypePointer Input %v4float 1063%int_2 = OpConstant %int 2 1064%gl_PerVertex_0 = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1 1065%_arr_gl_PerVertex_0_uint_3 = OpTypeArray %gl_PerVertex_0 %uint_3 1066%_ptr_Output__arr_gl_PerVertex_0_uint_3 = OpTypePointer Output %_arr_gl_PerVertex_0_uint_3 1067%gl_out = OpVariable %_ptr_Output__arr_gl_PerVertex_0_uint_3 Output 1068%uint_2 = OpConstant %uint 2 1069%_arr_float_uint_2 = OpTypeArray %float %uint_2 1070%_ptr_Output__arr_float_uint_2 = OpTypePointer Output %_arr_float_uint_2 1071%gl_TessLevelInner = OpVariable %_ptr_Output__arr_float_uint_2 Output 1072%float_2_79999995 = OpConstant %float 2.79999995 1073%_ptr_Output_float = OpTypePointer Output %float 1074%int_1 = OpConstant %int 1 1075%uint_4 = OpConstant %uint 4 1076%_arr_float_uint_4 = OpTypeArray %float %uint_4 1077%_ptr_Output__arr_float_uint_4 = OpTypePointer Output %_arr_float_uint_4 1078%gl_TessLevelOuter = OpVariable %_ptr_Output__arr_float_uint_4 Output 1079%int_3 = OpConstant %int 3 1080)"; 1081 1082 const std::string main_func = 1083 R"( 1084%main = OpFunction %void None %3 1085%5 = OpLabel 1086%param = OpVariable %_ptr_Function_float Function 1087%_203 = OpVariable %_ptr_Function_v4float Function 1088%14 = OpLoad %int %gl_InvocationID 1089%15 = OpAccessChain %_ptr_Input_int %_3 %14 1090%16 = OpLoad %int %15 1091%19 = OpIEqual %bool %16 %int_0 1092OpSelectionMerge %21 None 1093OpBranchConditional %19 %20 %26 1094%20 = OpLabel 1095;CHECK-NOT: %15 = OpAccessChain %_ptr_Input_int %_3 %14 1096;CHECK: OpBranch {{%\w+}} 1097;CHECK: {{%\w+}} = OpLabel 1098;CHECK: {{%\w+}} = OpLoad %int %gl_InvocationID 1099;CHECK: {{%\w+}} = OpAccessChain %_ptr_Input_int %_3 {{%\w+}} 1100;CHECK: {{%\w+}} = OpLoad %int {{%\w+}} 1101;CHECK: {{%\w+}} = OpIEqual %bool {{%\w+}} %int_0 1102;CHECK: OpSelectionMerge {{%\w+}} None 1103;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 1104;CHECK: {{%\w+}} = OpLabel 1105OpStore %param %float_0_0234375 1106OpBranch %21 1107%26 = OpLabel 1108OpStore %param %float_1_01561999 1109OpBranch %21 1110%21 = OpLabel 1111%33 = OpLoad %int %gl_InvocationID 1112%37 = OpLoad %34 %_77 1113%41 = OpLoad %38 %_78 1114%43 = OpSampledImage %42 %37 %41 1115%44 = OpLoad %float %param 1116;CHECK: {{%\w+}} = OpLoad %int %gl_InvocationID 1117;CHECK: {{%\w+}} = OpBitcast %uint {{%\w+}} 1118;CHECK: {{%\w+}} = OpLoad %uint %gl_PrimitiveID 1119;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_1 {{%\w+}} {{%\w+}} %uint_0 1120;CHECK: {{%\w+}} = OpFunctionCall %bool %inst_bindless_check_desc %uint_23 %uint_129 {{%\w+}} %uint_0 %uint_0 %uint_0 %uint_0 1121;CHECK: OpSelectionMerge {{%\w+}} None 1122;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 1123%46 = OpImageSampleExplicitLod %v4float %43 %44 Lod %float_0 1124%48 = OpAccessChain %_ptr_Output_v4float %_5 %33 1125OpStore %48 %46 1126;CHECK-NOT: %48 = OpAccessChain %_ptr_Output_v4float %_5 %33 1127;CHECK-NOT: OpStore %48 %46 1128;CHECK: [[phi_result:%\w+]] = OpPhi %v4float {{%\w+}} {{%\w+}} {{%\w+}} {{%\w+}} 1129;CHECK: [[access_chain:%\w+]] = OpAccessChain %_ptr_Output_v4float %_5 {{%\w+}} 1130;CHECK: OpStore [[access_chain]] [[phi_result]] 1131%49 = OpLoad %int %gl_InvocationID 1132%50 = OpIEqual %bool %49 %int_0 1133OpSelectionMerge %52 None 1134OpBranchConditional %50 %51 %64 1135%51 = OpLabel 1136%62 = OpAccessChain %_ptr_Input_v4float %gl_in %int_0 %int_0 1137%63 = OpLoad %v4float %62 1138OpStore %_203 %63 1139OpBranch %52 1140%64 = OpLabel 1141%66 = OpAccessChain %_ptr_Input_v4float %gl_in %int_2 %int_0 1142%67 = OpLoad %v4float %66 1143OpStore %_203 %67 1144OpBranch %52 1145%52 = OpLabel 1146%72 = OpLoad %int %gl_InvocationID 1147%73 = OpLoad %v4float %_203 1148%74 = OpAccessChain %_ptr_Output_v4float %gl_out %72 %int_0 1149OpStore %74 %73 1150%81 = OpAccessChain %_ptr_Output_float %gl_TessLevelInner %int_0 1151OpStore %81 %float_2_79999995 1152%83 = OpAccessChain %_ptr_Output_float %gl_TessLevelInner %int_1 1153OpStore %83 %float_2_79999995 1154%88 = OpAccessChain %_ptr_Output_float %gl_TessLevelOuter %int_0 1155OpStore %88 %float_2_79999995 1156%89 = OpAccessChain %_ptr_Output_float %gl_TessLevelOuter %int_1 1157OpStore %89 %float_2_79999995 1158%90 = OpAccessChain %_ptr_Output_float %gl_TessLevelOuter %int_2 1159OpStore %90 %float_2_79999995 1160%92 = OpAccessChain %_ptr_Output_float %gl_TessLevelOuter %int_3 1161OpStore %92 %float_2_79999995 1162OpReturn 1163OpFunctionEnd 1164)"; 1165 // clang-format on 1166 1167 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1168 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 1169 true, 23u); 1170} 1171 1172TEST_F(InstBindlessTest, MultipleDebugFunctions) { 1173 // Same source as Simple, but compiled -g and not optimized, especially not 1174 // inlined. The OpSource has had the source extracted for the sake of brevity. 1175 1176 // clang-format off 1177 const std::string defs = R"( 1178OpCapability Shader 1179;CHECK: OpCapability Linkage 1180%2 = OpExtInstImport "GLSL.std.450" 1181OpMemoryModel Logical GLSL450 1182OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor 1183;CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord 1184OpExecutionMode %MainPs OriginUpperLeft 1185%1 = OpString "foo5.frag" 1186OpSource HLSL 500 %1 1187OpName %MainPs "MainPs" 1188OpName %PS_INPUT "PS_INPUT" 1189OpMemberName %PS_INPUT 0 "vTextureCoords" 1190OpName %PS_OUTPUT "PS_OUTPUT" 1191OpMemberName %PS_OUTPUT 0 "vColor" 1192OpName %_MainPs_struct_PS_INPUT_vf21_ "@MainPs(struct-PS_INPUT-vf21;" 1193OpName %i "i" 1194OpName %ps_output "ps_output" 1195OpName %g_tColor "g_tColor" 1196OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" 1197OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" 1198OpName %_ "" 1199OpName %g_sAniso "g_sAniso" 1200OpName %i_0 "i" 1201OpName %i_vTextureCoords "i.vTextureCoords" 1202OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" 1203OpName %param "param" 1204OpDecorate %g_tColor DescriptorSet 1 1205OpDecorate %g_tColor Binding 2 1206OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 1207OpDecorate %PerViewConstantBuffer_t Block 1208OpDecorate %g_sAniso DescriptorSet 1 1209OpDecorate %g_sAniso Binding 3 1210OpDecorate %i_vTextureCoords Location 0 1211OpDecorate %_entryPointOutput_vColor Location 0 1212)" + kImportDeco + R"( 1213;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 1214%void = OpTypeVoid 1215%4 = OpTypeFunction %void 1216%float = OpTypeFloat 32 1217%v2float = OpTypeVector %float 2 1218%PS_INPUT = OpTypeStruct %v2float 1219%_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT 1220%v4float = OpTypeVector %float 4 1221%PS_OUTPUT = OpTypeStruct %v4float 1222%13 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT 1223%_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT 1224%int = OpTypeInt 32 1 1225%int_0 = OpConstant %int 0 1226%21 = OpTypeImage %float 2D 0 0 0 1 Unknown 1227%uint = OpTypeInt 32 0 1228%uint_128 = OpConstant %uint 128 1229%_arr_21_uint_128 = OpTypeArray %21 %uint_128 1230%_ptr_UniformConstant__arr_21_uint_128 = OpTypePointer UniformConstant %_arr_21_uint_128 1231%g_tColor = OpVariable %_ptr_UniformConstant__arr_21_uint_128 UniformConstant 1232%PerViewConstantBuffer_t = OpTypeStruct %uint 1233%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t 1234%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant 1235%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint 1236%_ptr_UniformConstant_21 = OpTypePointer UniformConstant %21 1237%36 = OpTypeSampler 1238%_ptr_UniformConstant_36 = OpTypePointer UniformConstant %36 1239%g_sAniso = OpVariable %_ptr_UniformConstant_36 UniformConstant 1240%40 = OpTypeSampledImage %21 1241%_ptr_Function_v2float = OpTypePointer Function %v2float 1242%_ptr_Function_v4float = OpTypePointer Function %v4float 1243%_ptr_Input_v2float = OpTypePointer Input %v2float 1244%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input 1245%_ptr_Output_v4float = OpTypePointer Output %v4float 1246%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output 1247;CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float 1248;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 1249;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 1250)"; 1251 1252 const std::string func1 = R"( 1253%MainPs = OpFunction %void None %4 1254%6 = OpLabel 1255%i_0 = OpVariable %_ptr_Function_PS_INPUT Function 1256%param = OpVariable %_ptr_Function_PS_INPUT Function 1257OpLine %1 21 0 1258%54 = OpLoad %v2float %i_vTextureCoords 1259%55 = OpAccessChain %_ptr_Function_v2float %i_0 %int_0 1260OpStore %55 %54 1261%59 = OpLoad %PS_INPUT %i_0 1262OpStore %param %59 1263%60 = OpFunctionCall %PS_OUTPUT %_MainPs_struct_PS_INPUT_vf21_ %param 1264%61 = OpCompositeExtract %v4float %60 0 1265OpStore %_entryPointOutput_vColor %61 1266OpReturn 1267OpFunctionEnd 1268)"; 1269 1270 const std::string func2 = R"( 1271%_MainPs_struct_PS_INPUT_vf21_ = OpFunction %PS_OUTPUT None %13 1272%i = OpFunctionParameter %_ptr_Function_PS_INPUT 1273%16 = OpLabel 1274%ps_output = OpVariable %_ptr_Function_PS_OUTPUT Function 1275OpLine %1 24 0 1276%31 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 1277%32 = OpLoad %uint %31 1278%34 = OpAccessChain %_ptr_UniformConstant_21 %g_tColor %32 1279%35 = OpLoad %21 %34 1280%39 = OpLoad %36 %g_sAniso 1281%41 = OpSampledImage %40 %35 %39 1282%43 = OpAccessChain %_ptr_Function_v2float %i %int_0 1283%44 = OpLoad %v2float %43 1284%45 = OpImageSampleImplicitLod %v4float %41 %44 1285;CHECK-NOT: %45 = OpImageSampleImplicitLod %v4float %41 %44 1286;CHECK: {{%\w+}} = OpLoad %v2float {{%\w+}} 1287;CHECK: OpNoLine 1288;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 1289;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 1290;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 1291;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 1292;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 1293;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_128 {{%\w+}} %uint_1 %uint_2 {{%\w+}} %uint_0 1294;CHECK: OpSelectionMerge {{%\w+}} None 1295;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 1296;CHECK: {{%\w+}} = OpLabel 1297;CHECK: {{%\w+}} = OpLoad %27 {{%\w+}} 1298;CHECK: {{%\w+}} = OpSampledImage %37 {{%\w+}} {{%\w+}} 1299;CHECK: OpLine %5 24 0 1300;CHECK: {{%\w+}} = OpImageSampleImplicitLod %v4float {{%\w+}} {{%\w+}} 1301;CHECK: OpNoLine 1302;CHECK: OpBranch {{%\w+}} 1303;CHECK: {{%\w+}} = OpLabel 1304;CHECK: OpBranch {{%\w+}} 1305;CHECK: {{%\w+}} = OpLabel 1306;CHECK: [[phi_result:%\w+]] = OpPhi %v4float {{%\w+}} {{%\w+}} [[null_v4float]] {{%\w+}} 1307%47 = OpAccessChain %_ptr_Function_v4float %ps_output %int_0 1308OpStore %47 %45 1309;CHECK-NOT: OpStore %47 %45 1310;CHECK: [[store_loc:%\w+]] = OpAccessChain %_ptr_Function_v4float %ps_output %int_0 1311;CHECK: OpStore [[store_loc]] [[phi_result]] 1312OpLine %1 25 0 1313%48 = OpLoad %PS_OUTPUT %ps_output 1314OpReturnValue %48 1315OpFunctionEnd 1316)"; 1317 // clang-format on 1318 1319 // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1320 SinglePassRunAndMatch<InstBindlessCheckPass>( 1321 defs + kImportStub + func1 + func2, true, 23u); 1322} 1323 1324TEST_F(InstBindlessTest, RuntimeArray) { 1325 // This test verifies that the pass will correctly instrument shader 1326 // with runtime descriptor array. This test was created by editing the 1327 // SPIR-V from the Simple test. 1328 1329 // clang-format off 1330 const std::string defs = R"( 1331OpCapability Shader 1332OpCapability RuntimeDescriptorArray 1333;CHECK: OpCapability Linkage 1334OpExtension "SPV_EXT_descriptor_indexing" 1335%1 = OpExtInstImport "GLSL.std.450" 1336OpMemoryModel Logical GLSL450 1337OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor 1338;CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord 1339OpExecutionMode %MainPs OriginUpperLeft 1340OpSource HLSL 500 1341OpName %MainPs "MainPs" 1342OpName %g_tColor "g_tColor" 1343OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" 1344OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" 1345OpName %_ "" 1346OpName %g_sAniso "g_sAniso" 1347OpName %i_vTextureCoords "i.vTextureCoords" 1348OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" 1349OpDecorate %g_tColor DescriptorSet 1 1350OpDecorate %g_tColor Binding 2 1351OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 1352OpDecorate %PerViewConstantBuffer_t Block 1353OpDecorate %g_sAniso DescriptorSet 1 1354OpDecorate %g_sAniso Binding 3 1355OpDecorate %i_vTextureCoords Location 0 1356OpDecorate %_entryPointOutput_vColor Location 0 1357)" + kImportDeco + R"( 1358;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 1359%void = OpTypeVoid 1360%3 = OpTypeFunction %void 1361%float = OpTypeFloat 32 1362%v2float = OpTypeVector %float 2 1363%v4float = OpTypeVector %float 4 1364%int = OpTypeInt 32 1 1365%int_0 = OpConstant %int 0 1366%20 = OpTypeImage %float 2D 0 0 0 1 Unknown 1367%uint = OpTypeInt 32 0 1368%uint_1 = OpConstant %uint 1 1369%_rarr_20 = OpTypeRuntimeArray %20 1370%_ptr_UniformConstant__arr_20 = OpTypePointer UniformConstant %_rarr_20 1371%g_tColor = OpVariable %_ptr_UniformConstant__arr_20 UniformConstant 1372%PerViewConstantBuffer_t = OpTypeStruct %uint 1373%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t 1374%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant 1375%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint 1376%_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20 1377%35 = OpTypeSampler 1378%_ptr_UniformConstant_35 = OpTypePointer UniformConstant %35 1379%g_sAniso = OpVariable %_ptr_UniformConstant_35 UniformConstant 1380%39 = OpTypeSampledImage %20 1381%_ptr_Input_v2float = OpTypePointer Input %v2float 1382%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input 1383%_ptr_Output_v4float = OpTypePointer Output %v4float 1384%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output 1385;CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float 1386;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 1387;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 1388)"; 1389 1390 const std::string main_func = R"( 1391%MainPs = OpFunction %void None %3 1392%5 = OpLabel 1393%53 = OpLoad %v2float %i_vTextureCoords 1394%63 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 1395%64 = OpLoad %uint %63 1396%65 = OpAccessChain %_ptr_UniformConstant_20 %g_tColor %64 1397%66 = OpLoad %20 %65 1398%67 = OpLoad %35 %g_sAniso 1399%68 = OpSampledImage %39 %66 %67 1400%71 = OpImageSampleImplicitLod %v4float %68 %53 1401OpStore %_entryPointOutput_vColor %71 1402;CHECK-NOT: %71 = OpImageSampleImplicitLod %v4float %68 %53 1403;CHECK-NOT: OpStore %_entryPointOutput_vColor %71 1404;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 1405;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 1406;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 1407;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 1408;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 1409;CHECK: [[check_result:%\w+]] = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_60 {{%\w+}} %uint_1 %uint_2 %32 %uint_0 1410;CHECK: OpSelectionMerge {{%\w+}} None 1411;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 1412;CHECK: {{%\w+}} = OpLabel 1413;CHECK: {{%\w+}} = OpLoad %16 %33 1414;CHECK: {{%\w+}} = OpSampledImage %26 {{%\w+}} %35 1415;CHECK: {{%\w+}} = OpImageSampleImplicitLod %v4float {{%\w+}} %30 1416;CHECK: OpBranch {{%\w+}} 1417;CHECK: {{%\w+}} = OpLabel 1418;CHECK: OpBranch {{%\w+}} 1419;CHECK: {{%\w+}} = OpLabel 1420;CHECK: [[phi_result_1:%\w+]] = OpPhi %v4float {{%\w+}} {{%\w+}} [[null_v4float]] {{%\w+}} 1421;CHECK: OpStore %_entryPointOutput_vColor [[phi_result_1]] 1422OpReturn 1423OpFunctionEnd 1424)"; 1425 // clang-format on 1426 1427 // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1428 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 1429 true, 23u); 1430} 1431 1432TEST_F(InstBindlessTest, InstrumentInitCheckOnScalarDescriptor) { 1433 // This test verifies that the pass will correctly instrument vanilla 1434 // texture sample on a scalar descriptor with an initialization check if the 1435 // input_init_enable argument is set to true. This can happen when the 1436 // descriptor indexing extension is enabled in the API but the SPIR-V 1437 // does not have the extension enabled because it does not contain a 1438 // runtime array. This is the same shader as NoInstrumentNonBindless. 1439 1440 // clang-format off 1441 const std::string defs = R"( 1442OpCapability Shader 1443;CHECK: OpCapability Linkage 1444%1 = OpExtInstImport "GLSL.std.450" 1445OpMemoryModel Logical GLSL450 1446OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor 1447;CHECK: OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord 1448OpExecutionMode %MainPs OriginUpperLeft 1449OpSource HLSL 500 1450OpName %MainPs "MainPs" 1451OpName %g_tColor "g_tColor" 1452OpName %g_sAniso "g_sAniso" 1453OpName %i_vTextureCoords "i.vTextureCoords" 1454OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" 1455OpDecorate %g_tColor DescriptorSet 1 1456OpDecorate %g_tColor Binding 2 1457OpDecorate %g_sAniso DescriptorSet 1 1458OpDecorate %g_sAniso Binding 2 1459OpDecorate %i_vTextureCoords Location 0 1460OpDecorate %_entryPointOutput_vColor Location 0 1461)" + kImportDeco + R"( 1462;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 1463%void = OpTypeVoid 1464%8 = OpTypeFunction %void 1465%float = OpTypeFloat 32 1466%v2float = OpTypeVector %float 2 1467%v4float = OpTypeVector %float 4 1468%12 = OpTypeImage %float 2D 0 0 0 1 Unknown 1469%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12 1470%g_tColor = OpVariable %_ptr_UniformConstant_12 UniformConstant 1471%14 = OpTypeSampler 1472%_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14 1473%g_sAniso = OpVariable %_ptr_UniformConstant_14 UniformConstant 1474%16 = OpTypeSampledImage %12 1475%_ptr_Input_v2float = OpTypePointer Input %v2float 1476%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input 1477%_ptr_Output_v4float = OpTypePointer Output %v4float 1478%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output 1479;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 1480)"; 1481 1482 const std::string main_func = R"( 1483%MainPs = OpFunction %void None %8 1484%19 = OpLabel 1485%20 = OpLoad %v2float %i_vTextureCoords 1486%21 = OpLoad %12 %g_tColor 1487%22 = OpLoad %14 %g_sAniso 1488%23 = OpSampledImage %16 %21 %22 1489%24 = OpImageSampleImplicitLod %v4float %23 %20 1490OpStore %_entryPointOutput_vColor %24 1491;CHECK-NOT: %24 = OpImageSampleImplicitLod %v4float %23 %20 1492;CHECK-NOT: OpStore %_entryPointOutput_vColor %24 1493;CHECK: [[check_result:%\w+]] = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_40 {{%\w+}} %uint_1 %uint_2 %uint_0 %uint_0 1494;CHECK: OpSelectionMerge {{%\w+}} None 1495;CHECK: OpBranchConditional [[check_result]] {{%\w+}} {{%\w+}} 1496;CHECK: {{%\w+}} = OpLabel 1497;CHECK: {{%\w+}} = OpLoad %12 %g_tColor 1498;CHECK: {{%\w+}} = OpSampledImage %16 {{%\w+}} %22 1499;CHECK: {{%\w+}} = OpImageSampleImplicitLod %v4float {{%\w+}} %20 1500;CHECK: OpBranch {{%\w+}} 1501;CHECK: {{%\w+}} = OpLabel 1502;CHECK: OpBranch {{%\w+}} 1503;CHECK: {{%\w+}} = OpLabel 1504;CHECK: [[phi_result:%\w+]] = OpPhi %v4float {{%\w+}} {{%\w+}} [[null_v4float]] {{%\w+}} 1505;CHECK: OpStore %_entryPointOutput_vColor [[phi_result]] 1506OpReturn 1507OpFunctionEnd 1508)"; 1509 // clang-format on 1510 1511 // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1512 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 1513 true, 23u); 1514} 1515 1516TEST_F(InstBindlessTest, SPV14AddToEntryPoint) { 1517 const std::string text = R"( 1518OpCapability Shader 1519OpExtension "SPV_EXT_descriptor_indexing" 1520OpMemoryModel Logical GLSL450 1521OpEntryPoint Fragment %foo "foo" %gid %image_var %sampler_var 1522;CHECK: OpEntryPoint Fragment {{%\w+}} "foo" {{%\w+}} {{%\w+}} {{%\w+}} %gl_FragCoord 1523OpExecutionMode %foo OriginUpperLeft 1524OpDecorate %image_var DescriptorSet 4 1525OpDecorate %image_var Binding 1 1526OpDecorate %sampler_var DescriptorSet 4 1527OpDecorate %sampler_var Binding 2 1528OpDecorate %gid DescriptorSet 0 1529OpDecorate %gid Binding 2 1530OpDecorate %struct Block 1531OpMemberDecorate %struct 0 Offset 0 1532%void = OpTypeVoid 1533%int = OpTypeInt 32 0 1534%int_0 = OpConstant %int 0 1535%v3int = OpTypeVector %int 3 1536%float = OpTypeFloat 32 1537%v3float = OpTypeVector %float 3 1538%v4float = OpTypeVector %float 4 1539%struct = OpTypeStruct %v3int 1540%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct 1541%ptr_ssbo_v3int = OpTypePointer StorageBuffer %v3int 1542%gid = OpVariable %ptr_ssbo_struct StorageBuffer 1543%image = OpTypeImage %float 3D 0 0 0 1 Unknown 1544%ptr_uc_image = OpTypePointer UniformConstant %image 1545%sampler = OpTypeSampler 1546%ptr_uc_sampler = OpTypePointer UniformConstant %sampler 1547%image_var = OpVariable %ptr_uc_image UniformConstant 1548%sampler_var = OpVariable %ptr_uc_sampler UniformConstant 1549%sampled = OpTypeSampledImage %image 1550%void_fn = OpTypeFunction %void 1551%foo = OpFunction %void None %void_fn 1552%entry = OpLabel 1553%ld_image = OpLoad %image %image_var 1554%ld_sampler = OpLoad %sampler %sampler_var 1555%gep = OpAccessChain %ptr_ssbo_v3int %gid %int_0 1556%ld_gid = OpLoad %v3int %gep 1557%convert = OpConvertUToF %v3float %ld_gid 1558%sampled_image = OpSampledImage %sampled %ld_image %ld_sampler 1559%sample = OpImageSampleImplicitLod %v4float %sampled_image %convert 1560OpReturn 1561OpFunctionEnd 1562)"; 1563 1564 SetTargetEnv(SPV_ENV_VULKAN_1_1_SPIRV_1_4); 1565 SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 23u); 1566} 1567 1568TEST_F(InstBindlessTest, SPV14AddToEntryPoints) { 1569 const std::string text = R"( 1570OpCapability Shader 1571;CHECK: OpCapability Linkage 1572OpExtension "SPV_EXT_descriptor_indexing" 1573OpMemoryModel Logical GLSL450 1574OpEntryPoint Fragment %foo "foo" %gid %image_var %sampler_var 1575;CHECK: OpEntryPoint Fragment {{%\w+}} "foo" {{%\w+}} {{%\w+}} {{%\w+}} %gl_FragCoord 1576OpEntryPoint Fragment %foo "bar" %gid %image_var %sampler_var 1577;CHECK: OpEntryPoint Fragment {{%\w+}} "bar" {{%\w+}} {{%\w+}} {{%\w+}} %gl_FragCoord 1578OpExecutionMode %foo OriginUpperLeft 1579OpDecorate %image_var DescriptorSet 3 1580OpDecorate %image_var Binding 2 1581OpDecorate %sampler_var DescriptorSet 3 1582OpDecorate %sampler_var Binding 3 1583OpDecorate %gid DescriptorSet 3 1584OpDecorate %gid Binding 4 1585OpDecorate %struct Block 1586OpMemberDecorate %struct 0 Offset 0 1587%void = OpTypeVoid 1588%int = OpTypeInt 32 0 1589%int_0 = OpConstant %int 0 1590%v3int = OpTypeVector %int 3 1591%float = OpTypeFloat 32 1592%v3float = OpTypeVector %float 3 1593%v4float = OpTypeVector %float 4 1594%struct = OpTypeStruct %v3int 1595%ptr_ssbo_struct = OpTypePointer StorageBuffer %struct 1596%ptr_ssbo_v3int = OpTypePointer StorageBuffer %v3int 1597%gid = OpVariable %ptr_ssbo_struct StorageBuffer 1598%image = OpTypeImage %float 3D 0 0 0 1 Unknown 1599%ptr_uc_image = OpTypePointer UniformConstant %image 1600%sampler = OpTypeSampler 1601%ptr_uc_sampler = OpTypePointer UniformConstant %sampler 1602%image_var = OpVariable %ptr_uc_image UniformConstant 1603%sampler_var = OpVariable %ptr_uc_sampler UniformConstant 1604%sampled = OpTypeSampledImage %image 1605%void_fn = OpTypeFunction %void 1606%foo = OpFunction %void None %void_fn 1607%entry = OpLabel 1608%ld_image = OpLoad %image %image_var 1609%ld_sampler = OpLoad %sampler %sampler_var 1610%gep = OpAccessChain %ptr_ssbo_v3int %gid %int_0 1611%ld_gid = OpLoad %v3int %gep 1612%convert = OpConvertUToF %v3float %ld_gid 1613%sampled_image = OpSampledImage %sampled %ld_image %ld_sampler 1614%sample = OpImageSampleImplicitLod %v4float %sampled_image %convert 1615OpReturn 1616OpFunctionEnd 1617)"; 1618 1619 SetTargetEnv(SPV_ENV_VULKAN_1_1_SPIRV_1_4); 1620 SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 23u); 1621} 1622 1623TEST_F(InstBindlessTest, InstBoundsAndInitLoadUnsizedUBOArray) { 1624 // #version 450 1625 // #extension GL_EXT_nonuniform_qualifier : enable 1626 // 1627 // layout(location=0) in nonuniformEXT flat int nu_ii; 1628 // layout(location=0) out float b; 1629 // 1630 // layout(set = 6, binding=3) uniform uname { float a; } uniformBuffer[]; 1631 // 1632 // void main() 1633 // { 1634 // b = uniformBuffer[nu_ii].a; 1635 // } 1636 1637 // clang-format off 1638 const std::string defs = R"( 1639OpCapability Shader 1640OpCapability ShaderNonUniform 1641OpCapability RuntimeDescriptorArray 1642OpCapability UniformBufferArrayNonUniformIndexing 1643;CHECK: OpCapability Linkage 1644OpExtension "SPV_EXT_descriptor_indexing" 1645%1 = OpExtInstImport "GLSL.std.450" 1646OpMemoryModel Logical GLSL450 1647OpEntryPoint Fragment %main "main" %b %nu_ii 1648;CHECK: OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord 1649OpExecutionMode %main OriginUpperLeft 1650OpSource GLSL 450 1651OpSourceExtension "GL_EXT_nonuniform_qualifier" 1652OpName %main "main" 1653OpName %b "b" 1654OpName %uname "uname" 1655OpMemberName %uname 0 "a" 1656OpName %uniformBuffer "uniformBuffer" 1657OpName %nu_ii "nu_ii" 1658OpDecorate %b Location 0 1659OpMemberDecorate %uname 0 Offset 0 1660OpDecorate %uname Block 1661OpDecorate %uniformBuffer DescriptorSet 6 1662OpDecorate %uniformBuffer Binding 3 1663OpDecorate %nu_ii Flat 1664OpDecorate %nu_ii Location 0 1665OpDecorate %nu_ii NonUniform 1666OpDecorate %16 NonUniform 1667OpDecorate %20 NonUniform 1668;CHECK: OpDecorate {{%\w+}} NonUniform 1669)" + kImportDeco + R"( 1670;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 1671;CHECK: OpDecorate {{%\w+}} NonUniform 1672%void = OpTypeVoid 1673%3 = OpTypeFunction %void 1674%float = OpTypeFloat 32 1675%_ptr_Output_float = OpTypePointer Output %float 1676%b = OpVariable %_ptr_Output_float Output 1677%uname = OpTypeStruct %float 1678%_runtimearr_uname = OpTypeRuntimeArray %uname 1679%_ptr_Uniform__runtimearr_uname = OpTypePointer Uniform %_runtimearr_uname 1680%uniformBuffer = OpVariable %_ptr_Uniform__runtimearr_uname Uniform 1681%int = OpTypeInt 32 1 1682%_ptr_Input_int = OpTypePointer Input %int 1683%nu_ii = OpVariable %_ptr_Input_int Input 1684%int_0 = OpConstant %int 0 1685%_ptr_Uniform_float = OpTypePointer Uniform %float 1686;CHECK: %v4uint = OpTypeVector %uint 4 1687;CHECK: %v4float = OpTypeVector %float 4 1688;CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float 1689;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 1690;CHECK: [[null_float:%\w+]] = OpConstantNull %float 1691)"; 1692 1693 const std::string main_func = R"( 1694%main = OpFunction %void None %3 1695%5 = OpLabel 1696%16 = OpLoad %int %nu_ii 1697%19 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %16 %int_0 1698%20 = OpLoad %float %19 1699OpStore %b %20 1700;CHECK-NOT: %20 = OpLoad %float %19 1701;CHECK-NOT: OpStore %b %20 1702;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 1703;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 1704;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 1705;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 1706;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 1707;CHECK: {{%\w+}} = OpBitcast %uint %7 1708;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_46 {{%\w+}} %uint_6 %uint_3 {{%\w+}} {{%\w+}} 1709;CHECK: OpSelectionMerge {{%\w+}} None 1710;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 1711;CHECK: {{%\w+}} = OpLabel 1712;CHECK: {{%\w+}} = OpLoad %float %20 1713;CHECK: OpBranch {{%\w+}} 1714;CHECK: {{%\w+}} = OpLabel 1715;CHECK: OpBranch {{%\w+}} 1716;CHECK: {{%\w+}} = OpLabel 1717;CHECK: [[phi_result:%\w+]] = OpPhi %float {{%\w+}} {{%\w+}} {{%\w+}} {{%\w+}} 1718;CHECK: OpStore %b [[phi_result]] 1719OpReturn 1720OpFunctionEnd 1721)"; 1722 // clang-format on 1723 1724 // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1725 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 1726 true, 23u); 1727} 1728 1729TEST_F(InstBindlessTest, InstBoundsAndInitLoadUnsizedSSBOArrayDeprecated) { 1730 // #version 450 1731 // #extension GL_EXT_nonuniform_qualifier : enable 1732 // 1733 // layout(location=0) in nonuniformEXT flat int nu_ii; 1734 // layout(location=0) out float b; 1735 // 1736 // layout(set = 7, binding=3) buffer bname { float b; } storageBuffer[]; 1737 // 1738 // void main() 1739 // { 1740 // b = storageBuffer[nu_ii].b; 1741 // } 1742 1743 // clang-format off 1744 const std::string defs = R"( 1745OpCapability Shader 1746OpCapability ShaderNonUniform 1747OpCapability RuntimeDescriptorArray 1748OpCapability StorageBufferArrayNonUniformIndexing 1749;CHECK: OpCapability Linkage 1750OpExtension "SPV_EXT_descriptor_indexing" 1751%1 = OpExtInstImport "GLSL.std.450" 1752OpMemoryModel Logical GLSL450 1753OpEntryPoint Fragment %main "main" %b %nu_ii 1754;CHECK: OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord 1755OpExecutionMode %main OriginUpperLeft 1756OpSource GLSL 450 1757OpSourceExtension "GL_EXT_nonuniform_qualifier" 1758OpName %main "main" 1759OpName %b "b" 1760OpName %bname "bname" 1761OpMemberName %bname 0 "a" 1762OpName %storageBuffer "storageBuffer" 1763OpName %nu_ii "nu_ii" 1764OpDecorate %b Location 0 1765OpMemberDecorate %bname 0 Offset 0 1766OpDecorate %bname Block 1767OpDecorate %storageBuffer DescriptorSet 7 1768OpDecorate %storageBuffer Binding 3 1769OpDecorate %nu_ii Flat 1770OpDecorate %nu_ii Location 0 1771OpDecorate %nu_ii NonUniform 1772OpDecorate %16 NonUniform 1773OpDecorate %20 NonUniform 1774)" + kImportDeco + R"( 1775;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 1776%void = OpTypeVoid 1777%3 = OpTypeFunction %void 1778%float = OpTypeFloat 32 1779%_ptr_Output_float = OpTypePointer Output %float 1780%b = OpVariable %_ptr_Output_float Output 1781%bname = OpTypeStruct %float 1782%_runtimearr_bname = OpTypeRuntimeArray %bname 1783%_ptr_StorageBuffer__runtimearr_bname = OpTypePointer StorageBuffer %_runtimearr_bname 1784%storageBuffer = OpVariable %_ptr_StorageBuffer__runtimearr_bname StorageBuffer 1785%int = OpTypeInt 32 1 1786%_ptr_Input_int = OpTypePointer Input %int 1787%nu_ii = OpVariable %_ptr_Input_int Input 1788%int_0 = OpConstant %int 0 1789%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float 1790;CHECK: %uint = OpTypeInt 32 0 1791;CHECK: %v4uint = OpTypeVector %uint 4 1792;CHECK: %v4float = OpTypeVector %float 4 1793;CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float 1794;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 1795;CHECK: [[null_float:%\w+]] = OpConstantNull %float 1796)"; 1797 1798 const std::string main_func = R"( 1799%main = OpFunction %void None %3 1800%5 = OpLabel 1801%16 = OpLoad %int %nu_ii 1802%19 = OpAccessChain %_ptr_StorageBuffer_float %storageBuffer %16 %int_0 1803%20 = OpLoad %float %19 1804OpStore %b %20 1805;CHECK-NOT: %20 = OpLoad %float %19 1806;CHECK-NOT: OpStore %b %20 1807;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 1808;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 1809;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 1810;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 1811;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 1812;CHECK: {{%\w+}} = OpBitcast %uint %7 1813;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_46 {{%\w+}} %uint_7 %uint_3 {{%\w+}} {{%\w+}} 1814;CHECK: OpSelectionMerge {{%\w+}} None 1815;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 1816;CHECK: {{%\w+}} = OpLabel 1817;CHECK: {{%\w+}} = OpLoad %float %20 1818;CHECK: OpBranch {{%\w+}} 1819;CHECK: {{%\w+}} = OpLabel 1820;CHECK: OpBranch {{%\w+}} 1821;CHECK: {{%\w+}} = OpLabel 1822;CHECK: [[phi_result:%\w+]] = OpPhi %float {{%\w+}} {{%\w+}} {{%\w+}} {{%\w+}} 1823;CHECK: OpStore %b [[phi_result]] 1824OpReturn 1825OpFunctionEnd 1826)"; 1827 // clang-format on 1828 1829 // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1830 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 1831 true, 23u); 1832} 1833 1834TEST_F(InstBindlessTest, InstBoundsAndInitLoadUnsizedSSBOArray) { 1835 // Same as Deprecated but declaring as StorageBuffer Block 1836 1837 // clang-format off 1838 const std::string defs = R"( 1839OpCapability Shader 1840OpCapability ShaderNonUniform 1841OpCapability RuntimeDescriptorArray 1842OpCapability StorageBufferArrayNonUniformIndexing 1843;CHECK: OpCapability Linkage 1844OpExtension "SPV_EXT_descriptor_indexing" 1845%1 = OpExtInstImport "GLSL.std.450" 1846OpMemoryModel Logical GLSL450 1847OpEntryPoint Fragment %main "main" %b %nu_ii 1848;CHECK: OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord 1849OpExecutionMode %main OriginUpperLeft 1850OpSource GLSL 450 1851OpSourceExtension "GL_EXT_nonuniform_qualifier" 1852OpName %main "main" 1853OpName %b "b" 1854OpName %bname "bname" 1855OpMemberName %bname 0 "a" 1856OpName %storageBuffer "storageBuffer" 1857OpName %nu_ii "nu_ii" 1858OpDecorate %b Location 0 1859OpMemberDecorate %bname 0 Offset 0 1860OpDecorate %bname Block 1861OpDecorate %storageBuffer DescriptorSet 0 1862OpDecorate %storageBuffer Binding 3 1863OpDecorate %nu_ii Flat 1864OpDecorate %nu_ii Location 0 1865OpDecorate %nu_ii NonUniform 1866OpDecorate %16 NonUniform 1867OpDecorate %20 NonUniform 1868;CHECK: OpDecorate {{%\w+}} NonUniform 1869)" + kImportDeco + R"( 1870;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 1871;CHECK: OpDecorate {{%\w+}} NonUniform 1872%void = OpTypeVoid 1873%3 = OpTypeFunction %void 1874%float = OpTypeFloat 32 1875%_ptr_Output_float = OpTypePointer Output %float 1876%b = OpVariable %_ptr_Output_float Output 1877%bname = OpTypeStruct %float 1878%_runtimearr_bname = OpTypeRuntimeArray %bname 1879%_ptr_StorageBuffer__runtimearr_bname = OpTypePointer StorageBuffer %_runtimearr_bname 1880%storageBuffer = OpVariable %_ptr_StorageBuffer__runtimearr_bname StorageBuffer 1881%int = OpTypeInt 32 1 1882%_ptr_Input_int = OpTypePointer Input %int 1883%nu_ii = OpVariable %_ptr_Input_int Input 1884%int_0 = OpConstant %int 0 1885%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float 1886;CHECK: %v4uint = OpTypeVector %uint 4 1887;CHECK: %v4float = OpTypeVector %float 4 1888;CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float 1889;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 1890;CHECK: [[null_float:%\w+]] = OpConstantNull %float 1891)"; 1892 1893 const std::string main_func = R"( 1894%main = OpFunction %void None %3 1895%5 = OpLabel 1896%16 = OpLoad %int %nu_ii 1897%19 = OpAccessChain %_ptr_StorageBuffer_float %storageBuffer %16 %int_0 1898%20 = OpLoad %float %19 1899OpStore %b %20 1900;CHECK-NOT: %20 = OpLoad %float %19 1901;CHECK-NOT: OpStore %b %20 1902;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 1903;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 1904;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 1905;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 1906;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 1907;CHECK: {{%\w+}} = OpBitcast %uint %7 1908;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_46 {{%\w+}} %uint_0 %uint_3 {{%\w+}} {{%\w+}} 1909;CHECK: OpSelectionMerge {{%\w+}} None 1910;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 1911;CHECK: {{%\w+}} = OpLabel 1912;CHECK: {{%\w+}} = OpLoad %float %20 1913;CHECK: OpBranch {{%\w+}} 1914;CHECK: {{%\w+}} = OpLabel 1915;CHECK: OpBranch {{%\w+}} 1916;CHECK: {{%\w+}} = OpLabel 1917;CHECK: {{%\w+}} = OpPhi %float {{%\w+}} {{%\w+}} {{%\w+}} {{%\w+}} 1918;CHECK: OpStore %b {{%\w+}} 1919OpReturn 1920OpFunctionEnd 1921)"; 1922 // clang-format on 1923 1924 // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1925 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 1926 true, 23u); 1927} 1928 1929TEST_F(InstBindlessTest, InstInitLoadUBOScalar) { 1930 // #version 450 1931 // #extension GL_EXT_nonuniform_qualifier : enable 1932 // 1933 // layout(location=0) out float b; 1934 // layout(set=7, binding=3) uniform uname { float a; } uniformBuffer; 1935 // 1936 // void main() 1937 // { 1938 // b = uniformBuffer.a; 1939 // } 1940 1941 // clang-format off 1942 const std::string defs = R"( 1943OpCapability Shader 1944;CHECK: OpCapability Linkage 1945OpExtension "SPV_EXT_descriptor_indexing" 1946%1 = OpExtInstImport "GLSL.std.450" 1947OpMemoryModel Logical GLSL450 1948OpEntryPoint Fragment %main "main" %b 1949;CHECK: OpEntryPoint Fragment %main "main" %b %gl_FragCoord 1950OpExecutionMode %main OriginUpperLeft 1951OpSource GLSL 450 1952OpSourceExtension "GL_EXT_nonuniform_qualifier" 1953OpName %main "main" 1954OpName %b "b" 1955OpName %uname "uname" 1956OpMemberName %uname 0 "a" 1957OpName %uniformBuffer "uniformBuffer" 1958OpDecorate %b Location 0 1959OpMemberDecorate %uname 0 Offset 0 1960OpDecorate %uname Block 1961OpDecorate %uniformBuffer DescriptorSet 7 1962OpDecorate %uniformBuffer Binding 3 1963)" + kImportDeco + R"( 1964;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 1965%void = OpTypeVoid 1966%3 = OpTypeFunction %void 1967%float = OpTypeFloat 32 1968%_ptr_Output_float = OpTypePointer Output %float 1969%b = OpVariable %_ptr_Output_float Output 1970%uname = OpTypeStruct %float 1971%_ptr_Uniform_uname = OpTypePointer Uniform %uname 1972%uniformBuffer = OpVariable %_ptr_Uniform_uname Uniform 1973%int = OpTypeInt 32 1 1974%int_0 = OpConstant %int 0 1975%_ptr_Uniform_float = OpTypePointer Uniform %float 1976;CHECK: %int = OpTypeInt 32 1 1977;CHECK: %_ptr_Uniform_float = OpTypePointer Uniform %float 1978;CHECK: %uint = OpTypeInt 32 0 1979;CHECK: %v4uint = OpTypeVector %uint 4 1980;CHECK: %v4float = OpTypeVector %float 4 1981;CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float 1982;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 1983;CHECK: [[null_float:%\w+]] = OpConstantNull %float 1984)"; 1985 1986 const std::string main_func = R"( 1987%main = OpFunction %void None %3 1988%5 = OpLabel 1989%15 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %int_0 1990%16 = OpLoad %float %15 1991OpStore %b %16 1992;CHECK-NOT: %16 = OpLoad %float %15 1993;CHECK-NOT: OpStore %b %16 1994;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 1995;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 1996;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 1997;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 1998;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 1999;CHECK: [[check_result:%\w+]] = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_33 {{%\w+}} %uint_7 %uint_3 %uint_0 {{%\w+}} 2000;CHECK: OpSelectionMerge {{%\w+}} None 2001;CHECK: OpBranchConditional [[check_result]] {{%\w+}} {{%\w+}} 2002;CHECK: {{%\w+}} = OpLabel 2003;CHECK: {{%\w+}} = OpLoad %float %15 2004;CHECK: OpBranch {{%\w+}} 2005;CHECK: {{%\w+}} = OpLabel 2006;CHECK: OpBranch {{%\w+}} 2007;CHECK: {{%\w+}} = OpLabel 2008;CHECK: [[phi_result:%\w+]] = OpPhi %float {{%\w+}} {{%\w+}} {{%\w+}} {{%\w+}} 2009;CHECK: OpStore %b [[phi_result]] 2010OpReturn 2011OpFunctionEnd 2012)"; 2013 // clang-format on 2014 2015 // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 2016 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 2017 true, 23u); 2018} 2019 2020TEST_F(InstBindlessTest, InstBoundsInitStoreUnsizedSSBOArray) { 2021 // #version 450 2022 // #extension GL_EXT_nonuniform_qualifier : enable 2023 // 2024 // layout(location=0) in nonuniformEXT flat int nu_ii; 2025 // layout(location=1) in float b; 2026 // 2027 // layout(set=5, binding=4) buffer bname { float b; } storageBuffer[]; 2028 // 2029 // void main() 2030 // { 2031 // storageBuffer[nu_ii].b = b; 2032 // } 2033 2034 // clang-format off 2035 const std::string defs = R"(OpCapability Shader 2036OpCapability ShaderNonUniform 2037OpCapability RuntimeDescriptorArray 2038OpCapability StorageBufferArrayNonUniformIndexing 2039;CHECK: OpCapability Linkage 2040OpExtension "SPV_EXT_descriptor_indexing" 2041%1 = OpExtInstImport "GLSL.std.450" 2042OpMemoryModel Logical GLSL450 2043OpEntryPoint Fragment %main "main" %nu_ii %b 2044;CHECK: OpEntryPoint Fragment %main "main" %nu_ii %b %gl_FragCoord 2045OpExecutionMode %main OriginUpperLeft 2046OpSource GLSL 450 2047OpSourceExtension "GL_EXT_nonuniform_qualifier" 2048OpName %main "main" 2049OpName %bname "bname" 2050OpMemberName %bname 0 "b" 2051OpName %storageBuffer "storageBuffer" 2052OpName %nu_ii "nu_ii" 2053OpName %b "b" 2054OpMemberDecorate %bname 0 Offset 0 2055OpDecorate %bname BufferBlock 2056OpDecorate %storageBuffer DescriptorSet 5 2057OpDecorate %storageBuffer Binding 4 2058OpDecorate %nu_ii Flat 2059OpDecorate %nu_ii Location 0 2060OpDecorate %nu_ii NonUniform 2061OpDecorate %14 NonUniform 2062OpDecorate %b Location 1 2063)" + kImportDeco + R"( 2064;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 2065%void = OpTypeVoid 2066%3 = OpTypeFunction %void 2067%float = OpTypeFloat 32 2068%bname = OpTypeStruct %float 2069%_runtimearr_bname = OpTypeRuntimeArray %bname 2070%_ptr_Uniform__runtimearr_bname = OpTypePointer Uniform %_runtimearr_bname 2071%storageBuffer = OpVariable %_ptr_Uniform__runtimearr_bname Uniform 2072%int = OpTypeInt 32 1 2073%_ptr_Input_int = OpTypePointer Input %int 2074%nu_ii = OpVariable %_ptr_Input_int Input 2075%int_0 = OpConstant %int 0 2076%_ptr_Input_float = OpTypePointer Input %float 2077%b = OpVariable %_ptr_Input_float Input 2078%_ptr_Uniform_float = OpTypePointer Uniform %float 2079;CHECK: %v4uint = OpTypeVector %uint 4 2080;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 2081)"; 2082 2083 const std::string main_func = R"( 2084%main = OpFunction %void None %3 2085%5 = OpLabel 2086%14 = OpLoad %int %nu_ii 2087%18 = OpLoad %float %b 2088%20 = OpAccessChain %_ptr_Uniform_float %storageBuffer %14 %int_0 2089OpStore %20 %18 2090;CHECK-NOT: OpStore %20 %18 2091;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 2092;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 2093;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 2094;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 2095;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 2096;CHECK: {{%\w+}} = OpBitcast %uint %7 2097;CHECK: [[check_result:%\w+]] = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_46 {{%\w+}} %uint_5 %uint_4 {{%\w+}} {{%\w+}} 2098;CHECK: OpSelectionMerge {{%\w+}} None 2099;CHECK: OpBranchConditional [[check_result]] {{%\w+}} {{%\w+}} 2100;CHECK: {{%\w+}} = OpLabel 2101;CHECK: OpStore %20 %19 2102;CHECK: OpBranch {{%\w+}} 2103;CHECK: {{%\w+}} = OpLabel 2104;CHECK: OpBranch {{%\w+}} 2105;CHECK: {{%\w+}} = OpLabel 2106OpReturn 2107OpFunctionEnd 2108)"; 2109 // clang-format on 2110 2111 // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 2112 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 2113 true, 23u); 2114} 2115 2116TEST_F(InstBindlessTest, InstBoundsInitLoadSizedUBOArray) { 2117 // #version 450 2118 // #extension GL_EXT_nonuniform_qualifier : enable 2119 // 2120 // layout(location=0) in nonuniformEXT flat int nu_ii; 2121 // layout(location=0) out float b; 2122 // 2123 // layout(set=1, binding=3) uniform uname { float a; } uniformBuffer[128]; 2124 // 2125 // void main() 2126 // { 2127 // b = uniformBuffer[nu_ii].a; 2128 // } 2129 2130 // clang-format off 2131 const std::string defs = R"( 2132OpCapability Shader 2133OpCapability ShaderNonUniform 2134OpCapability UniformBufferArrayNonUniformIndexing 2135;CHECK: OpCapability Linkage 2136OpExtension "SPV_EXT_descriptor_indexing" 2137%1 = OpExtInstImport "GLSL.std.450" 2138OpMemoryModel Logical GLSL450 2139OpEntryPoint Fragment %main "main" %b %nu_ii 2140;CHECK: OpEntryPoint Fragment %main "main" %b %nu_ii %gl_FragCoord 2141OpExecutionMode %main OriginUpperLeft 2142OpSource GLSL 450 2143OpSourceExtension "GL_EXT_nonuniform_qualifier" 2144OpName %main "main" 2145OpName %b "b" 2146OpName %uname "uname" 2147OpMemberName %uname 0 "a" 2148OpName %uniformBuffer "uniformBuffer" 2149OpName %nu_ii "nu_ii" 2150OpDecorate %b Location 0 2151OpMemberDecorate %uname 0 Offset 0 2152OpDecorate %uname Block 2153OpDecorate %uniformBuffer DescriptorSet 1 2154OpDecorate %uniformBuffer Binding 3 2155OpDecorate %nu_ii Flat 2156OpDecorate %nu_ii Location 0 2157OpDecorate %nu_ii NonUniform 2158OpDecorate %18 NonUniform 2159OpDecorate %22 NonUniform 2160)" + kImportDeco + R"( 2161;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 2162;CHECK: OpDecorate [[load_result:%\w+]] NonUniform 2163%void = OpTypeVoid 2164%3 = OpTypeFunction %void 2165%float = OpTypeFloat 32 2166%_ptr_Output_float = OpTypePointer Output %float 2167%b = OpVariable %_ptr_Output_float Output 2168%uname = OpTypeStruct %float 2169%uint = OpTypeInt 32 0 2170%uint_128 = OpConstant %uint 128 2171%_arr_uname_uint_128 = OpTypeArray %uname %uint_128 2172%_ptr_Uniform__arr_uname_uint_128 = OpTypePointer Uniform %_arr_uname_uint_128 2173%uniformBuffer = OpVariable %_ptr_Uniform__arr_uname_uint_128 Uniform 2174%int = OpTypeInt 32 1 2175%_ptr_Input_int = OpTypePointer Input %int 2176%nu_ii = OpVariable %_ptr_Input_int Input 2177%int_0 = OpConstant %int 0 2178%_ptr_Uniform_float = OpTypePointer Uniform %float 2179;CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float 2180;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 2181;CHECK: [[null_float:%\w+]] = OpConstantNull %float 2182)"; 2183 2184 const std::string main_func = R"( 2185%main = OpFunction %void None %3 2186%5 = OpLabel 2187%18 = OpLoad %int %nu_ii 2188%21 = OpAccessChain %_ptr_Uniform_float %uniformBuffer %18 %int_0 2189%22 = OpLoad %float %21 2190OpStore %b %22 2191;CHECK-NOT: %22 = OpLoad %float %21 2192;CHECK-NOT: OpStore %b %22 2193;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 2194;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 2195;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 2196;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 2197;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 2198;CHECK: {{%\w+}} = OpBitcast %uint %7 2199;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_47 {{%\w+}} %uint_1 %uint_3 {{%\w+}} {{%\w+}} 2200;CHECK: OpSelectionMerge {{%\w+}} None 2201;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 2202;CHECK: {{%\w+}} = OpLabel 2203;CHECK: {{%\w+}} = OpLoad %float %22 2204;CHECK: OpBranch {{%\w+}} 2205;CHECK: {{%\w+}} = OpLabel 2206;CHECK: OpBranch {{%\w+}} 2207;CHECK: {{%\w+}} = OpLabel 2208;CHECK: {{%\w+}} = OpPhi %float {{%\w+}} {{%\w+}} {{%\w+}} {{%\w+}} 2209;CHECK: OpStore %b {{%\w+}} 2210OpReturn 2211OpFunctionEnd 2212)"; 2213 // clang-format on 2214 2215 // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 2216 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 2217 true, 23u); 2218} 2219 2220TEST_F(InstBindlessTest, 2221 InstBoundsComputeShaderInitLoadVariableSizedSampledImagesArray) { 2222 // #version 450 2223 // #extension GL_EXT_nonuniform_qualifier : enable 2224 // 2225 // layout (local_size_x = 1, local_size_y = 1) in; 2226 // 2227 // layout(set = 2, binding = 0, std140) buffer Input { 2228 // uint index; 2229 // float red; 2230 // } sbo; 2231 // 2232 // layout(set = 2, binding = 1, rgba32f) readonly uniform image2D images[]; 2233 // 2234 // void main() 2235 // { 2236 // sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r; 2237 // } 2238 2239 // clang-format off 2240 const std::string defs = R"( 2241OpCapability Shader 2242OpCapability RuntimeDescriptorArray 2243;CHECK: OpCapability Linkage 2244OpExtension "SPV_EXT_descriptor_indexing" 2245%1 = OpExtInstImport "GLSL.std.450" 2246OpMemoryModel Logical GLSL450 2247OpEntryPoint GLCompute %main "main" 2248;CHECK: OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID 2249OpExecutionMode %main LocalSize 1 1 1 2250OpSource GLSL 450 2251OpSourceExtension "GL_EXT_nonuniform_qualifier" 2252OpName %main "main" 2253OpName %Input "Input" 2254OpMemberName %Input 0 "index" 2255OpMemberName %Input 1 "red" 2256OpName %sbo "sbo" 2257OpName %images "images" 2258OpMemberDecorate %Input 0 Offset 0 2259OpMemberDecorate %Input 1 Offset 4 2260OpDecorate %Input BufferBlock 2261OpDecorate %sbo DescriptorSet 2 2262OpDecorate %sbo Binding 0 2263OpDecorate %images DescriptorSet 2 2264OpDecorate %images Binding 1 2265OpDecorate %images NonWritable 2266)" + kImportDeco + R"( 2267;CHECK: OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId 2268%void = OpTypeVoid 2269%3 = OpTypeFunction %void 2270%uint = OpTypeInt 32 0 2271%float = OpTypeFloat 32 2272%Input = OpTypeStruct %uint %float 2273%_ptr_Uniform_Input = OpTypePointer Uniform %Input 2274%sbo = OpVariable %_ptr_Uniform_Input Uniform 2275%int = OpTypeInt 32 1 2276%int_1 = OpConstant %int 1 2277%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f 2278%_runtimearr_13 = OpTypeRuntimeArray %13 2279%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 2280%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant 2281%int_0 = OpConstant %int 0 2282%_ptr_Uniform_uint = OpTypePointer Uniform %uint 2283%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 2284%v2int = OpTypeVector %int 2 2285%25 = OpConstantComposite %v2int %int_0 %int_0 2286%v4float = OpTypeVector %float 4 2287%uint_0 = OpConstant %uint 0 2288%_ptr_Uniform_float = OpTypePointer Uniform %float 2289;CHECK: %v3uint = OpTypeVector %uint 3 2290;CHECK: %_ptr_Input_v3uint = OpTypePointer Input %v3uint 2291;CHECK: %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input 2292;CHECK: [[null_uint:%\w+]] = OpConstantNull %uint 2293;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 2294)"; 2295 2296 const std::string main_func = R"( 2297%main = OpFunction %void None %3 2298%5 = OpLabel 2299%19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 2300%20 = OpLoad %uint %19 2301%22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 2302%23 = OpLoad %13 %22 2303%27 = OpImageRead %v4float %23 %25 2304%29 = OpCompositeExtract %float %27 0 2305%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 2306OpStore %31 %29 2307;CHECK-NOT: OpStore %31 %29 2308;CHECK: {{%\w+}} = OpLoad %v3uint %gl_GlobalInvocationID 2309;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 2310;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 2311;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2 2312;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_5 {{%\w+}} {{%\w+}} {{%\w+}} 2313;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_48 {{%\w+}} %uint_2 %uint_0 %uint_0 {{%\w+}} 2314;CHECK: OpSelectionMerge {{%\w+}} None 2315;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 2316;CHECK: {{%\w+}} = OpLabel 2317;CHECK: {{%\w+}} = OpLoad %uint %25 2318;CHECK: OpBranch {{%\w+}} 2319;CHECK: {{%\w+}} = OpLabel 2320;CHECK: OpBranch {{%\w+}} 2321;CHECK: {{%\w+}} = OpLabel 2322;CHECK: {{%\w+}} = OpPhi %uint {{%\w+}} {{%\w+}} {{%\w+}} {{%\w+}} 2323;CHECK: {{%\w+}} = OpAccessChain %_ptr_UniformConstant_13 %images {{%\w+}} 2324;CHECK: {{%\w+}} = OpLoad %13 {{%\w+}} 2325;CHECK: {{%\w+}} = OpLoad %v3uint %gl_GlobalInvocationID 2326;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 2327;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 2328;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2 2329;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_5 {{%\w+}} {{%\w+}} {{%\w+}} 2330;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_51 {{%\w+}} %uint_2 %uint_1 {{%\w+}} %uint_0 2331;CHECK: OpSelectionMerge {{%\w+}} None 2332;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 2333;CHECK: {{%\w+}} = OpLabel 2334;CHECK: {{%\w+}} = OpLoad %13 {{%\w+}} 2335;CHECK: {{%\w+}} = OpImageRead %v4float {{%\w+}} %20 2336;CHECK: OpBranch {{%\w+}} 2337;CHECK: {{%\w+}} = OpLabel 2338;CHECK: OpBranch {{%\w+}} 2339;CHECK: {{%\w+}} = OpLabel 2340;CHECK: {{%\w+}} = OpPhi %v4float {{%\w+}} {{%\w+}} {{%\w+}} {{%\w+}} 2341;CHECK: {{%\w+}} = OpCompositeExtract %float {{%\w+}} 0 2342;CHECK: {{%\w+}} = OpAccessChain %_ptr_Uniform_float %sbo %int_1 2343;CHECK: {{%\w+}} = OpLoad %v3uint %gl_GlobalInvocationID 2344;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 2345;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 2346;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2 2347;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_5 {{%\w+}} {{%\w+}} {{%\w+}} 2348;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_54 {{%\w+}} %uint_2 %uint_0 %uint_0 {{%\w+}} 2349;CHECK: OpSelectionMerge {{%\w+}} None 2350;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 2351;CHECK: {{%\w+}} = OpLabel 2352;CHECK: OpStore %31 {{%\w+}} 2353;CHECK: OpBranch {{%\w+}} 2354;CHECK: {{%\w+}} = OpLabel 2355;CHECK: OpBranch {{%\w+}} 2356;CHECK: {{%\w+}} = OpLabel 2357OpReturn 2358OpFunctionEnd 2359)"; 2360 // clang-format on 2361 2362 // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 2363 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 2364 true, 23u); 2365} 2366 2367TEST_F(InstBindlessTest, 2368 InstBoundsRayGenerationInitLoadVariableSizedSampledImagesArray) { 2369 // #version 460 2370 // #extension GL_EXT_nonuniform_qualifier : require 2371 // #extension GL_NV_ray_tracing : require 2372 // 2373 // layout(set = 3, binding = 1, std140) buffer StorageBuffer { 2374 // uint index; 2375 // float red; 2376 // } sbo; 2377 // 2378 // layout(set = 3, binding = 5, rgba32f) readonly uniform image2D images[]; 2379 // 2380 // void main() 2381 // { 2382 // sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r; 2383 // } 2384 2385 // clang-format off 2386 const std::string defs = R"( 2387OpCapability RuntimeDescriptorArray 2388OpCapability RayTracingNV 2389;CHECK: OpCapability Linkage 2390OpExtension "SPV_EXT_descriptor_indexing" 2391OpExtension "SPV_NV_ray_tracing" 2392%1 = OpExtInstImport "GLSL.std.450" 2393OpMemoryModel Logical GLSL450 2394OpEntryPoint RayGenerationNV %main "main" 2395;CHECK: OpEntryPoint RayGenerationNV %main "main" [[launch_id:%\w+]] 2396OpSource GLSL 460 2397OpSourceExtension "GL_EXT_nonuniform_qualifier" 2398OpSourceExtension "GL_NV_ray_tracing" 2399OpName %main "main" 2400OpName %StorageBuffer "StorageBuffer" 2401OpMemberName %StorageBuffer 0 "index" 2402OpMemberName %StorageBuffer 1 "red" 2403OpName %sbo "sbo" 2404OpName %images "images" 2405OpMemberDecorate %StorageBuffer 0 Offset 0 2406OpMemberDecorate %StorageBuffer 1 Offset 4 2407OpDecorate %StorageBuffer BufferBlock 2408OpDecorate %sbo DescriptorSet 3 2409OpDecorate %sbo Binding 1 2410OpDecorate %images DescriptorSet 3 2411OpDecorate %images Binding 5 2412OpDecorate %images NonWritable 2413)" + kImportDeco + R"( 2414;CHECK: OpDecorate [[launch_id]] BuiltIn LaunchIdNV 2415%void = OpTypeVoid 2416%3 = OpTypeFunction %void 2417%uint = OpTypeInt 32 0 2418%float = OpTypeFloat 32 2419%StorageBuffer = OpTypeStruct %uint %float 2420%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer 2421%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform 2422%int = OpTypeInt 32 1 2423%int_1 = OpConstant %int 1 2424%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f 2425%_runtimearr_13 = OpTypeRuntimeArray %13 2426%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 2427%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant 2428%int_0 = OpConstant %int 0 2429%_ptr_Uniform_uint = OpTypePointer Uniform %uint 2430%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 2431%v2int = OpTypeVector %int 2 2432%25 = OpConstantComposite %v2int %int_0 %int_0 2433%v4float = OpTypeVector %float 4 2434%uint_0 = OpConstant %uint 0 2435%_ptr_Uniform_float = OpTypePointer Uniform %float 2436;CHECK: [[null_uint:%\w+]] = OpConstantNull %uint 2437;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 2438)"; 2439 2440 const std::string main_func = R"( 2441%main = OpFunction %void None %3 2442%5 = OpLabel 2443%19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 2444%20 = OpLoad %uint %19 2445%22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 2446%23 = OpLoad %13 %22 2447%27 = OpImageRead %v4float %23 %25 2448%29 = OpCompositeExtract %float %27 0 2449%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 2450OpStore %31 %29 2451;CHECK-NOT: OpStore %31 %29 2452;CHECK: {{%\w+}} = OpLoad %v3uint {{%\w+}} 2453;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 2454;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 2455;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2 2456;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_5313 {{%\w+}} {{%\w+}} {{%\w+}} 2457;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_49 {{%\w+}} %uint_3 %uint_1 %uint_0 {{%\w+}} 2458;CHECK: OpSelectionMerge {{%\w+}} None 2459;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 2460;CHECK: {{%\w+}} = OpLabel 2461;CHECK: {{%\w+}} = OpLoad %uint %25 2462;CHECK: OpBranch {{%\w+}} 2463;CHECK: {{%\w+}} = OpLabel 2464;CHECK: OpBranch {{%\w+}} 2465;CHECK: {{%\w+}} = OpLabel 2466;CHECK: {{%\w+}} = OpPhi %uint {{%\w+}} {{%\w+}} [[null_uint]] {{%\w+}} 2467;CHECK: {{%\w+}} = OpAccessChain %_ptr_UniformConstant_13 %images {{%\w+}} 2468;CHECK: {{%\w+}} = OpLoad %13 {{%\w+}} 2469;CHECK: {{%\w+}} = OpLoad %v3uint {{%\w+}} 2470;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 2471;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 2472;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2 2473;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_5313 {{%\w+}} {{%\w+}} {{%\w+}} 2474;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_52 {{%\w+}} %uint_3 %uint_5 {{%\w+}} %uint_0 2475;CHECK: OpSelectionMerge {{%\w+}} None 2476;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 2477;CHECK: {{%\w+}} = OpLabel 2478;CHECK: {{%\w+}} = OpLoad %13 {{%\w+}} 2479;CHECK: {{%\w+}} = OpImageRead %v4float {{%\w+}} %20 2480;CHECK: OpBranch {{%\w+}} 2481;CHECK: {{%\w+}} = OpLabel 2482;CHECK: OpBranch {{%\w+}} 2483;CHECK: {{%\w+}} = OpLabel 2484;CHECK: {{%\w+}} = OpPhi %v4float {{%\w+}} {{%\w+}} [[null_v4float]] {{%\w+}} 2485;CHECK: {{%\w+}} = OpCompositeExtract %float {{%\w+}} 0 2486;CHECK: {{%\w+}} = OpAccessChain %_ptr_Uniform_float %sbo %int_1 2487;CHECK: {{%\w+}} = OpLoad %v3uint {{%\w+}} 2488;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 2489;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 2490;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2 2491;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_5313 {{%\w+}} {{%\w+}} {{%\w+}} 2492;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_55 {{%\w+}} %uint_3 %uint_1 %uint_0 {{%\w+}} 2493;CHECK: OpSelectionMerge {{%\w+}} None 2494;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 2495;CHECK: {{%\w+}} = OpLabel 2496;CHECK: OpStore {{%\w+}} {{%\w+}} 2497;CHECK: OpBranch {{%\w+}} 2498;CHECK: {{%\w+}} = OpLabel 2499;CHECK: OpBranch {{%\w+}} 2500;CHECK: {{%\w+}} = OpLabel 2501OpReturn 2502OpFunctionEnd 2503)"; 2504 // clang-format on 2505 2506 // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 2507 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 2508 true, 23u); 2509} 2510 2511TEST_F(InstBindlessTest, 2512 InstBoundsIntersectionInitLoadVariableSizedSampledImagesArray) { 2513 // #version 460 2514 // #extension GL_EXT_nonuniform_qualifier : require 2515 // #extension GL_NV_ray_tracing : require 2516 // 2517 // layout(set = 5, binding = 1, std140) buffer StorageBuffer { 2518 // uint index; 2519 // float red; 2520 // } sbo; 2521 // 2522 // layout(set = 5, binding = 3, rgba32f) readonly uniform image2D images[]; 2523 // 2524 // void main() 2525 // { 2526 // sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r; 2527 // } 2528 2529 // clang-format off 2530 const std::string defs = R"( 2531OpCapability RuntimeDescriptorArray 2532OpCapability RayTracingNV 2533;CHECK: OpCapability Linkage 2534OpExtension "SPV_EXT_descriptor_indexing" 2535OpExtension "SPV_NV_ray_tracing" 2536%1 = OpExtInstImport "GLSL.std.450" 2537OpMemoryModel Logical GLSL450 2538OpEntryPoint IntersectionNV %main "main" 2539;CHECK: OpEntryPoint IntersectionNV %main "main" [[launch_id:%\w+]] 2540OpSource GLSL 460 2541OpSourceExtension "GL_EXT_nonuniform_qualifier" 2542OpSourceExtension "GL_NV_ray_tracing" 2543OpName %main "main" 2544OpName %StorageBuffer "StorageBuffer" 2545OpMemberName %StorageBuffer 0 "index" 2546OpMemberName %StorageBuffer 1 "red" 2547OpName %sbo "sbo" 2548OpName %images "images" 2549OpMemberDecorate %StorageBuffer 0 Offset 0 2550OpMemberDecorate %StorageBuffer 1 Offset 4 2551OpDecorate %StorageBuffer BufferBlock 2552OpDecorate %sbo DescriptorSet 5 2553OpDecorate %sbo Binding 1 2554OpDecorate %images DescriptorSet 5 2555OpDecorate %images Binding 3 2556OpDecorate %images NonWritable 2557)" + kImportDeco + R"( 2558;CHECK: OpDecorate [[launch_id]] BuiltIn LaunchIdNV 2559%void = OpTypeVoid 2560%3 = OpTypeFunction %void 2561%uint = OpTypeInt 32 0 2562%float = OpTypeFloat 32 2563%StorageBuffer = OpTypeStruct %uint %float 2564%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer 2565%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform 2566%int = OpTypeInt 32 1 2567%int_1 = OpConstant %int 1 2568%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f 2569%_runtimearr_13 = OpTypeRuntimeArray %13 2570%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 2571%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant 2572%int_0 = OpConstant %int 0 2573%_ptr_Uniform_uint = OpTypePointer Uniform %uint 2574%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 2575%v2int = OpTypeVector %int 2 2576%25 = OpConstantComposite %v2int %int_0 %int_0 2577%v4float = OpTypeVector %float 4 2578%uint_0 = OpConstant %uint 0 2579%_ptr_Uniform_float = OpTypePointer Uniform %float 2580;CHECK: [[launch_id]] = OpVariable %_ptr_Input_v3uint Input 2581;CHECK: [[null_uint:%\w+]] = OpConstantNull %uint 2582;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 2583)"; 2584 2585 const std::string main_func = R"( 2586%main = OpFunction %void None %3 2587%5 = OpLabel 2588%19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 2589%20 = OpLoad %uint %19 2590%22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 2591%23 = OpLoad %13 %22 2592%27 = OpImageRead %v4float %23 %25 2593%29 = OpCompositeExtract %float %27 0 2594%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 2595OpStore %31 %29 2596;CHECK-NOT: OpStore %31 %29 2597;CHECK: {{%\w+}} = OpLoad %v3uint {{%\w+}} 2598;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 2599;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 2600;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2 2601;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_5314 {{%\w+}} {{%\w+}} {{%\w+}} 2602;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_49 {{%\w+}} %uint_5 %uint_1 %uint_0 {{%\w+}} 2603;CHECK: OpSelectionMerge {{%\w+}} None 2604;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 2605;CHECK: {{%\w+}} = OpLabel 2606;CHECK: {{%\w+}} = OpLoad %uint %25 2607;CHECK: OpBranch {{%\w+}} 2608;CHECK: {{%\w+}} = OpLabel 2609;CHECK: OpBranch {{%\w+}} 2610;CHECK: {{%\w+}} = OpLabel 2611;CHECK: {{%\w+}} = OpPhi %uint {{%\w+}} {{%\w+}} [[null_uint]] {{%\w+}} 2612;CHECK: {{%\w+}} = OpAccessChain %_ptr_UniformConstant_13 %images {{%\w+}} 2613;CHECK: {{%\w+}} = OpLoad %13 {{%\w+}} 2614;CHECK: {{%\w+}} = OpLoad %v3uint {{%\w+}} 2615;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 2616;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 2617;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2 2618;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_5314 {{%\w+}} {{%\w+}} {{%\w+}} 2619;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_52 {{%\w+}} %uint_5 %uint_3 {{%\w+}} %uint_0 2620;CHECK: OpSelectionMerge {{%\w+}} None 2621;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 2622;CHECK: {{%\w+}} = OpLabel 2623;CHECK: {{%\w+}} = OpLoad %13 {{%\w+}} 2624;CHECK: {{%\w+}} = OpImageRead %v4float {{%\w+}} %20 2625;CHECK: OpBranch {{%\w+}} 2626;CHECK: {{%\w+}} = OpLabel 2627;CHECK: OpBranch {{%\w+}} 2628;CHECK: {{%\w+}} = OpLabel 2629;CHECK: {{%\w+}} = OpPhi %v4float {{%\w+}} {{%\w+}} [[null_v4float]] {{%\w+}} 2630;CHECK: {{%\w+}} = OpCompositeExtract %float {{%\w+}} 0 2631;CHECK: {{%\w+}} = OpAccessChain %_ptr_Uniform_float %sbo %int_1 2632;CHECK: {{%\w+}} = OpLoad %v3uint {{%\w+}} 2633;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 2634;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 2635;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2 2636;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_5314 {{%\w+}} {{%\w+}} {{%\w+}} 2637;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_55 {{%\w+}} %uint_5 %uint_1 %uint_0 {{%\w+}} 2638;CHECK: OpSelectionMerge {{%\w+}} None 2639;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 2640;CHECK: {{%\w+}} = OpLabel 2641;CHECK: OpStore %31 {{%\w+}} 2642;CHECK: OpBranch {{%\w+}} 2643;CHECK: {{%\w+}} = OpLabel 2644;CHECK: OpBranch {{%\w+}} 2645OpReturn 2646OpFunctionEnd 2647)"; 2648 // clang-format on 2649 2650 // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 2651 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 2652 true, 23u); 2653} 2654 2655TEST_F(InstBindlessTest, 2656 InstBoundsAnyHitInitLoadVariableSizedSampledImagesArray) { 2657 // #version 460 2658 // #extension GL_EXT_nonuniform_qualifier : require 2659 // #extension GL_NV_ray_tracing : require 2660 // 2661 // layout(set = 2, binding = 1, std140) buffer StorageBuffer { 2662 // uint index; 2663 // float red; 2664 // } sbo; 2665 // 2666 // layout(set = 2, binding = 3, rgba32f) readonly uniform image2D images[]; 2667 // 2668 // void main() 2669 // { 2670 // sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r; 2671 // } 2672 2673 // clang-format off 2674 const std::string defs = R"( 2675OpCapability RuntimeDescriptorArray 2676OpCapability RayTracingNV 2677;CHECK: OpCapability Linkage 2678OpExtension "SPV_EXT_descriptor_indexing" 2679OpExtension "SPV_NV_ray_tracing" 2680%1 = OpExtInstImport "GLSL.std.450" 2681OpMemoryModel Logical GLSL450 2682OpEntryPoint AnyHitNV %main "main" 2683;CHECK: OpEntryPoint AnyHitNV %main "main" [[launch_id:%\w+]] 2684OpSource GLSL 460 2685OpSourceExtension "GL_EXT_nonuniform_qualifier" 2686OpSourceExtension "GL_NV_ray_tracing" 2687OpName %main "main" 2688OpName %StorageBuffer "StorageBuffer" 2689OpMemberName %StorageBuffer 0 "index" 2690OpMemberName %StorageBuffer 1 "red" 2691OpName %sbo "sbo" 2692OpName %images "images" 2693OpMemberDecorate %StorageBuffer 0 Offset 0 2694OpMemberDecorate %StorageBuffer 1 Offset 4 2695OpDecorate %StorageBuffer BufferBlock 2696OpDecorate %sbo DescriptorSet 2 2697OpDecorate %sbo Binding 1 2698OpDecorate %images DescriptorSet 2 2699OpDecorate %images Binding 3 2700OpDecorate %images NonWritable 2701)" + kImportDeco + R"( 2702;CHECK: OpDecorate [[launch_id]] BuiltIn LaunchIdNV 2703%void = OpTypeVoid 2704%3 = OpTypeFunction %void 2705%uint = OpTypeInt 32 0 2706%float = OpTypeFloat 32 2707%StorageBuffer = OpTypeStruct %uint %float 2708%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer 2709%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform 2710%int = OpTypeInt 32 1 2711%int_1 = OpConstant %int 1 2712%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f 2713%_runtimearr_13 = OpTypeRuntimeArray %13 2714%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 2715%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant 2716%int_0 = OpConstant %int 0 2717%_ptr_Uniform_uint = OpTypePointer Uniform %uint 2718%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 2719%v2int = OpTypeVector %int 2 2720%25 = OpConstantComposite %v2int %int_0 %int_0 2721%v4float = OpTypeVector %float 4 2722%uint_0 = OpConstant %uint 0 2723%_ptr_Uniform_float = OpTypePointer Uniform %float 2724;CHECK: [[launch_id]] = OpVariable %_ptr_Input_v3uint Input 2725;CHECK: [[null_uint:%\w+]] = OpConstantNull %uint 2726;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 2727)"; 2728 2729 const std::string main_func = R"( 2730%main = OpFunction %void None %3 2731%5 = OpLabel 2732%19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 2733%20 = OpLoad %uint %19 2734%22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 2735%23 = OpLoad %13 %22 2736%27 = OpImageRead %v4float %23 %25 2737%29 = OpCompositeExtract %float %27 0 2738%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 2739OpStore %31 %29 2740;CHECK-NOT: %20 = OpLoad %uint %19 2741;CHECK-NOT: %22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 2742;CHECK-NOT: %23 = OpLoad %13 %22 2743;CHECK-NOT: %27 = OpImageRead %v4float %23 %25 2744;CHECK-NOT: %29 = OpCompositeExtract %float %27 0 2745;CHECK-NOT: %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 2746;CHECK-NOT: OpStore %31 %29 2747;CHECK: {{%\w+}} = OpLoad %v3uint {{%\w+}} 2748;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 2749;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 2750;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2 2751;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_5315 {{%\w+}} {{%\w+}} {{%\w+}} 2752;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_49 {{%\w+}} %uint_2 %uint_1 %uint_0 {{%\w+}} 2753;CHECK: OpSelectionMerge {{%\w+}} None 2754;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 2755;CHECK: {{%\w+}} = OpLabel 2756;CHECK: {{%\w+}} = OpLoad %uint %25 2757;CHECK: OpBranch {{%\w+}} 2758;CHECK: {{%\w+}} = OpLabel 2759;CHECK: OpBranch {{%\w+}} 2760;CHECK: {{%\w+}} = OpLabel 2761;CHECK: [[phi_result:%\w+]] = OpPhi %uint {{%\w+}} {{%\w+}} [[null_uint]] {{%\w+}} 2762;CHECK: %27 = OpAccessChain %_ptr_UniformConstant_13 %images [[phi_result]] 2763;CHECK: %28 = OpLoad %13 %27 2764;CHECK: {{%\w+}} = OpLoad %v3uint {{%\w+}} 2765;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 2766;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 2767;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2 2768;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_5315 {{%\w+}} {{%\w+}} {{%\w+}} 2769;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_52 {{%\w+}} %uint_2 %uint_3 {{%\w+}} %uint_0 2770;CHECK: OpSelectionMerge {{%\w+}} None 2771;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 2772;CHECK: {{%\w+}} = OpLabel 2773;CHECK: {{%\w+}} = OpLoad %13 %27 2774;CHECK: {{%\w+}} = OpImageRead %v4float {{%\w+}} %20 2775;CHECK: OpBranch {{%\w+}} 2776;CHECK: {{%\w+}} = OpLabel 2777;CHECK: OpBranch {{%\w+}} 2778;CHECK: {{%\w+}} = OpLabel 2779;CHECK: {{%\w+}} = OpPhi %v4float {{%\w+}} {{%\w+}} [[null_v4float]] {{%\w+}} 2780;CHECK: %30 = OpCompositeExtract %float {{%\w+}} 0 2781;CHECK: %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 2782;CHECK: {{%\w+}} = OpLoad %v3uint {{%\w+}} 2783;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 2784;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 2785;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2 2786;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_5315 {{%\w+}} {{%\w+}} {{%\w+}} 2787;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_55 {{%\w+}} %uint_2 %uint_1 %uint_0 {{%\w+}} 2788;CHECK: OpSelectionMerge {{%\w+}} None 2789;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 2790;CHECK: {{%\w+}} = OpLabel 2791;CHECK: OpStore %31 %30 2792;CHECK: OpBranch {{%\w+}} 2793;CHECK: {{%\w+}} = OpLabel 2794;CHECK: OpBranch {{%\w+}} 2795;CHECK: {{%\w+}} = OpLabel 2796OpReturn 2797OpFunctionEnd 2798)"; 2799 // clang-format on 2800 2801 // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 2802 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 2803 true, 23u); 2804} 2805 2806TEST_F(InstBindlessTest, 2807 InstBoundsClosestHitInitLoadVariableSizedSampledImagesArray) { 2808 // #version 460 2809 // #extension GL_EXT_nonuniform_qualifier : require 2810 // #extension GL_NV_ray_tracing : require 2811 // 2812 // layout(set = 1, binding = 2, std140) buffer StorageBuffer { 2813 // uint index; 2814 // float red; 2815 // } sbo; 2816 // 2817 // layout(set = 1, binding = 3, rgba32f) readonly uniform image2D images[]; 2818 // 2819 // void main() 2820 // { 2821 // sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r; 2822 // } 2823 2824 // clang-format off 2825 const std::string defs = R"( 2826OpCapability RuntimeDescriptorArray 2827OpCapability RayTracingNV 2828;CHECK: OpCapability Linkage 2829OpExtension "SPV_EXT_descriptor_indexing" 2830OpExtension "SPV_NV_ray_tracing" 2831%1 = OpExtInstImport "GLSL.std.450" 2832OpMemoryModel Logical GLSL450 2833OpEntryPoint ClosestHitNV %main "main" 2834;CHECK: OpEntryPoint ClosestHitNV %main "main" [[launch_id:%\w+]] 2835OpSource GLSL 460 2836OpSourceExtension "GL_EXT_nonuniform_qualifier" 2837OpSourceExtension "GL_NV_ray_tracing" 2838OpName %main "main" 2839OpName %StorageBuffer "StorageBuffer" 2840OpMemberName %StorageBuffer 0 "index" 2841OpMemberName %StorageBuffer 1 "red" 2842OpName %sbo "sbo" 2843OpName %images "images" 2844OpMemberDecorate %StorageBuffer 0 Offset 0 2845OpMemberDecorate %StorageBuffer 1 Offset 4 2846OpDecorate %StorageBuffer BufferBlock 2847OpDecorate %sbo DescriptorSet 1 2848OpDecorate %sbo Binding 2 2849OpDecorate %images DescriptorSet 1 2850OpDecorate %images Binding 3 2851OpDecorate %images NonWritable 2852)" + kImportDeco + R"( 2853;CHECK: OpDecorate [[launch_id]] BuiltIn LaunchIdNV 2854%void = OpTypeVoid 2855%3 = OpTypeFunction %void 2856%uint = OpTypeInt 32 0 2857%float = OpTypeFloat 32 2858%StorageBuffer = OpTypeStruct %uint %float 2859%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer 2860%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform 2861%int = OpTypeInt 32 1 2862%int_1 = OpConstant %int 1 2863%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f 2864%_runtimearr_13 = OpTypeRuntimeArray %13 2865%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 2866%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant 2867%int_0 = OpConstant %int 0 2868%_ptr_Uniform_uint = OpTypePointer Uniform %uint 2869%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 2870%v2int = OpTypeVector %int 2 2871%25 = OpConstantComposite %v2int %int_0 %int_0 2872%v4float = OpTypeVector %float 4 2873%uint_0 = OpConstant %uint 0 2874%_ptr_Uniform_float = OpTypePointer Uniform %float 2875;CHECK: [[launch_id]] = OpVariable %_ptr_Input_v3uint Input 2876;CHECK: [[null_uint:%\w+]] = OpConstantNull %uint 2877;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 2878)"; 2879 2880 const std::string main_func = R"( 2881%main = OpFunction %void None %3 2882%5 = OpLabel 2883%19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 2884%20 = OpLoad %uint %19 2885%22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 2886%23 = OpLoad %13 %22 2887%27 = OpImageRead %v4float %23 %25 2888%29 = OpCompositeExtract %float %27 0 2889%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 2890OpStore %31 %29 2891;CHECK-NOT: %20 = OpLoad %uint %19 2892;CHECK-NOT: %22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 2893;CHECK-NOT: %23 = OpLoad %13 %22 2894;CHECK-NOT: %27 = OpImageRead %v4float %23 %25 2895;CHECK-NOT: %29 = OpCompositeExtract %float %27 0 2896;CHECK-NOT: %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 2897;CHECK-NOT: OpStore %31 %29 2898;CHECK: {{%\w+}} = OpLoad %v3uint {{%\w+}} 2899;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 2900;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 2901;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2 2902;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_5316 {{%\w+}} {{%\w+}} {{%\w+}} 2903;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_49 {{%\w+}} %uint_1 %uint_2 %uint_0 {{%\w+}} 2904;CHECK: OpSelectionMerge {{%\w+}} None 2905;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 2906;CHECK: {{%\w+}} = OpLabel 2907;CHECK: {{%\w+}} = OpLoad %uint %25 2908;CHECK: OpBranch {{%\w+}} 2909;CHECK: {{%\w+}} = OpLabel 2910;CHECK: OpBranch {{%\w+}} 2911;CHECK: {{%\w+}} = OpLabel 2912;CHECK: [[phi_result:%\w+]] = OpPhi %uint {{%\w+}} {{%\w+}} [[null_uint]] {{%\w+}} 2913;CHECK: %27 = OpAccessChain %_ptr_UniformConstant_13 %images [[phi_result]] 2914;CHECK: %28 = OpLoad %13 %27 2915;CHECK: {{%\w+}} = OpLoad %v3uint {{%\w+}} 2916;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 2917;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 2918;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2 2919;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_5316 {{%\w+}} {{%\w+}} {{%\w+}} 2920;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_52 {{%\w+}} %uint_1 %uint_3 {{%\w+}} %uint_0 2921;CHECK: OpSelectionMerge {{%\w+}} None 2922;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 2923;CHECK: {{%\w+}} = OpLabel 2924;CHECK: {{%\w+}} = OpLoad %13 %27 2925;CHECK: {{%\w+}} = OpImageRead %v4float {{%\w+}} %20 2926;CHECK: OpBranch {{%\w+}} 2927;CHECK: {{%\w+}} = OpLabel 2928;CHECK: OpBranch {{%\w+}} 2929;CHECK: {{%\w+}} = OpLabel 2930;CHECK: {{%\w+}} = OpPhi %v4float {{%\w+}} {{%\w+}} [[null_v4float]] {{%\w+}} 2931;CHECK: %30 = OpCompositeExtract %float {{%\w+}} 0 2932;CHECK: %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 2933;CHECK: {{%\w+}} = OpLoad %v3uint {{%\w+}} 2934;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 2935;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 2936;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2 2937;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_5316 {{%\w+}} {{%\w+}} {{%\w+}} 2938;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_55 {{%\w+}} %uint_1 %uint_2 %uint_0 {{%\w+}} 2939;CHECK: OpSelectionMerge {{%\w+}} None 2940;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 2941;CHECK: {{%\w+}} = OpLabel 2942;CHECK: OpStore %31 %30 2943;CHECK: OpBranch {{%\w+}} 2944;CHECK: {{%\w+}} = OpLabel 2945;CHECK: OpBranch {{%\w+}} 2946;CHECK: {{%\w+}} = OpLabel 2947OpReturn 2948OpFunctionEnd 2949)"; 2950 // clang-format on 2951 2952 // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 2953 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 2954 true, 23u); 2955} 2956 2957TEST_F(InstBindlessTest, 2958 InstBoundsMissInitLoadVariableSizedSampledImagesArray) { 2959 // #version 460 2960 // #extension GL_EXT_nonuniform_qualifier : require 2961 // #extension GL_NV_ray_tracing : require 2962 // 2963 // layout(set = 1, binding = 2, std140) buffer StorageBuffer { 2964 // uint index; 2965 // float red; 2966 // } sbo; 2967 // 2968 // layout(set = 1, binding = 3, rgba32f) readonly uniform image2D images[]; 2969 // 2970 // void main() 2971 // { 2972 // sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r; 2973 // } 2974 2975 // clang-format off 2976 const std::string defs = R"( 2977OpCapability RuntimeDescriptorArray 2978OpCapability RayTracingNV 2979;CHECK: OpCapability Linkage 2980OpExtension "SPV_EXT_descriptor_indexing" 2981OpExtension "SPV_NV_ray_tracing" 2982%1 = OpExtInstImport "GLSL.std.450" 2983OpMemoryModel Logical GLSL450 2984OpEntryPoint MissNV %main "main" 2985;CHECK: OpEntryPoint MissNV %main "main" [[launch_id:%\w+]] 2986OpSource GLSL 460 2987OpSourceExtension "GL_EXT_nonuniform_qualifier" 2988OpSourceExtension "GL_NV_ray_tracing" 2989OpName %main "main" 2990OpName %StorageBuffer "StorageBuffer" 2991OpMemberName %StorageBuffer 0 "index" 2992OpMemberName %StorageBuffer 1 "red" 2993OpName %sbo "sbo" 2994OpName %images "images" 2995OpMemberDecorate %StorageBuffer 0 Offset 0 2996OpMemberDecorate %StorageBuffer 1 Offset 4 2997OpDecorate %StorageBuffer BufferBlock 2998OpDecorate %sbo DescriptorSet 1 2999OpDecorate %sbo Binding 2 3000OpDecorate %images DescriptorSet 1 3001OpDecorate %images Binding 3 3002OpDecorate %images NonWritable 3003)" + kImportDeco + R"( 3004;CHECK: OpDecorate [[launch_id]] BuiltIn LaunchIdNV 3005%void = OpTypeVoid 3006%3 = OpTypeFunction %void 3007%uint = OpTypeInt 32 0 3008%float = OpTypeFloat 32 3009%StorageBuffer = OpTypeStruct %uint %float 3010%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer 3011%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform 3012%int = OpTypeInt 32 1 3013%int_1 = OpConstant %int 1 3014%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f 3015%_runtimearr_13 = OpTypeRuntimeArray %13 3016%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 3017%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant 3018%int_0 = OpConstant %int 0 3019%_ptr_Uniform_uint = OpTypePointer Uniform %uint 3020%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 3021%v2int = OpTypeVector %int 2 3022%25 = OpConstantComposite %v2int %int_0 %int_0 3023%v4float = OpTypeVector %float 4 3024%uint_0 = OpConstant %uint 0 3025%_ptr_Uniform_float = OpTypePointer Uniform %float 3026;CHECK: [[launch_id]] = OpVariable %_ptr_Input_v3uint Input 3027;CHECK: [[null_uint:%\w+]] = OpConstantNull %uint 3028;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 3029)"; 3030 3031 const std::string main_func = R"( 3032%main = OpFunction %void None %3 3033%5 = OpLabel 3034%19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 3035%20 = OpLoad %uint %19 3036%22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 3037%23 = OpLoad %13 %22 3038%27 = OpImageRead %v4float %23 %25 3039%29 = OpCompositeExtract %float %27 0 3040%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 3041OpStore %31 %29 3042;CHECK-NOT: %20 = OpLoad %uint %19 3043;CHECK-NOT: %22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 3044;CHECK-NOT: %27 = OpImageRead %v4float %23 %25 3045;CHECK-NOT: %29 = OpCompositeExtract %float %27 0 3046;CHECK-NOT OpStore %31 %29 3047;CHECK: {{%\w+}} = OpLoad %v3uint {{%\w+}} 3048;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 3049;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 3050;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2 3051;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_5317 {{%\w+}} {{%\w+}} {{%\w+}} 3052;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_49 {{%\w+}} %uint_1 %uint_2 %uint_0 {{%\w+}} 3053;CHECK: OpSelectionMerge {{%\w+}} None 3054;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 3055;CHECK: {{%\w+}} = OpLabel 3056;CHECK: {{%\w+}} = OpLoad %uint %25 3057;CHECK: OpBranch {{%\w+}} 3058;CHECK: {{%\w+}} = OpLabel 3059;CHECK: OpBranch {{%\w+}} 3060;CHECK: {{%\w+}} = OpLabel 3061;CHECK: [[phi_result:%\w+]] = OpPhi %uint {{%\w+}} {{%\w+}} [[null_uint]] {{%\w+}} 3062;CHECK: %27 = OpAccessChain %_ptr_UniformConstant_13 %images [[phi_result]] 3063;CHECK: {{%\w+}} = OpLoad %v3uint {{%\w+}} 3064;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 3065;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 3066;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2 3067;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_5317 {{%\w+}} {{%\w+}} {{%\w+}} 3068;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_52 {{%\w+}} %uint_1 %uint_3 {{%\w+}} %uint_0 3069;CHECK: OpSelectionMerge {{%\w+}} None 3070;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 3071;CHECK: {{%\w+}} = OpLabel 3072;CHECK: {{%\w+}} = OpLoad %13 %27 3073;CHECK: {{%\w+}} = OpImageRead %v4float {{%\w+}} %20 3074;CHECK: OpBranch {{%\w+}} 3075;CHECK: {{%\w+}} = OpLabel 3076;CHECK: OpBranch {{%\w+}} 3077;CHECK: {{%\w+}} = OpLabel 3078;CHECK: {{%\w+}} = OpPhi %v4float {{%\w+}} {{%\w+}} [[null_v4float]] {{%\w+}} 3079;CHECK: %30 = OpCompositeExtract %float {{%\w+}} 0 3080;CHECK: %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 3081;CHECK: {{%\w+}} = OpLoad %v3uint {{%\w+}} 3082;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 3083;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 3084;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2 3085;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_5317 {{%\w+}} {{%\w+}} {{%\w+}} 3086;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_55 {{%\w+}} %uint_1 %uint_2 %uint_0 {{%\w+}} 3087;CHECK: OpSelectionMerge {{%\w+}} None 3088;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 3089;CHECK: {{%\w+}} = OpLabel 3090;CHECK: OpStore %31 %30 3091;CHECK: OpBranch {{%\w+}} 3092;CHECK: {{%\w+}} = OpLabel 3093;CHECK: OpBranch {{%\w+}} 3094;CHECK: {{%\w+}} = OpLabel 3095OpReturn 3096OpFunctionEnd 3097)"; 3098 // clang-format on 3099 3100 // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 3101 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 3102 true, 23u); 3103} 3104 3105TEST_F(InstBindlessTest, 3106 InstBoundsCallableInitLoadVariableSizedSampledImagesArray) { 3107 // #version 460 3108 // #extension GL_EXT_nonuniform_qualifier : require 3109 // #extension GL_NV_ray_tracing : require 3110 // 3111 // layout(set = 1, binding = 2, std140) buffer StorageBuffer { 3112 // uint index; 3113 // float red; 3114 // } sbo; 3115 // 3116 // layout(set = 1, binding = 3, rgba32f) readonly uniform image2D images[]; 3117 // 3118 // void main() 3119 // { 3120 // sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r; 3121 // } 3122 3123 // clang-format off 3124 const std::string defs = R"( 3125OpCapability RuntimeDescriptorArray 3126OpCapability RayTracingNV 3127;CHECK: OpCapability Linkage 3128OpExtension "SPV_EXT_descriptor_indexing" 3129OpExtension "SPV_NV_ray_tracing" 3130%1 = OpExtInstImport "GLSL.std.450" 3131OpMemoryModel Logical GLSL450 3132OpEntryPoint CallableNV %main "main" 3133;CHECK: OpEntryPoint CallableNV %main "main" [[launch_id:%\w+]] 3134OpSource GLSL 460 3135OpSourceExtension "GL_EXT_nonuniform_qualifier" 3136OpSourceExtension "GL_NV_ray_tracing" 3137OpName %main "main" 3138OpName %StorageBuffer "StorageBuffer" 3139OpMemberName %StorageBuffer 0 "index" 3140OpMemberName %StorageBuffer 1 "red" 3141OpName %sbo "sbo" 3142OpName %images "images" 3143OpMemberDecorate %StorageBuffer 0 Offset 0 3144OpMemberDecorate %StorageBuffer 1 Offset 4 3145OpDecorate %StorageBuffer BufferBlock 3146OpDecorate %sbo DescriptorSet 1 3147OpDecorate %sbo Binding 2 3148OpDecorate %images DescriptorSet 1 3149OpDecorate %images Binding 3 3150OpDecorate %images NonWritable 3151)" + kImportDeco + R"( 3152;CHECK: OpDecorate [[launch_id]] BuiltIn LaunchIdNV 3153%void = OpTypeVoid 3154%3 = OpTypeFunction %void 3155%uint = OpTypeInt 32 0 3156%float = OpTypeFloat 32 3157%StorageBuffer = OpTypeStruct %uint %float 3158%_ptr_Uniform_StorageBuffer = OpTypePointer Uniform %StorageBuffer 3159%sbo = OpVariable %_ptr_Uniform_StorageBuffer Uniform 3160%int = OpTypeInt 32 1 3161%int_1 = OpConstant %int 1 3162%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f 3163%_runtimearr_13 = OpTypeRuntimeArray %13 3164%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13 3165%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant 3166%int_0 = OpConstant %int 0 3167%_ptr_Uniform_uint = OpTypePointer Uniform %uint 3168%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 3169%v2int = OpTypeVector %int 2 3170%25 = OpConstantComposite %v2int %int_0 %int_0 3171%v4float = OpTypeVector %float 4 3172%uint_0 = OpConstant %uint 0 3173%_ptr_Uniform_float = OpTypePointer Uniform %float 3174;CHECK: [[null_uint:%\w+]] = OpConstantNull %uint 3175;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 3176)"; 3177 3178 const std::string main_func = R"( 3179%main = OpFunction %void None %3 3180%5 = OpLabel 3181%19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0 3182%20 = OpLoad %uint %19 3183%22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 3184%23 = OpLoad %13 %22 3185%27 = OpImageRead %v4float %23 %25 3186%29 = OpCompositeExtract %float %27 0 3187;CHECK-NOT: %20 = OpLoad %uint %19 3188;CHECK-NOT: %22 = OpAccessChain %_ptr_UniformConstant_13 %images %20 3189;CHECK: {{%\w+}} = OpLoad %v3uint {{%\w+}} 3190;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 3191;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 3192;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2 3193;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_5318 {{%\w+}} {{%\w+}} {{%\w+}} 3194;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_49 {{%\w+}} %uint_1 %uint_2 %uint_0 {{%\w+}} 3195;CHECK: OpSelectionMerge {{%\w+}} None 3196;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 3197;CHECK: {{%\w+}} = OpLabel 3198;CHECK: {{%\w+}} = OpLoad %uint %25 3199;CHECK: OpBranch {{%\w+}} 3200;CHECK: {{%\w+}} = OpLabel 3201;CHECK: OpBranch {{%\w+}} 3202;CHECK: {{%\w+}} = OpLabel 3203;CHECK: {{%\w+}} = OpPhi %uint {{%\w+}} {{%\w+}} [[null_uint]] {{%\w+}} 3204;CHECK: %27 = OpAccessChain %_ptr_UniformConstant_13 %images {{%\w+}} 3205;CHECK-NOT: %23 = OpLoad %13 %22 3206;CHECK-NOT: %27 = OpImageRead %v4float %23 %25 3207;CHECK-NOT: %29 = OpCompositeExtract %float %27 0 3208;CHECK: {{%\w+}} = OpLoad %v3uint {{%\w+}} 3209;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 3210;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 3211;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2 3212;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_5318 {{%\w+}} {{%\w+}} {{%\w+}} 3213;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_52 {{%\w+}} %uint_1 %uint_3 {{%\w+}} %uint_0 3214;CHECK: OpSelectionMerge {{%\w+}} None 3215;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 3216;CHECK: {{%\w+}} = OpLabel 3217;CHECK: {{%\w+}} = OpLoad %13 %27 3218;CHECK: {{%\w+}} = OpImageRead %v4float {{%\w+}} %20 3219;CHECK: OpBranch {{%\w+}} 3220;CHECK: {{%\w+}} = OpLabel 3221;CHECK: OpBranch {{%\w+}} 3222;CHECK: {{%\w+}} = OpLabel 3223;CHECK: {{%\w+}} = OpPhi %v4float {{%\w+}} {{%\w+}} [[null_v4float]] {{%\w+}} 3224;CHECK: %30 = OpCompositeExtract %float {{%\w+}} 0 3225;CHECK: %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 3226%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 3227OpStore %31 %29 3228;CHECK-NOT: %31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1 3229;CHECK-NOT: OpStore %31 %29 3230;CHECK: {{%\w+}} = OpLoad %v3uint {{%\w+}} 3231;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 3232;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 3233;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 2 3234;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_5318 {{%\w+}} {{%\w+}} {{%\w+}} 3235;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_55 {{%\w+}} %uint_1 %uint_2 %uint_0 {{%\w+}} 3236;CHECK: OpSelectionMerge {{%\w+}} None 3237;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 3238;CHECK: {{%\w+}} = OpLabel 3239;CHECK: OpStore %31 %30 3240;CHECK: OpBranch {{%\w+}} 3241;CHECK: {{%\w+}} = OpLabel 3242;CHECK: OpBranch {{%\w+}} 3243;CHECK: {{%\w+}} = OpLabel 3244OpReturn 3245OpFunctionEnd 3246)"; 3247 // clang-format on 3248 3249 // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 3250 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 3251 true, 23u); 3252} 3253 3254TEST_F(InstBindlessTest, InstBoundsInitSameBlockOpReplication) { 3255 // Test that same block ops like OpSampledImage are replicated properly 3256 // where needed. 3257 // 3258 // clang-format off 3259 // 3260 // #version 450 core 3261 // #extension GL_EXT_nonuniform_qualifier : enable 3262 // 3263 // layout(location = 0) in vec2 inTexcoord; 3264 // layout(location = 0) out vec4 outColor; 3265 // 3266 // layout(set = 1, binding = 0) uniform Uniforms { 3267 // vec2 var0; 3268 // } uniforms; 3269 // 3270 // layout(set = 1, binding = 1) uniform sampler uniformSampler; 3271 // layout(set = 1, binding = 2) uniform texture2D uniformTex; 3272 // layout(set = 1, binding = 3) uniform texture2D uniformTexArr[8]; 3273 // 3274 // void main() { 3275 // int index = 0; 3276 // float x = texture(sampler2D(uniformTexArr[nonuniformEXT(index)], uniformSampler), inTexcoord.xy).x; 3277 // float y = texture(sampler2D(uniformTex, uniformSampler), inTexcoord.xy * uniforms.var0.xy).x; 3278 // outColor = vec4(x, y, 0.0, 0.0); 3279 // } 3280 // 3281 3282 const std::string defs = R"( 3283OpCapability Shader 3284OpCapability ShaderNonUniformEXT 3285OpCapability SampledImageArrayNonUniformIndexingEXT 3286;CHECK: OpCapability Linkage 3287OpExtension "SPV_EXT_descriptor_indexing" 3288%1 = OpExtInstImport "GLSL.std.450" 3289OpMemoryModel Logical GLSL450 3290OpEntryPoint Fragment %main "main" %inTexcoord %outColor 3291;CHECK: OpEntryPoint Fragment %main "main" %inTexcoord %outColor %gl_FragCoord 3292OpExecutionMode %main OriginUpperLeft 3293OpSource GLSL 450 3294OpSourceExtension "GL_EXT_nonuniform_qualifier" 3295OpName %main "main" 3296OpName %index "index" 3297OpName %x "x" 3298OpName %uniformTexArr "uniformTexArr" 3299OpName %uniformSampler "uniformSampler" 3300OpName %inTexcoord "inTexcoord" 3301OpName %y "y" 3302OpName %uniformTex "uniformTex" 3303OpName %Uniforms "Uniforms" 3304OpMemberName %Uniforms 0 "var0" 3305OpName %uniforms "uniforms" 3306OpName %outColor "outColor" 3307OpDecorate %uniformTexArr DescriptorSet 1 3308OpDecorate %uniformTexArr Binding 3 3309OpDecorate %19 NonUniformEXT 3310OpDecorate %22 NonUniformEXT 3311OpDecorate %uniformSampler DescriptorSet 1 3312OpDecorate %uniformSampler Binding 1 3313OpDecorate %inTexcoord Location 0 3314OpDecorate %uniformTex DescriptorSet 1 3315OpDecorate %uniformTex Binding 2 3316OpMemberDecorate %Uniforms 0 Offset 0 3317OpDecorate %Uniforms Block 3318OpDecorate %uniforms DescriptorSet 1 3319OpDecorate %uniforms Binding 0 3320OpDecorate %outColor Location 0 3321;CHECK: OpDecorate {{%\w+}} NonUniform 3322;CHECK: OpDecorate {{%\w+}} NonUniform 3323)" + kImportDeco + R"( 3324;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 3325;CHECK: OpDecorate [[desc_state_result:%\w+]] NonUniform 3326%void = OpTypeVoid 3327%3 = OpTypeFunction %void 3328%int = OpTypeInt 32 1 3329%_ptr_Function_int = OpTypePointer Function %int 3330%int_0 = OpConstant %int 0 3331%float = OpTypeFloat 32 3332%_ptr_Function_float = OpTypePointer Function %float 3333%13 = OpTypeImage %float 2D 0 0 0 1 Unknown 3334%uint = OpTypeInt 32 0 3335%uint_8 = OpConstant %uint 8 3336%_arr_13_uint_8 = OpTypeArray %13 %uint_8 3337%_ptr_UniformConstant__arr_13_uint_8 = OpTypePointer UniformConstant %_arr_13_uint_8 3338%uniformTexArr = OpVariable %_ptr_UniformConstant__arr_13_uint_8 UniformConstant 3339%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 3340%23 = OpTypeSampler 3341%_ptr_UniformConstant_23 = OpTypePointer UniformConstant %23 3342%uniformSampler = OpVariable %_ptr_UniformConstant_23 UniformConstant 3343%27 = OpTypeSampledImage %13 3344%v2float = OpTypeVector %float 2 3345%_ptr_Input_v2float = OpTypePointer Input %v2float 3346%inTexcoord = OpVariable %_ptr_Input_v2float Input 3347%v4float = OpTypeVector %float 4 3348%uint_0 = OpConstant %uint 0 3349%uniformTex = OpVariable %_ptr_UniformConstant_13 UniformConstant 3350%Uniforms = OpTypeStruct %v2float 3351%_ptr_Uniform_Uniforms = OpTypePointer Uniform %Uniforms 3352%uniforms = OpVariable %_ptr_Uniform_Uniforms Uniform 3353%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float 3354%_ptr_Output_v4float = OpTypePointer Output %v4float 3355%outColor = OpVariable %_ptr_Output_v4float Output 3356%float_0 = OpConstant %float 0 3357;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 3358;CHECK: [[null_v2float:%\w+]] = OpConstantNull %v2float 3359)"; 3360 3361 const std::string main_func = R"( 3362%main = OpFunction %void None %3 3363%5 = OpLabel 3364%index = OpVariable %_ptr_Function_int Function 3365%x = OpVariable %_ptr_Function_float Function 3366%y = OpVariable %_ptr_Function_float Function 3367OpStore %index %int_0 3368%19 = OpLoad %int %index 3369%21 = OpAccessChain %_ptr_UniformConstant_13 %uniformTexArr %19 3370%22 = OpLoad %13 %21 3371%26 = OpLoad %23 %uniformSampler 3372%28 = OpSampledImage %27 %22 %26 3373%32 = OpLoad %v2float %inTexcoord 3374%34 = OpImageSampleImplicitLod %v4float %28 %32 3375%36 = OpCompositeExtract %float %34 0 3376;CHECK-NOT: %34 = OpImageSampleImplicitLod %v4float %28 %32 3377;CHECK-NOT: %36 = OpCompositeExtract %float %34 0 3378;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 3379;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 3380;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 3381;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 3382;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 3383;CHECK: {{%\w+}} = OpBitcast %uint %19 3384;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_80 {{%\w+}} %uint_1 %uint_3 {{%\w+}} %uint_0 3385;CHECK: OpSelectionMerge {{%\w+}} None 3386;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 3387;CHECK: {{%\w+}} = OpLabel 3388;CHECK: {{%\w+}} = OpLoad %13 %21 3389;CHECK: {{%\w+}} = OpSampledImage %27 {{%\w+}} %26 3390;CHECK: {{%\w+}} = OpImageSampleImplicitLod %v4float {{%\w+}} %32 3391;CHECK: OpBranch {{%\w+}} 3392;CHECK: {{%\w+}} = OpLabel 3393;CHECK: OpBranch {{%\w+}} 3394;CHECK: {{%\w+}} = OpLabel 3395;CHECK: {{%\w+}} = OpPhi %v4float {{%\w+}} {{%\w+}} [[null_v4float]] {{%\w+}} 3396OpStore %x %36 3397%39 = OpLoad %13 %uniformTex 3398%40 = OpLoad %23 %uniformSampler 3399%41 = OpSampledImage %27 %39 %40 3400%42 = OpLoad %v2float %inTexcoord 3401%47 = OpAccessChain %_ptr_Uniform_v2float %uniforms %int_0 3402%48 = OpLoad %v2float %47 3403%49 = OpFMul %v2float %42 %48 3404;CHECK-NOT: %48 = OpLoad %v2float %47 3405;CHECK-NOT: %49 = OpFMul %v2float %42 %48 3406;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 3407;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 3408;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 3409;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 3410;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 3411;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_88 {{%\w+}} %uint_1 %uint_0 %uint_0 {{%\w+}} 3412;CHECK: OpSelectionMerge {{%\w+}} None 3413;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 3414;CHECK: {{%\w+}} = OpLabel 3415;CHECK: {{%\w+}} = OpLoad %v2float %47 3416;CHECK: OpBranch {{%\w+}} 3417;CHECK: {{%\w+}} = OpLabel 3418;CHECK: OpBranch {{%\w+}} 3419;CHECK: {{%\w+}} = OpLabel 3420;CHECK: [[phi_result:%\w+]] = OpPhi %v2float {{%\w+}} {{%\w+}} [[null_v2float]] {{%\w+}} 3421;CHECK: %49 = OpFMul %v2float %42 [[phi_result]] 3422%50 = OpImageSampleImplicitLod %v4float %41 %49 3423%51 = OpCompositeExtract %float %50 0 3424OpStore %y %51 3425;CHECK-NOT: %50 = OpImageSampleImplicitLod %v4float %41 %49 3426;CHECK-NOT: %51 = OpCompositeExtract %float %50 0 3427;CHECK: {{%\w+}} = OpSampledImage %27 %39 %40 3428;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 3429;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 3430;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 3431;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 3432;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 3433;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_90 {{%\w+}} %uint_1 %uint_2 %uint_0 %uint_0 3434;CHECK: OpSelectionMerge {{%\w+}} None 3435;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 3436;CHECK: {{%\w+}} = OpLabel 3437;CHECK: {{%\w+}} = OpLoad %13 %uniformTex 3438;CHECK: {{%\w+}} = OpSampledImage %27 {{%\w+}} %40 3439;CHECK: {{%\w+}} = OpImageSampleImplicitLod %v4float {{%\w+}} %49 3440;CHECK: OpBranch {{%\w+}} 3441;CHECK: {{%\w+}} = OpLabel 3442;CHECK: OpBranch {{%\w+}} 3443;CHECK: {{%\w+}} = OpLabel 3444;CHECK: {{%\w+}} = OpPhi %v4float {{%\w+}} {{%\w+}} [[null_v4float]] {{%\w+}} 3445;CHECK: %51 = OpCompositeExtract %float {{%\w+}} 0 3446OpStore %y %51 3447%54 = OpLoad %float %x 3448%55 = OpLoad %float %y 3449%57 = OpCompositeConstruct %v4float %54 %55 %float_0 %float_0 3450OpStore %outColor %57 3451OpReturn 3452OpFunctionEnd 3453)"; 3454 // clang-format on 3455 3456 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 3457 SinglePassRunAndMatch<InstBindlessCheckPass>(defs + kImportStub + main_func, 3458 true, 23u); 3459} 3460 3461TEST_F(InstBindlessTest, MultipleUniformNonAggregateRefsNoDescInit) { 3462 // Check that uniform refs do not go out-of-bounds. All checks use same input 3463 // buffer read function call result at top of function for uniform buffer 3464 // length. Because descriptor indexing is not being checked, we can avoid one 3465 // buffer load. 3466 // 3467 // Texture2D g_tColor; 3468 // SamplerState g_sAniso; 3469 // 3470 // layout(push_constant) cbuffer PerViewPushConst_t { bool g_B; }; 3471 // 3472 // cbuffer PerViewConstantBuffer_t { 3473 // float2 g_TexOff0; 3474 // float2 g_TexOff1; 3475 // }; 3476 // 3477 // struct PS_INPUT { 3478 // float2 vTextureCoords : TEXCOORD2; 3479 // }; 3480 // 3481 // struct PS_OUTPUT { 3482 // float4 vColor : SV_Target0; 3483 // }; 3484 // 3485 // PS_OUTPUT MainPs(PS_INPUT i) { 3486 // PS_OUTPUT ps_output; 3487 // float2 off; 3488 // float2 vtc; 3489 // if (g_B) 3490 // off = g_TexOff0; 3491 // else 3492 // off = g_TexOff1; 3493 // vtc = i.vTextureCoords.xy + off; 3494 // ps_output.vColor = g_tColor.Sample(g_sAniso, vtc); 3495 // return ps_output; 3496 // } 3497 3498 // clang-format off 3499 const std::string text = R"( 3500OpCapability Shader 3501;CHECK: OpCapability Linkage 3502%1 = OpExtInstImport "GLSL.std.450" 3503OpMemoryModel Logical GLSL450 3504OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor 3505;CHECK: OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord 3506OpExecutionMode %MainPs OriginUpperLeft 3507OpSource HLSL 500 3508OpName %MainPs "MainPs" 3509OpName %PerViewPushConst_t "PerViewPushConst_t" 3510OpMemberName %PerViewPushConst_t 0 "g_B" 3511OpName %_ "" 3512OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" 3513OpMemberName %PerViewConstantBuffer_t 0 "g_TexOff0" 3514OpMemberName %PerViewConstantBuffer_t 1 "g_TexOff1" 3515OpName %__0 "" 3516OpName %g_tColor "g_tColor" 3517OpName %g_sAniso "g_sAniso" 3518OpName %i_vTextureCoords "i.vTextureCoords" 3519OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" 3520OpMemberDecorate %PerViewPushConst_t 0 Offset 0 3521OpDecorate %PerViewPushConst_t Block 3522OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 3523OpMemberDecorate %PerViewConstantBuffer_t 1 Offset 8 3524OpDecorate %PerViewConstantBuffer_t Block 3525OpDecorate %__0 DescriptorSet 0 3526OpDecorate %__0 Binding 1 3527OpDecorate %g_tColor DescriptorSet 0 3528OpDecorate %g_tColor Binding 0 3529OpDecorate %g_sAniso DescriptorSet 0 3530OpDecorate %g_sAniso Binding 2 3531OpDecorate %i_vTextureCoords Location 0 3532OpDecorate %_entryPointOutput_vColor Location 0 3533)" + kImportDeco + R"( 3534;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 3535%void = OpTypeVoid 3536%3 = OpTypeFunction %void 3537%float = OpTypeFloat 32 3538%v2float = OpTypeVector %float 2 3539%v4float = OpTypeVector %float 4 3540%uint = OpTypeInt 32 0 3541%PerViewPushConst_t = OpTypeStruct %uint 3542%_ptr_PushConstant_PerViewPushConst_t = OpTypePointer PushConstant %PerViewPushConst_t 3543%_ = OpVariable %_ptr_PushConstant_PerViewPushConst_t PushConstant 3544%int = OpTypeInt 32 1 3545%int_0 = OpConstant %int 0 3546%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint 3547%bool = OpTypeBool 3548%uint_0 = OpConstant %uint 0 3549%PerViewConstantBuffer_t = OpTypeStruct %v2float %v2float 3550%_ptr_Uniform_PerViewConstantBuffer_t = OpTypePointer Uniform %PerViewConstantBuffer_t 3551%__0 = OpVariable %_ptr_Uniform_PerViewConstantBuffer_t Uniform 3552%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float 3553%int_1 = OpConstant %int 1 3554%49 = OpTypeImage %float 2D 0 0 0 1 Unknown 3555%_ptr_UniformConstant_49 = OpTypePointer UniformConstant %49 3556%g_tColor = OpVariable %_ptr_UniformConstant_49 UniformConstant 3557%53 = OpTypeSampler 3558%_ptr_UniformConstant_53 = OpTypePointer UniformConstant %53 3559%g_sAniso = OpVariable %_ptr_UniformConstant_53 UniformConstant 3560%57 = OpTypeSampledImage %49 3561%_ptr_Input_v2float = OpTypePointer Input %v2float 3562%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input 3563%_ptr_Output_v4float = OpTypePointer Output %v4float 3564%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output 3565;CHECK: %v4uint = OpTypeVector %uint 4 3566;CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float 3567;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 3568;CHECK: [[null_v2float:%\w+]] = OpConstantNull %v2float 3569 )" + kImportStub + R"( 3570%MainPs = OpFunction %void None %3 3571%5 = OpLabel 3572%69 = OpLoad %v2float %i_vTextureCoords 3573%82 = OpAccessChain %_ptr_PushConstant_uint %_ %int_0 3574%83 = OpLoad %uint %82 3575%84 = OpINotEqual %bool %83 %uint_0 3576OpSelectionMerge %91 None 3577OpBranchConditional %84 %85 %88 3578%85 = OpLabel 3579%86 = OpAccessChain %_ptr_Uniform_v2float %__0 %int_0 3580%87 = OpLoad %v2float %86 3581;CHECK-NOT: %87 = OpLoad %v2float %86 3582;CHECK: {{%\w+}} = OpLabel 3583;CHECK: {{%\w+}} = OpIAdd %uint %uint_0 %uint_7 3584;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 3585;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 3586;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 3587;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 3588;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 3589;CHECK: [[desc_state_result:%\w+]] = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_72 {{%\w+}} %uint_0 %uint_1 %uint_0 {{%\w+}} 3590;CHECK: OpSelectionMerge {{%\w+}} None 3591;CHECK: OpBranchConditional [[desc_state_result]] {{%\w+}} {{%\w+}} 3592;CHECK: {{%\w+}} = OpLabel 3593;CHECK: {{%\w+}} = OpLoad %v2float %86 3594;CHECK: OpBranch {{%\w+}} 3595;CHECK: {{%\w+}} = OpLabel 3596;CHECK: OpBranch {{%\w+}} 3597;CHECK: {{%\w+}} = OpLabel 3598 ;CHECK: {{%\w+}} = OpPhi %v2float {{%\w+}} {{%\w+}} [[null_v2float]] {{%\w+}} 3599OpBranch %91 3600%88 = OpLabel 3601%89 = OpAccessChain %_ptr_Uniform_v2float %__0 %int_1 3602%90 = OpLoad %v2float %89 3603;CHECK-NOT: %90 = OpLoad %v2float %89 3604;CHECK: {{%\w+}} = OpIAdd %uint %uint_8 %uint_7 3605;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 3606;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 3607;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 3608;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 3609;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 3610;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_76 {{%\w+}} %uint_0 %uint_1 %uint_0 {{%\w+}} 3611;CHECK: OpSelectionMerge {{%\w+}} None 3612;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 3613;CHECK: {{%\w+}} = OpLabel 3614;CHECK: {{%\w+}} = OpLoad %v2float %89 3615;CHECK: OpBranch {{%\w+}} 3616;CHECK: {{%\w+}} = OpLabel 3617;CHECK: OpBranch {{%\w+}} 3618;CHECK: {{%\w+}} = OpLabel 3619;CHECK: {{%\w+}} = OpPhi %v2float {{%\w+}} {{%\w+}} [[null_v2float]] {{%\w+}} 3620OpBranch %91 3621%91 = OpLabel 3622%115 = OpPhi %v2float %87 %85 %90 %88 3623;CHECK-NOT: %115 = OpPhi %v2float %87 %85 %90 %88 3624;CHECK: %115 = OpPhi %v2float {{%\w+}} {{%\w+}} {{%\w+}} {{%\w+}} 3625%95 = OpFAdd %v2float %69 %115 3626%96 = OpLoad %49 %g_tColor 3627%97 = OpLoad %53 %g_sAniso 3628%98 = OpSampledImage %57 %96 %97 3629%100 = OpImageSampleImplicitLod %v4float %98 %95 3630OpStore %_entryPointOutput_vColor %100 3631OpReturn 3632OpFunctionEnd 3633)"; 3634 // clang-format on 3635 3636 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); 3637 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 3638 SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 23u); 3639} 3640 3641TEST_F(InstBindlessTest, UniformArrayRefNoDescInit) { 3642 // Check that uniform array ref does not go out-of-bounds. 3643 // 3644 // Texture2D g_tColor; 3645 // SamplerState g_sAniso; 3646 // 3647 // layout(push_constant) cbuffer PerViewPushConst_t { uint g_c; }; 3648 // 3649 // struct PerBatchEnvMapConstantBuffer_t { 3650 // float4x3 g_matEnvMapWorldToLocal; 3651 // float4 g_vEnvironmentMapBoxMins; 3652 // float2 g_TexOff; 3653 // }; 3654 // 3655 // cbuffer _BindlessFastEnvMapCB_PS_t { 3656 // PerBatchEnvMapConstantBuffer_t g_envMapConstants[128]; 3657 // }; 3658 // 3659 // struct PS_INPUT { 3660 // float2 vTextureCoords : TEXCOORD2; 3661 // }; 3662 // 3663 // struct PS_OUTPUT { 3664 // float4 vColor : SV_Target0; 3665 // }; 3666 // 3667 // PS_OUTPUT MainPs(PS_INPUT i) { 3668 // PS_OUTPUT ps_output; 3669 // float2 off; 3670 // float2 vtc; 3671 // off = g_envMapConstants[g_c].g_TexOff; 3672 // vtc = i.vTextureCoords.xy + off; 3673 // ps_output.vColor = g_tColor.Sample(g_sAniso, vtc); 3674 // return ps_output; 3675 // } 3676 3677 // clang-format off 3678 const std::string text = R"( 3679OpCapability Shader 3680;CHECK: OpCapability Linkage 3681%1 = OpExtInstImport "GLSL.std.450" 3682OpMemoryModel Logical GLSL450 3683OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor 3684OpExecutionMode %MainPs OriginUpperLeft 3685OpSource HLSL 500 3686OpName %MainPs "MainPs" 3687OpName %PerBatchEnvMapConstantBuffer_t "PerBatchEnvMapConstantBuffer_t" 3688OpMemberName %PerBatchEnvMapConstantBuffer_t 0 "g_matEnvMapWorldToLocal" 3689OpMemberName %PerBatchEnvMapConstantBuffer_t 1 "g_vEnvironmentMapBoxMins" 3690OpMemberName %PerBatchEnvMapConstantBuffer_t 2 "g_TexOff" 3691OpName %_BindlessFastEnvMapCB_PS_t "_BindlessFastEnvMapCB_PS_t" 3692OpMemberName %_BindlessFastEnvMapCB_PS_t 0 "g_envMapConstants" 3693OpName %_ "" 3694OpName %PerViewPushConst_t "PerViewPushConst_t" 3695OpMemberName %PerViewPushConst_t 0 "g_c" 3696OpName %__0 "" 3697OpName %g_tColor "g_tColor" 3698OpName %g_sAniso "g_sAniso" 3699OpName %i_vTextureCoords "i.vTextureCoords" 3700OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" 3701OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 0 RowMajor 3702OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 0 Offset 0 3703OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 0 MatrixStride 16 3704OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 1 Offset 48 3705OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 2 Offset 64 3706OpDecorate %_arr_PerBatchEnvMapConstantBuffer_t_uint_128 ArrayStride 80 3707OpMemberDecorate %_BindlessFastEnvMapCB_PS_t 0 Offset 0 3708OpDecorate %_BindlessFastEnvMapCB_PS_t Block 3709OpDecorate %_ DescriptorSet 0 3710OpDecorate %_ Binding 2 3711OpMemberDecorate %PerViewPushConst_t 0 Offset 0 3712OpDecorate %PerViewPushConst_t Block 3713OpDecorate %g_tColor DescriptorSet 0 3714OpDecorate %g_tColor Binding 0 3715OpDecorate %g_sAniso DescriptorSet 0 3716OpDecorate %g_sAniso Binding 1 3717OpDecorate %i_vTextureCoords Location 0 3718OpDecorate %_entryPointOutput_vColor Location 0 3719)" + kImportDeco + R"( 3720;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 3721%void = OpTypeVoid 3722%3 = OpTypeFunction %void 3723%float = OpTypeFloat 32 3724%v2float = OpTypeVector %float 2 3725%v4float = OpTypeVector %float 4 3726%v3float = OpTypeVector %float 3 3727%mat4v3float = OpTypeMatrix %v3float 4 3728%PerBatchEnvMapConstantBuffer_t = OpTypeStruct %mat4v3float %v4float %v2float 3729%uint = OpTypeInt 32 0 3730%uint_128 = OpConstant %uint 128 3731%_arr_PerBatchEnvMapConstantBuffer_t_uint_128 = OpTypeArray %PerBatchEnvMapConstantBuffer_t %uint_128 3732%_BindlessFastEnvMapCB_PS_t = OpTypeStruct %_arr_PerBatchEnvMapConstantBuffer_t_uint_128 3733%_ptr_Uniform__BindlessFastEnvMapCB_PS_t = OpTypePointer Uniform %_BindlessFastEnvMapCB_PS_t 3734%_ = OpVariable %_ptr_Uniform__BindlessFastEnvMapCB_PS_t Uniform 3735%int = OpTypeInt 32 1 3736%int_0 = OpConstant %int 0 3737%PerViewPushConst_t = OpTypeStruct %uint 3738%_ptr_PushConstant_PerViewPushConst_t = OpTypePointer PushConstant %PerViewPushConst_t 3739%__0 = OpVariable %_ptr_PushConstant_PerViewPushConst_t PushConstant 3740%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint 3741%int_2 = OpConstant %int 2 3742%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float 3743%46 = OpTypeImage %float 2D 0 0 0 1 Unknown 3744%_ptr_UniformConstant_46 = OpTypePointer UniformConstant %46 3745%g_tColor = OpVariable %_ptr_UniformConstant_46 UniformConstant 3746%50 = OpTypeSampler 3747%_ptr_UniformConstant_50 = OpTypePointer UniformConstant %50 3748%g_sAniso = OpVariable %_ptr_UniformConstant_50 UniformConstant 3749%54 = OpTypeSampledImage %46 3750%_ptr_Input_v2float = OpTypePointer Input %v2float 3751%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input 3752%_ptr_Output_v4float = OpTypePointer Output %v4float 3753%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output 3754;CHECK: %v4uint = OpTypeVector %uint 4 3755;CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float 3756;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 3757;CHECK: [[null_v2float:%\w+]] = OpConstantNull %v2float 3758)" + kImportStub + R"( 3759%MainPs = OpFunction %void None %3 3760%5 = OpLabel 3761%66 = OpLoad %v2float %i_vTextureCoords 3762%79 = OpAccessChain %_ptr_PushConstant_uint %__0 %int_0 3763%80 = OpLoad %uint %79 3764%81 = OpAccessChain %_ptr_Uniform_v2float %_ %int_0 %80 %int_2 3765%82 = OpLoad %v2float %81 3766;CHECK-NOT: %82 = OpLoad %v2float %81 3767;CHECK: {{%\w+}} = OpIMul %uint %uint_80 %80 3768;CHECK: {{%\w+}} = OpIAdd %uint %uint_0 {{%\w+}} 3769;CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_64 3770;CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_7 3771;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 3772;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 3773;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 3774;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 3775;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 3776;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_79 {{%\w+}} %uint_0 %uint_2 %uint_0 {{%\w+}} 3777;CHECK: OpSelectionMerge {{%\w+}} None 3778;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 3779;CHECK: {{%\w+}} = OpLabel 3780;CHECK: {{%\w+}} = OpLoad %v2float %81 3781;CHECK: OpBranch {{%\w+}} 3782;CHECK: {{%\w+}} = OpLabel 3783;CHECK: OpBranch {{%\w+}} 3784;CHECK: {{%\w+}} = OpLabel 3785;CHECK: {{%\w+}} = OpPhi %v2float {{%\w+}} {{%\w+}} [[null_v2float]] {{%\w+}} 3786%86 = OpFAdd %v2float %66 %82 3787;CHECK-NOT: %86 = OpFAdd %v2float %66 %82 3788;CHECK: %86 = OpFAdd %v2float %66 {{%\w+}} 3789%87 = OpLoad %46 %g_tColor 3790%88 = OpLoad %50 %g_sAniso 3791%89 = OpSampledImage %54 %87 %88 3792%91 = OpImageSampleImplicitLod %v4float %89 %86 3793OpStore %_entryPointOutput_vColor %91 3794OpReturn 3795OpFunctionEnd 3796)"; 3797 // clang-format on 3798 3799 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); 3800 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 3801 SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 23u); 3802} 3803 3804TEST_F(InstBindlessTest, UniformArrayRefWithDescInit) { 3805 // The buffer-oob and desc-init checks should use the same debug 3806 // output buffer write function. 3807 // 3808 // Same source as UniformArrayRefNoDescInit 3809 3810 // clang-format off 3811 const std::string text = R"( 3812OpCapability Shader 3813;CHECK: OpCapability Linkage 3814%1 = OpExtInstImport "GLSL.std.450" 3815OpMemoryModel Logical GLSL450 3816OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor 3817;CHECK: OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord 3818OpExecutionMode %MainPs OriginUpperLeft 3819OpSource HLSL 500 3820OpName %MainPs "MainPs" 3821OpName %PerBatchEnvMapConstantBuffer_t "PerBatchEnvMapConstantBuffer_t" 3822OpMemberName %PerBatchEnvMapConstantBuffer_t 0 "g_matEnvMapWorldToLocal" 3823OpMemberName %PerBatchEnvMapConstantBuffer_t 1 "g_vEnvironmentMapBoxMins" 3824OpMemberName %PerBatchEnvMapConstantBuffer_t 2 "g_TexOff" 3825OpName %_BindlessFastEnvMapCB_PS_t "_BindlessFastEnvMapCB_PS_t" 3826OpMemberName %_BindlessFastEnvMapCB_PS_t 0 "g_envMapConstants" 3827OpName %_ "" 3828OpName %PerViewPushConst_t "PerViewPushConst_t" 3829OpMemberName %PerViewPushConst_t 0 "g_c" 3830OpName %__0 "" 3831OpName %g_tColor "g_tColor" 3832OpName %g_sAniso "g_sAniso" 3833OpName %i_vTextureCoords "i.vTextureCoords" 3834OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" 3835OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 0 RowMajor 3836OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 0 Offset 0 3837OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 0 MatrixStride 16 3838OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 1 Offset 48 3839OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 2 Offset 64 3840OpDecorate %_arr_PerBatchEnvMapConstantBuffer_t_uint_128 ArrayStride 80 3841OpMemberDecorate %_BindlessFastEnvMapCB_PS_t 0 Offset 0 3842OpDecorate %_BindlessFastEnvMapCB_PS_t Block 3843OpDecorate %_ DescriptorSet 0 3844OpDecorate %_ Binding 2 3845OpMemberDecorate %PerViewPushConst_t 0 Offset 0 3846OpDecorate %PerViewPushConst_t Block 3847OpDecorate %g_tColor DescriptorSet 0 3848OpDecorate %g_tColor Binding 0 3849OpDecorate %g_sAniso DescriptorSet 0 3850OpDecorate %g_sAniso Binding 1 3851OpDecorate %i_vTextureCoords Location 0 3852OpDecorate %_entryPointOutput_vColor Location 0 3853)" + kImportDeco + R"( 3854;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 3855%void = OpTypeVoid 3856%3 = OpTypeFunction %void 3857%float = OpTypeFloat 32 3858%v2float = OpTypeVector %float 2 3859%v4float = OpTypeVector %float 4 3860%v3float = OpTypeVector %float 3 3861%mat4v3float = OpTypeMatrix %v3float 4 3862%PerBatchEnvMapConstantBuffer_t = OpTypeStruct %mat4v3float %v4float %v2float 3863%uint = OpTypeInt 32 0 3864%uint_128 = OpConstant %uint 128 3865%_arr_PerBatchEnvMapConstantBuffer_t_uint_128 = OpTypeArray %PerBatchEnvMapConstantBuffer_t %uint_128 3866%_BindlessFastEnvMapCB_PS_t = OpTypeStruct %_arr_PerBatchEnvMapConstantBuffer_t_uint_128 3867%_ptr_Uniform__BindlessFastEnvMapCB_PS_t = OpTypePointer Uniform %_BindlessFastEnvMapCB_PS_t 3868%_ = OpVariable %_ptr_Uniform__BindlessFastEnvMapCB_PS_t Uniform 3869%int = OpTypeInt 32 1 3870%int_0 = OpConstant %int 0 3871%PerViewPushConst_t = OpTypeStruct %uint 3872%_ptr_PushConstant_PerViewPushConst_t = OpTypePointer PushConstant %PerViewPushConst_t 3873%__0 = OpVariable %_ptr_PushConstant_PerViewPushConst_t PushConstant 3874%_ptr_PushConstant_uint = OpTypePointer PushConstant %uint 3875%int_2 = OpConstant %int 2 3876%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float 3877%46 = OpTypeImage %float 2D 0 0 0 1 Unknown 3878%_ptr_UniformConstant_46 = OpTypePointer UniformConstant %46 3879%g_tColor = OpVariable %_ptr_UniformConstant_46 UniformConstant 3880%50 = OpTypeSampler 3881%_ptr_UniformConstant_50 = OpTypePointer UniformConstant %50 3882%g_sAniso = OpVariable %_ptr_UniformConstant_50 UniformConstant 3883%54 = OpTypeSampledImage %46 3884%_ptr_Input_v2float = OpTypePointer Input %v2float 3885%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input 3886%_ptr_Output_v4float = OpTypePointer Output %v4float 3887%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output 3888;CHECK: %v4uint = OpTypeVector %uint 4 3889;CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float 3890;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 3891;CHECK: [[null_v2float:%\w+]] = OpConstantNull %v2float 3892;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 3893)" + kImportStub + R"( 3894%MainPs = OpFunction %void None %3 3895%5 = OpLabel 3896%66 = OpLoad %v2float %i_vTextureCoords 3897%79 = OpAccessChain %_ptr_PushConstant_uint %__0 %int_0 3898%80 = OpLoad %uint %79 3899%81 = OpAccessChain %_ptr_Uniform_v2float %_ %int_0 %80 %int_2 3900%82 = OpLoad %v2float %81 3901%86 = OpFAdd %v2float %66 %82 3902;CHECK-NOT: %82 = OpLoad %v2float %81 3903;CHECK-NOT: %86 = OpFAdd %v2float %66 %82 3904;CHECK: {{%\w+}} = OpIMul %uint %uint_80 %80 3905;CHECK: {{%\w+}} = OpIAdd %uint %uint_0 {{%\w+}} 3906;CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_64 3907;CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_7 3908;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 3909;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 3910;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 3911;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 3912;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 3913;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_79 {{%\w+}} %uint_0 %uint_2 %uint_0 {{%\w+}} 3914;CHECK: OpSelectionMerge {{%\w+}} None 3915;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 3916;CHECK: {{%\w+}} = OpLabel 3917;CHECK: {{%\w+}} = OpLoad %v2float %81 3918;CHECK: OpBranch {{%\w+}} 3919;CHECK: {{%\w+}} = OpLabel 3920;CHECK: OpBranch {{%\w+}} 3921;CHECK: {{%\w+}} = OpLabel 3922;CHECK: {{%\w+}} = OpPhi %v2float {{%\w+}} {{%\w+}} [[null_v2float]] {{%\w+}} 3923;CHECK: %86 = OpFAdd %v2float %66 {{%\w+}} 3924%87 = OpLoad %46 %g_tColor 3925%88 = OpLoad %50 %g_sAniso 3926%89 = OpSampledImage %54 %87 %88 3927%91 = OpImageSampleImplicitLod %v4float %89 %86 3928OpStore %_entryPointOutput_vColor %91 3929;CHECK-NOT: %91 = OpImageSampleImplicitLod %v4float %89 %86 3930;CHECK-NOT: OpStore %_entryPointOutput_vColor %91 3931;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 3932;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 3933;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 3934;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 3935;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 3936;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_84 {{%\w+}} %uint_0 %uint_0 %uint_0 %uint_0 3937;CHECK: OpSelectionMerge {{%\w+}} None 3938;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 3939;CHECK: {{%\w+}} = OpLabel 3940;CHECK: {{%\w+}} = OpLoad %46 %g_tColor 3941;CHECK: {{%\w+}} = OpSampledImage %54 {{%\w+}} %88 3942;CHECK: {{%\w+}} = OpImageSampleImplicitLod %v4float {{%\w+}} %86 3943;CHECK: OpBranch {{%\w+}} 3944;CHECK: {{%\w+}} = OpLabel 3945;CHECK: OpBranch {{%\w+}} 3946;CHECK: {{%\w+}} = OpLabel 3947;CHECK: {{%\w+}} = OpPhi %v4float {{%\w+}} {{%\w+}} [[null_v4float]] {{%\w+}} 3948;CHECK: OpStore %_entryPointOutput_vColor {{%\w+}} 3949OpReturn 3950OpFunctionEnd 3951)"; 3952 // clang-format on 3953 3954 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); 3955 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 3956 SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 23u); 3957} 3958 3959TEST_F(InstBindlessTest, Descriptor16BitIdxRef) { 3960 // Check that descriptor indexed with 16bit index is inbounds and 3961 // initialized 3962 // 3963 // Use Simple source with min16uint g_nDataIdx 3964 3965 // clang-format off 3966 const std::string text = R"( 3967OpCapability Shader 3968OpCapability Int16 3969OpCapability StoragePushConstant16 3970;CHECK: OpCapability Linkage 3971%1 = OpExtInstImport "GLSL.std.450" 3972OpMemoryModel Logical GLSL450 3973OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %_ %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor 3974;CHECK: OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %_ %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord 3975OpExecutionMode %MainPs OriginUpperLeft 3976OpSource HLSL 500 3977OpName %MainPs "MainPs" 3978OpName %g_tColor "g_tColor" 3979OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t" 3980OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx" 3981OpName %_ "" 3982OpName %g_sAniso "g_sAniso" 3983OpName %i_vTextureCoords "i.vTextureCoords" 3984OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" 3985OpDecorate %g_tColor DescriptorSet 1 3986OpDecorate %g_tColor Binding 2 3987OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0 3988OpDecorate %PerViewConstantBuffer_t Block 3989OpDecorate %g_sAniso DescriptorSet 1 3990OpDecorate %g_sAniso Binding 2 3991OpDecorate %i_vTextureCoords Location 0 3992OpDecorate %_entryPointOutput_vColor Location 0 3993)" + kImportDeco + R"( 3994;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 3995%void = OpTypeVoid 3996%10 = OpTypeFunction %void 3997%float = OpTypeFloat 32 3998%v2float = OpTypeVector %float 2 3999%v4float = OpTypeVector %float 4 4000%int = OpTypeInt 32 1 4001%int_0 = OpConstant %int 0 4002%16 = OpTypeImage %float 2D 0 0 0 1 Unknown 4003%uint = OpTypeInt 32 0 4004%uint_128 = OpConstant %uint 128 4005%_arr_16_uint_128 = OpTypeArray %16 %uint_128 4006%_ptr_UniformConstant__arr_16_uint_128 = OpTypePointer UniformConstant %_arr_16_uint_128 4007%g_tColor = OpVariable %_ptr_UniformConstant__arr_16_uint_128 UniformConstant 4008%ushort = OpTypeInt 16 0 4009%PerViewConstantBuffer_t = OpTypeStruct %ushort 4010%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t 4011%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant 4012%_ptr_PushConstant_ushort = OpTypePointer PushConstant %ushort 4013%_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16 4014%25 = OpTypeSampler 4015%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %25 4016%g_sAniso = OpVariable %_ptr_UniformConstant_25 UniformConstant 4017%27 = OpTypeSampledImage %16 4018%_ptr_Input_v2float = OpTypePointer Input %v2float 4019%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input 4020%_ptr_Output_v4float = OpTypePointer Output %v4float 4021%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output 4022;CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float 4023;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 4024;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 4025)" + kImportStub + R"( 4026%MainPs = OpFunction %void None %10 4027%30 = OpLabel 4028;CHECK: OpBranch %39 4029;CHECK: %39 = OpLabel 4030%31 = OpLoad %v2float %i_vTextureCoords 4031%32 = OpAccessChain %_ptr_PushConstant_ushort %_ %int_0 4032%33 = OpLoad %ushort %32 4033%34 = OpAccessChain %_ptr_UniformConstant_16 %g_tColor %33 4034%35 = OpLoad %16 %34 4035%36 = OpLoad %25 %g_sAniso 4036%37 = OpSampledImage %27 %35 %36 4037%38 = OpImageSampleImplicitLod %v4float %37 %31 4038OpStore %_entryPointOutput_vColor %38 4039;CHECK-NOT: %38 = OpImageSampleImplicitLod %v4float %37 %31 4040;CHECK-NOT: OpStore %_entryPointOutput_vColor %38 4041;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 4042;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 4043;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 4044;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 4045;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 4046;CHECK: {{%\w+}} = OpUConvert %uint %33 4047;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_61 {{%\w+}} %uint_1 %uint_2 {{%\w+}} %uint_0 4048;CHECK: OpSelectionMerge {{%\w+}} None 4049;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 4050;CHECK: {{%\w+}} = OpLabel 4051;CHECK: {{%\w+}} = OpLoad %16 %34 4052;CHECK: {{%\w+}} = OpSampledImage %27 {{%\w+}} %36 4053;CHECK: {{%\w+}} = OpImageSampleImplicitLod %v4float {{%\w+}} %31 4054;CHECK: OpBranch {{%\w+}} 4055;CHECK: {{%\w+}} = OpLabel 4056;CHECK: OpBranch {{%\w+}} 4057;CHECK: {{%\w+}} = OpLabel 4058;CHECK: [[phi_result:%\w+]] = OpPhi %v4float {{%\w+}} {{%\w+}} [[null_v4float]] {{%\w+}} 4059;CHECK: OpStore %_entryPointOutput_vColor [[phi_result]] 4060OpReturn 4061OpFunctionEnd 4062)"; 4063 // clang-format on 4064 4065 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); 4066 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 4067 SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 23u); 4068} 4069 4070TEST_F(InstBindlessTest, UniformArray16bitIdxRef) { 4071 // Check that uniform array ref with 16bit index does not go out-of-bounds. 4072 // 4073 // Texture2D g_tColor; 4074 // SamplerState g_sAniso; 4075 // 4076 // layout(push_constant) cbuffer PerViewPushConst_t { min16uint g_c; }; 4077 // 4078 // struct PerBatchEnvMapConstantBuffer_t { 4079 // float4x3 g_matEnvMapWorldToLocal; 4080 // float4 g_vEnvironmentMapBoxMins; 4081 // float2 g_TexOff; 4082 // }; 4083 // 4084 // cbuffer _BindlessFastEnvMapCB_PS_t { 4085 // PerBatchEnvMapConstantBuffer_t g_envMapConstants[128]; 4086 // }; 4087 // 4088 // struct PS_INPUT { 4089 // float2 vTextureCoords : TEXCOORD2; 4090 // }; 4091 // 4092 // struct PS_OUTPUT { 4093 // float4 vColor : SV_Target0; 4094 // }; 4095 // 4096 // PS_OUTPUT MainPs(PS_INPUT i) { 4097 // PS_OUTPUT ps_output; 4098 // float2 off; 4099 // float2 vtc; 4100 // off = g_envMapConstants[g_c].g_TexOff; 4101 // vtc = i.vTextureCoords.xy + off; 4102 // ps_output.vColor = g_tColor.Sample(g_sAniso, vtc); 4103 // return ps_output; 4104 // } 4105 4106 // clang-format off 4107 const std::string text = R"( 4108OpCapability Shader 4109OpCapability Int16 4110OpCapability StoragePushConstant16 4111;CHECK: OpCapability Linkage 4112%1 = OpExtInstImport "GLSL.std.450" 4113OpMemoryModel Logical GLSL450 4114OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor 4115;CHECK: OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor %gl_FragCoord 4116OpExecutionMode %MainPs OriginUpperLeft 4117OpSource HLSL 500 4118OpName %MainPs "MainPs" 4119OpName %PerBatchEnvMapConstantBuffer_t "PerBatchEnvMapConstantBuffer_t" 4120OpMemberName %PerBatchEnvMapConstantBuffer_t 0 "g_matEnvMapWorldToLocal" 4121OpMemberName %PerBatchEnvMapConstantBuffer_t 1 "g_vEnvironmentMapBoxMins" 4122OpMemberName %PerBatchEnvMapConstantBuffer_t 2 "g_TexOff" 4123OpName %_BindlessFastEnvMapCB_PS_t "_BindlessFastEnvMapCB_PS_t" 4124OpMemberName %_BindlessFastEnvMapCB_PS_t 0 "g_envMapConstants" 4125OpName %_ "" 4126OpName %PerViewPushConst_t "PerViewPushConst_t" 4127OpMemberName %PerViewPushConst_t 0 "g_c" 4128OpName %__0 "" 4129OpName %g_tColor "g_tColor" 4130OpName %g_sAniso "g_sAniso" 4131OpName %i_vTextureCoords "i.vTextureCoords" 4132OpName %_entryPointOutput_vColor "@entryPointOutput.vColor" 4133OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 0 RowMajor 4134OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 0 Offset 0 4135OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 0 MatrixStride 16 4136OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 1 Offset 48 4137OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 2 Offset 64 4138OpDecorate %_arr_PerBatchEnvMapConstantBuffer_t_uint_128 ArrayStride 80 4139OpMemberDecorate %_BindlessFastEnvMapCB_PS_t 0 Offset 0 4140OpDecorate %_BindlessFastEnvMapCB_PS_t Block 4141OpDecorate %_ DescriptorSet 0 4142OpDecorate %_ Binding 0 4143OpMemberDecorate %PerViewPushConst_t 0 Offset 0 4144OpDecorate %PerViewPushConst_t Block 4145OpDecorate %g_tColor DescriptorSet 0 4146OpDecorate %g_tColor Binding 0 4147OpDecorate %g_sAniso DescriptorSet 0 4148OpDecorate %g_sAniso Binding 0 4149OpDecorate %i_vTextureCoords Location 0 4150OpDecorate %_entryPointOutput_vColor Location 0 4151)" + kImportDeco + R"( 4152;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 4153%void = OpTypeVoid 4154%14 = OpTypeFunction %void 4155%float = OpTypeFloat 32 4156%v2float = OpTypeVector %float 2 4157%v4float = OpTypeVector %float 4 4158%v3float = OpTypeVector %float 3 4159%mat4v3float = OpTypeMatrix %v3float 4 4160%PerBatchEnvMapConstantBuffer_t = OpTypeStruct %mat4v3float %v4float %v2float 4161%uint = OpTypeInt 32 0 4162%uint_128 = OpConstant %uint 128 4163%_arr_PerBatchEnvMapConstantBuffer_t_uint_128 = OpTypeArray %PerBatchEnvMapConstantBuffer_t %uint_128 4164%_BindlessFastEnvMapCB_PS_t = OpTypeStruct %_arr_PerBatchEnvMapConstantBuffer_t_uint_128 4165%_ptr_Uniform__BindlessFastEnvMapCB_PS_t = OpTypePointer Uniform %_BindlessFastEnvMapCB_PS_t 4166%_ = OpVariable %_ptr_Uniform__BindlessFastEnvMapCB_PS_t Uniform 4167%int = OpTypeInt 32 1 4168%int_0 = OpConstant %int 0 4169%ushort = OpTypeInt 16 0 4170%PerViewPushConst_t = OpTypeStruct %ushort 4171%_ptr_PushConstant_PerViewPushConst_t = OpTypePointer PushConstant %PerViewPushConst_t 4172%__0 = OpVariable %_ptr_PushConstant_PerViewPushConst_t PushConstant 4173%_ptr_PushConstant_ushort = OpTypePointer PushConstant %ushort 4174%int_2 = OpConstant %int 2 4175%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float 4176%30 = OpTypeImage %float 2D 0 0 0 1 Unknown 4177%_ptr_UniformConstant_30 = OpTypePointer UniformConstant %30 4178%g_tColor = OpVariable %_ptr_UniformConstant_30 UniformConstant 4179%32 = OpTypeSampler 4180%_ptr_UniformConstant_32 = OpTypePointer UniformConstant %32 4181%g_sAniso = OpVariable %_ptr_UniformConstant_32 UniformConstant 4182%34 = OpTypeSampledImage %30 4183%_ptr_Input_v2float = OpTypePointer Input %v2float 4184%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input 4185%_ptr_Output_v4float = OpTypePointer Output %v4float 4186%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output 4187;CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float 4188;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 4189;CHECK: [[null_v2float:%\w+]] = OpConstantNull %v2float 4190)" + kImportStub + R"( 4191%MainPs = OpFunction %void None %14 4192%37 = OpLabel 4193%38 = OpLoad %v2float %i_vTextureCoords 4194%39 = OpAccessChain %_ptr_PushConstant_ushort %__0 %int_0 4195%40 = OpLoad %ushort %39 4196%41 = OpAccessChain %_ptr_Uniform_v2float %_ %int_0 %40 %int_2 4197%42 = OpLoad %v2float %41 4198%43 = OpFAdd %v2float %38 %42 4199;CHECK-NOT: %42 = OpLoad %v2float %41 4200;CHECK-NOT: %43 = OpFAdd %v2float %38 %42 4201;CHECK: {{%\w+}} = OpUConvert %uint %40 4202;CHECK: {{%\w+}} = OpIMul %uint %uint_80 {{%\w+}} 4203;CHECK: {{%\w+}} = OpIAdd %uint %uint_0 {{%\w+}} 4204;CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_64 4205;CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_7 4206;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 4207;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 4208;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 4209;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 4210;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 4211;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_82 {{%\w+}} %uint_0 %uint_0 %uint_0 {{%\w+}} 4212;CHECK: OpSelectionMerge {{%\w+}} None 4213;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 4214;CHECK: {{%\w+}} = OpLabel 4215;CHECK: {{%\w+}} = OpLoad %v2float %41 4216;CHECK: OpBranch {{%\w+}} 4217;CHECK: {{%\w+}} = OpLabel 4218;CHECK: OpBranch {{%\w+}} 4219;CHECK: {{%\w+}} = OpLabel 4220;CHECK: {{%\w+}} = OpPhi %v2float {{%\w+}} {{%\w+}} [[null_v2float]] {{%\w+}} 4221;CHECK: %43 = OpFAdd %v2float %38 {{%\w+}} 4222%44 = OpLoad %30 %g_tColor 4223%45 = OpLoad %32 %g_sAniso 4224%46 = OpSampledImage %34 %44 %45 4225%47 = OpImageSampleImplicitLod %v4float %46 %43 4226OpStore %_entryPointOutput_vColor %47 4227OpReturn 4228OpFunctionEnd 4229)"; 4230 // clang-format on 4231 4232 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); 4233 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 4234 SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 23u); 4235} 4236 4237TEST_F(InstBindlessTest, UniformMatrixRefRowMajor) { 4238 // The buffer-oob row major matrix check 4239 // 4240 // #version 450 4241 // #extension GL_EXT_scalar_block_layout : enable 4242 // 4243 // layout(location = 0) in highp vec4 a_position; 4244 // layout(location = 0) out mediump float v_vtxResult; 4245 // 4246 // layout(set = 0, binding = 0, std430, row_major) uniform Block 4247 // { 4248 // lowp mat4x2 var; 4249 // }; 4250 // 4251 // void main (void) 4252 // { 4253 // v_vtxResult = var[2][1]; 4254 // } 4255 4256 // clang-format off 4257 std::string text = R"( 4258OpCapability Shader 4259;CHECK: OpCapability Linkage 4260%1 = OpExtInstImport "GLSL.std.450" 4261OpMemoryModel Logical GLSL450 4262OpEntryPoint Vertex %main "main" %v_vtxResult %_ %a_position 4263;CHECK: OpEntryPoint Vertex %main "main" %v_vtxResult %_ %a_position %gl_VertexIndex %gl_InstanceIndex 4264OpSource GLSL 450 4265OpSourceExtension "GL_EXT_scalar_block_layout" 4266OpName %main "main" 4267OpName %v_vtxResult "v_vtxResult" 4268OpName %Block "Block" 4269OpMemberName %Block 0 "var" 4270OpName %_ "" 4271OpName %a_position "a_position" 4272OpDecorate %v_vtxResult RelaxedPrecision 4273OpDecorate %v_vtxResult Location 0 4274OpMemberDecorate %Block 0 RowMajor 4275OpMemberDecorate %Block 0 RelaxedPrecision 4276OpMemberDecorate %Block 0 Offset 0 4277OpMemberDecorate %Block 0 MatrixStride 16 4278OpDecorate %Block Block 4279OpDecorate %_ DescriptorSet 0 4280OpDecorate %_ Binding 0 4281OpDecorate %21 RelaxedPrecision 4282;CHECK-NOT: OpDecorate %21 RelaxedPrecision 4283;CHECK: OpDecorate %v_vtxResult RelaxedPrecision 4284;CHECK: OpDecorate [[phi_result:%\w+]] RelaxedPrecision 4285OpDecorate %a_position Location 0 4286)" + kImportDeco + R"( 4287;CHECK: OpDecorate %gl_VertexIndex BuiltIn VertexIndex 4288;CHECK: OpDecorate %gl_InstanceIndex BuiltIn InstanceIndex 4289;CHECK: OpDecorate [[load_result:%\w+]] RelaxedPrecision 4290%void = OpTypeVoid 4291%3 = OpTypeFunction %void 4292%float = OpTypeFloat 32 4293%_ptr_Output_float = OpTypePointer Output %float 4294%v_vtxResult = OpVariable %_ptr_Output_float Output 4295%v2float = OpTypeVector %float 2 4296%mat4v2float = OpTypeMatrix %v2float 4 4297%Block = OpTypeStruct %mat4v2float 4298%_ptr_Uniform_Block = OpTypePointer Uniform %Block 4299%_ = OpVariable %_ptr_Uniform_Block Uniform 4300%int = OpTypeInt 32 1 4301%int_0 = OpConstant %int 0 4302%int_2 = OpConstant %int 2 4303%uint = OpTypeInt 32 0 4304%uint_1 = OpConstant %uint 1 4305%_ptr_Uniform_float = OpTypePointer Uniform %float 4306%v4float = OpTypeVector %float 4 4307%_ptr_Input_v4float = OpTypePointer Input %v4float 4308%a_position = OpVariable %_ptr_Input_v4float Input 4309;CHECK: %_ptr_Input_uint = OpTypePointer Input %uint 4310;CHECK: %gl_VertexIndex = OpVariable %_ptr_Input_uint Input 4311;CHECK: %gl_InstanceIndex = OpVariable %_ptr_Input_uint Input 4312;CHECK: [[null_float:%\w+]] = OpConstantNull %float 4313)" + kImportStub + R"( 4314%main = OpFunction %void None %3 4315%5 = OpLabel 4316;CHECK: OpBranch {{%\w+}} 4317;CHECK: {{%\w+}} = OpLabel 4318%20 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %int_2 %uint_1 4319%21 = OpLoad %float %20 4320;CHECK-NOT: %21 = OpLoad %float %20 4321;CHECK: {{%\w+}} = OpIMul %uint %uint_4 %int_2 4322;CHECK: {{%\w+}} = OpIAdd %uint %uint_0 {{%\w+}} 4323;CHECK: {{%\w+}} = OpIMul %uint %uint_16 %uint_1 4324;CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} {{%\w+}} 4325;CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_3 4326;CHECK: {{%\w+}} = OpLoad %uint %gl_VertexIndex 4327;CHECK: {{%\w+}} = OpLoad %uint %gl_InstanceIndex 4328;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_0 {{%\w+}} {{%\w+}} %uint_0 4329;CHECK: [[desc_state:%\w+]] = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_46 {{%\w+}} %uint_0 %uint_0 %uint_0 {{%\w+}} 4330;CHECK: OpSelectionMerge {{%\w+}} None 4331;CHECK: OpBranchConditional [[desc_state]] {{%\w+}} {{%\w+}} 4332;CHECK: {{%\w+}} = OpLabel 4333;CHECK: [[load_result]] = OpLoad %float %20 4334;CHECK: OpBranch {{%\w+}} 4335;CHECK: {{%\w+}} = OpLabel 4336;CHECK: OpBranch {{%\w+}} 4337;CHECK: {{%\w+}} = OpLabel 4338;CHECK: [[phi_result]] = OpPhi %float [[load_result]] {{%\w+}} [[null_float]] {{%\w+}} 4339OpStore %v_vtxResult %21 4340;CHECK-NOT: OpStore %v_vtxResult %21$ 4341;CHECK: OpStore %v_vtxResult [[phi_result]] 4342OpReturn 4343OpFunctionEnd 4344)"; 4345 // clang-format on 4346 4347 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); 4348 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 4349 SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 23u); 4350} 4351 4352TEST_F(InstBindlessTest, UniformMatrixRefColumnMajor) { 4353 // The buffer-oob column major matrix check 4354 // 4355 // #version 450 4356 // #extension GL_EXT_scalar_block_layout : enable 4357 // 4358 // layout(location = 0) in highp vec4 a_position; 4359 // layout(location = 0) out mediump float v_vtxResult; 4360 // 4361 // layout(set = 0, binding = 0, std430, column_major) uniform Block 4362 // { 4363 // lowp mat4x2 var; 4364 // }; 4365 // 4366 // void main (void) 4367 // { 4368 // v_vtxResult = var[2][1]; 4369 // } 4370 4371 // clang-format off 4372 const std::string text = R"( 4373OpCapability Shader 4374;CHECK: OpCapability Linkage 4375%1 = OpExtInstImport "GLSL.std.450" 4376OpMemoryModel Logical GLSL450 4377OpEntryPoint Vertex %main "main" %v_vtxResult %_ %a_position 4378;CHECK: OpEntryPoint Vertex %main "main" %v_vtxResult %_ %a_position %gl_VertexIndex %gl_InstanceIndex 4379OpSource GLSL 450 4380OpSourceExtension "GL_EXT_scalar_block_layout" 4381OpName %main "main" 4382OpName %v_vtxResult "v_vtxResult" 4383OpName %Block "Block" 4384OpMemberName %Block 0 "var" 4385OpName %_ "" 4386OpName %a_position "a_position" 4387OpDecorate %v_vtxResult RelaxedPrecision 4388OpDecorate %v_vtxResult Location 0 4389OpMemberDecorate %Block 0 ColMajor 4390OpMemberDecorate %Block 0 RelaxedPrecision 4391OpMemberDecorate %Block 0 Offset 0 4392OpMemberDecorate %Block 0 MatrixStride 8 4393OpDecorate %Block Block 4394OpDecorate %_ DescriptorSet 0 4395OpDecorate %_ Binding 0 4396OpDecorate %21 RelaxedPrecision 4397;CHECK-NOT: OpDecorate %21 RelaxedPrecision 4398;CHECK: OpDecorate %v_vtxResult RelaxedPrecision 4399;CHECK: OpDecorate [[phi_result:%\w+]] RelaxedPrecision 4400OpDecorate %a_position Location 0 4401)" + kImportDeco + R"( 4402;CHECK: OpDecorate %gl_VertexIndex BuiltIn VertexIndex 4403;CHECK: OpDecorate %gl_InstanceIndex BuiltIn InstanceIndex 4404;CHECK: OpDecorate [[load_result:%\w+]] RelaxedPrecision 4405%void = OpTypeVoid 4406%3 = OpTypeFunction %void 4407%float = OpTypeFloat 32 4408%_ptr_Output_float = OpTypePointer Output %float 4409%v_vtxResult = OpVariable %_ptr_Output_float Output 4410%v2float = OpTypeVector %float 2 4411%mat4v2float = OpTypeMatrix %v2float 4 4412%Block = OpTypeStruct %mat4v2float 4413%_ptr_Uniform_Block = OpTypePointer Uniform %Block 4414%_ = OpVariable %_ptr_Uniform_Block Uniform 4415%int = OpTypeInt 32 1 4416%int_0 = OpConstant %int 0 4417%int_2 = OpConstant %int 2 4418%uint = OpTypeInt 32 0 4419%uint_1 = OpConstant %uint 1 4420%_ptr_Uniform_float = OpTypePointer Uniform %float 4421%v4float = OpTypeVector %float 4 4422%_ptr_Input_v4float = OpTypePointer Input %v4float 4423%a_position = OpVariable %_ptr_Input_v4float Input 4424;CHECK: %_ptr_Input_uint = OpTypePointer Input %uint 4425;CHECK: %gl_VertexIndex = OpVariable %_ptr_Input_uint Input 4426;CHECK: %gl_InstanceIndex = OpVariable %_ptr_Input_uint Input 4427;CHECK: [[null_float:%\w+]] = OpConstantNull %float 4428)" + kImportStub + R"( 4429%main = OpFunction %void None %3 4430%5 = OpLabel 4431%20 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %int_2 %uint_1 4432%21 = OpLoad %float %20 4433;CHECK-NOT: %21 = OpLoad %float %20 4434;CHECK: OpBranch {{%\w+}} 4435;CHECK: {{%\w+}} = OpLabel 4436;CHECK: {{%\w+}} = OpIMul %uint %uint_8 %int_2 4437;CHECK: {{%\w+}} = OpIAdd %uint %uint_0 {{%\w+}} 4438;CHECK: {{%\w+}} = OpIMul %uint %uint_4 %uint_1 4439;CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} {{%\w+}} 4440;CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_3 4441;CHECK: {{%\w+}} = OpLoad %uint %gl_VertexIndex 4442;CHECK: {{%\w+}} = OpLoad %uint %gl_InstanceIndex 4443;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_0 {{%\w+}} {{%\w+}} %uint_0 4444;CHECK: [[desc_state:%\w+]] = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_46 {{%\w+}} %uint_0 %uint_0 %uint_0 {{%\w+}} 4445;CHECK: OpSelectionMerge {{%\w+}} None 4446;CHECK: OpBranchConditional [[desc_state]] {{%\w+}} {{%\w+}} 4447;CHECK: {{%\w+}} = OpLabel 4448;CHECK:[[load_result]] = OpLoad %float %20 4449;CHECK: OpBranch {{%\w+}} 4450;CHECK: {{%\w+}} = OpLabel 4451;CHECK: OpBranch {{%\w+}} 4452;CHECK: {{%\w+}} = OpLabel 4453;CHECK: [[phi_result]] = OpPhi %float [[load_result]] {{%\w+}} [[null_float]] {{%\w+}} 4454OpStore %v_vtxResult %21 4455;CHECK-NOT: OpStore %v_vtxResult %21$ 4456;CHECK: OpStore %v_vtxResult [[phi_result]] 4457OpReturn 4458OpFunctionEnd 4459)"; 4460 // clang-format on 4461 4462 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); 4463 ValidatorOptions()->uniform_buffer_standard_layout = true; 4464 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 4465 SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 23u); 4466} 4467 4468TEST_F(InstBindlessTest, UniformMatrixVecRefRowMajor) { 4469 // The buffer-oob row major matrix vector ref check 4470 // 4471 // #version 450 4472 // #extension GL_EXT_scalar_block_layout : enable 4473 // 4474 // layout(location = 0) in highp vec4 a_position; 4475 // layout(location = 0) out highp vec2 v_vtxResult; 4476 // 4477 // layout(set = 3, binding = 7, std430, row_major) uniform Block 4478 // { 4479 // lowp mat2 var[3][4]; 4480 // }; 4481 // 4482 // void main (void) 4483 // { 4484 // v_vtxResult = var[2][3][1]; 4485 // } 4486 4487 // clang-format off 4488 const std::string text = R"( 4489OpCapability Shader 4490;CHECK: OpCapability Linkage 4491%1 = OpExtInstImport "GLSL.std.450" 4492OpMemoryModel Logical GLSL450 4493OpEntryPoint Vertex %main "main" %v_vtxResult %_ %a_position 4494;CHECK: OpEntryPoint Vertex %main "main" %v_vtxResult %_ %a_position %gl_VertexIndex %gl_InstanceIndex 4495OpSource GLSL 450 4496OpSourceExtension "GL_EXT_scalar_block_layout" 4497OpName %main "main" 4498OpName %v_vtxResult "v_vtxResult" 4499OpName %Block "Block" 4500OpMemberName %Block 0 "var" 4501OpName %_ "" 4502OpName %a_position "a_position" 4503OpDecorate %v_vtxResult Location 0 4504OpDecorate %_arr_mat2v2float_uint_4 ArrayStride 32 4505OpDecorate %_arr__arr_mat2v2float_uint_4_uint_3 ArrayStride 128 4506OpMemberDecorate %Block 0 RowMajor 4507OpMemberDecorate %Block 0 RelaxedPrecision 4508OpMemberDecorate %Block 0 Offset 0 4509OpMemberDecorate %Block 0 MatrixStride 16 4510OpDecorate %Block Block 4511OpDecorate %_ DescriptorSet 3 4512OpDecorate %_ Binding 7 4513OpDecorate %26 RelaxedPrecision 4514;CHECK-NOT: OpDecorate %26 RelaxedPrecision 4515;CHECK: OpDecorate [[phi_result:%\w+]] RelaxedPrecision 4516OpDecorate %a_position Location 0 4517)" + kImportDeco + R"( 4518;CHECK: OpDecorate %gl_VertexIndex BuiltIn VertexIndex 4519;CHECK: OpDecorate %gl_InstanceIndex BuiltIn InstanceIndex 4520;CHECK: OpDecorate [[load_result:%\w+]] RelaxedPrecision 4521%void = OpTypeVoid 4522%3 = OpTypeFunction %void 4523%float = OpTypeFloat 32 4524%v2float = OpTypeVector %float 2 4525%_ptr_Output_v2float = OpTypePointer Output %v2float 4526%v_vtxResult = OpVariable %_ptr_Output_v2float Output 4527%mat2v2float = OpTypeMatrix %v2float 2 4528%uint = OpTypeInt 32 0 4529%uint_4 = OpConstant %uint 4 4530%_arr_mat2v2float_uint_4 = OpTypeArray %mat2v2float %uint_4 4531%uint_3 = OpConstant %uint 3 4532%_arr__arr_mat2v2float_uint_4_uint_3 = OpTypeArray %_arr_mat2v2float_uint_4 %uint_3 4533%Block = OpTypeStruct %_arr__arr_mat2v2float_uint_4_uint_3 4534%_ptr_Uniform_Block = OpTypePointer Uniform %Block 4535%_ = OpVariable %_ptr_Uniform_Block Uniform 4536%int = OpTypeInt 32 1 4537%int_0 = OpConstant %int 0 4538%int_2 = OpConstant %int 2 4539%int_3 = OpConstant %int 3 4540%int_1 = OpConstant %int 1 4541%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float 4542%v4float = OpTypeVector %float 4 4543%_ptr_Input_v4float = OpTypePointer Input %v4float 4544%a_position = OpVariable %_ptr_Input_v4float Input 4545;CHECK: %_ptr_Input_uint = OpTypePointer Input %uint 4546;CHECK: %gl_VertexIndex = OpVariable %_ptr_Input_uint Input 4547;CHECK: %gl_InstanceIndex = OpVariable %_ptr_Input_uint Input 4548;CHECK: [[null_v2float:%\w+]] = OpConstantNull %v2float 4549)" + kImportStub + R"( 4550%main = OpFunction %void None %3 4551%5 = OpLabel 4552%25 = OpAccessChain %_ptr_Uniform_v2float %_ %int_0 %int_2 %int_3 %int_1 4553;CHECK: {{%\w+}} = OpIMul %uint %uint_128 %int_2 4554;CHECK: {{%\w+}} = OpIAdd %uint %uint_0 {{%\w+}} 4555;CHECK: {{%\w+}} = OpIMul %uint %uint_32 %int_3 4556;CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} {{%\w+}} 4557;CHECK: {{%\w+}} = OpIMul %uint %uint_4 %int_1 4558;CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} {{%\w+}} 4559;CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_19 4560;CHECK: {{%\w+}} = OpLoad %uint %gl_VertexIndex 4561;CHECK: {{%\w+}} = OpLoad %uint %gl_InstanceIndex 4562;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_0 {{%\w+}} {{%\w+}} %uint_0 4563;CHECK: [[desc_state:%\w+]] = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_52 {{%\w+}} %uint_3 %uint_7 %uint_0 {{%\w+}} 4564%26 = OpLoad %v2float %25 4565OpStore %v_vtxResult %26 4566;CHECK-NOT: %26 = OpLoad %v2float %25 4567;CHECK-NOT: OpStore %v_vtxResult %26 4568;CHECK: OpSelectionMerge {{%\w+}} None 4569;CHECK: OpBranchConditional [[desc_state]] {{%\w+}} {{%\w+}} 4570;CHECK: {{%\w+}} = OpLabel 4571;CHECK: [[load_result]] = OpLoad %v2float %25 4572;CHECK: OpBranch {{%\w+}} 4573;CHECK: {{%\w+}} = OpLabel 4574;CHECK: OpBranch {{%\w+}} 4575;CHECK: {{%\w+}} = OpLabel 4576;CHECK: [[phi_result]] = OpPhi %v2float [[load_result]] {{%\w+}} [[null_v2float]] {{%\w+}} 4577;CHECK: OpStore %v_vtxResult [[phi_result]] 4578OpReturn 4579OpFunctionEnd 4580)"; 4581 // clang-format on 4582 4583 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); 4584 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 4585 SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 23u); 4586} 4587 4588TEST_F(InstBindlessTest, ImageBufferOOBRead) { 4589 // Texel buffer (imagebuffer) oob check for ImageRead 4590 // 4591 // #version 450 4592 // layout(set=3, binding=7, r32f) uniform readonly imageBuffer s; 4593 // layout(location=11) out vec4 x; 4594 // layout(location=13) in flat int ii; 4595 // 4596 // void main(){ 4597 // x = imageLoad(s, ii); 4598 // } 4599 4600 // clang-format off 4601 const std::string text = R"( 4602OpCapability Shader 4603OpCapability ImageBuffer 4604;CHECK: OpCapability Linkage 4605%1 = OpExtInstImport "GLSL.std.450" 4606OpMemoryModel Logical GLSL450 4607OpEntryPoint Fragment %main "main" %x %s %ii 4608OpExecutionMode %main OriginUpperLeft 4609OpSource GLSL 450 4610OpName %main "main" 4611OpName %x "x" 4612OpName %s "s" 4613OpName %ii "ii" 4614OpDecorate %x Location 11 4615OpDecorate %s DescriptorSet 3 4616OpDecorate %s Binding 7 4617OpDecorate %s NonWritable 4618OpDecorate %ii Flat 4619OpDecorate %ii Location 13 4620)" + kImportDeco + R"( 4621;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 4622%void = OpTypeVoid 4623%3 = OpTypeFunction %void 4624%float = OpTypeFloat 32 4625%v4float = OpTypeVector %float 4 4626%_ptr_Output_v4float = OpTypePointer Output %v4float 4627%x = OpVariable %_ptr_Output_v4float Output 4628%10 = OpTypeImage %float Buffer 0 0 0 2 R32f 4629%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10 4630%s = OpVariable %_ptr_UniformConstant_10 UniformConstant 4631%int = OpTypeInt 32 1 4632%_ptr_Input_int = OpTypePointer Input %int 4633%ii = OpVariable %_ptr_Input_int Input 4634;CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float 4635;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 4636;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 4637%main = OpFunction %void None %3 4638%5 = OpLabel 4639;CHECK: OpBranch %19 4640;CHECK: %19 = OpLabel 4641%13 = OpLoad %10 %s 4642%17 = OpLoad %int %ii 4643%18 = OpImageRead %v4float %13 %17 4644OpStore %x %18 4645;CHECK-NOT: %18 = OpImageRead %v4float %13 %17 4646;CHECK-NOT: OpStore %x %18 4647;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 4648;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 4649;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 4650;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 4651;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 4652;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_34 {{%\w+}} %uint_3 %uint_7 %uint_0 %22 4653;CHECK: OpSelectionMerge {{%\w+}} None 4654;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 4655;CHECK: {{%\w+}} = OpLabel 4656;CHECK: {{%\w+}} = OpLoad %10 %s 4657;CHECK: {{%\w+}} = OpImageRead %v4float {{%\w+}} %17 4658;CHECK: OpBranch {{%\w+}} 4659;CHECK: {{%\w+}} = OpLabel 4660;CHECK: OpBranch {{%\w+}} 4661;CHECK: {{%\w+}} = OpLabel 4662;CHECK: [[phi_result:%\w+]] = OpPhi %v4float {{%\w+}} {{%\w+}} [[null_v4float]] {{%\w+}} 4663;CHECK: OpStore %x [[phi_result]] 4664OpReturn 4665OpFunctionEnd 4666)"; 4667 // clang-format on 4668 4669 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); 4670 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 4671 SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 23u); 4672} 4673 4674TEST_F(InstBindlessTest, ImageBufferOOBWrite) { 4675 // Texel buffer (imagebuffer) oob check for ImageWrite 4676 // 4677 // #version 450 4678 // layout(set=3, binding=7, r32f) uniform readonly imageBuffer s; 4679 // layout(location=11) out vec4 x; 4680 // layout(location=13) in flat int ii; 4681 // 4682 // void main(){ 4683 // imageStore(s, ii, x); 4684 // } 4685 4686 // clang-format off 4687 const std::string text = R"( 4688OpCapability Shader 4689OpCapability ImageBuffer 4690;CHECK: OpCapability Linkage 4691%1 = OpExtInstImport "GLSL.std.450" 4692OpMemoryModel Logical GLSL450 4693OpEntryPoint Fragment %main "main" %s %ii %x 4694;CHECK: OpEntryPoint Fragment %main "main" %s %ii %x %gl_FragCoord 4695OpExecutionMode %main OriginUpperLeft 4696OpSource GLSL 450 4697OpName %main "main" 4698OpName %s "s" 4699OpName %ii "ii" 4700OpName %x "x" 4701OpDecorate %s DescriptorSet 3 4702OpDecorate %s Binding 7 4703OpDecorate %s NonReadable 4704OpDecorate %ii Flat 4705OpDecorate %ii Location 13 4706OpDecorate %x Location 11 4707)" + kImportDeco + R"( 4708;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 4709%void = OpTypeVoid 4710%3 = OpTypeFunction %void 4711%float = OpTypeFloat 32 4712%7 = OpTypeImage %float Buffer 0 0 0 2 R32f 4713%_ptr_UniformConstant_7 = OpTypePointer UniformConstant %7 4714%s = OpVariable %_ptr_UniformConstant_7 UniformConstant 4715%int = OpTypeInt 32 1 4716%_ptr_Input_int = OpTypePointer Input %int 4717%ii = OpVariable %_ptr_Input_int Input 4718%v4float = OpTypeVector %float 4 4719%_ptr_Output_v4float = OpTypePointer Output %v4float 4720%x = OpVariable %_ptr_Output_v4float Output 4721;CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float 4722;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 4723)" + kImportStub + R"( 4724%main = OpFunction %void None %3 4725%5 = OpLabel 4726;CHECK: {{%\w+}} = OpLabel 4727;CHECK: OpBranch {{%\w+}} 4728;CHECK: %19 = OpLabel 4729%10 = OpLoad %7 %s 4730%14 = OpLoad %int %ii 4731%18 = OpLoad %v4float %x 4732OpImageWrite %10 %14 %18 4733;CHECK-NOT: OpImageWrite %10 %14 %18 4734;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 4735;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 4736;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 4737;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 4738;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 4739;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_35 {{%\w+}} %uint_3 %uint_7 %uint_0 {{%\w+}} 4740;CHECK: OpSelectionMerge {{%\w+}} None 4741;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 4742;CHECK: {{%\w+}} = OpLabel 4743;CHECK: {{%\w+}} = OpLoad %7 %s 4744;CHECK: OpImageWrite {{%\w+}} %14 %18 4745;CHECK: OpBranch {{%\w+}} 4746;CHECK: {{%\w+}} = OpLabel 4747;CHECK: OpBranch {{%\w+}} 4748;CHECK: {{%\w+}} = OpLabel 4749OpReturn 4750OpFunctionEnd 4751)"; 4752 // clang-format on 4753 4754 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); 4755 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 4756 SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 23u); 4757} 4758 4759TEST_F(InstBindlessTest, TextureBufferOOBFetch) { 4760 // Texel buffer (texturebuffer) oob check for ImageFetch 4761 // 4762 // #version 450 4763 // layout(set=3, binding=7) uniform textureBuffer s; 4764 // layout(location=11) out vec4 x; 4765 // layout(location=13) in flat int ii; 4766 // 4767 // void main(){ 4768 // x = texelFetch(s, ii); 4769 // } 4770 4771 // clang-format off 4772 const std::string text = R"( 4773OpCapability Shader 4774OpCapability SampledBuffer 4775;CHECK: OpCapability Linkage 4776%1 = OpExtInstImport "GLSL.std.450" 4777OpMemoryModel Logical GLSL450 4778OpEntryPoint Fragment %main "main" %x %s %ii 4779;CHECK: OpEntryPoint Fragment %main "main" %x %s %ii %gl_FragCoord 4780OpExecutionMode %main OriginUpperLeft 4781OpSource GLSL 450 4782OpName %main "main" 4783OpName %x "x" 4784OpName %s "s" 4785OpName %ii "ii" 4786OpDecorate %x Location 11 4787OpDecorate %s DescriptorSet 3 4788OpDecorate %s Binding 7 4789OpDecorate %ii Flat 4790OpDecorate %ii Location 13 4791;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 4792%void = OpTypeVoid 4793%3 = OpTypeFunction %void 4794%float = OpTypeFloat 32 4795%v4float = OpTypeVector %float 4 4796%_ptr_Output_v4float = OpTypePointer Output %v4float 4797%x = OpVariable %_ptr_Output_v4float Output 4798%10 = OpTypeImage %float Buffer 0 0 0 1 Unknown 4799%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10 4800%s = OpVariable %_ptr_UniformConstant_10 UniformConstant 4801%int = OpTypeInt 32 1 4802%_ptr_Input_int = OpTypePointer Input %int 4803%ii = OpVariable %_ptr_Input_int Input 4804;CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float 4805;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 4806;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 4807%main = OpFunction %void None %3 4808%5 = OpLabel 4809;CHECK: OpBranch %19 4810;CHECK: %19 = OpLabel 4811%13 = OpLoad %10 %s 4812%17 = OpLoad %int %ii 4813%18 = OpImageFetch %v4float %13 %17 4814OpStore %x %18 4815;CHECK-NOT: %18 = OpImageFetch %v4float %13 %17 4816;CHECK-NOT: OpStore %x %18 4817;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 4818;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 4819;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 4820;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 4821;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 4822;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_33 {{%\w+}} %uint_3 %uint_7 %uint_0 {{%\w+}} 4823;CHECK: OpSelectionMerge {{%\w+}} None 4824;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 4825;CHECK: {{%\w+}} = OpLabel 4826;CHECK: {{%\w+}} = OpLoad %10 %s 4827;CHECK: {{%\w+}} = OpImageFetch %v4float {{%\w+}} %17 4828;CHECK: OpBranch {{%\w+}} 4829;CHECK: {{%\w+}} = OpLabel 4830;CHECK: OpBranch {{%\w+}} 4831;CHECK: {{%\w+}} = OpLabel 4832;CHECK: [[phi_result:%\w+]] = OpPhi %v4float {{%\w+}} {{%\w+}} [[null_v4float]] {{%\w+}} 4833;CHECK: OpStore %x [[phi_result]] 4834OpReturn 4835OpFunctionEnd 4836)"; 4837 // clang-format on 4838 4839 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); 4840 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 4841 SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 23u); 4842} 4843 4844TEST_F(InstBindlessTest, SamplerBufferOOBFetch) { 4845 // Texel buffer (samplerbuffer) oob check for ImageFetch 4846 // 4847 // #version 450 4848 // layout(set=3, binding=7) uniform samplerBuffer s; 4849 // layout(location=11) out vec4 x; 4850 // layout(location=13) in flat int ii; 4851 // 4852 // void main(){ 4853 // x = texelFetch(s, ii); 4854 // } 4855 4856 // clang-format off 4857 const std::string text = R"( 4858OpCapability Shader 4859OpCapability SampledBuffer 4860;CHECK: OpCapability Linkage 4861%1 = OpExtInstImport "GLSL.std.450" 4862OpMemoryModel Logical GLSL450 4863OpEntryPoint Fragment %main "main" %x %s %ii 4864;CHECK: OpEntryPoint Fragment %main "main" %x %s %ii %gl_FragCoord 4865OpExecutionMode %main OriginUpperLeft 4866OpSource GLSL 450 4867OpName %main "main" 4868OpName %x "x" 4869OpName %s "s" 4870OpName %ii "ii" 4871OpDecorate %x Location 11 4872OpDecorate %s DescriptorSet 3 4873OpDecorate %s Binding 7 4874OpDecorate %ii Flat 4875OpDecorate %ii Location 13 4876)" + kImportDeco + R"( 4877;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 4878%void = OpTypeVoid 4879%3 = OpTypeFunction %void 4880%float = OpTypeFloat 32 4881%v4float = OpTypeVector %float 4 4882%_ptr_Output_v4float = OpTypePointer Output %v4float 4883%x = OpVariable %_ptr_Output_v4float Output 4884%10 = OpTypeImage %float Buffer 0 0 0 1 Unknown 4885%11 = OpTypeSampledImage %10 4886%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11 4887%s = OpVariable %_ptr_UniformConstant_11 UniformConstant 4888%int = OpTypeInt 32 1 4889%_ptr_Input_int = OpTypePointer Input %int 4890%ii = OpVariable %_ptr_Input_int Input 4891;CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float 4892;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 4893;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 4894)" + kImportStub + R"( 4895%main = OpFunction %void None %3 4896%5 = OpLabel 4897;CHECK: OpBranch %21 4898;CHECK: %21 = OpLabel 4899%14 = OpLoad %11 %s 4900%18 = OpLoad %int %ii 4901%19 = OpImage %10 %14 4902%20 = OpImageFetch %v4float %19 %18 4903OpStore %x %20 4904;CHECK-NOT: %20 = OpImageFetch %v4float %19 %18 4905;CHECK-NOT: OpStore %x %20 4906;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 4907;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 4908;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 4909;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 4910;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 4911;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_35 {{%\w+}} %uint_3 %uint_7 %uint_0 {{%\w+}} 4912;CHECK: OpSelectionMerge {{%\w+}} None 4913;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 4914;CHECK: {{%\w+}} = OpLabel 4915;CHECK: {{%\w+}} = OpLoad %11 %s 4916;CHECK: {{%\w+}} = OpImage %10 {{%\w+}} 4917;CHECK: {{%\w+}} = OpImageFetch %v4float {{%\w+}} {{%\w+}} 4918;CHECK: OpBranch {{%\w+}} 4919;CHECK: {{%\w+}} = OpLabel 4920;CHECK: OpBranch {{%\w+}} 4921;CHECK: {{%\w+}} = OpLabel 4922;CHECK: [[phi_result:%\w+]] = OpPhi %v4float {{%\w+}} {{%\w+}} [[null_v4float]] {{%\w+}} 4923;CHECK: OpStore %x [[phi_result]] 4924OpReturn 4925OpFunctionEnd 4926)"; 4927 // clang-format on 4928 4929 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); 4930 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 4931 SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 23u); 4932} 4933 4934TEST_F(InstBindlessTest, SamplerBufferConstructorOOBFetch) { 4935 // Texel buffer (samplerbuffer constructor) oob check for ImageFetch 4936 // 4937 // #version 450 4938 // layout(set=3, binding=7) uniform textureBuffer tBuf; 4939 // layout(set=3, binding=8) uniform sampler s; 4940 // layout(location=11) out vec4 x; 4941 // layout(location=13) in flat int ii; 4942 // 4943 // void main(){ 4944 // x = texelFetch(samplerBuffer(tBuf, s), ii); 4945 // } 4946 4947 // clang-format off 4948 const std::string text = R"( 4949OpCapability Shader 4950OpCapability SampledBuffer 4951;CHECK: OpCapability Linkage 4952%1 = OpExtInstImport "GLSL.std.450" 4953OpMemoryModel Logical GLSL450 4954OpEntryPoint Fragment %main "main" %x %tBuf %s %ii 4955;CHECK: OpEntryPoint Fragment %main "main" %x %tBuf %s %ii %gl_FragCoord 4956OpExecutionMode %main OriginUpperLeft 4957OpSource GLSL 450 4958OpName %main "main" 4959OpName %x "x" 4960OpName %tBuf "tBuf" 4961OpName %s "s" 4962OpName %ii "ii" 4963OpDecorate %x Location 11 4964OpDecorate %tBuf DescriptorSet 3 4965OpDecorate %tBuf Binding 7 4966OpDecorate %s DescriptorSet 3 4967OpDecorate %s Binding 8 4968OpDecorate %ii Flat 4969OpDecorate %ii Location 13 4970)" + kImportDeco + R"( 4971;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord 4972%void = OpTypeVoid 4973%3 = OpTypeFunction %void 4974%float = OpTypeFloat 32 4975%v4float = OpTypeVector %float 4 4976%_ptr_Output_v4float = OpTypePointer Output %v4float 4977%x = OpVariable %_ptr_Output_v4float Output 4978%10 = OpTypeImage %float Buffer 0 0 0 1 Unknown 4979%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10 4980%tBuf = OpVariable %_ptr_UniformConstant_10 UniformConstant 4981%14 = OpTypeSampler 4982%_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14 4983%s = OpVariable %_ptr_UniformConstant_14 UniformConstant 4984%18 = OpTypeSampledImage %10 4985%int = OpTypeInt 32 1 4986%_ptr_Input_int = OpTypePointer Input %int 4987%ii = OpVariable %_ptr_Input_int Input 4988;CHECK: %_ptr_Input_v4float = OpTypePointer Input %v4float 4989;CHECK: %gl_FragCoord = OpVariable %_ptr_Input_v4float Input 4990;CHECK: [[null_v4float:%\w+]] = OpConstantNull %v4float 4991%main = OpFunction %void None %3 4992%5 = OpLabel 4993%13 = OpLoad %10 %tBuf 4994%17 = OpLoad %14 %s 4995%19 = OpSampledImage %18 %13 %17 4996%23 = OpLoad %int %ii 4997%24 = OpImage %10 %19 4998%25 = OpImageFetch %v4float %24 %23 4999OpStore %x %25 5000;CHECK-NOT: %25 = OpImageFetch %v4float %24 %23 5001;CHECK-NOT: OpStore %x %25 5002;CHECK: {{%\w+}} = OpLoad %v4float %gl_FragCoord 5003;CHECK: {{%\w+}} = OpBitcast %v4uint {{%\w+}} 5004;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 5005;CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 1 5006;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_4 {{%\w+}} {{%\w+}} %uint_0 5007;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_43 {{%\w+}} %uint_3 %uint_7 %uint_0 {{%\w+}} 5008;CHECK: OpSelectionMerge {{%\w+}} None 5009;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 5010;CHECK: {{%\w+}} = OpLabel 5011;CHECK: {{%\w+}} = OpLoad %10 %tBuf 5012;CHECK: {{%\w+}} = OpSampledImage %18 {{%\w+}} %17 5013;CHECK: {{%\w+}} = OpImage %10 {{%\w+}} 5014;CHECK: {{%\w+}} = OpImageFetch %v4float {{%\w+}} %23 5015;CHECK: OpBranch {{%\w+}} 5016;CHECK: {{%\w+}} = OpLabel 5017;CHECK: OpBranch {{%\w+}} 5018;CHECK: {{%\w+}} = OpLabel 5019;CHECK: [[phi_result:%\w+]] = OpPhi %v4float {{%\w+}} {{%\w+}} [[null_v4float]] {{%\w+}} 5020;CHECK: OpStore %x [[phi_result]] 5021OpReturn 5022OpFunctionEnd 5023)"; 5024 // clang-format on 5025 5026 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); 5027 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 5028 SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 23u); 5029} 5030 5031TEST_F(InstBindlessTest, DeviceBufferAddressOOB) { 5032 // #version 450 5033 // #extension GL_EXT_buffer_reference : enable 5034 // layout(buffer_reference, buffer_reference_align = 16) buffer bufStruct; 5035 // layout(set = 0, binding = 0) uniform ufoo { 5036 // bufStruct data; 5037 // int nWrites; 5038 // } u_info; 5039 // layout(buffer_reference, std140) buffer bufStruct { 5040 // int a[4]; 5041 // }; 5042 // void main() { 5043 // for (int i=0; i < u_info.nWrites; ++i) { 5044 // u_info.data.a[i] = 0xdeadca71; 5045 // } 5046 // } 5047 5048 // clang-format off 5049 const std::string text = R"( 5050OpCapability Shader 5051OpCapability PhysicalStorageBufferAddresses 5052;CHECK: OpCapability Linkage 5053;CHECK: OpCapability Int64 5054OpExtension "SPV_KHR_physical_storage_buffer" 5055%1 = OpExtInstImport "GLSL.std.450" 5056OpMemoryModel PhysicalStorageBuffer64 GLSL450 5057OpEntryPoint Vertex %main "main" %u_info 5058;CHECK: OpEntryPoint Vertex %main "main" %u_info %gl_VertexIndex %gl_InstanceIndex 5059OpSource GLSL 450 5060OpSourceExtension "GL_EXT_buffer_reference" 5061OpName %main "main" 5062OpName %i "i" 5063OpName %ufoo "ufoo" 5064OpMemberName %ufoo 0 "data" 5065OpMemberName %ufoo 1 "nWrites" 5066OpName %bufStruct "bufStruct" 5067OpMemberName %bufStruct 0 "a" 5068OpName %u_info "u_info" 5069OpMemberDecorate %ufoo 0 Offset 0 5070OpMemberDecorate %ufoo 1 Offset 8 5071OpDecorate %ufoo Block 5072OpDecorate %_arr_int_uint_4 ArrayStride 16 5073OpMemberDecorate %bufStruct 0 Offset 0 5074OpDecorate %bufStruct Block 5075OpDecorate %u_info DescriptorSet 0 5076OpDecorate %u_info Binding 0 5077%void = OpTypeVoid 5078%3 = OpTypeFunction %void 5079%int = OpTypeInt 32 1 5080%_ptr_Function_int = OpTypePointer Function %int 5081%int_0 = OpConstant %int 0 5082OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_bufStruct PhysicalStorageBuffer 5083%ufoo = OpTypeStruct %_ptr_PhysicalStorageBuffer_bufStruct %int 5084%uint = OpTypeInt 32 0 5085%uint_4 = OpConstant %uint 4 5086%_arr_int_uint_4 = OpTypeArray %int %uint_4 5087%bufStruct = OpTypeStruct %_arr_int_uint_4 5088%_ptr_PhysicalStorageBuffer_bufStruct = OpTypePointer PhysicalStorageBuffer %bufStruct 5089%_ptr_Uniform_ufoo = OpTypePointer Uniform %ufoo 5090%u_info = OpVariable %_ptr_Uniform_ufoo Uniform 5091%int_1 = OpConstant %int 1 5092%_ptr_Uniform_int = OpTypePointer Uniform %int 5093%bool = OpTypeBool 5094%_ptr_Uniform__ptr_PhysicalStorageBuffer_bufStruct = OpTypePointer Uniform %_ptr_PhysicalStorageBuffer_bufStruct 5095%int_n559035791 = OpConstant %int -559035791 5096%_ptr_PhysicalStorageBuffer_int = OpTypePointer PhysicalStorageBuffer %int 5097)" + kImportStub + R"( 5098%main = OpFunction %void None %3 5099%5 = OpLabel 5100%i = OpVariable %_ptr_Function_int Function 5101OpStore %i %int_0 5102OpBranch %10 5103%10 = OpLabel 5104OpLoopMerge %12 %13 None 5105OpBranch %14 5106%14 = OpLabel 5107%15 = OpLoad %int %i 5108%26 = OpAccessChain %_ptr_Uniform_int %u_info %int_1 5109;CHECK: {{%\w+}} = OpIAdd %uint %uint_8 %uint_3 5110;CHECK: {{%\w+}} = OpLoad %uint %gl_VertexIndex 5111;CHECK: {{%\w+}} = OpLoad %uint %gl_InstanceIndex 5112;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_0 {{%\w+}} {{%\w+}} %uint_0 5113;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_56 {{%\w+}} %uint_0 %uint_0 %uint_0 {{%\w+}} 5114;CHECK: OpSelectionMerge {{%\w+}} None 5115;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 5116;CHECK: {{%\w+}} = OpLabel 5117;CHECK: [[load_result:%\w+]] = OpLoad %int %26 5118;CHECK: OpBranch {{%\w+}} 5119;CHECK: {{%\w+}} = OpLabel 5120;CHECK: OpBranch {{%\w+}} 5121;CHECK: {{%\w+}} = OpLabel 5122;CHECK: [[phi_result:%\w+]] = OpPhi %int [[load_result]] {{%\w+}} {{%\w+}} {{%\w+}} 5123%27 = OpLoad %int %26 5124%29 = OpSLessThan %bool %15 %27 5125;CHECK-NOT: %27 = OpLoad %int %26 5126;CHECK-NOT: %29 = OpSLessThan %bool %15 %27 5127;CHECK: %29 = OpSLessThan %bool %15 [[phi_result]] 5128OpBranchConditional %29 %11 %12 5129%11 = OpLabel 5130%31 = OpAccessChain %_ptr_Uniform__ptr_PhysicalStorageBuffer_bufStruct %u_info %int_0 5131%32 = OpLoad %_ptr_PhysicalStorageBuffer_bufStruct %31 5132;CHECK-NOT: %32 = OpLoad %_ptr_PhysicalStorageBuffer_bufStruct %31 5133;CHECK: {{%\w+}} = OpIAdd %uint %uint_0 %uint_7 5134;CHECK: {{%\w+}} = OpLoad %uint %gl_VertexIndex 5135;CHECK: {{%\w+}} = OpLoad %uint %gl_InstanceIndex 5136;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_0 {{%\w+}} {{%\w+}} %uint_0 5137;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_61 {{%\w+}} %uint_0 %uint_0 %uint_0 {{%\w+}} 5138;CHECK: OpSelectionMerge {{%\w+}} None 5139;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 5140;CHECK: {{%\w+}} = OpLabel 5141;CHECK: [[load_result_2:%\w+]] = OpLoad %_ptr_PhysicalStorageBuffer_bufStruct %31 5142;CHECK: OpBranch {{%\w+}} 5143;CHECK: {{%\w+}} = OpLabel 5144;CHECK: {{%\w+}} = OpConvertUToPtr %_ptr_PhysicalStorageBuffer_bufStruct {{%\w+}} 5145;CHECK: OpBranch {{%\w+}} 5146;CHECK: {{%\w+}} = OpLabel 5147;CHECK: [[phi_result_2:%\w+]] = OpPhi %_ptr_PhysicalStorageBuffer_bufStruct [[load_result_2]] {{%\w+}} {{%\w+}} {{%\w+}} 5148%33 = OpLoad %int %i 5149%36 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %32 %int_0 %33 5150;CHECK-NOT: %36 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %32 %int_0 %33 5151;CHECK: %36 = OpAccessChain %_ptr_PhysicalStorageBuffer_int [[phi_result_2]] %int_0 %33 5152OpStore %36 %int_n559035791 Aligned 16 5153OpBranch %13 5154%13 = OpLabel 5155%37 = OpLoad %int %i 5156%38 = OpIAdd %int %37 %int_1 5157OpStore %i %38 5158OpBranch %10 5159%12 = OpLabel 5160OpReturn 5161OpFunctionEnd)"; 5162 // clang-format on 5163 5164 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); 5165 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 5166 SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 23u); 5167} 5168 5169TEST_F(InstBindlessTest, VertexIndexOOB) { 5170 // #version 450 5171 // layout(std140, binding = 0) uniform foo { uint tex_index[1]; } 5172 // uniform_index_buffer; layout(location = 0) out flat uint index; vec2 5173 // vertices[3]; void main() { 5174 // vertices[0] = vec2(-1.0, -1.0); 5175 // vertices[1] = vec2( 1.0, -1.0); 5176 // vertices[2] = vec2( 0.0, 1.0); 5177 // gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0); 5178 // index = uniform_index_buffer.tex_index[0]; 5179 // } 5180 // clang-format off 5181 const std::string text = R"( 5182OpCapability Shader 5183%1 = OpExtInstImport "GLSL.std.450" 5184OpMemoryModel Logical GLSL450 5185OpEntryPoint Vertex %main "main" %vertices %_ %gl_VertexIndex %index %uniform_index_buffer 5186OpSource GLSL 450 5187OpName %main "main" 5188OpName %vertices "vertices" 5189OpName %gl_PerVertex "gl_PerVertex" 5190OpMemberName %gl_PerVertex 0 "gl_Position" 5191OpMemberName %gl_PerVertex 1 "gl_PointSize" 5192OpMemberName %gl_PerVertex 2 "gl_ClipDistance" 5193OpMemberName %gl_PerVertex 3 "gl_CullDistance" 5194OpName %_ "" 5195OpName %gl_VertexIndex "gl_VertexIndex" 5196OpName %index "index" 5197OpName %foo "foo" 5198OpMemberName %foo 0 "tex_index" 5199OpName %uniform_index_buffer "uniform_index_buffer" 5200OpMemberDecorate %gl_PerVertex 0 BuiltIn Position 5201OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize 5202OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance 5203OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance 5204OpDecorate %gl_PerVertex Block 5205OpDecorate %gl_VertexIndex BuiltIn VertexIndex 5206OpDecorate %index Flat 5207OpDecorate %index Location 0 5208OpDecorate %_arr_uint_uint_1 ArrayStride 16 5209OpMemberDecorate %foo 0 Offset 0 5210OpDecorate %foo Block 5211OpDecorate %uniform_index_buffer DescriptorSet 0 5212OpDecorate %uniform_index_buffer Binding 0 5213%void = OpTypeVoid 5214%3 = OpTypeFunction %void 5215%float = OpTypeFloat 32 5216%v2float = OpTypeVector %float 2 5217%uint = OpTypeInt 32 0 5218%uint_3 = OpConstant %uint 3 5219%_arr_v2float_uint_3 = OpTypeArray %v2float %uint_3 5220%_ptr_Private__arr_v2float_uint_3 = OpTypePointer Private %_arr_v2float_uint_3 5221%vertices = OpVariable %_ptr_Private__arr_v2float_uint_3 Private 5222%int = OpTypeInt 32 1 5223%int_0 = OpConstant %int 0 5224%float_n1 = OpConstant %float -1 5225%16 = OpConstantComposite %v2float %float_n1 %float_n1 5226%_ptr_Private_v2float = OpTypePointer Private %v2float 5227%int_1 = OpConstant %int 1 5228%float_1 = OpConstant %float 1 5229%21 = OpConstantComposite %v2float %float_1 %float_n1 5230%int_2 = OpConstant %int 2 5231%float_0 = OpConstant %float 0 5232%25 = OpConstantComposite %v2float %float_0 %float_1 5233%v4float = OpTypeVector %float 4 5234%uint_1 = OpConstant %uint 1 5235%_arr_float_uint_1 = OpTypeArray %float %uint_1 5236%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1 5237%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex 5238%_ = OpVariable %_ptr_Output_gl_PerVertex Output 5239%_ptr_Input_int = OpTypePointer Input %int 5240%gl_VertexIndex = OpVariable %_ptr_Input_int Input 5241%int_3 = OpConstant %int 3 5242%_ptr_Output_v4float = OpTypePointer Output %v4float 5243%_ptr_Output_uint = OpTypePointer Output %uint 5244%index = OpVariable %_ptr_Output_uint Output 5245%_arr_uint_uint_1 = OpTypeArray %uint %uint_1 5246%foo = OpTypeStruct %_arr_uint_uint_1 5247%_ptr_Uniform_foo = OpTypePointer Uniform %foo 5248%uniform_index_buffer = OpVariable %_ptr_Uniform_foo Uniform 5249%_ptr_Uniform_uint = OpTypePointer Uniform %uint 5250)" + kImportStub + R"( 5251%main = OpFunction %void None %3 5252%5 = OpLabel 5253%18 = OpAccessChain %_ptr_Private_v2float %vertices %int_0 5254OpStore %18 %16 5255%22 = OpAccessChain %_ptr_Private_v2float %vertices %int_1 5256OpStore %22 %21 5257%26 = OpAccessChain %_ptr_Private_v2float %vertices %int_2 5258OpStore %26 %25 5259%35 = OpLoad %int %gl_VertexIndex 5260%37 = OpSMod %int %35 %int_3 5261%38 = OpAccessChain %_ptr_Private_v2float %vertices %37 5262%39 = OpLoad %v2float %38 5263%40 = OpCompositeExtract %float %39 0 5264%41 = OpCompositeExtract %float %39 1 5265%42 = OpCompositeConstruct %v4float %40 %41 %float_0 %float_1 5266%44 = OpAccessChain %_ptr_Output_v4float %_ %int_0 5267OpStore %44 %42 5268%52 = OpAccessChain %_ptr_Uniform_uint %uniform_index_buffer %int_0 %int_0 5269%53 = OpLoad %uint %52 5270;CHECK-NOT: %53 = OpLoad %uint %52 5271;CHECK: {{%\w+}} = OpIMul %uint %uint_16 %int_0 5272;CHECK: {{%\w+}} = OpIAdd %uint %uint_0 {{%\w+}} 5273;CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} %uint_3 5274;CHECK: {{%\w+}} = OpLoad %int %gl_VertexIndex 5275;CHECK: {{%\w+}} = OpBitcast %uint {{%\w+}} 5276;CHECK: {{%\w+}} = OpLoad %uint %gl_InstanceIndex 5277;CHECK: {{%\w+}} = OpCompositeConstruct %v4uint %uint_0 {{%\w+}} {{%\w+}} %uint_0 5278;CHECK: {{%\w+}} = OpFunctionCall %bool %)" + kFuncName + R"( %uint_23 %uint_87 {{%\w+}} %uint_0 %uint_0 %uint_0 {{%\w+}} 5279;CHECK: OpSelectionMerge {{%\w+}} None 5280;CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} 5281;CHECK: {{%\w+}} = OpLabel 5282;CHECK: {{%\w+}} = OpLoad %uint %52 5283;CHECK: OpBranch {{%\w+}} 5284;CHECK: {{%\w+}} = OpLabel 5285;CHECK: OpBranch {{%\w+}} 5286;CHECK: {{%\w+}} = OpLabel 5287;CHECK: [[phi_result:%\w+]] = OpPhi %uint {{%\w+}} {{%\w+}} {{%\w+}} {{%\w+}} 5288;CHECK: OpStore %index [[phi_result]] 5289OpStore %index %53 5290;CHECK-NOT: OpStore %index %53 5291OpReturn 5292;CHECK: OpReturn 5293OpFunctionEnd)"; 5294 // clang-format on 5295 5296 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); 5297 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 5298 SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 23u); 5299} 5300 5301// TODO(greg-lunarg): Add tests to verify handling of these cases: 5302// 5303// Compute shader 5304// Geometry shader 5305// Tessellation control shader 5306// Tessellation eval shader 5307// OpImage 5308// SampledImage variable 5309 5310} // namespace 5311} // namespace opt 5312} // namespace spvtools 5313