Copy OpDecorateStrings in DescriptorScalarReplacementPass (#4649)

Along with OpDecorate, also clone the OpDecorateString instructions for
variables created in the descriptor scalar replacement pass.

Fixes microsoft/DirectXShaderCompiler#3705
This commit is contained in:
Natalie Chouinard 2021-11-29 02:11:22 -05:00 committed by GitHub
parent b023c0da1d
commit d0a827a9f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 95 additions and 6 deletions

View File

@ -169,7 +169,7 @@ void DescriptorScalarReplacement::CopyDecorationsForNewVariable(
Instruction* old_var, uint32_t index, uint32_t new_var_id,
uint32_t new_var_ptr_type_id, const bool is_old_var_array,
const bool is_old_var_struct, Instruction* old_var_type) {
// Handle OpDecorate instructions.
// Handle OpDecorate and OpDecorateString instructions.
for (auto old_decoration :
get_decoration_mgr()->GetDecorationsFor(old_var->result_id(), true)) {
uint32_t new_binding = 0;
@ -212,7 +212,8 @@ uint32_t DescriptorScalarReplacement::GetNewBindingForElement(
void DescriptorScalarReplacement::CreateNewDecorationForNewVariable(
Instruction* old_decoration, uint32_t new_var_id, uint32_t new_binding) {
assert(old_decoration->opcode() == SpvOpDecorate);
assert(old_decoration->opcode() == SpvOpDecorate ||
old_decoration->opcode() == SpvOpDecorateString);
std::unique_ptr<Instruction> new_decoration(old_decoration->Clone(context()));
new_decoration->SetInOperand(0, {new_var_id});

View File

@ -115,10 +115,11 @@ class DescriptorScalarReplacement : public Pass {
const bool is_old_var_struct,
Instruction* old_var_type);
// Create a new OpDecorate instruction by cloning |old_decoration|. The new
// OpDecorate instruction will be used for a variable whose id is
// |new_var_ptr_type_id|. If |old_decoration| is a decoration for a binding,
// the new OpDecorate instruction will have |new_binding| as its binding.
// Create a new OpDecorate(String) instruction by cloning |old_decoration|.
// The new OpDecorate(String) instruction will be used for a variable whose id
// is |new_var_ptr_type_id|. If |old_decoration| is a decoration for a
// binding, the new OpDecorate(String) instruction will have |new_binding| as
// its binding.
void CreateNewDecorationForNewVariable(Instruction* old_decoration,
uint32_t new_var_id,
uint32_t new_binding);

View File

@ -833,6 +833,93 @@ TEST_F(DescriptorScalarReplacementTest, MemberDecorationForResourceStruct) {
SinglePassRunAndMatch<DescriptorScalarReplacement>(shader, true);
}
TEST_F(DescriptorScalarReplacementTest, DecorateStringForReflect) {
// Check that an OpDecorateString instruction is correctly cloned to new
// variable.
const std::string shader = R"(
; CHECK: OpName %g_testTextures_0_ "g_testTextures[0]"
; CHECK: OpDecorate %g_testTextures_0_ DescriptorSet 0
; CHECK: OpDecorate %g_testTextures_0_ Binding 0
; CHECK: OpDecorateString %g_testTextures_0_ UserTypeGOOGLE "texture2d"
OpCapability Shader
OpExtension "SPV_GOOGLE_hlsl_functionality1"
OpExtension "SPV_GOOGLE_user_type"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %gl_FragCoord %out_var_SV_Target
OpExecutionMode %main OriginUpperLeft
OpSource HLSL 600
OpName %type_2d_image "type.2d.image"
OpName %g_testTextures "g_testTextures"
OpName %out_var_SV_Target "out.var.SV_Target"
OpName %main "main"
OpName %param_var_vPixelPos "param.var.vPixelPos"
OpName %src_main "src.main"
OpName %vPixelPos "vPixelPos"
OpName %bb_entry "bb.entry"
OpDecorate %gl_FragCoord BuiltIn FragCoord
OpDecorateString %gl_FragCoord UserSemantic "SV_Position"
OpDecorateString %out_var_SV_Target UserSemantic "SV_Target"
OpDecorate %out_var_SV_Target Location 0
OpDecorate %g_testTextures DescriptorSet 0
OpDecorate %g_testTextures Binding 0
OpDecorateString %g_testTextures UserTypeGOOGLE "texture2d"
%uint = OpTypeInt 32 0
%uint_0 = OpConstant %uint 0
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%uint_2 = OpConstant %uint 2
%float = OpTypeFloat 32
%type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
%_arr_type_2d_image_uint_2 = OpTypeArray %type_2d_image %uint_2
%_ptr_UniformConstant__arr_type_2d_image_uint_2 = OpTypePointer UniformConstant %_arr_type_2d_image_uint_2
%v4float = OpTypeVector %float 4
%_ptr_Input_v4float = OpTypePointer Input %v4float
%_ptr_Output_v4float = OpTypePointer Output %v4float
%void = OpTypeVoid
%18 = OpTypeFunction %void
%_ptr_Function_v4float = OpTypePointer Function %v4float
%25 = OpTypeFunction %v4float %_ptr_Function_v4float
%v2float = OpTypeVector %float 2
%v3uint = OpTypeVector %uint 3
%v3int = OpTypeVector %int 3
%v2int = OpTypeVector %int 2
%_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
%g_testTextures = OpVariable %_ptr_UniformConstant__arr_type_2d_image_uint_2 UniformConstant
%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
%out_var_SV_Target = OpVariable %_ptr_Output_v4float Output
%main = OpFunction %void None %18
%19 = OpLabel
%param_var_vPixelPos = OpVariable %_ptr_Function_v4float Function
%22 = OpLoad %v4float %gl_FragCoord
OpStore %param_var_vPixelPos %22
%23 = OpFunctionCall %v4float %src_main %param_var_vPixelPos
OpStore %out_var_SV_Target %23
OpReturn
OpFunctionEnd
%src_main = OpFunction %v4float None %25
%vPixelPos = OpFunctionParameter %_ptr_Function_v4float
%bb_entry = OpLabel
%28 = OpLoad %v4float %vPixelPos
%30 = OpVectorShuffle %v2float %28 %28 0 1
%31 = OpCompositeExtract %float %30 0
%32 = OpCompositeExtract %float %30 1
%33 = OpConvertFToU %uint %31
%34 = OpConvertFToU %uint %32
%36 = OpCompositeConstruct %v3uint %33 %34 %uint_0
%38 = OpBitcast %v3int %36
%40 = OpVectorShuffle %v2int %38 %38 0 1
%41 = OpCompositeExtract %int %38 2
%43 = OpAccessChain %_ptr_UniformConstant_type_2d_image %g_testTextures %int_0
%44 = OpLoad %type_2d_image %43
%45 = OpImageFetch %v4float %44 %40 Lod %41
OpReturnValue %45
OpFunctionEnd
)";
SinglePassRunAndMatch<DescriptorScalarReplacement>(shader, true);
}
} // namespace
} // namespace opt
} // namespace spvtools