tint/msl: Preserve trailing vec3 padding

In order to preserve padding properly for MSL, we need to use its
packed_vec type for all vec3 types in storage buffers, not just struct
members. This commit includes a complete rewrite of the PackedVec3
transform to achieve this. The key details are:

* An internal `__packed_vec3<>` type was added, which corresponds to a
  `type::Vector` with an additional flag to indicate that it will be
  emitted as packed vector.

* The `PackedVec3` transform replaces all vec3 types used in
  host-shareable address spaces with the internal `__packed_vec3`
  type. This includes vec3 types that appear as the store type of a
  pointer.

* When used as an array element, these `__packed_vec3` types are
  wrapped in a struct that contains a single `__packed_vec3`
  member. This allows us to add an `@align()` attribute that ensures
  that `array<vec3<T>>` still has the correct array element stride.

* When the `vec3<T>` appears as a struct member in the input program,
  we apply the `@align()` to that member to ensure that we do not
  change its offset.

* Matrix types with three rows that are used in memory are replaced
  with an array of columns, where each column uses a `__packed_vec3`
  inside an aligned wrapper structure as above.

* Accesses to host-shareable memory that involve any of these types
  invoke a "pack" or "unpack" helper function to convert them to the
  equivalent type that uses `__packed_vec3` or a regular `vec3` as
  required.

* The `chromium_internal_relaxed_uniform_layout` extension is used to
  avoid issues where modifying a type in the uniform address space
  triggers stricter layout validation rules.

Bug: tint:1571
Fixed: tint:1837
Change-Id: Idaf2da2f5bcb2be00c85ec657edfb614186476bb
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/121200
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
James Price
2023-02-27 20:21:03 +00:00
committed by Dawn LUCI CQ
parent 55183e6c3a
commit 4d3af66bbd
389 changed files with 16692 additions and 3527 deletions

View File

@@ -23,15 +23,16 @@ TINT_INSTANTIATE_TYPEINFO(tint::type::Vector);
namespace tint::type {
Vector::Vector(Type const* subtype, uint32_t width)
: Base(utils::Hash(TypeInfo::Of<Vector>().full_hashcode, width, subtype),
Vector::Vector(Type const* subtype, uint32_t width, bool packed /* = false */)
: Base(utils::Hash(TypeInfo::Of<Vector>().full_hashcode, width, subtype, packed),
type::Flags{
Flag::kConstructable,
Flag::kCreationFixedFootprint,
Flag::kFixedFootprint,
}),
subtype_(subtype),
width_(width) {
width_(width),
packed_(packed) {
TINT_ASSERT(Type, width_ > 1);
TINT_ASSERT(Type, width_ < 5);
}
@@ -40,13 +41,16 @@ Vector::~Vector() = default;
bool Vector::Equals(const UniqueNode& other) const {
if (auto* v = other.As<Vector>()) {
return v->width_ == width_ && v->subtype_ == subtype_;
return v->width_ == width_ && v->subtype_ == subtype_ && v->packed_ == packed_;
}
return false;
}
std::string Vector::FriendlyName(const SymbolTable& symbols) const {
std::ostringstream out;
if (packed_) {
out << "__packed_";
}
out << "vec" << width_ << "<" << subtype_->FriendlyName(symbols) << ">";
return out.str();
}
@@ -60,7 +64,7 @@ uint32_t Vector::Align() const {
case 2:
return subtype_->Size() * 2;
case 3:
return subtype_->Size() * 4;
return subtype_->Size() * (packed_ ? 1 : 4);
case 4:
return subtype_->Size() * 4;
}
@@ -69,7 +73,7 @@ uint32_t Vector::Align() const {
Vector* Vector::Clone(CloneContext& ctx) const {
auto* subtype = subtype_->Clone(ctx);
return ctx.dst.mgr->Get<Vector>(subtype, width_);
return ctx.dst.mgr->Get<Vector>(subtype, width_, packed_);
}
} // namespace tint::type

View File

@@ -22,12 +22,13 @@
namespace tint::type {
/// A vector type.
class Vector final : public Castable<Vector, Type> {
class Vector : public Castable<Vector, Type> {
public:
/// Constructor
/// @param subtype the vector element type
/// @param size the number of elements in the vector
Vector(Type const* subtype, uint32_t size);
/// @param packed the optional 'packed' modifier
Vector(Type const* subtype, uint32_t size, bool packed = false);
/// Destructor
~Vector() override;
@@ -50,10 +51,12 @@ class Vector final : public Castable<Vector, Type> {
/// @returns the size in bytes of the type. This may include tail padding.
uint32_t Size() const override;
/// @returns the alignment in bytes of the type. This may include tail
/// padding.
/// @returns the alignment in bytes of the type. This may include tail padding.
uint32_t Align() const override;
/// @returns `true` if this vector is packed, false otherwise
bool Packed() const { return packed_; }
/// @param width the width of the vector
/// @returns the size in bytes of a vector of the given width.
static uint32_t SizeOf(uint32_t width);
@@ -69,6 +72,7 @@ class Vector final : public Castable<Vector, Type> {
private:
Type const* const subtype_;
const uint32_t width_;
const bool packed_;
};
} // namespace tint::type

View File

@@ -34,6 +34,21 @@ TEST_F(VectorTest, Creation) {
EXPECT_NE(a, d);
}
TEST_F(VectorTest, Creation_Packed) {
auto* v = create<Vector>(create<F32>(), 3u);
auto* p1 = create<Vector>(create<F32>(), 3u, true);
auto* p2 = create<Vector>(create<F32>(), 3u, true);
EXPECT_FALSE(v->Packed());
EXPECT_EQ(p1->type(), create<F32>());
EXPECT_EQ(p1->Width(), 3u);
EXPECT_TRUE(p1->Packed());
EXPECT_NE(v, p1);
EXPECT_EQ(p1, p2);
}
TEST_F(VectorTest, Hash) {
auto* a = create<Vector>(create<I32>(), 2u);
auto* b = create<Vector>(create<I32>(), 2u);
@@ -59,6 +74,12 @@ TEST_F(VectorTest, FriendlyName) {
EXPECT_EQ(v->FriendlyName(Symbols()), "vec3<f32>");
}
TEST_F(VectorTest, FriendlyName_Packed) {
auto* f32 = create<F32>();
auto* v = create<Vector>(f32, 3u, true);
EXPECT_EQ(v->FriendlyName(Symbols()), "__packed_vec3<f32>");
}
TEST_F(VectorTest, Clone) {
auto* a = create<Vector>(create<I32>(), 2u);
@@ -68,6 +89,19 @@ TEST_F(VectorTest, Clone) {
auto* vec = a->Clone(ctx);
EXPECT_TRUE(vec->type()->Is<I32>());
EXPECT_EQ(vec->Width(), 2u);
EXPECT_FALSE(vec->Packed());
}
TEST_F(VectorTest, Clone_Packed) {
auto* a = create<Vector>(create<I32>(), 3u, true);
type::Manager mgr;
type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
auto* vec = a->Clone(ctx);
EXPECT_TRUE(vec->type()->Is<I32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TRUE(vec->Packed());
}
} // namespace