Update type for loaded builtin GlobalInvocationID in pass instrumentation (#2705)

When working on descriptor indexing validation for compute shaders, the
gl_GlobalInvocationID builtin was being loaded as uint which would cause
compute shaders instrumented by the bindless check pass to have:

%83 = OpLoad %uint %gl_GlobalInvocationID
%84 = OpCompositeExtract %uint %83 0
%85 = OpCompositeExtract %uint %83 1
%86 = OpCompositeExtract %uint %83 2

which results in validation failures:

error: line 127: Reached non-composite type while indexes still remain
to be traversed.
%84 = OpCompositeExtract %uint %83 0

for trying to extract a uint from a uint.
This commit is contained in:
Jason Macnak 2019-06-28 06:46:16 -07:00 committed by Steven Perron
parent 6ccb52b864
commit e6e3e2ccc6
2 changed files with 330 additions and 2 deletions

View File

@ -678,12 +678,18 @@ uint32_t IRContext::GetBuiltinInputVarId(uint32_t builtin) {
case SpvBuiltInVertexIndex:
case SpvBuiltInInstanceIndex:
case SpvBuiltInPrimitiveId:
case SpvBuiltInInvocationId:
case SpvBuiltInGlobalInvocationId: {
case SpvBuiltInInvocationId: {
analysis::Integer uint_ty(32, false);
reg_type = type_mgr->GetRegisteredType(&uint_ty);
break;
}
case SpvBuiltInGlobalInvocationId: {
analysis::Integer uint_ty(32, false);
analysis::Type* reg_uint_ty = type_mgr->GetRegisteredType(&uint_ty);
analysis::Vector v3uint_ty(reg_uint_ty, 3);
reg_type = type_mgr->GetRegisteredType(&v3uint_ty);
break;
}
default: {
assert(false && "unhandled builtin");
return 0;

View File

@ -8276,6 +8276,328 @@ OpFunctionEnd
true, 7u, 23u, true, true, 2u);
}
TEST_F(InstBindlessTest,
InstBoundsComputeShaderInitLoadVariableSizedSampledImagesArray) {
// #version 450
// #extension GL_EXT_nonuniform_qualifier : enable
//
// layout (local_size_x = 1, local_size_y = 1) in;
//
// layout(set = 0, binding = 0, std140) buffer Input {
// uint index;
// float red;
// } sbo;
//
// layout(set = 0, binding = 1, rgba32f) readonly uniform image2D images[];
//
// void main()
// {
// sbo.red = imageLoad(images[sbo.index], ivec2(0, 0)).r;
// }
const std::string defs_before =
R"(OpCapability Shader
OpCapability RuntimeDescriptorArrayEXT
OpExtension "SPV_EXT_descriptor_indexing"
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
OpSource GLSL 450
OpSourceExtension "GL_EXT_nonuniform_qualifier"
OpName %main "main"
OpName %Input "Input"
OpMemberName %Input 0 "index"
OpMemberName %Input 1 "red"
OpName %sbo "sbo"
OpName %images "images"
OpMemberDecorate %Input 0 Offset 0
OpMemberDecorate %Input 1 Offset 4
OpDecorate %Input BufferBlock
OpDecorate %sbo DescriptorSet 0
OpDecorate %sbo Binding 0
OpDecorate %images DescriptorSet 0
OpDecorate %images Binding 1
OpDecorate %images NonWritable
%void = OpTypeVoid
%3 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%float = OpTypeFloat 32
%Input = OpTypeStruct %uint %float
%_ptr_Uniform_Input = OpTypePointer Uniform %Input
%sbo = OpVariable %_ptr_Uniform_Input Uniform
%int = OpTypeInt 32 1
%int_1 = OpConstant %int 1
%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
%_runtimearr_13 = OpTypeRuntimeArray %13
%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
%int_0 = OpConstant %int 0
%_ptr_Uniform_uint = OpTypePointer Uniform %uint
%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
%v2int = OpTypeVector %int 2
%25 = OpConstantComposite %v2int %int_0 %int_0
%v4float = OpTypeVector %float 4
%uint_0 = OpConstant %uint 0
%_ptr_Uniform_float = OpTypePointer Uniform %float
)";
const std::string defs_after =
R"(OpCapability Shader
OpCapability RuntimeDescriptorArrayEXT
OpExtension "SPV_EXT_descriptor_indexing"
OpExtension "SPV_KHR_storage_buffer_storage_class"
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID
OpExecutionMode %main LocalSize 1 1 1
OpSource GLSL 450
OpSourceExtension "GL_EXT_nonuniform_qualifier"
OpName %main "main"
OpName %Input "Input"
OpMemberName %Input 0 "index"
OpMemberName %Input 1 "red"
OpName %sbo "sbo"
OpName %images "images"
OpMemberDecorate %Input 0 Offset 0
OpMemberDecorate %Input 1 Offset 4
OpDecorate %Input BufferBlock
OpDecorate %sbo DescriptorSet 0
OpDecorate %sbo Binding 0
OpDecorate %images DescriptorSet 0
OpDecorate %images Binding 1
OpDecorate %images NonWritable
OpDecorate %_runtimearr_uint ArrayStride 4
OpDecorate %_struct_39 Block
OpMemberDecorate %_struct_39 0 Offset 0
OpDecorate %41 DescriptorSet 7
OpDecorate %41 Binding 1
OpDecorate %_struct_63 Block
OpMemberDecorate %_struct_63 0 Offset 0
OpMemberDecorate %_struct_63 1 Offset 4
OpDecorate %65 DescriptorSet 7
OpDecorate %65 Binding 0
OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
%void = OpTypeVoid
%7 = OpTypeFunction %void
%uint = OpTypeInt 32 0
%float = OpTypeFloat 32
%Input = OpTypeStruct %uint %float
%_ptr_Uniform_Input = OpTypePointer Uniform %Input
%sbo = OpVariable %_ptr_Uniform_Input Uniform
%int = OpTypeInt 32 1
%int_1 = OpConstant %int 1
%13 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
%_runtimearr_13 = OpTypeRuntimeArray %13
%_ptr_UniformConstant__runtimearr_13 = OpTypePointer UniformConstant %_runtimearr_13
%images = OpVariable %_ptr_UniformConstant__runtimearr_13 UniformConstant
%int_0 = OpConstant %int 0
%_ptr_Uniform_uint = OpTypePointer Uniform %uint
%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
%v2int = OpTypeVector %int 2
%20 = OpConstantComposite %v2int %int_0 %int_0
%v4float = OpTypeVector %float 4
%uint_0 = OpConstant %uint 0
%_ptr_Uniform_float = OpTypePointer Uniform %float
%uint_1 = OpConstant %uint 1
%34 = OpTypeFunction %uint %uint %uint
%_runtimearr_uint = OpTypeRuntimeArray %uint
%_struct_39 = OpTypeStruct %_runtimearr_uint
%_ptr_StorageBuffer__struct_39 = OpTypePointer StorageBuffer %_struct_39
%41 = OpVariable %_ptr_StorageBuffer__struct_39 StorageBuffer
%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
%bool = OpTypeBool
%57 = OpTypeFunction %void %uint %uint %uint %uint
%_struct_63 = OpTypeStruct %uint %_runtimearr_uint
%_ptr_StorageBuffer__struct_63 = OpTypePointer StorageBuffer %_struct_63
%65 = OpVariable %_ptr_StorageBuffer__struct_63 StorageBuffer
%uint_10 = OpConstant %uint 10
%uint_4 = OpConstant %uint 4
%uint_23 = OpConstant %uint 23
%uint_2 = OpConstant %uint 2
%uint_5 = OpConstant %uint 5
%uint_3 = OpConstant %uint 3
%v3uint = OpTypeVector %uint 3
%_ptr_Input_v3uint = OpTypePointer Input %v3uint
%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
%uint_6 = OpConstant %uint 6
%uint_7 = OpConstant %uint 7
%uint_8 = OpConstant %uint 8
%uint_9 = OpConstant %uint 9
%uint_50 = OpConstant %uint 50
%112 = OpConstantNull %v4float
%115 = OpTypeFunction %uint %uint %uint %uint %uint
%uint_47 = OpConstant %uint 47
%140 = OpConstantNull %uint
%uint_53 = OpConstant %uint 53
)";
const std::string func_before =
R"(%main = OpFunction %void None %3
%5 = OpLabel
%19 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
%20 = OpLoad %uint %19
%22 = OpAccessChain %_ptr_UniformConstant_13 %images %20
%23 = OpLoad %13 %22
%27 = OpImageRead %v4float %23 %25
%29 = OpCompositeExtract %float %27 0
%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
OpStore %31 %29
OpReturn
OpFunctionEnd
)";
const std::string func_after =
R"(%main = OpFunction %void None %7
%24 = OpLabel
%25 = OpAccessChain %_ptr_Uniform_uint %sbo %int_0
%132 = OpFunctionCall %uint %114 %uint_0 %uint_0 %uint_0 %uint_0
%133 = OpINotEqual %bool %132 %uint_0
OpSelectionMerge %134 None
OpBranchConditional %133 %135 %136
%135 = OpLabel
%137 = OpLoad %uint %25
OpBranch %134
%136 = OpLabel
%139 = OpFunctionCall %void %56 %uint_47 %uint_1 %uint_0 %uint_0
OpBranch %134
%134 = OpLabel
%141 = OpPhi %uint %137 %135 %140 %136
%27 = OpAccessChain %_ptr_UniformConstant_13 %images %141
%28 = OpLoad %13 %27
%48 = OpFunctionCall %uint %33 %uint_1 %uint_1
%50 = OpULessThan %bool %141 %48
OpSelectionMerge %51 None
OpBranchConditional %50 %52 %53
%52 = OpLabel
%54 = OpLoad %13 %27
%142 = OpFunctionCall %uint %114 %uint_0 %uint_0 %uint_1 %141
%143 = OpINotEqual %bool %142 %uint_0
OpSelectionMerge %144 None
OpBranchConditional %143 %145 %146
%145 = OpLabel
%147 = OpLoad %13 %27
%148 = OpImageRead %v4float %147 %20
OpBranch %144
%146 = OpLabel
%149 = OpFunctionCall %void %56 %uint_50 %uint_1 %141 %uint_0
OpBranch %144
%144 = OpLabel
%150 = OpPhi %v4float %148 %145 %112 %146
OpBranch %51
%53 = OpLabel
%111 = OpFunctionCall %void %56 %uint_50 %uint_0 %141 %48
OpBranch %51
%51 = OpLabel
%113 = OpPhi %v4float %150 %144 %112 %53
%30 = OpCompositeExtract %float %113 0
%31 = OpAccessChain %_ptr_Uniform_float %sbo %int_1
%151 = OpFunctionCall %uint %114 %uint_0 %uint_0 %uint_0 %uint_0
%152 = OpINotEqual %bool %151 %uint_0
OpSelectionMerge %153 None
OpBranchConditional %152 %154 %155
%154 = OpLabel
OpStore %31 %30
OpBranch %153
%155 = OpLabel
%157 = OpFunctionCall %void %56 %uint_53 %uint_1 %uint_0 %uint_0
OpBranch %153
%153 = OpLabel
OpReturn
OpFunctionEnd
)";
const std::string new_funcs =
R"(%33 = OpFunction %uint None %34
%35 = OpFunctionParameter %uint
%36 = OpFunctionParameter %uint
%37 = OpLabel
%43 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %35
%44 = OpLoad %uint %43
%45 = OpIAdd %uint %44 %36
%46 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %45
%47 = OpLoad %uint %46
OpReturnValue %47
OpFunctionEnd
%56 = OpFunction %void None %57
%58 = OpFunctionParameter %uint
%59 = OpFunctionParameter %uint
%60 = OpFunctionParameter %uint
%61 = OpFunctionParameter %uint
%62 = OpLabel
%66 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_0
%69 = OpAtomicIAdd %uint %66 %uint_4 %uint_0 %uint_10
%70 = OpIAdd %uint %69 %uint_10
%71 = OpArrayLength %uint %65 1
%72 = OpULessThanEqual %bool %70 %71
OpSelectionMerge %73 None
OpBranchConditional %72 %74 %73
%74 = OpLabel
%75 = OpIAdd %uint %69 %uint_0
%76 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %75
OpStore %76 %uint_10
%78 = OpIAdd %uint %69 %uint_1
%79 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %78
OpStore %79 %uint_23
%81 = OpIAdd %uint %69 %uint_2
%82 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %81
OpStore %82 %58
%85 = OpIAdd %uint %69 %uint_3
%86 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %85
OpStore %86 %uint_5
%90 = OpLoad %v3uint %gl_GlobalInvocationID
%91 = OpCompositeExtract %uint %90 0
%92 = OpCompositeExtract %uint %90 1
%93 = OpCompositeExtract %uint %90 2
%94 = OpIAdd %uint %69 %uint_4
%95 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %94
OpStore %95 %91
%96 = OpIAdd %uint %69 %uint_5
%97 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %96
OpStore %97 %92
%99 = OpIAdd %uint %69 %uint_6
%100 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %99
OpStore %100 %93
%102 = OpIAdd %uint %69 %uint_7
%103 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %102
OpStore %103 %59
%105 = OpIAdd %uint %69 %uint_8
%106 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %105
OpStore %106 %60
%108 = OpIAdd %uint %69 %uint_9
%109 = OpAccessChain %_ptr_StorageBuffer_uint %65 %uint_1 %108
OpStore %109 %61
OpBranch %73
%73 = OpLabel
OpReturn
OpFunctionEnd
%114 = OpFunction %uint None %115
%116 = OpFunctionParameter %uint
%117 = OpFunctionParameter %uint
%118 = OpFunctionParameter %uint
%119 = OpFunctionParameter %uint
%120 = OpLabel
%121 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %116
%122 = OpLoad %uint %121
%123 = OpIAdd %uint %122 %117
%124 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %123
%125 = OpLoad %uint %124
%126 = OpIAdd %uint %125 %118
%127 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %126
%128 = OpLoad %uint %127
%129 = OpIAdd %uint %128 %119
%130 = OpAccessChain %_ptr_StorageBuffer_uint %41 %uint_0 %129
%131 = OpLoad %uint %130
OpReturnValue %131
OpFunctionEnd
)";
// SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
SinglePassRunAndCheck<InstBindlessCheckPass>(
defs_before + func_before, defs_after + func_after + new_funcs, true,
true, 7u, 23u, true, true, 2u);
}
// TODO(greg-lunarg): Add tests to verify handling of these cases:
//
// Compute shader