[hlsl] Add `quantizeToF16` support to HLSL IR backend.
This CL adds the polyfill for the `quantizeToF16` method to the HLSL IR
backend.
Bug: 42251045
Change-Id: Ia2d87511151eee979169f5c94c1bd7256b088416
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/198561
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/hlsl/writer/builtin_test.cc b/src/tint/lang/hlsl/writer/builtin_test.cc
index 64ea3a5..7c345dc 100644
--- a/src/tint/lang/hlsl/writer/builtin_test.cc
+++ b/src/tint/lang/hlsl/writer/builtin_test.cc
@@ -1318,6 +1318,24 @@
)");
}
+TEST_F(HlslWriterTest, BuiltinQuantizeToF16) {
+ auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+ b.Append(func->Block(), [&] {
+ auto* v = b.Var("x", b.Zero(ty.vec2<f32>()));
+ b.Let("a", b.Call(ty.vec2<f32>(), core::BuiltinFn::kQuantizeToF16, b.Load(v)));
+ b.Return(func);
+ });
+
+ ASSERT_TRUE(Generate()) << err_ << output_.hlsl;
+ EXPECT_EQ(output_.hlsl, R"(
+void foo() {
+ float2 x = (0.0f).xx;
+ float2 a = f16tof32(f32tof16(x));
+}
+
+)");
+}
+
TEST_F(HlslWriterTest, BuiltinUnpack2x16Float) {
auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
b.Append(func->Block(), [&] {
diff --git a/src/tint/lang/hlsl/writer/raise/builtin_polyfill.cc b/src/tint/lang/hlsl/writer/raise/builtin_polyfill.cc
index ef0d92e..77536a7 100644
--- a/src/tint/lang/hlsl/writer/raise/builtin_polyfill.cc
+++ b/src/tint/lang/hlsl/writer/raise/builtin_polyfill.cc
@@ -87,6 +87,7 @@
}
if (auto* call = inst->As<core::ir::CoreBuiltinCall>()) {
switch (call->Func()) {
+ case core::BuiltinFn::kQuantizeToF16:
case core::BuiltinFn::kSelect:
case core::BuiltinFn::kSign:
case core::BuiltinFn::kTextureDimensions:
@@ -132,6 +133,9 @@
// Replace the builtin calls that we found
for (auto* call : call_worklist) {
switch (call->Func()) {
+ case core::BuiltinFn::kQuantizeToF16:
+ QuantizeToF16(call);
+ break;
case core::BuiltinFn::kSelect:
Select(call);
break;
@@ -824,6 +828,17 @@
});
call->Destroy();
}
+
+ void QuantizeToF16(core::ir::CoreBuiltinCall* call) {
+ auto* u32_type = ty.match_width(ty.u32(), call->Result(0)->Type());
+ b.InsertBefore(call, [&] {
+ auto* inner = b.Call<hlsl::ir::BuiltinCall>(u32_type, hlsl::BuiltinFn::kF32Tof16,
+ call->Args()[0]);
+ b.CallWithResult<hlsl::ir::BuiltinCall>(call->DetachResult(),
+ hlsl::BuiltinFn::kF16Tof32, inner);
+ });
+ call->Destroy();
+ }
};
} // namespace
diff --git a/src/tint/lang/hlsl/writer/raise/builtin_polyfill_test.cc b/src/tint/lang/hlsl/writer/raise/builtin_polyfill_test.cc
index ed52790..c46fba9 100644
--- a/src/tint/lang/hlsl/writer/raise/builtin_polyfill_test.cc
+++ b/src/tint/lang/hlsl/writer/raise/builtin_polyfill_test.cc
@@ -1173,6 +1173,44 @@
EXPECT_EQ(expect, str());
}
+TEST_F(HlslWriter_BuiltinPolyfillTest, QuantizeToF16) {
+ auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
+ b.Append(func->Block(), [&] {
+ auto* v = b.Var("x", b.Zero(ty.vec2<f32>()));
+ b.Let("a", b.Call(ty.vec2<f32>(), core::BuiltinFn::kQuantizeToF16, b.Load(v)));
+ b.Return(func);
+ });
+
+ auto* src = R"(
+%foo = @fragment func():void {
+ $B1: {
+ %x:ptr<function, vec2<f32>, read_write> = var, vec2<f32>(0.0f)
+ %3:vec2<f32> = load %x
+ %4:vec2<f32> = quantizeToF16 %3
+ %a:vec2<f32> = let %4
+ ret
+ }
+}
+)";
+ ASSERT_EQ(src, str());
+
+ auto* expect = R"(
+%foo = @fragment func():void {
+ $B1: {
+ %x:ptr<function, vec2<f32>, read_write> = var, vec2<f32>(0.0f)
+ %3:vec2<f32> = load %x
+ %4:vec2<u32> = hlsl.f32tof16 %3
+ %5:vec2<f32> = hlsl.f16tof32 %4
+ %a:vec2<f32> = let %5
+ ret
+ }
+}
+)";
+ Run(BuiltinPolyfill);
+
+ EXPECT_EQ(expect, str());
+}
+
TEST_F(HlslWriter_BuiltinPolyfillTest, Unpack2x16Float) {
auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
b.Append(func->Block(), [&] {