Fix bounds check instrumentation to handle 16-bit values (#3983)
This commit is contained in:
Родитель
abe2eff36f
Коммит
34ae8a4757
|
@ -349,8 +349,9 @@ uint32_t InstBindlessCheckPass::GenLastByteIdx(ref_analysis* ref,
|
|||
: SpvDecorationArrayStride;
|
||||
uint32_t arr_stride = FindStride(curr_ty_id, stride_deco);
|
||||
uint32_t arr_stride_id = builder->GetUintConstantId(arr_stride);
|
||||
uint32_t curr_idx_32b_id = Gen32BitCvtCode(curr_idx_id, builder);
|
||||
Instruction* curr_offset_inst = builder->AddBinaryOp(
|
||||
GetUintId(), SpvOpIMul, arr_stride_id, curr_idx_id);
|
||||
GetUintId(), SpvOpIMul, arr_stride_id, curr_idx_32b_id);
|
||||
curr_offset_id = curr_offset_inst->result_id();
|
||||
// Get element type for next step
|
||||
curr_ty_id = curr_ty_inst->GetSingleWordInOperand(0);
|
||||
|
@ -360,8 +361,9 @@ uint32_t InstBindlessCheckPass::GenLastByteIdx(ref_analysis* ref,
|
|||
uint32_t comp_ty_id = curr_ty_inst->GetSingleWordInOperand(0u);
|
||||
uint32_t vec_stride = ByteSize(comp_ty_id);
|
||||
uint32_t vec_stride_id = builder->GetUintConstantId(vec_stride);
|
||||
uint32_t curr_idx_32b_id = Gen32BitCvtCode(curr_idx_id, builder);
|
||||
Instruction* curr_offset_inst = builder->AddBinaryOp(
|
||||
GetUintId(), SpvOpIMul, vec_stride_id, curr_idx_id);
|
||||
GetUintId(), SpvOpIMul, vec_stride_id, curr_idx_32b_id);
|
||||
curr_offset_id = curr_offset_inst->result_id();
|
||||
// Get element type for next step
|
||||
curr_ty_id = comp_ty_id;
|
||||
|
@ -434,18 +436,27 @@ void InstBindlessCheckPass::GenCheckCode(
|
|||
new_blk_ptr.reset(new BasicBlock(std::move(invalid_label)));
|
||||
builder.SetInsertPoint(&*new_blk_ptr);
|
||||
uint32_t u_index_id = GenUintCastCode(ref->desc_idx_id, &builder);
|
||||
if (offset_id != 0)
|
||||
if (offset_id != 0) {
|
||||
// Buffer OOB
|
||||
uint32_t u_offset_id = GenUintCastCode(offset_id, &builder);
|
||||
uint32_t u_length_id = GenUintCastCode(length_id, &builder);
|
||||
GenDebugStreamWrite(uid2offset_[ref->ref_inst->unique_id()], stage_idx,
|
||||
{error_id, u_index_id, offset_id, length_id}, &builder);
|
||||
else if (buffer_bounds_enabled_)
|
||||
// So all error modes will use same debug stream write function
|
||||
{error_id, u_index_id, u_offset_id, u_length_id},
|
||||
&builder);
|
||||
} else if (buffer_bounds_enabled_) {
|
||||
// Uninitialized Descriptor - Return additional unused zero so all error
|
||||
// modes will use same debug stream write function
|
||||
uint32_t u_length_id = GenUintCastCode(length_id, &builder);
|
||||
GenDebugStreamWrite(
|
||||
uid2offset_[ref->ref_inst->unique_id()], stage_idx,
|
||||
{error_id, u_index_id, length_id, builder.GetUintConstantId(0)},
|
||||
{error_id, u_index_id, u_length_id, builder.GetUintConstantId(0)},
|
||||
&builder);
|
||||
else
|
||||
} else {
|
||||
// Uninitialized Descriptor - Normal error return
|
||||
uint32_t u_length_id = GenUintCastCode(length_id, &builder);
|
||||
GenDebugStreamWrite(uid2offset_[ref->ref_inst->unique_id()], stage_idx,
|
||||
{error_id, u_index_id, length_id}, &builder);
|
||||
{error_id, u_index_id, u_length_id}, &builder);
|
||||
}
|
||||
// Remember last invalid block id
|
||||
uint32_t last_invalid_blk_id = new_blk_ptr->GetLabelInst()->result_id();
|
||||
// Gen zero for invalid reference
|
||||
|
@ -516,8 +527,11 @@ void InstBindlessCheckPass::GenDescIdxCheckCode(
|
|||
// Generate full runtime bounds test code with true branch
|
||||
// being full reference and false branch being debug output and zero
|
||||
// for the referenced value.
|
||||
uint32_t desc_idx_32b_id = Gen32BitCvtCode(ref.desc_idx_id, &builder);
|
||||
uint32_t length_32b_id = Gen32BitCvtCode(length_id, &builder);
|
||||
Instruction* ult_inst = builder.AddBinaryOp(GetBoolId(), SpvOpULessThan,
|
||||
ref.desc_idx_id, length_id);
|
||||
desc_idx_32b_id, length_32b_id);
|
||||
ref.desc_idx_id = desc_idx_32b_id;
|
||||
GenCheckCode(ult_inst->result_id(), error_id, 0u, length_id, stage_idx, &ref,
|
||||
new_blocks);
|
||||
// Move original block's remaining code into remainder/merge block and add
|
||||
|
|
|
@ -88,12 +88,36 @@ std::unique_ptr<Instruction> InstrumentPass::NewLabel(uint32_t label_id) {
|
|||
return newLabel;
|
||||
}
|
||||
|
||||
uint32_t InstrumentPass::Gen32BitCvtCode(uint32_t val_id,
|
||||
InstructionBuilder* builder) {
|
||||
// Convert integer value to 32-bit if necessary
|
||||
analysis::TypeManager* type_mgr = context()->get_type_mgr();
|
||||
uint32_t val_ty_id = get_def_use_mgr()->GetDef(val_id)->type_id();
|
||||
analysis::Integer* val_ty = type_mgr->GetType(val_ty_id)->AsInteger();
|
||||
if (val_ty->width() == 32) return val_id;
|
||||
bool is_signed = val_ty->IsSigned();
|
||||
analysis::Integer val_32b_ty(32, is_signed);
|
||||
analysis::Type* val_32b_reg_ty = type_mgr->GetRegisteredType(&val_32b_ty);
|
||||
uint32_t val_32b_reg_ty_id = type_mgr->GetId(val_32b_reg_ty);
|
||||
if (is_signed)
|
||||
return builder->AddUnaryOp(val_32b_reg_ty_id, SpvOpSConvert, val_id)
|
||||
->result_id();
|
||||
else
|
||||
return builder->AddUnaryOp(val_32b_reg_ty_id, SpvOpUConvert, val_id)
|
||||
->result_id();
|
||||
}
|
||||
|
||||
uint32_t InstrumentPass::GenUintCastCode(uint32_t val_id,
|
||||
InstructionBuilder* builder) {
|
||||
// Cast value to 32-bit unsigned if necessary
|
||||
if (get_def_use_mgr()->GetDef(val_id)->type_id() == GetUintId())
|
||||
return val_id;
|
||||
return builder->AddUnaryOp(GetUintId(), SpvOpBitcast, val_id)->result_id();
|
||||
// Convert value to 32-bit if necessary
|
||||
uint32_t val_32b_id = Gen32BitCvtCode(val_id, builder);
|
||||
// Cast value to unsigned if necessary
|
||||
analysis::TypeManager* type_mgr = context()->get_type_mgr();
|
||||
uint32_t val_ty_id = get_def_use_mgr()->GetDef(val_32b_id)->type_id();
|
||||
analysis::Integer* val_ty = type_mgr->GetType(val_ty_id)->AsInteger();
|
||||
if (!val_ty->IsSigned()) return val_32b_id;
|
||||
return builder->AddUnaryOp(GetUintId(), SpvOpBitcast, val_32b_id)
|
||||
->result_id();
|
||||
}
|
||||
|
||||
void InstrumentPass::GenDebugOutputFieldCode(uint32_t base_offset_id,
|
||||
|
|
|
@ -213,8 +213,12 @@ class InstrumentPass : public Pass {
|
|||
uint32_t GenDebugDirectRead(const std::vector<uint32_t>& offset_ids,
|
||||
InstructionBuilder* builder);
|
||||
|
||||
// Generate code to cast |value_id| to unsigned, if needed. Return
|
||||
// an id to the unsigned equivalent.
|
||||
// Generate code to convert integer |value_id| to 32bit, if needed. Return
|
||||
// an id to the 32bit equivalent.
|
||||
uint32_t Gen32BitCvtCode(uint32_t value_id, InstructionBuilder* builder);
|
||||
|
||||
// Generate code to cast integer |value_id| to 32bit unsigned, if needed.
|
||||
// Return an id to the Uint equivalent.
|
||||
uint32_t GenUintCastCode(uint32_t value_id, InstructionBuilder* builder);
|
||||
|
||||
// Return new label.
|
||||
|
|
|
@ -7977,6 +7977,499 @@ TEST_F(InstBindlessTest, UniformArrayRefWithDescInit) {
|
|||
true);
|
||||
}
|
||||
|
||||
TEST_F(InstBindlessTest, Descriptor16BitIdxRef) {
|
||||
// Check that descriptor indexed with 16bit index is inbounds and
|
||||
// initialized
|
||||
//
|
||||
// Use Simple source with min16uint g_nDataIdx
|
||||
|
||||
const std::string text = R"(
|
||||
OpCapability Shader
|
||||
OpCapability Int16
|
||||
OpCapability StoragePushConstant16
|
||||
;CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %_ %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor
|
||||
;CHECK: OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %_ %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor %60 %gl_FragCoord %119
|
||||
OpExecutionMode %MainPs OriginUpperLeft
|
||||
OpSource HLSL 500
|
||||
OpName %MainPs "MainPs"
|
||||
OpName %g_tColor "g_tColor"
|
||||
OpName %PerViewConstantBuffer_t "PerViewConstantBuffer_t"
|
||||
OpMemberName %PerViewConstantBuffer_t 0 "g_nDataIdx"
|
||||
OpName %_ ""
|
||||
OpName %g_sAniso "g_sAniso"
|
||||
OpName %i_vTextureCoords "i.vTextureCoords"
|
||||
OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
|
||||
OpDecorate %g_tColor DescriptorSet 0
|
||||
OpDecorate %g_tColor Binding 0
|
||||
OpMemberDecorate %PerViewConstantBuffer_t 0 Offset 0
|
||||
OpDecorate %PerViewConstantBuffer_t Block
|
||||
OpDecorate %g_sAniso DescriptorSet 0
|
||||
OpDecorate %g_sAniso Binding 0
|
||||
OpDecorate %i_vTextureCoords Location 0
|
||||
OpDecorate %_entryPointOutput_vColor Location 0
|
||||
;CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
|
||||
;CHECK: OpDecorate %_struct_58 Block
|
||||
;CHECK: OpMemberDecorate %_struct_58 0 Offset 0
|
||||
;CHECK: OpMemberDecorate %_struct_58 1 Offset 4
|
||||
;CHECK: OpDecorate %60 DescriptorSet 7
|
||||
;CHECK: OpDecorate %60 Binding 0
|
||||
;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
|
||||
;CHECK: OpDecorate %_struct_117 Block
|
||||
;CHECK: OpMemberDecorate %_struct_117 0 Offset 0
|
||||
;CHECK: OpDecorate %119 DescriptorSet 7
|
||||
;CHECK: OpDecorate %119 Binding 1
|
||||
%void = OpTypeVoid
|
||||
%10 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v2float = OpTypeVector %float 2
|
||||
%v4float = OpTypeVector %float 4
|
||||
%int = OpTypeInt 32 1
|
||||
%int_0 = OpConstant %int 0
|
||||
%16 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_128 = OpConstant %uint 128
|
||||
%_arr_16_uint_128 = OpTypeArray %16 %uint_128
|
||||
%_ptr_UniformConstant__arr_16_uint_128 = OpTypePointer UniformConstant %_arr_16_uint_128
|
||||
%g_tColor = OpVariable %_ptr_UniformConstant__arr_16_uint_128 UniformConstant
|
||||
%ushort = OpTypeInt 16 0
|
||||
%PerViewConstantBuffer_t = OpTypeStruct %ushort
|
||||
%_ptr_PushConstant_PerViewConstantBuffer_t = OpTypePointer PushConstant %PerViewConstantBuffer_t
|
||||
%_ = OpVariable %_ptr_PushConstant_PerViewConstantBuffer_t PushConstant
|
||||
%_ptr_PushConstant_ushort = OpTypePointer PushConstant %ushort
|
||||
%_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16
|
||||
%25 = OpTypeSampler
|
||||
%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %25
|
||||
%g_sAniso = OpVariable %_ptr_UniformConstant_25 UniformConstant
|
||||
%27 = OpTypeSampledImage %16
|
||||
%_ptr_Input_v2float = OpTypePointer Input %v2float
|
||||
%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
|
||||
;CHECK: %uint_0 = OpConstant %uint 0
|
||||
;CHECK: %bool = OpTypeBool
|
||||
;CHECK: %51 = OpTypeFunction %void %uint %uint %uint %uint
|
||||
;CHECK:%_runtimearr_uint = OpTypeRuntimeArray %uint
|
||||
;CHECK: %_struct_58 = OpTypeStruct %uint %_runtimearr_uint
|
||||
;CHECK:%_ptr_StorageBuffer__struct_58 = OpTypePointer StorageBuffer %_struct_58
|
||||
;CHECK: %60 = OpVariable %_ptr_StorageBuffer__struct_58 StorageBuffer
|
||||
;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
|
||||
;CHECK: %uint_10 = OpConstant %uint 10
|
||||
;CHECK: %uint_4 = OpConstant %uint 4
|
||||
;CHECK: %uint_1 = OpConstant %uint 1
|
||||
;CHECK: %uint_23 = OpConstant %uint 23
|
||||
;CHECK: %uint_2 = OpConstant %uint 2
|
||||
;CHECK: %uint_3 = OpConstant %uint 3
|
||||
;CHECK:%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
;CHECK:%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
|
||||
;CHECK: %v4uint = OpTypeVector %uint 4
|
||||
;CHECK: %uint_5 = OpConstant %uint 5
|
||||
;CHECK: %uint_7 = OpConstant %uint 7
|
||||
;CHECK: %uint_8 = OpConstant %uint 8
|
||||
;CHECK: %uint_9 = OpConstant %uint 9
|
||||
;CHECK: %uint_60 = OpConstant %uint 60
|
||||
;CHECK: %106 = OpConstantNull %v4float
|
||||
;CHECK: %111 = OpTypeFunction %uint %uint %uint %uint %uint
|
||||
;CHECK:%_struct_117 = OpTypeStruct %_runtimearr_uint
|
||||
;CHECK:%_ptr_StorageBuffer__struct_117 = OpTypePointer StorageBuffer %_struct_117
|
||||
;CHECK: %119 = OpVariable %_ptr_StorageBuffer__struct_117 StorageBuffer
|
||||
%MainPs = OpFunction %void None %10
|
||||
%30 = OpLabel
|
||||
;CHECK: OpBranch %108
|
||||
;CHECK: %108 = OpLabel
|
||||
;CHECK: OpBranch %39
|
||||
;CHECK: %39 = OpLabel
|
||||
%31 = OpLoad %v2float %i_vTextureCoords
|
||||
%32 = OpAccessChain %_ptr_PushConstant_ushort %_ %int_0
|
||||
%33 = OpLoad %ushort %32
|
||||
%34 = OpAccessChain %_ptr_UniformConstant_16 %g_tColor %33
|
||||
%35 = OpLoad %16 %34
|
||||
%36 = OpLoad %25 %g_sAniso
|
||||
%37 = OpSampledImage %27 %35 %36
|
||||
%38 = OpImageSampleImplicitLod %v4float %37 %31
|
||||
OpStore %_entryPointOutput_vColor %38
|
||||
;CHECK-NOT: %38 = OpImageSampleImplicitLod %v4float %37 %31
|
||||
;CHECK-NOT: OpStore %_entryPointOutput_vColor %38
|
||||
;CHECK: %41 = OpUConvert %uint %33
|
||||
;CHECK: %43 = OpULessThan %bool %41 %uint_128
|
||||
;CHECK: OpSelectionMerge %44 None
|
||||
;CHECK: OpBranchConditional %43 %45 %46
|
||||
;CHECK: %45 = OpLabel
|
||||
;CHECK: %47 = OpLoad %16 %34
|
||||
;CHECK: %48 = OpSampledImage %27 %47 %36
|
||||
;CHECK: %109 = OpUConvert %uint %33
|
||||
;CHECK: %131 = OpFunctionCall %uint %110 %uint_0 %uint_0 %uint_0 %109
|
||||
;CHECK: %132 = OpULessThan %bool %uint_0 %131
|
||||
;CHECK: OpSelectionMerge %133 None
|
||||
;CHECK: OpBranchConditional %132 %134 %135
|
||||
;CHECK: %134 = OpLabel
|
||||
;CHECK: %136 = OpLoad %16 %34
|
||||
;CHECK: %137 = OpSampledImage %27 %136 %36
|
||||
;CHECK: %138 = OpImageSampleImplicitLod %v4float %137 %31
|
||||
;CHECK: OpBranch %133
|
||||
;CHECK: %135 = OpLabel
|
||||
;CHECK: %139 = OpUConvert %uint %33
|
||||
;CHECK: %140 = OpFunctionCall %void %50 %uint_60 %uint_1 %139 %uint_0
|
||||
;CHECK: OpBranch %133
|
||||
;CHECK: %133 = OpLabel
|
||||
;CHECK: %141 = OpPhi %v4float %138 %134 %106 %135
|
||||
;CHECK: OpBranch %44
|
||||
;CHECK: %46 = OpLabel
|
||||
;CHECK: %105 = OpFunctionCall %void %50 %uint_60 %uint_0 %41 %uint_128
|
||||
;CHECK: OpBranch %44
|
||||
;CHECK: %44 = OpLabel
|
||||
;CHECK: %107 = OpPhi %v4float %141 %133 %106 %46
|
||||
;CHECK: OpStore %_entryPointOutput_vColor %107
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
;CHECK: %50 = OpFunction %void None %51
|
||||
;CHECK: %52 = OpFunctionParameter %uint
|
||||
;CHECK: %53 = OpFunctionParameter %uint
|
||||
;CHECK: %54 = OpFunctionParameter %uint
|
||||
;CHECK: %55 = OpFunctionParameter %uint
|
||||
;CHECK: %56 = OpLabel
|
||||
;CHECK: %62 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_0
|
||||
;CHECK: %65 = OpAtomicIAdd %uint %62 %uint_4 %uint_0 %uint_10
|
||||
;CHECK: %66 = OpIAdd %uint %65 %uint_10
|
||||
;CHECK: %67 = OpArrayLength %uint %60 1
|
||||
;CHECK: %68 = OpULessThanEqual %bool %66 %67
|
||||
;CHECK: OpSelectionMerge %69 None
|
||||
;CHECK: OpBranchConditional %68 %70 %69
|
||||
;CHECK: %70 = OpLabel
|
||||
;CHECK: %71 = OpIAdd %uint %65 %uint_0
|
||||
;CHECK: %73 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %71
|
||||
;CHECK: OpStore %73 %uint_10
|
||||
;CHECK: %75 = OpIAdd %uint %65 %uint_1
|
||||
;CHECK: %76 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %75
|
||||
;CHECK: OpStore %76 %uint_23
|
||||
;CHECK: %78 = OpIAdd %uint %65 %uint_2
|
||||
;CHECK: %79 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %78
|
||||
;CHECK: OpStore %79 %52
|
||||
;CHECK: %81 = OpIAdd %uint %65 %uint_3
|
||||
;CHECK: %82 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %81
|
||||
;CHECK: OpStore %82 %uint_4
|
||||
;CHECK: %85 = OpLoad %v4float %gl_FragCoord
|
||||
;CHECK: %87 = OpBitcast %v4uint %85
|
||||
;CHECK: %88 = OpCompositeExtract %uint %87 0
|
||||
;CHECK: %89 = OpIAdd %uint %65 %uint_4
|
||||
;CHECK: %90 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %89
|
||||
;CHECK: OpStore %90 %88
|
||||
;CHECK: %91 = OpCompositeExtract %uint %87 1
|
||||
;CHECK: %93 = OpIAdd %uint %65 %uint_5
|
||||
;CHECK: %94 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %93
|
||||
;CHECK: OpStore %94 %91
|
||||
;CHECK: %96 = OpIAdd %uint %65 %uint_7
|
||||
;CHECK: %97 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %96
|
||||
;CHECK: OpStore %97 %53
|
||||
;CHECK: %99 = OpIAdd %uint %65 %uint_8
|
||||
;CHECK: %100 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %99
|
||||
;CHECK: OpStore %100 %54
|
||||
;CHECK: %102 = OpIAdd %uint %65 %uint_9
|
||||
;CHECK: %103 = OpAccessChain %_ptr_StorageBuffer_uint %60 %uint_1 %102
|
||||
;CHECK: OpStore %103 %55
|
||||
;CHECK: OpBranch %69
|
||||
;CHECK: %69 = OpLabel
|
||||
;CHECK: OpReturn
|
||||
;CHECK: OpFunctionEnd
|
||||
;CHECK: %110 = OpFunction %uint None %111
|
||||
;CHECK: %112 = OpFunctionParameter %uint
|
||||
;CHECK: %113 = OpFunctionParameter %uint
|
||||
;CHECK: %114 = OpFunctionParameter %uint
|
||||
;CHECK: %115 = OpFunctionParameter %uint
|
||||
;CHECK: %116 = OpLabel
|
||||
;CHECK: %120 = OpAccessChain %_ptr_StorageBuffer_uint %119 %uint_0 %112
|
||||
;CHECK: %121 = OpLoad %uint %120
|
||||
;CHECK: %122 = OpIAdd %uint %121 %113
|
||||
;CHECK: %123 = OpAccessChain %_ptr_StorageBuffer_uint %119 %uint_0 %122
|
||||
;CHECK: %124 = OpLoad %uint %123
|
||||
;CHECK: %125 = OpIAdd %uint %124 %114
|
||||
;CHECK: %126 = OpAccessChain %_ptr_StorageBuffer_uint %119 %uint_0 %125
|
||||
;CHECK: %127 = OpLoad %uint %126
|
||||
;CHECK: %128 = OpIAdd %uint %127 %115
|
||||
;CHECK: %129 = OpAccessChain %_ptr_StorageBuffer_uint %119 %uint_0 %128
|
||||
;CHECK: %130 = OpLoad %uint %129
|
||||
;CHECK: OpReturnValue %130
|
||||
;CHECK: OpFunctionEnd
|
||||
)";
|
||||
|
||||
SetTargetEnv(SPV_ENV_VULKAN_1_2);
|
||||
SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, true, true,
|
||||
false);
|
||||
}
|
||||
|
||||
TEST_F(InstBindlessTest, UniformArray16bitIdxRef) {
|
||||
// Check that uniform array ref with 16bit index does not go out-of-bounds.
|
||||
//
|
||||
// Texture2D g_tColor;
|
||||
// SamplerState g_sAniso;
|
||||
//
|
||||
// layout(push_constant) cbuffer PerViewPushConst_t { min16uint g_c; };
|
||||
//
|
||||
// struct PerBatchEnvMapConstantBuffer_t {
|
||||
// float4x3 g_matEnvMapWorldToLocal;
|
||||
// float4 g_vEnvironmentMapBoxMins;
|
||||
// float2 g_TexOff;
|
||||
// };
|
||||
//
|
||||
// cbuffer _BindlessFastEnvMapCB_PS_t {
|
||||
// PerBatchEnvMapConstantBuffer_t g_envMapConstants[128];
|
||||
// };
|
||||
//
|
||||
// struct PS_INPUT {
|
||||
// float2 vTextureCoords : TEXCOORD2;
|
||||
// };
|
||||
//
|
||||
// struct PS_OUTPUT {
|
||||
// float4 vColor : SV_Target0;
|
||||
// };
|
||||
//
|
||||
// PS_OUTPUT MainPs(PS_INPUT i) {
|
||||
// PS_OUTPUT ps_output;
|
||||
// float2 off;
|
||||
// float2 vtc;
|
||||
// off = g_envMapConstants[g_c].g_TexOff;
|
||||
// vtc = i.vTextureCoords.xy + off;
|
||||
// ps_output.vColor = g_tColor.Sample(g_sAniso, vtc);
|
||||
// return ps_output;
|
||||
// }
|
||||
|
||||
const std::string text = R"(
|
||||
OpCapability Shader
|
||||
OpCapability Int16
|
||||
OpCapability StoragePushConstant16
|
||||
;CHECK: OpExtension "SPV_KHR_storage_buffer_storage_class"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor
|
||||
;CHECK: OpEntryPoint Fragment %MainPs "MainPs" %_ %__0 %g_tColor %g_sAniso %i_vTextureCoords %_entryPointOutput_vColor %69 %97 %gl_FragCoord
|
||||
OpExecutionMode %MainPs OriginUpperLeft
|
||||
OpSource HLSL 500
|
||||
OpName %MainPs "MainPs"
|
||||
OpName %PerBatchEnvMapConstantBuffer_t "PerBatchEnvMapConstantBuffer_t"
|
||||
OpMemberName %PerBatchEnvMapConstantBuffer_t 0 "g_matEnvMapWorldToLocal"
|
||||
OpMemberName %PerBatchEnvMapConstantBuffer_t 1 "g_vEnvironmentMapBoxMins"
|
||||
OpMemberName %PerBatchEnvMapConstantBuffer_t 2 "g_TexOff"
|
||||
OpName %_BindlessFastEnvMapCB_PS_t "_BindlessFastEnvMapCB_PS_t"
|
||||
OpMemberName %_BindlessFastEnvMapCB_PS_t 0 "g_envMapConstants"
|
||||
OpName %_ ""
|
||||
OpName %PerViewPushConst_t "PerViewPushConst_t"
|
||||
OpMemberName %PerViewPushConst_t 0 "g_c"
|
||||
OpName %__0 ""
|
||||
OpName %g_tColor "g_tColor"
|
||||
OpName %g_sAniso "g_sAniso"
|
||||
OpName %i_vTextureCoords "i.vTextureCoords"
|
||||
OpName %_entryPointOutput_vColor "@entryPointOutput.vColor"
|
||||
OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 0 RowMajor
|
||||
OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 0 Offset 0
|
||||
OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 0 MatrixStride 16
|
||||
OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 1 Offset 48
|
||||
OpMemberDecorate %PerBatchEnvMapConstantBuffer_t 2 Offset 64
|
||||
OpDecorate %_arr_PerBatchEnvMapConstantBuffer_t_uint_128 ArrayStride 80
|
||||
OpMemberDecorate %_BindlessFastEnvMapCB_PS_t 0 Offset 0
|
||||
OpDecorate %_BindlessFastEnvMapCB_PS_t Block
|
||||
OpDecorate %_ DescriptorSet 0
|
||||
OpDecorate %_ Binding 0
|
||||
OpMemberDecorate %PerViewPushConst_t 0 Offset 0
|
||||
OpDecorate %PerViewPushConst_t Block
|
||||
OpDecorate %g_tColor DescriptorSet 0
|
||||
OpDecorate %g_tColor Binding 0
|
||||
OpDecorate %g_sAniso DescriptorSet 0
|
||||
OpDecorate %g_sAniso Binding 0
|
||||
OpDecorate %i_vTextureCoords Location 0
|
||||
OpDecorate %_entryPointOutput_vColor Location 0
|
||||
;CHECK: OpDecorate %_runtimearr_uint ArrayStride 4
|
||||
;CHECK: OpDecorate %_struct_67 Block
|
||||
;CHECK: OpMemberDecorate %_struct_67 0 Offset 0
|
||||
;CHECK: OpDecorate %69 DescriptorSet 7
|
||||
;CHECK: OpDecorate %69 Binding 1
|
||||
;CHECK: OpDecorate %_struct_95 Block
|
||||
;CHECK: OpMemberDecorate %_struct_95 0 Offset 0
|
||||
;CHECK: OpMemberDecorate %_struct_95 1 Offset 4
|
||||
;CHECK: OpDecorate %97 DescriptorSet 7
|
||||
;CHECK: OpDecorate %97 Binding 0
|
||||
;CHECK: OpDecorate %gl_FragCoord BuiltIn FragCoord
|
||||
%void = OpTypeVoid
|
||||
%14 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v2float = OpTypeVector %float 2
|
||||
%v4float = OpTypeVector %float 4
|
||||
%v3float = OpTypeVector %float 3
|
||||
%mat4v3float = OpTypeMatrix %v3float 4
|
||||
%PerBatchEnvMapConstantBuffer_t = OpTypeStruct %mat4v3float %v4float %v2float
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_128 = OpConstant %uint 128
|
||||
%_arr_PerBatchEnvMapConstantBuffer_t_uint_128 = OpTypeArray %PerBatchEnvMapConstantBuffer_t %uint_128
|
||||
%_BindlessFastEnvMapCB_PS_t = OpTypeStruct %_arr_PerBatchEnvMapConstantBuffer_t_uint_128
|
||||
%_ptr_Uniform__BindlessFastEnvMapCB_PS_t = OpTypePointer Uniform %_BindlessFastEnvMapCB_PS_t
|
||||
%_ = OpVariable %_ptr_Uniform__BindlessFastEnvMapCB_PS_t Uniform
|
||||
%int = OpTypeInt 32 1
|
||||
%int_0 = OpConstant %int 0
|
||||
%ushort = OpTypeInt 16 0
|
||||
%PerViewPushConst_t = OpTypeStruct %ushort
|
||||
%_ptr_PushConstant_PerViewPushConst_t = OpTypePointer PushConstant %PerViewPushConst_t
|
||||
%__0 = OpVariable %_ptr_PushConstant_PerViewPushConst_t PushConstant
|
||||
%_ptr_PushConstant_ushort = OpTypePointer PushConstant %ushort
|
||||
%int_2 = OpConstant %int 2
|
||||
%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
|
||||
%30 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%_ptr_UniformConstant_30 = OpTypePointer UniformConstant %30
|
||||
%g_tColor = OpVariable %_ptr_UniformConstant_30 UniformConstant
|
||||
%32 = OpTypeSampler
|
||||
%_ptr_UniformConstant_32 = OpTypePointer UniformConstant %32
|
||||
%g_sAniso = OpVariable %_ptr_UniformConstant_32 UniformConstant
|
||||
%34 = OpTypeSampledImage %30
|
||||
%_ptr_Input_v2float = OpTypePointer Input %v2float
|
||||
%i_vTextureCoords = OpVariable %_ptr_Input_v2float Input
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%_entryPointOutput_vColor = OpVariable %_ptr_Output_v4float Output
|
||||
;CHECK: %uint_0 = OpConstant %uint 0
|
||||
;CHECK: %uint_80 = OpConstant %uint 80
|
||||
;CHECK: %uint_64 = OpConstant %uint 64
|
||||
;CHECK: %uint_7 = OpConstant %uint 7
|
||||
;CHECK: %uint_1 = OpConstant %uint 1
|
||||
;CHECK: %61 = OpTypeFunction %uint %uint %uint %uint
|
||||
;CHECK:%_runtimearr_uint = OpTypeRuntimeArray %uint
|
||||
;CHECK: %_struct_67 = OpTypeStruct %_runtimearr_uint
|
||||
;CHECK:%_ptr_StorageBuffer__struct_67 = OpTypePointer StorageBuffer %_struct_67
|
||||
;CHECK: %69 = OpVariable %_ptr_StorageBuffer__struct_67 StorageBuffer
|
||||
;CHECK:%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
|
||||
;CHECK: %bool = OpTypeBool
|
||||
;CHECK: %uint_3 = OpConstant %uint 3
|
||||
;CHECK: %88 = OpTypeFunction %void %uint %uint %uint %uint %uint
|
||||
;CHECK: %_struct_95 = OpTypeStruct %uint %_runtimearr_uint
|
||||
;CHECK:%_ptr_StorageBuffer__struct_95 = OpTypePointer StorageBuffer %_struct_95
|
||||
;CHECK: %97 = OpVariable %_ptr_StorageBuffer__struct_95 StorageBuffer
|
||||
;CHECK: %uint_11 = OpConstant %uint 11
|
||||
;CHECK: %uint_4 = OpConstant %uint 4
|
||||
;CHECK: %uint_23 = OpConstant %uint 23
|
||||
;CHECK: %uint_2 = OpConstant %uint 2
|
||||
;CHECK:%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
;CHECK:%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
|
||||
;CHECK: %v4uint = OpTypeVector %uint 4
|
||||
;CHECK: %uint_5 = OpConstant %uint 5
|
||||
;CHECK: %uint_8 = OpConstant %uint 8
|
||||
;CHECK: %uint_9 = OpConstant %uint 9
|
||||
;CHECK: %uint_10 = OpConstant %uint 10
|
||||
;CHECK: %uint_81 = OpConstant %uint 81
|
||||
;CHECK: %142 = OpConstantNull %v2float
|
||||
%MainPs = OpFunction %void None %14
|
||||
%37 = OpLabel
|
||||
;CHECK: %79 = OpFunctionCall %uint %60 %uint_1 %uint_0 %uint_0
|
||||
;CHECK: OpBranch %49
|
||||
;CHECK: %49 = OpLabel
|
||||
;CHECK: OpBranch %48
|
||||
;CHECK: %48 = OpLabel
|
||||
%38 = OpLoad %v2float %i_vTextureCoords
|
||||
%39 = OpAccessChain %_ptr_PushConstant_ushort %__0 %int_0
|
||||
%40 = OpLoad %ushort %39
|
||||
%41 = OpAccessChain %_ptr_Uniform_v2float %_ %int_0 %40 %int_2
|
||||
%42 = OpLoad %v2float %41
|
||||
%43 = OpFAdd %v2float %38 %42
|
||||
;CHECK-NOT: %42 = OpLoad %v2float %41
|
||||
;CHECK-NOT: %43 = OpFAdd %v2float %38 %42
|
||||
;CHECK: %52 = OpUConvert %uint %40
|
||||
;CHECK: %53 = OpIMul %uint %uint_80 %52
|
||||
;CHECK: %54 = OpIAdd %uint %uint_0 %53
|
||||
;CHECK: %56 = OpIAdd %uint %54 %uint_64
|
||||
;CHECK: %58 = OpIAdd %uint %56 %uint_7
|
||||
;CHECK: %81 = OpULessThan %bool %58 %79
|
||||
;CHECK: OpSelectionMerge %83 None
|
||||
;CHECK: OpBranchConditional %81 %84 %85
|
||||
;CHECK: %84 = OpLabel
|
||||
;CHECK: %86 = OpLoad %v2float %41
|
||||
;CHECK: OpBranch %83
|
||||
;CHECK: %85 = OpLabel
|
||||
;CHECK: %141 = OpFunctionCall %void %87 %uint_81 %uint_3 %uint_0 %58 %79
|
||||
;CHECK: OpBranch %83
|
||||
;CHECK: %83 = OpLabel
|
||||
;CHECK: %143 = OpPhi %v2float %86 %84 %142 %85
|
||||
;CHECK: %43 = OpFAdd %v2float %38 %143
|
||||
%44 = OpLoad %30 %g_tColor
|
||||
%45 = OpLoad %32 %g_sAniso
|
||||
%46 = OpSampledImage %34 %44 %45
|
||||
%47 = OpImageSampleImplicitLod %v4float %46 %43
|
||||
OpStore %_entryPointOutput_vColor %47
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
;CHECK: %60 = OpFunction %uint None %61
|
||||
;CHECK: %62 = OpFunctionParameter %uint
|
||||
;CHECK: %63 = OpFunctionParameter %uint
|
||||
;CHECK: %64 = OpFunctionParameter %uint
|
||||
;CHECK: %65 = OpLabel
|
||||
;CHECK: %71 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_0 %62
|
||||
;CHECK: %72 = OpLoad %uint %71
|
||||
;CHECK: %73 = OpIAdd %uint %72 %63
|
||||
;CHECK: %74 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_0 %73
|
||||
;CHECK: %75 = OpLoad %uint %74
|
||||
;CHECK: %76 = OpIAdd %uint %75 %64
|
||||
;CHECK: %77 = OpAccessChain %_ptr_StorageBuffer_uint %69 %uint_0 %76
|
||||
;CHECK: %78 = OpLoad %uint %77
|
||||
;CHECK: OpReturnValue %78
|
||||
;CHECK: OpFunctionEnd
|
||||
;CHECK: %87 = OpFunction %void None %88
|
||||
;CHECK: %89 = OpFunctionParameter %uint
|
||||
;CHECK: %90 = OpFunctionParameter %uint
|
||||
;CHECK: %91 = OpFunctionParameter %uint
|
||||
;CHECK: %92 = OpFunctionParameter %uint
|
||||
;CHECK: %93 = OpFunctionParameter %uint
|
||||
;CHECK: %94 = OpLabel
|
||||
;CHECK: %98 = OpAccessChain %_ptr_StorageBuffer_uint %97 %uint_0
|
||||
;CHECK: %101 = OpAtomicIAdd %uint %98 %uint_4 %uint_0 %uint_11
|
||||
;CHECK: %102 = OpIAdd %uint %101 %uint_11
|
||||
;CHECK: %103 = OpArrayLength %uint %97 1
|
||||
;CHECK: %104 = OpULessThanEqual %bool %102 %103
|
||||
;CHECK: OpSelectionMerge %105 None
|
||||
;CHECK: OpBranchConditional %104 %106 %105
|
||||
;CHECK: %106 = OpLabel
|
||||
;CHECK: %107 = OpIAdd %uint %101 %uint_0
|
||||
;CHECK: %108 = OpAccessChain %_ptr_StorageBuffer_uint %97 %uint_1 %107
|
||||
;CHECK: OpStore %108 %uint_11
|
||||
;CHECK: %110 = OpIAdd %uint %101 %uint_1
|
||||
;CHECK: %111 = OpAccessChain %_ptr_StorageBuffer_uint %97 %uint_1 %110
|
||||
;CHECK: OpStore %111 %uint_23
|
||||
;CHECK: %113 = OpIAdd %uint %101 %uint_2
|
||||
;CHECK: %114 = OpAccessChain %_ptr_StorageBuffer_uint %97 %uint_1 %113
|
||||
;CHECK: OpStore %114 %89
|
||||
;CHECK: %115 = OpIAdd %uint %101 %uint_3
|
||||
;CHECK: %116 = OpAccessChain %_ptr_StorageBuffer_uint %97 %uint_1 %115
|
||||
;CHECK: OpStore %116 %uint_4
|
||||
;CHECK: %119 = OpLoad %v4float %gl_FragCoord
|
||||
;CHECK: %121 = OpBitcast %v4uint %119
|
||||
;CHECK: %122 = OpCompositeExtract %uint %121 0
|
||||
;CHECK: %123 = OpIAdd %uint %101 %uint_4
|
||||
;CHECK: %124 = OpAccessChain %_ptr_StorageBuffer_uint %97 %uint_1 %123
|
||||
;CHECK: OpStore %124 %122
|
||||
;CHECK: %125 = OpCompositeExtract %uint %121 1
|
||||
;CHECK: %127 = OpIAdd %uint %101 %uint_5
|
||||
;CHECK: %128 = OpAccessChain %_ptr_StorageBuffer_uint %97 %uint_1 %127
|
||||
;CHECK: OpStore %128 %125
|
||||
;CHECK: %129 = OpIAdd %uint %101 %uint_7
|
||||
;CHECK: %130 = OpAccessChain %_ptr_StorageBuffer_uint %97 %uint_1 %129
|
||||
;CHECK: OpStore %130 %90
|
||||
;CHECK: %132 = OpIAdd %uint %101 %uint_8
|
||||
;CHECK: %133 = OpAccessChain %_ptr_StorageBuffer_uint %97 %uint_1 %132
|
||||
;CHECK: OpStore %133 %91
|
||||
;CHECK: %135 = OpIAdd %uint %101 %uint_9
|
||||
;CHECK: %136 = OpAccessChain %_ptr_StorageBuffer_uint %97 %uint_1 %135
|
||||
;CHECK: OpStore %136 %92
|
||||
;CHECK: %138 = OpIAdd %uint %101 %uint_10
|
||||
;CHECK: %139 = OpAccessChain %_ptr_StorageBuffer_uint %97 %uint_1 %138
|
||||
;CHECK: OpStore %139 %93
|
||||
;CHECK: OpBranch %105
|
||||
;CHECK: %105 = OpLabel
|
||||
;CHECK: OpReturn
|
||||
;CHECK: OpFunctionEnd
|
||||
)";
|
||||
|
||||
SetTargetEnv(SPV_ENV_VULKAN_1_2);
|
||||
SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndMatch<InstBindlessCheckPass>(text, true, 7u, 23u, false,
|
||||
false, true);
|
||||
}
|
||||
|
||||
// TODO(greg-lunarg): Add tests to verify handling of these cases:
|
||||
//
|
||||
// Compute shader
|
||||
|
|
Загрузка…
Ссылка в новой задаче