Update binding_array type for runtime arrays
Update the methods in the `binding_array` type class to support runtime
arrays. This mimics how an array works when set as a runtime array. Add
a `runtime_binding_array` helper method to the type manager.
Bug: 439626909
Change-Id: I1ba30aa19aadd279eeea6bcc919b5136ba1fd92e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/257895
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/core/type/binding_array.cc b/src/tint/lang/core/type/binding_array.cc
index ece058d..7b834b8 100644
--- a/src/tint/lang/core/type/binding_array.cc
+++ b/src/tint/lang/core/type/binding_array.cc
@@ -55,21 +55,36 @@
std::string BindingArray::FriendlyName() const {
StringStream out;
- out << "binding_array<" << element_->FriendlyName() << ", " << count_->FriendlyName() << ">";
+ out << "binding_array<" << element_->FriendlyName();
+
+ auto count_str = count_->FriendlyName();
+ if (!count_str.empty()) {
+ out << ", " << count_str;
+ }
+ out << ">";
+
return out.str();
}
-TypeAndCount BindingArray::Elements([[maybe_unused]] const Type*, [[maybe_unused]] uint32_t) const {
- return {element_, count_->As<ConstantArrayCount>()->value};
+TypeAndCount BindingArray::Elements([[maybe_unused]] const Type*, uint32_t count_if_invalid) const {
+ uint32_t n = count_if_invalid;
+ if (auto* const_count = count_->As<ConstantArrayCount>()) {
+ n = const_count->value;
+ }
+ return {element_, n};
}
const Type* BindingArray::Element(uint32_t index) const {
- return index < count_->As<ConstantArrayCount>()->value ? element_ : nullptr;
+ if (auto* count = count_->As<ConstantArrayCount>()) {
+ return index < count->value ? element_ : nullptr;
+ }
+ return element_;
}
BindingArray* BindingArray::Clone(CloneContext& ctx) const {
auto* elem_ty = element_->Clone(ctx);
- return ctx.dst.mgr->Get<BindingArray>(elem_ty, count_);
+ auto* count = count_->Clone(ctx);
+ return ctx.dst.mgr->Get<BindingArray>(elem_ty, count);
}
} // namespace tint::core::type
diff --git a/src/tint/lang/core/type/binding_array_test.cc b/src/tint/lang/core/type/binding_array_test.cc
index e91e6a1..e6f8ff5 100644
--- a/src/tint/lang/core/type/binding_array_test.cc
+++ b/src/tint/lang/core/type/binding_array_test.cc
@@ -49,6 +49,15 @@
EXPECT_EQ(a->Count()->As<ConstantArrayCount>()->value, 3u);
}
+TEST_F(BindingArrayTest, RuntimeCreation) {
+ Manager ty;
+ auto* t = ty.sampled_texture(TextureDimension::k2d, ty.f32());
+ auto* a = ty.runtime_binding_array(t);
+
+ EXPECT_EQ(a->ElemType(), t);
+ EXPECT_TRUE(a->Count()->Is<RuntimeArrayCount>());
+}
+
TEST_F(BindingArrayTest, Hash) {
Manager ty;
auto* t = ty.sampled_texture(TextureDimension::k2d, ty.f32());
@@ -67,10 +76,24 @@
auto* a2 = ty.binding_array(t1, 3u);
auto* a_count = ty.binding_array(t1, 4u);
auto* a_type = ty.binding_array(t2, 3u);
+ auto* r = ty.runtime_binding_array(t1);
+ auto* r1 = ty.runtime_binding_array(t1);
+ auto* r2 = ty.runtime_binding_array(t2);
EXPECT_EQ(a, a2);
EXPECT_NE(a, a_count);
EXPECT_NE(a, a_type);
+
+ EXPECT_NE(a, r);
+ EXPECT_EQ(r, r1);
+ EXPECT_NE(r, r2);
+}
+
+TEST_F(BindingArrayTest, RuntimeFriendlyName) {
+ Manager ty;
+ auto* t = ty.sampled_texture(TextureDimension::k2d, ty.f32());
+ auto* a = ty.runtime_binding_array(t);
+ EXPECT_EQ(a->FriendlyName(), "binding_array<texture_2d<f32>>");
}
TEST_F(BindingArrayTest, FriendlyName) {
@@ -88,6 +111,14 @@
EXPECT_EQ(a->Element(3), nullptr);
}
+TEST_F(BindingArrayTest, RuntimeElement) {
+ Manager ty;
+ auto* t = ty.sampled_texture(TextureDimension::k2d, ty.f32());
+ auto* a = ty.runtime_binding_array(t);
+ EXPECT_EQ(a->Element(2), t);
+ EXPECT_EQ(a->Element(3), t);
+}
+
TEST_F(BindingArrayTest, Elements) {
Manager ty;
auto* t = ty.sampled_texture(TextureDimension::k2d, ty.f32());
@@ -96,6 +127,14 @@
EXPECT_EQ(a->Elements().count, 3u);
}
+TEST_F(BindingArrayTest, RuntimeElements) {
+ Manager ty;
+ auto* t = ty.sampled_texture(TextureDimension::k2d, ty.f32());
+ auto* a = ty.runtime_binding_array(t);
+ EXPECT_EQ(a->Elements().type, t);
+ EXPECT_EQ(a->Elements().count, 0u);
+}
+
TEST_F(BindingArrayTest, Clone) {
Manager ty;
auto* t = ty.sampled_texture(TextureDimension::k2d, ty.f32());
@@ -111,5 +150,19 @@
EXPECT_EQ(s->Count()->As<ConstantArrayCount>()->value, 3u);
}
+TEST_F(BindingArrayTest, RuntimeClone) {
+ Manager ty;
+ auto* t = ty.sampled_texture(TextureDimension::k2d, ty.f32());
+ auto* a = ty.runtime_binding_array(t);
+
+ core::type::Manager mgr;
+ core::type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
+
+ auto* s = a->Clone(ctx);
+ EXPECT_TRUE(s->ElemType()->Is<SampledTexture>());
+ EXPECT_TRUE(s->ElemType()->As<SampledTexture>()->Type()->Is<F32>());
+ EXPECT_TRUE(s->Count()->Is<RuntimeArrayCount>());
+}
+
} // namespace
} // namespace tint::core::type
diff --git a/src/tint/lang/core/type/manager.cc b/src/tint/lang/core/type/manager.cc
index a3658d3..4969d1c 100644
--- a/src/tint/lang/core/type/manager.cc
+++ b/src/tint/lang/core/type/manager.cc
@@ -339,6 +339,10 @@
return Get<core::type::BindingArray>(elem_ty, Get<ConstantArrayCount>(count));
}
+const core::type::BindingArray* Manager::runtime_binding_array(const core::type::Type* elem_ty) {
+ return Get<core::type::BindingArray>(elem_ty, Get<RuntimeArrayCount>());
+}
+
const core::type::Pointer* Manager::ptr(core::AddressSpace address_space,
const core::type::Type* subtype,
core::Access access /* = core::Access::kUndefined */) {
diff --git a/src/tint/lang/core/type/manager.h b/src/tint/lang/core/type/manager.h
index 9036bcf..c2b3a01 100644
--- a/src/tint/lang/core/type/manager.h
+++ b/src/tint/lang/core/type/manager.h
@@ -565,6 +565,10 @@
/// @returns the array type
const core::type::BindingArray* binding_array(const core::type::Type* elem_ty, uint32_t count);
+ /// @param elem_ty the array element type
+ /// @returns the array type
+ const core::type::BindingArray* runtime_binding_array(const core::type::Type* elem_ty);
+
/// @param address_space the address space
/// @param subtype the pointer subtype
/// @param access the access settings