[spirv-reader][shader-io] Fold away lets to var's.
If there is a `let` of a `var` (which can happen from an `OpCopyObject`)
then we need to fold away the let and use the var directly in ShaderIO.
The var then folds away and becomes an input parameter.
Add support for folding through `lets`.
Bug: 42250952
Change-Id: I91db43a07cafcb4d1f1d9b50019316883e36db79
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/245594
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/spirv/reader/lower/shader_io.cc b/src/tint/lang/spirv/reader/lower/shader_io.cc
index 84382b4..ceaccf0 100644
--- a/src/tint/lang/spirv/reader/lower/shader_io.cc
+++ b/src/tint/lang/spirv/reader/lower/shader_io.cc
@@ -365,6 +365,11 @@
a->Result()->SetType(a->Result()->Type()->UnwrapPtr());
ReplaceInputPointerUses(var, a->Result());
},
+ [&](core::ir::Let* l) {
+ // Fold away
+ ReplaceInputPointerUses(var, l->Result());
+ to_destroy.Push(l);
+ },
TINT_ICE_ON_NO_MATCH);
});
diff --git a/src/tint/lang/spirv/reader/lower/shader_io_test.cc b/src/tint/lang/spirv/reader/lower/shader_io_test.cc
index 5471411..d1515a3 100644
--- a/src/tint/lang/spirv/reader/lower/shader_io_test.cc
+++ b/src/tint/lang/spirv/reader/lower/shader_io_test.cc
@@ -286,6 +286,100 @@
EXPECT_EQ(expect, str());
}
+TEST_F(SpirvReader_ShaderIOTest, Inputs_Copied) {
+ auto* val = b.Var("val", ty.ptr(core::AddressSpace::kIn, ty.u32()));
+ val->SetBuiltin(core::BuiltinValue::kSampleIndex);
+ mod.root_block->Append(val);
+
+ auto* f = b.Function("main", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+ b.Append(f->Block(), [&] {
+ auto* c = b.Let("copy", val);
+ b.Let("res", b.Load(c));
+ b.Return(f);
+ });
+
+ auto* src = R"(
+$B1: { # root
+ %val:ptr<__in, u32, read> = var undef @builtin(sample_index)
+}
+
+%main = @fragment func():void {
+ $B2: {
+ %copy:ptr<__in, u32, read> = let %val
+ %4:u32 = load %copy
+ %res:u32 = let %4
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%main = @fragment func(%val:u32 [@sample_index]):void {
+ $B1: {
+ %res:u32 = let %val
+ ret
+ }
+}
+)";
+
+ Run(ShaderIO);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(SpirvReader_ShaderIOTest, Inputs_Copied_Chain) {
+ auto* val = b.Var("val", ty.ptr(core::AddressSpace::kIn, ty.u32()));
+ val->SetBuiltin(core::BuiltinValue::kSampleIndex);
+ mod.root_block->Append(val);
+
+ auto* f = b.Function("main", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+ b.Append(f->Block(), [&] {
+ auto* c1 = b.Let("c1", val);
+ auto* c2 = b.Let("c2", c1);
+ auto* c3 = b.Let("c3", c2);
+ auto* c4 = b.Let("c4", c3);
+ auto* c5 = b.Let("c5", c4);
+ auto* c6 = b.Let("c6", c5);
+ b.Let("res", b.Load(c6));
+ b.Return(f);
+ });
+
+ auto* src = R"(
+$B1: { # root
+ %val:ptr<__in, u32, read> = var undef @builtin(sample_index)
+}
+
+%main = @fragment func():void {
+ $B2: {
+ %c1:ptr<__in, u32, read> = let %val
+ %c2:ptr<__in, u32, read> = let %c1
+ %c3:ptr<__in, u32, read> = let %c2
+ %c4:ptr<__in, u32, read> = let %c3
+ %c5:ptr<__in, u32, read> = let %c4
+ %c6:ptr<__in, u32, read> = let %c5
+ %9:u32 = load %c6
+ %res:u32 = let %9
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%main = @fragment func(%val:u32 [@sample_index]):void {
+ $B1: {
+ %res:u32 = let %val
+ ret
+ }
+}
+)";
+
+ Run(ShaderIO);
+
+ EXPECT_EQ(expect, str());
+}
+
TEST_F(SpirvReader_ShaderIOTest, Inputs_UsedEntryPointAndHelper) {
auto* gid = b.Var("gid", ty.ptr(core::AddressSpace::kIn, ty.vec3<u32>()));
gid->SetBuiltin(core::BuiltinValue::kGlobalInvocationId);