[hlsl] Support `textureNumLayers`
This CL adds support to the HLSL IR backend for `textureNumLayers`.
Bug: 42251045
Change-Id: I43e83c7d56162197fde5cee51831001a75761841
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/197356
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/lang/hlsl/writer/builtin_test.cc b/src/tint/lang/hlsl/writer/builtin_test.cc
index 97bb1b3..099b78a 100644
--- a/src/tint/lang/hlsl/writer/builtin_test.cc
+++ b/src/tint/lang/hlsl/writer/builtin_test.cc
@@ -840,5 +840,59 @@
)");
}
+TEST_F(HlslWriterTest, BuiltinTextureLayers2dArray) {
+ auto* t = b.FunctionParam(
+ "t", ty.Get<core::type::SampledTexture>(core::type::TextureDimension::k2dArray, ty.f32()));
+
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({t});
+
+ b.Append(func->Block(), [&] {
+ b.Let("d", b.Call(ty.u32(), core::BuiltinFn::kTextureNumLayers, t));
+ b.Return(func);
+ });
+
+ ASSERT_TRUE(Generate()) << err_ << output_.hlsl;
+ EXPECT_EQ(output_.hlsl, R"(
+void foo(Texture2DArray<float4> t) {
+ uint3 v = (0u).xxx;
+ t.GetDimensions(v[0u], v[1u], v[2u]);
+ uint d = v.z;
+}
+
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+}
+
+)");
+}
+
+TEST_F(HlslWriterTest, BuiltinTextureNumLayersCubeArray) {
+ auto* t = b.FunctionParam("t", ty.Get<core::type::SampledTexture>(
+ core::type::TextureDimension::kCubeArray, ty.f32()));
+
+ auto* func = b.Function("foo", ty.void_());
+ func->SetParams({t});
+
+ b.Append(func->Block(), [&] {
+ b.Let("d", b.Call(ty.u32(), core::BuiltinFn::kTextureNumLayers, t));
+ b.Return(func);
+ });
+
+ ASSERT_TRUE(Generate()) << err_ << output_.hlsl;
+ EXPECT_EQ(output_.hlsl, R"(
+void foo(TextureCubeArray<float4> t) {
+ uint3 v = (0u).xxx;
+ t.GetDimensions(v[0u], v[1u], v[2u]);
+ uint d = v.z;
+}
+
+[numthreads(1, 1, 1)]
+void unused_entry_point() {
+}
+
+)");
+}
+
} // namespace
} // namespace tint::hlsl::writer
diff --git a/src/tint/lang/hlsl/writer/raise/builtin_polyfill.cc b/src/tint/lang/hlsl/writer/raise/builtin_polyfill.cc
index ef5ce91..34fbe0c 100644
--- a/src/tint/lang/hlsl/writer/raise/builtin_polyfill.cc
+++ b/src/tint/lang/hlsl/writer/raise/builtin_polyfill.cc
@@ -80,6 +80,7 @@
switch (call->Func()) {
case core::BuiltinFn::kSelect:
case core::BuiltinFn::kSign:
+ case core::BuiltinFn::kTextureNumLayers:
case core::BuiltinFn::kTextureNumLevels:
case core::BuiltinFn::kTrunc:
call_worklist.Push(call);
@@ -117,6 +118,9 @@
case core::BuiltinFn::kSign:
Sign(call);
break;
+ case core::BuiltinFn::kTextureNumLayers:
+ TextureNumLayers(call);
+ break;
case core::BuiltinFn::kTextureNumLevels:
TextureNumLevels(call);
break;
@@ -385,6 +389,30 @@
bitcast->Destroy();
}
+ void TextureNumLayers(core::ir::CoreBuiltinCall* call) {
+ auto* tex = call->Args()[0];
+ auto* tex_type = tex->Type()->As<core::type::Texture>();
+
+ TINT_ASSERT(tex_type->dim() == core::type::TextureDimension::k2dArray ||
+ tex_type->dim() == core::type::TextureDimension::kCubeArray);
+
+ const core::type::Type* query_ty = ty.vec(ty.u32(), 3);
+ b.InsertBefore(call, [&] {
+ core::ir::Instruction* out = b.Var(ty.ptr(function, query_ty));
+
+ b.MemberCall<hlsl::ir::MemberBuiltinCall>(
+ ty.void_(), hlsl::BuiltinFn::kGetDimensions, tex,
+ Vector<core::ir::Value*, 3>{
+ b.Access(ty.ptr<function, u32>(), out, 0_u)->Result(0),
+ b.Access(ty.ptr<function, u32>(), out, 1_u)->Result(0),
+ b.Access(ty.ptr<function, u32>(), out, 2_u)->Result(0)});
+
+ out = b.Swizzle(ty.u32(), out, {2_u});
+ call->Result(0)->ReplaceAllUsesWith(out->Result(0));
+ });
+ call->Destroy();
+ }
+
void TextureNumLevels(core::ir::CoreBuiltinCall* call) {
auto* tex = call->Args()[0];
auto* tex_type = tex->Type()->As<core::type::Texture>();
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 1b2165a..829c9a3 100644
--- a/src/tint/lang/hlsl/writer/raise/builtin_polyfill_test.cc
+++ b/src/tint/lang/hlsl/writer/raise/builtin_polyfill_test.cc
@@ -497,5 +497,45 @@
EXPECT_EQ(expect, str());
}
+TEST_F(HlslWriter_BuiltinPolyfillTest, TextureNumLayers) {
+ auto* t = b.FunctionParam("t", ty.Get<core::type::SampledTexture>(
+ core::type::TextureDimension::kCubeArray, ty.f32()));
+ auto* func = b.Function("foo", ty.u32());
+ func->SetParams({t});
+ b.Append(func->Block(), [&] {
+ auto* result = b.Call<u32>(core::BuiltinFn::kTextureNumLayers, t);
+ b.Return(func, result);
+ });
+
+ auto* src = R"(
+%foo = func(%t:texture_cube_array<f32>):u32 {
+ $B1: {
+ %3:u32 = textureNumLayers %t
+ ret %3
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+%foo = func(%t:texture_cube_array<f32>):u32 {
+ $B1: {
+ %3:ptr<function, vec3<u32>, read_write> = var
+ %4:ptr<function, u32, read_write> = access %3, 0u
+ %5:ptr<function, u32, read_write> = access %3, 1u
+ %6:ptr<function, u32, read_write> = access %3, 2u
+ %7:void = %t.GetDimensions %4, %5, %6
+ %8:u32 = swizzle %3, z
+ ret %8
+ }
+}
+)";
+
+ capabilities = core::ir::Capabilities{core::ir::Capability::kAllowVectorElementPointer};
+ Run(BuiltinPolyfill);
+
+ EXPECT_EQ(expect, str());
+}
+
} // namespace
} // namespace tint::hlsl::writer::raise