[hlsl] Emit `swizzle` instructions
This CL adds `swizzle` support to the HLSL IR backend.
Bug: 42251045
Change-Id: Id3986fb5ef81536f8eba3a9003e61a86929c23b5
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/194025
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/lang/hlsl/writer/access_test.cc b/src/tint/lang/hlsl/writer/access_test.cc
index 087b791..84764f4 100644
--- a/src/tint/lang/hlsl/writer/access_test.cc
+++ b/src/tint/lang/hlsl/writer/access_test.cc
@@ -183,5 +183,47 @@
)");
}
+TEST_F(HlslWriterTest, AccessSwizzle) {
+ auto* f = b.Function("a", ty.void_(), core::ir::Function::PipelineStage::kCompute);
+ f->SetWorkgroupSize(1, 1, 1);
+
+ b.Append(f->Block(), [&] {
+ auto* v = b.Var("v", b.Zero<vec3<f32>>());
+ b.Let("b", b.Swizzle(ty.f32(), v, {1u}));
+ b.Return(f);
+ });
+
+ ASSERT_TRUE(Generate()) << err_ << output_.hlsl;
+ EXPECT_EQ(output_.hlsl, R"(
+[numthreads(1, 1, 1)]
+void a() {
+ float3 v = (0.0f).xxx;
+ float b = v.y;
+}
+
+)");
+}
+
+TEST_F(HlslWriterTest, AccessSwizzleMulti) {
+ auto* f = b.Function("a", ty.void_(), core::ir::Function::PipelineStage::kCompute);
+ f->SetWorkgroupSize(1, 1, 1);
+
+ b.Append(f->Block(), [&] {
+ auto* v = b.Var("v", b.Zero<vec4<f32>>());
+ b.Let("b", b.Swizzle(ty.vec4<f32>(), v, {3u, 2u, 1u, 0u}));
+ b.Return(f);
+ });
+
+ ASSERT_TRUE(Generate()) << err_ << output_.hlsl;
+ EXPECT_EQ(output_.hlsl, R"(
+[numthreads(1, 1, 1)]
+void a() {
+ float4 v = (0.0f).xxxx;
+ float4 b = v.wzyx;
+}
+
+)");
+}
+
} // namespace
} // namespace tint::hlsl::writer
diff --git a/src/tint/lang/hlsl/writer/printer/printer.cc b/src/tint/lang/hlsl/writer/printer/printer.cc
index 99dc490..e9d3229 100644
--- a/src/tint/lang/hlsl/writer/printer/printer.cc
+++ b/src/tint/lang/hlsl/writer/printer/printer.cc
@@ -387,12 +387,36 @@
[&](const core::ir::Let* l) { out << NameOf(l->Result(0)); }, //
[&](const core::ir::Load* l) { EmitLoad(out, l); }, //
[&](const core::ir::UserCall* c) { EmitUserCall(out, c); }, //
+ [&](const core::ir::Swizzle* s) { EmitSwizzle(out, s); }, //
[&](const core::ir::Var* var) { out << NameOf(var->Result(0)); }, //
TINT_ICE_ON_NO_MATCH);
},
TINT_ICE_ON_NO_MATCH);
}
+ void EmitSwizzle(StringStream& out, const core::ir::Swizzle* swizzle) {
+ EmitValue(out, swizzle->Object());
+ out << ".";
+ for (const auto i : swizzle->Indices()) {
+ switch (i) {
+ case 0:
+ out << "x";
+ break;
+ case 1:
+ out << "y";
+ break;
+ case 2:
+ out << "z";
+ break;
+ case 3:
+ out << "w";
+ break;
+ default:
+ TINT_UNREACHABLE();
+ }
+ }
+ }
+
/// Emit an access instruction
void EmitAccess(StringStream& out, const core::ir::Access* a) {
EmitValue(out, a->Object());