Don't convert struct members to half (#5201)

This commit is contained in:
Chris Oattes 2023-05-08 17:14:42 +01:00 committed by GitHub
parent d6310f4168
commit e803fe6717
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 0 deletions

View File

@ -39,6 +39,13 @@ bool ConvertToHalfPass::IsFloat(Instruction* inst, uint32_t width) {
return Pass::IsFloat(ty_id, width);
}
bool ConvertToHalfPass::IsStruct(Instruction* inst) {
uint32_t ty_id = inst->type_id();
if (ty_id == 0) return false;
Instruction* ty_inst = Pass::GetBaseType(ty_id);
return (ty_inst->opcode() == spv::Op::OpTypeStruct);
}
bool ConvertToHalfPass::IsDecoratedRelaxed(Instruction* inst) {
uint32_t r_id = inst->result_id();
for (auto r_inst : get_decoration_mgr()->GetDecorationsFor(r_id, false))
@ -294,6 +301,7 @@ bool ConvertToHalfPass::CloseRelaxInst(Instruction* inst) {
bool relax = true;
inst->ForEachInId([&relax, this](uint32_t* idp) {
Instruction* op_inst = get_def_use_mgr()->GetDef(*idp);
if (IsStruct(op_inst)) relax = false;
if (!IsFloat(op_inst, 32)) return;
if (!IsRelaxed(*idp)) relax = false;
});

View File

@ -45,6 +45,7 @@ class ConvertToHalfPass : public Pass {
// Return true if |inst| returns scalar, vector or matrix type with base
// float and |width|
bool IsFloat(Instruction* inst, uint32_t width);
bool IsStruct(Instruction* inst);
// Return true if |inst| is decorated with RelaxedPrecision
bool IsDecoratedRelaxed(Instruction* inst);

View File

@ -1570,6 +1570,49 @@ TEST_F(ConvertToHalfTest, HandleNonRelaxedPhi) {
EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
}
TEST_F(ConvertToHalfTest, DoNotReplaceStructMember) {
// See https://github.com/KhronosGroup/SPIRV-Tools/issues/4814
// This test is a case with a non-relaxed phi with a relaxed operand.
// A convert must be inserted at the end of the block associated with
// the operand.
const std::string test =
R"(OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %PSMain "PSMain" %out_var_SV_TARGET %MyConstants
OpExecutionMode %PSMain OriginUpperLeft
OpSource HLSL 600
OpName %type_ConstantBuffer_myStruct "type.ConstantBuffer.myStruct"
OpMemberName %type_ConstantBuffer_myStruct 0 "f"
OpName %MyConstants "MyConstants"
OpName %out_var_SV_TARGET "out.var.SV_TARGET"
OpName %PSMain "PSMain"
OpDecorate %out_var_SV_TARGET Location 0
OpDecorate %MyConstants DescriptorSet 1
OpDecorate %MyConstants Binding 2
OpMemberDecorate %type_ConstantBuffer_myStruct 0 Offset 0
OpDecorate %type_ConstantBuffer_myStruct Block
%float = OpTypeFloat 32
%type_ConstantBuffer_myStruct = OpTypeStruct %float
%_ptr_Uniform_type_ConstantBuffer_myStruct = OpTypePointer Uniform %type_ConstantBuffer_myStruct
%_ptr_Output_float = OpTypePointer Output %float
%void = OpTypeVoid
%9 = OpTypeFunction %void
%MyConstants = OpVariable %_ptr_Uniform_type_ConstantBuffer_myStruct Uniform
%out_var_SV_TARGET = OpVariable %_ptr_Output_float Output
%PSMain = OpFunction %void None %9
%10 = OpLabel
%11 = OpLoad %type_ConstantBuffer_myStruct %MyConstants
%12 = OpCompositeExtract %float %11 0
OpStore %out_var_SV_TARGET %12
OpReturn
OpFunctionEnd
)";
SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
SinglePassRunAndCheck<ConvertToHalfPass>(test, test, true);
}
} // namespace
} // namespace opt
} // namespace spvtools