spirv-reader: Fix for SelectUsingReferenceVariable
Started from https://dawn-review.googlesource.com/c/dawn/+/99220/2
Fixed: tint:1650
Change-Id: Ic5e097135a54c68e2cb9736198082179b522a4ba
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/101069
Commit-Queue: David Neto <dneto@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/reader/spirv/function.cc b/src/tint/reader/spirv/function.cc
index 7824ca4..0acfa1d 100644
--- a/src/tint/reader/spirv/function.cc
+++ b/src/tint/reader/spirv/function.cc
@@ -5000,7 +5000,7 @@
// - true_value false_value, and result type to match.
// - you can't select over pointers or pointer vectors, unless you also have
// a VariablePointers* capability, which is not allowed in by WebGPU.
- auto* op_ty = true_value.type;
+ auto* op_ty = true_value.type->UnwrapRef();
if (op_ty->Is<Vector>() || op_ty->IsFloatScalar() || op_ty->IsIntegerScalar() ||
op_ty->Is<Bool>()) {
ExpressionList params;
diff --git a/src/tint/reader/spirv/parser_impl_handle_test.cc b/src/tint/reader/spirv/parser_impl_handle_test.cc
index 3c10961..a165f7b 100644
--- a/src/tint/reader/spirv/parser_impl_handle_test.cc
+++ b/src/tint/reader/spirv/parser_impl_handle_test.cc
@@ -4009,5 +4009,82 @@
ASSERT_EQ(expect, got);
}
+TEST_F(SpvParserHandleTest, SimpleSelectCanSelectFromHoistedConstant) {
+ // Demonstrates fix for crbug.com/tint/1642
+ // The problem is an operand to a simple select can be a value
+ // that is hoisted into a 'var' declaration.
+ //
+ // The selection-generation logic has to UnwrapRef if needed.
+ const auto assembly = Preamble() + R"(
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %100 "main" %gl_Position
+ OpSource HLSL 600
+ OpName %100 "main"
+ OpDecorate %gl_Position BuiltIn Position
+ %float = OpTypeFloat 32
+ %float_0 = OpConstant %float 0
+ %float_1 = OpConstant %float 1
+ %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+ %void = OpTypeVoid
+ %9 = OpTypeFunction %void
+ %bool = OpTypeBool
+%gl_Position = OpVariable %_ptr_Output_v4float Output
+ %11 = OpUndef %float
+ %100 = OpFunction %void None %9
+ %12 = OpLabel
+ OpBranch %13
+ %13 = OpLabel
+ %14 = OpPhi %float %11 %12 %15 %16
+ %15 = OpPhi %float %float_0 %12 %17 %16
+ %18 = OpFOrdLessThan %bool %15 %float_1
+ OpLoopMerge %19 %16 None
+ OpBranchConditional %18 %16 %19
+ %16 = OpLabel
+ %17 = OpFAdd %float %15 %float_1
+ OpBranch %13
+ %19 = OpLabel
+ %20 = OpFOrdGreaterThan %bool %14 %float_1
+ %21 = OpSelect %float %20 %14 %float_0
+ %22 = OpCompositeConstruct %v4float %21 %21 %21 %21
+ OpStore %gl_Position %22
+ 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_14 : f32;
+var x_14_phi_1 : f32;
+var x_15_phi_1 : f32;
+x_14_phi_1 = 0.0f;
+x_15_phi_1 = 0.0f;
+loop {
+ var x_17 : f32;
+ x_14 = x_14_phi_1;
+ let x_15 : f32 = x_15_phi_1;
+ if ((x_15 < 1.0f)) {
+ } else {
+ break;
+ }
+
+ continuing {
+ x_17 = (x_15 + 1.0f);
+ x_14_phi_1 = x_15;
+ x_15_phi_1 = x_17;
+ }
+}
+let x_21 : f32 = select(0.0f, x_14, (x_14 > 1.0f));
+x_1 = vec4<f32>(x_21, x_21, x_21, x_21);
+return;
+)";
+ ASSERT_EQ(expect, got);
+}
+
} // namespace
} // namespace tint::reader::spirv