spirv-reader: Fix texel type confusion in loop

Started from https://dawn-review.googlesource.com/c/dawn/+/99001

Fixed: tint:1642
Change-Id: Ia5d7e45dc3de5de8303a2f161c9bf365227f9b5e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/101068
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: David Neto <dneto@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
Robert Stewart 2022-09-02 16:48:32 +00:00 committed by Dawn LUCI CQ
parent 434d6edd2b
commit ece807852d
2 changed files with 93 additions and 4 deletions

View File

@ -5716,7 +5716,7 @@ const ast::Expression* FunctionEmitter::ConvertTexelForStorage(
TypedExpression texel,
const Texture* texture_type) {
auto* storage_texture_type = As<StorageTexture>(texture_type);
auto* src_type = texel.type;
auto* src_type = texel.type->UnwrapRef();
if (!storage_texture_type) {
Fail() << "writing to other than storage texture: " << inst.PrettyPrint();
return nullptr;
@ -5764,14 +5764,14 @@ const ast::Expression* FunctionEmitter::ConvertTexelForStorage(
if (src_count < dest_count) {
// Expand the texel to a 4 element vector.
auto* component_type = texel.type->IsScalar() ? texel.type : texel.type->As<Vector>()->type;
texel.type = ty_.Vector(component_type, dest_count);
auto* component_type = src_type->IsScalar() ? src_type : src_type->As<Vector>()->type;
src_type = ty_.Vector(component_type, dest_count);
ExpressionList exprs;
exprs.Push(texel.expr);
for (auto i = src_count; i < dest_count; i++) {
exprs.Push(parser_impl_.MakeNullExpression(component_type).expr);
}
texel.expr = builder_.Construct(Source{}, texel.type->Build(builder_), std::move(exprs));
texel.expr = builder_.Construct(Source{}, src_type->Build(builder_), std::move(exprs));
}
return texel.expr;

View File

@ -3840,5 +3840,94 @@ return;
ASSERT_EQ(expect, got);
}
TEST_F(SpvParserHandleTest, TexelTypeWhenLoop) {
// Demonstrates fix for crbug.com/tint/1642
// The problem is the texel value for an image write
// can be given in 'var' declaration.
//
// The texel value handling has to unwrap the ref type first.
const auto assembly = Preamble() + R"(
OpCapability Shader
OpCapability StorageImageExtendedFormats
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %100 "main"
OpExecutionMode %100 LocalSize 8 8 1
OpSource HLSL 600
OpName %type_2d_image "type.2d.image"
OpName %Output2Texture2D "Output2Texture2D"
OpName %100 "main"
OpDecorate %Output2Texture2D DescriptorSet 0
OpDecorate %Output2Texture2D Binding 0
%float = OpTypeFloat 32
%float_0 = OpConstant %float 0
%v2float = OpTypeVector %float 2
%7 = OpConstantComposite %v2float %float_0 %float_0
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%int_2 = OpConstant %int 2
%float_1 = OpConstant %float 1
%12 = OpConstantComposite %v2float %float_1 %float_1
%int_1 = OpConstant %int 1
%uint = OpTypeInt 32 0
%uint_1 = OpConstant %uint 1
%v2uint = OpTypeVector %uint 2
%17 = OpConstantComposite %v2uint %uint_1 %uint_1
%type_2d_image = OpTypeImage %float 2D 2 0 0 2 Rg32f
%_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
%void = OpTypeVoid
%20 = OpTypeFunction %void
%bool = OpTypeBool
%Output2Texture2D = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
%100 = OpFunction %void None %20
%22 = OpLabel
OpBranch %23
%23 = OpLabel
%24 = OpPhi %v2float %7 %22 %12 %25
%26 = OpPhi %int %int_0 %22 %27 %25
%28 = OpSLessThan %bool %26 %int_2
OpLoopMerge %29 %25 None
OpBranchConditional %28 %25 %29
%25 = OpLabel
%27 = OpIAdd %int %26 %int_1
OpBranch %23
%29 = OpLabel
%30 = OpLoad %type_2d_image %Output2Texture2D
OpImageWrite %30 %17 %24 None
OpReturn
OpFunctionEnd
)";
auto p = parser(test::Assemble(assembly));
EXPECT_TRUE(p->BuildAndParseInternalModule()) << assembly;
auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody()) << p->error();
EXPECT_TRUE(p->error().empty()) << p->error();
auto ast_body = fe.ast_body();
const auto got = test::ToString(p->program(), ast_body);
auto* expect = R"(var x_24 : vec2<f32>;
var x_24_phi_1 : vec2<f32>;
var x_26_phi_1 : i32;
x_24_phi_1 = vec2<f32>(0.0f, 0.0f);
x_26_phi_1 = 0i;
loop {
var x_27 : i32;
x_24 = x_24_phi_1;
let x_26 : i32 = x_26_phi_1;
if ((x_26 < 2i)) {
} else {
break;
}
continuing {
x_27 = (x_26 + 1i);
x_24_phi_1 = vec2<f32>(1.0f, 1.0f);
x_26_phi_1 = x_27;
}
}
textureStore(Output2Texture2D, vec2<i32>(vec2<u32>(1u, 1u)), vec4<f32>(x_24, 0.0f, 0.0f));
return;
)";
ASSERT_EQ(expect, got);
}
} // namespace
} // namespace tint::reader::spirv