tint/writer/msl: Move packed_vector hacks to transform
Attempting to paper over all the MSL standard library holes for packed_vector in the MSL writer added complexity to the writer, produced messy output, and didn't actually catch all the cases where casts were needed.
Add a new PackedVec3 transform that applies the packed_vector -> vec casts in a smarter, more precise way.
Fixed: tint:1534
Change-Id: I73ce7e5a62fbc9cb04e1093133070f5fb8965dce
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/107340
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Commit-Queue: Ben Clayton <bclayton@chromium.org>
diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn
index 6560b6f..d2c69e1 100644
--- a/src/tint/BUILD.gn
+++ b/src/tint/BUILD.gn
@@ -517,6 +517,8 @@
"transform/multiplanar_external_texture.h",
"transform/num_workgroups_from_uniform.cc",
"transform/num_workgroups_from_uniform.h",
+ "transform/packed_vec3.cc",
+ "transform/packed_vec3.h",
"transform/pad_structs.cc",
"transform/pad_structs.h",
"transform/promote_initializers_to_let.cc",
@@ -1225,6 +1227,7 @@
"transform/module_scope_var_to_entry_point_param_test.cc",
"transform/multiplanar_external_texture_test.cc",
"transform/num_workgroups_from_uniform_test.cc",
+ "transform/packed_vec3_test.cc",
"transform/pad_structs_test.cc",
"transform/promote_initializers_to_let_test.cc",
"transform/promote_side_effects_to_decl_test.cc",
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt
index af4384c..47b44a5 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -430,6 +430,8 @@
transform/multiplanar_external_texture.h
transform/num_workgroups_from_uniform.cc
transform/num_workgroups_from_uniform.h
+ transform/packed_vec3.cc
+ transform/packed_vec3.h
transform/pad_structs.cc
transform/pad_structs.h
transform/promote_initializers_to_let.cc
@@ -1141,6 +1143,7 @@
transform/module_scope_var_to_entry_point_param_test.cc
transform/multiplanar_external_texture_test.cc
transform/num_workgroups_from_uniform_test.cc
+ transform/packed_vec3_test.cc
transform/pad_structs_test.cc
transform/promote_initializers_to_let_test.cc
transform/promote_side_effects_to_decl_test.cc
diff --git a/src/tint/transform/packed_vec3.cc b/src/tint/transform/packed_vec3.cc
new file mode 100644
index 0000000..dde5aca
--- /dev/null
+++ b/src/tint/transform/packed_vec3.cc
@@ -0,0 +1,194 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/transform/packed_vec3.h"
+
+#include <algorithm>
+#include <string>
+#include <utility>
+
+#include "src/tint/program_builder.h"
+#include "src/tint/sem/index_accessor_expression.h"
+#include "src/tint/sem/member_accessor_expression.h"
+#include "src/tint/sem/statement.h"
+#include "src/tint/sem/variable.h"
+#include "src/tint/utils/hashmap.h"
+#include "src/tint/utils/hashset.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::transform::PackedVec3);
+TINT_INSTANTIATE_TYPEINFO(tint::transform::PackedVec3::Attribute);
+
+using namespace tint::number_suffixes; // NOLINT
+
+namespace tint::transform {
+
+/// The PIMPL state for the PackedVec3 transform
+struct PackedVec3::State {
+ /// Constructor
+ /// @param c the CloneContext
+ explicit State(CloneContext& c) : ctx(c) {}
+
+ /// Runs the transform
+ void Run() {
+ // Packed vec3<T> struct members
+ utils::Hashset<const sem::StructMember*, 8> members;
+
+ // Find all the packed vector struct members, and apply the @internal(packed_vector)
+ // attribute.
+ for (auto* decl : ctx.src->AST().GlobalDeclarations()) {
+ if (auto* str = sem.Get<sem::Struct>(decl)) {
+ if (str->IsHostShareable()) {
+ for (auto* member : str->Members()) {
+ if (auto* vec = member->Type()->As<sem::Vector>()) {
+ if (vec->Width() == 3) {
+ members.Add(member);
+
+ // Apply the PackedVec3::Attribute to the member
+ auto* member_decl = member->Declaration();
+ auto name = ctx.Clone(member_decl->symbol);
+ auto* type = ctx.Clone(member_decl->type);
+ utils::Vector<const ast::Attribute*, 4> attrs{
+ b.ASTNodes().Create<Attribute>(b.ID(), b.AllocateNodeID()),
+ };
+ for (auto* attr : member_decl->attributes) {
+ attrs.Push(ctx.Clone(attr));
+ }
+ ctx.Replace(member_decl, b.Member(name, type, std::move(attrs)));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Walk the nodes, starting with the most deeply nested, finding all the AST expressions
+ // that load a whole packed vector (not a scalar / swizzle of the vector).
+ utils::Hashset<const sem::Expression*, 16> refs;
+ for (auto* node : ctx.src->ASTNodes().Objects()) {
+ Switch(
+ sem.Get(node), //
+ [&](const sem::StructMemberAccess* access) {
+ if (members.Contains(access->Member())) {
+ // Access to a packed vector member. Seed the expression tracking.
+ refs.Add(access);
+ }
+ },
+ [&](const sem::IndexAccessorExpression* access) {
+ // Not loading a whole packed vector. Ignore.
+ refs.Remove(access->Object());
+ },
+ [&](const sem::Swizzle* access) {
+ // Not loading a whole packed vector. Ignore.
+ refs.Remove(access->Object());
+ },
+ [&](const sem::VariableUser* user) {
+ auto* v = user->Variable();
+ if (v->Declaration()->Is<ast::Let>() && // if variable is let...
+ v->Type()->Is<sem::Pointer>() && // and let is a pointer...
+ refs.Contains(v->Initializer())) { // and pointer is to a packed vector...
+ refs.Add(user); // then propagate tracking to pointer usage
+ }
+ },
+ [&](const sem::Expression* expr) {
+ if (auto* unary = expr->Declaration()->As<ast::UnaryOpExpression>()) {
+ if (unary->op == ast::UnaryOp::kAddressOf ||
+ unary->op == ast::UnaryOp::kIndirection) {
+ // Memory access on the packed vector. Track these.
+ auto* inner = sem.Get(unary->expr);
+ if (refs.Remove(inner)) {
+ refs.Add(expr);
+ }
+ }
+ // Note: non-memory ops (e.g. '-') are ignored, leaving any tracked
+ // reference at the inner expression, so we'd cast, then apply the unary op.
+ }
+ },
+ [&](const sem::Statement* e) {
+ if (auto* assign = e->Declaration()->As<ast::AssignmentStatement>()) {
+ // We don't want to cast packed_vectors if they're being assigned to.
+ refs.Remove(sem.Get(assign->lhs));
+ }
+ });
+ }
+
+ // Wrap the load expressions with a cast to the unpacked type.
+ utils::Hashmap<const sem::Vector*, Symbol, 3> unpack_fns;
+ for (auto* ref : refs) {
+ // ref is either a packed vec3 that needs casting, or a pointer to a vec3 which we just
+ // leave alone.
+ if (auto* vec_ty = ref->Type()->UnwrapRef()->As<sem::Vector>()) {
+ auto* expr = ref->Declaration();
+ ctx.Replace(expr, [this, vec_ty, expr] { //
+ auto* packed = ctx.CloneWithoutTransform(expr);
+ return b.Construct(CreateASTTypeFor(ctx, vec_ty), packed);
+ });
+ }
+ }
+
+ ctx.Clone();
+ }
+
+ /// @returns true if this transform should be run for the given program
+ /// @param program the program to inspect
+ static bool ShouldRun(const Program* program) {
+ for (auto* decl : program->AST().GlobalDeclarations()) {
+ if (auto* str = program->Sem().Get<sem::Struct>(decl)) {
+ if (str->IsHostShareable()) {
+ for (auto* member : str->Members()) {
+ if (auto* vec = member->Type()->As<sem::Vector>()) {
+ if (vec->Width() == 3) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ private:
+ /// The clone context
+ CloneContext& ctx;
+ /// Alias to the semantic info in ctx.src
+ const sem::Info& sem = ctx.src->Sem();
+ /// Alias to the symbols in ctx.src
+ const SymbolTable& sym = ctx.src->Symbols();
+ /// Alias to the ctx.dst program builder
+ ProgramBuilder& b = *ctx.dst;
+};
+
+PackedVec3::Attribute::Attribute(ProgramID pid, ast::NodeID nid) : Base(pid, nid) {}
+PackedVec3::Attribute::~Attribute() = default;
+
+const PackedVec3::Attribute* PackedVec3::Attribute::Clone(CloneContext* ctx) const {
+ return ctx->dst->ASTNodes().Create<Attribute>(ctx->dst->ID(), ctx->dst->AllocateNodeID());
+}
+
+std::string PackedVec3::Attribute::InternalName() const {
+ return "packed_vector";
+}
+
+PackedVec3::PackedVec3() = default;
+PackedVec3::~PackedVec3() = default;
+
+bool PackedVec3::ShouldRun(const Program* program, const DataMap&) const {
+ return State::ShouldRun(program);
+}
+
+void PackedVec3::Run(CloneContext& ctx, const DataMap&, DataMap&) const {
+ State(ctx).Run();
+}
+
+} // namespace tint::transform
diff --git a/src/tint/transform/packed_vec3.h b/src/tint/transform/packed_vec3.h
new file mode 100644
index 0000000..9d899cb
--- /dev/null
+++ b/src/tint/transform/packed_vec3.h
@@ -0,0 +1,78 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_TRANSFORM_PACKED_VEC3_H_
+#define SRC_TINT_TRANSFORM_PACKED_VEC3_H_
+
+#include <string>
+
+#include "src/tint/ast/internal_attribute.h"
+#include "src/tint/transform/transform.h"
+
+namespace tint::transform {
+
+/// A transform to be used by the MSL backend which will:
+/// * Apply the `@internal('packed_vector')` attribute (PackedVec3::Attribute) to all host-sharable
+/// structure members that have a vec3<T> type.
+/// * Cast all direct (not sub-accessed) loads of these packed vectors to the 'unpacked' vec3<T>
+/// type before usage.
+///
+/// This transform papers over overload holes in the MSL standard library where an MSL
+/// `packed_vector` type cannot be interchangable used as a regular `vec` type.
+class PackedVec3 final : public Castable<PackedVec3, Transform> {
+ public:
+ /// Attribute is the attribute applied to padded vector structure members.
+ class Attribute final : public Castable<Attribute, ast::InternalAttribute> {
+ public:
+ /// Constructor
+ /// @param pid the identifier of the program that owns this node
+ /// @param nid the unique node identifier
+ Attribute(ProgramID pid, ast::NodeID nid);
+ /// Destructor
+ ~Attribute() override;
+
+ /// @returns "packed_vector".
+ std::string InternalName() const override;
+
+ /// Performs a deep clone of this object using the CloneContext `ctx`.
+ /// @param ctx the clone context
+ /// @return the newly cloned object
+ const Attribute* Clone(CloneContext* ctx) const override;
+ };
+
+ /// Constructor
+ PackedVec3();
+ /// Destructor
+ ~PackedVec3() override;
+
+ /// @param program the program to inspect
+ /// @param data optional extra transform-specific input data
+ /// @returns true if this transform should be run for the given program
+ bool ShouldRun(const Program* program, const DataMap& data = {}) const override;
+
+ private:
+ struct State;
+
+ /// Runs the transform using the CloneContext built for transforming a
+ /// program. Run() is responsible for calling Clone() on the CloneContext.
+ /// @param ctx the CloneContext primed with the input program and
+ /// ProgramBuilder
+ /// @param inputs optional extra transform-specific input data
+ /// @param outputs optional extra transform-specific output data
+ void Run(CloneContext& ctx, const DataMap& inputs, DataMap& outputs) const override;
+};
+
+} // namespace tint::transform
+
+#endif // SRC_TINT_TRANSFORM_PACKED_VEC3_H_
diff --git a/src/tint/transform/packed_vec3_test.cc b/src/tint/transform/packed_vec3_test.cc
new file mode 100644
index 0000000..0f5c92e
--- /dev/null
+++ b/src/tint/transform/packed_vec3_test.cc
@@ -0,0 +1,662 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/transform/packed_vec3.h"
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "src/tint/transform/test_helper.h"
+#include "src/tint/utils/string.h"
+
+namespace tint::transform {
+namespace {
+
+using PackedVec3Test = TransformTest;
+
+TEST_F(PackedVec3Test, ShouldRun_EmptyModule) {
+ auto* src = R"()";
+
+ EXPECT_FALSE(ShouldRun<PackedVec3>(src));
+}
+
+TEST_F(PackedVec3Test, ShouldRun_NonHostSharableStruct) {
+ auto* src = R"(
+struct S {
+ v : vec3<f32>,
+}
+
+fn f() {
+ var v : S; // function address-space - not host sharable
+}
+)";
+
+ EXPECT_FALSE(ShouldRun<PackedVec3>(src));
+}
+
+TEST_F(PackedVec3Test, ShouldRun_Vec4Vec2) {
+ auto* src = R"(
+struct S {
+ v4 : vec4<f32>,
+ v2 : vec2<f32>,
+}
+
+@group(0) @binding(0) var<uniform> P : S; // Host sharable
+)";
+
+ EXPECT_FALSE(ShouldRun<PackedVec3>(src));
+}
+
+TEST_F(PackedVec3Test, ShouldRun_HostSharableStruct) {
+ auto* src = R"(
+struct S {
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<uniform> P : S; // Host sharable
+)";
+
+ EXPECT_TRUE(ShouldRun<PackedVec3>(src));
+}
+
+TEST_F(PackedVec3Test, UniformAddressSpace) {
+ auto* src = R"(
+struct S {
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<uniform> P : S;
+
+fn f() {
+ let x = P.v;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @internal(packed_vector)
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<uniform> P : S;
+
+fn f() {
+ let x = vec3<f32>(P.v);
+}
+)";
+
+ DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StorageAddressSpace) {
+ auto* src = R"(
+struct S {
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let x = P.v;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @internal(packed_vector)
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let x = vec3<f32>(P.v);
+}
+)";
+
+ DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ExistingMemberAttributes) {
+ auto* src = R"(
+struct S {
+ @align(32) @size(64) v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let x = P.v;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @internal(packed_vector) @align(32) @size(64)
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let x = vec3<f32>(P.v);
+}
+)";
+
+ DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, MultipleVectors) {
+ auto* src = R"(
+struct S {
+ v2_a : vec2<f32>,
+ v3_a : vec3<f32>,
+ v4_a : vec4<f32>,
+ v2_b : vec2<f32>,
+ v3_b : vec3<f32>,
+ v4_b : vec4<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let v2_a = P.v2_a;
+ let v3_a = P.v3_a;
+ let v4_a = P.v4_a;
+ let v2_b = P.v2_b;
+ let v3_b = P.v3_b;
+ let v4_b = P.v4_b;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ v2_a : vec2<f32>,
+ @internal(packed_vector)
+ v3_a : vec3<f32>,
+ v4_a : vec4<f32>,
+ v2_b : vec2<f32>,
+ @internal(packed_vector)
+ v3_b : vec3<f32>,
+ v4_b : vec4<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let v2_a = P.v2_a;
+ let v3_a = vec3<f32>(P.v3_a);
+ let v4_a = P.v4_a;
+ let v2_b = P.v2_b;
+ let v3_b = vec3<f32>(P.v3_b);
+ let v4_b = P.v4_b;
+}
+)";
+
+ DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, MixedAddressSpace) {
+ auto* src = R"(
+struct S {
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ var f : S;
+ let x = f.v;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @internal(packed_vector)
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ var f : S;
+ let x = vec3<f32>(f.v);
+}
+)";
+
+ DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ReadMemberAccessChain) {
+ auto* src = R"(
+struct S {
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let x = P.v.yz.x;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @internal(packed_vector)
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let x = P.v.yz.x;
+}
+)";
+
+ DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ReadVector) {
+ auto* src = R"(
+struct S {
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let x = P.v;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @internal(packed_vector)
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let x = vec3<f32>(P.v);
+}
+)";
+
+ DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ReadIndexAccessor) {
+ auto* src = R"(
+struct S {
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let x = P.v[1];
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @internal(packed_vector)
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let x = P.v[1];
+}
+)";
+
+ DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ReadViaStructPtrDirect) {
+ auto* src = R"(
+struct S {
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let x = (*(&(*(&P)))).v;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @internal(packed_vector)
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let x = vec3<f32>((*(&(*(&(P))))).v);
+}
+)";
+
+ DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ReadViaVectorPtrDirect) {
+ auto* src = R"(
+struct S {
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let x = *(&(*(&(P.v))));
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @internal(packed_vector)
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let x = vec3<f32>(*(&(*(&(P.v)))));
+}
+)";
+
+ DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ReadViaStructPtrViaLet) {
+ auto* src = R"(
+struct S {
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let p0 = &P;
+ let p1 = &(*(p0));
+ let a = (*p1).v;
+ let p2 = &(*(p1));
+ let b = (*p2).v;
+ let c = (*p2).v;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @internal(packed_vector)
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let p0 = &(P);
+ let p1 = &(*(p0));
+ let a = vec3<f32>((*(p1)).v);
+ let p2 = &(*(p1));
+ let b = vec3<f32>((*(p2)).v);
+ let c = vec3<f32>((*(p2)).v);
+}
+)";
+
+ DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ReadViaVectorPtrViaLet) {
+ auto* src = R"(
+struct S {
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let p0 = &(P.v);
+ let p1 = &(*(p0));
+ let a = *p1;
+ let p2 = &(*(p1));
+ let b = *p2;
+ let c = *p2;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @internal(packed_vector)
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let p0 = &(P.v);
+ let p1 = &(*(p0));
+ let a = vec3<f32>(*(p1));
+ let p2 = &(*(p1));
+ let b = vec3<f32>(*(p2));
+ let c = vec3<f32>(*(p2));
+}
+)";
+
+ DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ReadUnaryOp) {
+ auto* src = R"(
+struct S {
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let x = -P.v;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @internal(packed_vector)
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let x = -(vec3<f32>(P.v));
+}
+)";
+
+ DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ReadBinaryOp) {
+ auto* src = R"(
+struct S {
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let x = P.v + P.v;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @internal(packed_vector)
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let x = (vec3<f32>(P.v) + vec3<f32>(P.v));
+}
+)";
+
+ DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, WriteVector) {
+ auto* src = R"(
+struct S {
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+ P.v = vec3(1.23);
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @internal(packed_vector)
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+ P.v = vec3(1.23);
+}
+)";
+
+ DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, WriteMemberAccess) {
+ auto* src = R"(
+struct S {
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+ P.v.y = 1.23;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @internal(packed_vector)
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+ P.v.y = 1.23;
+}
+)";
+
+ DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, WriteIndexAccessor) {
+ auto* src = R"(
+struct S {
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+ P.v[1] = 1.23;
+}
+)";
+
+ auto* expect = R"(
+struct S {
+ @internal(packed_vector)
+ v : vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+ P.v[1] = 1.23;
+}
+)";
+
+ DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+} // namespace
+} // namespace tint::transform
diff --git a/src/tint/writer/msl/generator_impl.cc b/src/tint/writer/msl/generator_impl.cc
index 0bc8c39..cf67e10 100644
--- a/src/tint/writer/msl/generator_impl.cc
+++ b/src/tint/writer/msl/generator_impl.cc
@@ -66,6 +66,7 @@
#include "src/tint/transform/expand_compound_assignment.h"
#include "src/tint/transform/manager.h"
#include "src/tint/transform/module_scope_var_to_entry_point_param.h"
+#include "src/tint/transform/packed_vec3.h"
#include "src/tint/transform/promote_initializers_to_let.h"
#include "src/tint/transform/promote_side_effects_to_decl.h"
#include "src/tint/transform/remove_phonies.h"
@@ -154,32 +155,6 @@
std::ostream& s;
};
-class ScopedCast {
- public:
- ScopedCast(GeneratorImpl* generator,
- std::ostream& stream,
- const sem::Type* curr_type,
- const sem::Type* target_type)
- : s(stream) {
- auto* target_vec_type = target_type->As<sem::Vector>();
-
- // If we need to promote from scalar to vector, cast the scalar to the
- // vector element type.
- if (curr_type->is_scalar() && target_vec_type) {
- target_type = target_vec_type->type();
- }
-
- // Cast
- generator->EmitType(s, target_type, "");
- s << "(";
- }
-
- ~ScopedCast() { s << ")"; }
-
- private:
- std::ostream& s;
-};
-
} // namespace
SanitizedResult::SanitizedResult() = default;
@@ -259,6 +234,7 @@
// it assumes that the form of the array length argument is &var.array.
manager.Add<transform::ArrayLengthFromUniform>();
manager.Add<transform::ModuleScopeVarToEntryPointParam>();
+ manager.Add<transform::PackedVec3>();
data.Add<transform::ArrayLengthFromUniform::Config>(std::move(array_length_from_uniform_cfg));
data.Add<transform::CanonicalizeEntryPointIO::Config>(std::move(entry_point_io_cfg));
auto out = manager.Run(in, data);
@@ -554,18 +530,8 @@
ScopedParen sp(out);
{
ScopedBitCast lhs_uint_cast(this, out, lhs_type, unsigned_type_of(target_type));
-
- // In case the type is packed, cast to our own type in order to remove the packing.
- // Otherwise, this just casts to itself.
- if (lhs_type->is_signed_integer_vector()) {
- ScopedCast lhs_self_cast(this, out, lhs_type, lhs_type);
- if (!EmitExpression(out, expr->lhs)) {
- return false;
- }
- } else {
- if (!EmitExpression(out, expr->lhs)) {
- return false;
- }
+ if (!EmitExpression(out, expr->lhs)) {
+ return false;
}
}
if (!emit_op()) {
@@ -573,18 +539,8 @@
}
{
ScopedBitCast rhs_uint_cast(this, out, rhs_type, unsigned_type_of(target_type));
-
- // In case the type is packed, cast to our own type in order to remove the packing.
- // Otherwise, this just casts to itself.
- if (rhs_type->is_signed_integer_vector()) {
- ScopedCast rhs_self_cast(this, out, rhs_type, rhs_type);
- if (!EmitExpression(out, expr->rhs)) {
- return false;
- }
- } else {
- if (!EmitExpression(out, expr->rhs)) {
- return false;
- }
+ if (!EmitExpression(out, expr->rhs)) {
+ return false;
}
}
return true;
@@ -601,18 +557,8 @@
ScopedParen sp(out);
{
ScopedBitCast lhs_uint_cast(this, out, lhs_type, unsigned_type_of(lhs_type));
-
- // In case the type is packed, cast to our own type in order to remove the packing.
- // Otherwise, this just casts to itself.
- if (lhs_type->is_signed_integer_vector()) {
- ScopedCast lhs_self_cast(this, out, lhs_type, lhs_type);
- if (!EmitExpression(out, expr->lhs)) {
- return false;
- }
- } else {
- if (!EmitExpression(out, expr->lhs)) {
- return false;
- }
+ if (!EmitExpression(out, expr->lhs)) {
+ return false;
}
}
if (!emit_op()) {
@@ -2780,41 +2726,6 @@
return false;
}
-bool GeneratorImpl::EmitPackedType(std::ostream& out,
- const sem::Type* type,
- const std::string& name) {
- auto* vec = type->As<sem::Vector>();
- if (vec && vec->Width() == 3) {
- out << "packed_";
- if (!EmitType(out, vec, "")) {
- return false;
- }
-
- if (vec->is_float_vector() && !matrix_packed_vector_overloads_) {
- // Overload operators for matrix-vector arithmetic where the vector
- // operand is packed, as these overloads to not exist in the metal
- // namespace.
- TextBuffer b;
- TINT_DEFER(helpers_.Append(b));
- line(&b) << R"(template<typename T, int N, int M>
-inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) {
- return lhs * vec<T, N>(rhs);
-}
-
-template<typename T, int N, int M>
-inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) {
- return vec<T, M>(lhs) * rhs;
-}
-)";
- matrix_packed_vector_overloads_ = true;
- }
-
- return true;
- }
-
- return EmitType(out, type, name);
-}
-
bool GeneratorImpl::EmitStructType(TextBuffer* b, const sem::Struct* str) {
line(b) << "struct " << StructName(str) << " {";
@@ -2861,14 +2772,15 @@
}
add_byte_offset_comment(out, msl_offset);
+ }
- if (!EmitPackedType(out, mem->Type(), mem_name)) {
- return false;
+ if (auto* decl = mem->Declaration()) {
+ if (ast::HasAttribute<transform::PackedVec3::Attribute>(decl->attributes)) {
+ out << "packed_";
}
- } else {
- if (!EmitType(out, mem->Type(), mem_name)) {
- return false;
- }
+ }
+ if (!EmitType(out, mem->Type(), mem_name)) {
+ return false;
}
auto* ty = mem->Type();
@@ -2934,6 +2846,7 @@
[&](const ast::StructMemberOffsetAttribute*) { return true; },
[&](const ast::StructMemberAlignAttribute*) { return true; },
[&](const ast::StructMemberSizeAttribute*) { return true; },
+ [&](const transform::PackedVec3::Attribute*) { return true; },
[&](Default) {
TINT_ICE(Writer, diagnostics_)
<< "unhandled struct member attribute: " << attr->Name();
diff --git a/src/tint/writer/msl/generator_impl.h b/src/tint/writer/msl/generator_impl.h
index 188bfea..c3e1ac0 100644
--- a/src/tint/writer/msl/generator_impl.h
+++ b/src/tint/writer/msl/generator_impl.h
@@ -328,14 +328,6 @@
/// @param sc the address space to generate
/// @returns true if the address space is emitted
bool EmitAddressSpace(std::ostream& out, ast::AddressSpace sc);
- /// Handles generating an MSL-packed storage type.
- /// If the type does not have a packed form, the standard non-packed form is
- /// emitted.
- /// @param out the output of the type stream
- /// @param type the type to generate
- /// @param name the name of the variable, only used for array emission
- /// @returns true if the type is emitted
- bool EmitPackedType(std::ostream& out, const sem::Type* type, const std::string& name);
/// Handles generating a struct declaration
/// @param buffer the text buffer that the type declaration will be written to
/// @param str the struct to generate
@@ -431,8 +423,8 @@
/// Non-empty only if an invariant attribute has been generated.
std::string invariant_define_name_;
- /// True if matrix-packed_vector operator overloads have been generated.
- bool matrix_packed_vector_overloads_ = false;
+ /// The generated name for the packed vec3 type.
+ std::string packed_vec3_ty_;
/// Unique name of the tint_array<T, N> template.
/// Non-empty only if the template has been generated.
diff --git a/src/tint/writer/msl/generator_impl_binary_test.cc b/src/tint/writer/msl/generator_impl_binary_test.cc
index e08c420..fc03507 100644
--- a/src/tint/writer/msl/generator_impl_binary_test.cc
+++ b/src/tint/writer/msl/generator_impl_binary_test.cc
@@ -128,18 +128,14 @@
}
using Op = ast::BinaryOp;
constexpr BinaryData signed_overflow_defined_behaviour_chained_cases[] = {
- {"as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(a) << b))) << "
- "b))",
+ {R"(as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(a) << b))) << b)))",
Op::kShiftLeft},
- {"((a >> b) >> b)", Op::kShiftRight},
- {"as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(a) + "
- "as_type<uint>(b)))) + as_type<uint>(b)))",
+ {R"(((a >> b) >> b))", Op::kShiftRight},
+ {R"(as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(a) + as_type<uint>(b)))) + as_type<uint>(b))))",
Op::kAdd},
- {"as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(a) - "
- "as_type<uint>(b)))) - as_type<uint>(b)))",
+ {R"(as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(a) - as_type<uint>(b)))) - as_type<uint>(b))))",
Op::kSubtract},
- {"as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(a) * "
- "as_type<uint>(b)))) * as_type<uint>(b)))",
+ {R"(as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(a) * as_type<uint>(b)))) * as_type<uint>(b))))",
Op::kMultiply}};
INSTANTIATE_TEST_SUITE_P(MslGeneratorImplTest,
MslBinaryTest_SignedOverflowDefinedBehaviour_Chained,
diff --git a/src/tint/writer/msl/generator_impl_type_test.cc b/src/tint/writer/msl/generator_impl_type_test.cc
index bc9767a..27de589 100644
--- a/src/tint/writer/msl/generator_impl_type_test.cc
+++ b/src/tint/writer/msl/generator_impl_type_test.cc
@@ -60,7 +60,7 @@
// Size and alignments taken from the MSL spec:
// https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf
DECLARE_TYPE(float2, 8, 8);
-DECLARE_TYPE(packed_float3, 12, 4);
+DECLARE_TYPE(float3, 12, 4);
DECLARE_TYPE(float4, 16, 16);
DECLARE_TYPE(float2x2, 16, 8);
DECLARE_TYPE(float2x3, 32, 16);
@@ -301,7 +301,7 @@
FIELD(0x0100, float2, 0, c) \
FIELD(0x0108, uint, 0, d) \
FIELD(0x010c, int8_t, 4, tint_pad_2) \
- FIELD(0x0110, packed_float3, 0, e) \
+ FIELD(0x0110, float3, 0, e) \
FIELD(0x011c, uint, 0, f) \
FIELD(0x0120, float4, 0, g) \
FIELD(0x0130, uint, 0, h) \
@@ -641,7 +641,7 @@
/* 0x0100 */ float2 tint_pad_33;
/* 0x0108 */ uint tint_pad_1;
/* 0x010c */ tint_array<int8_t, 4> tint_pad_12;
- /* 0x0110 */ packed_float3 tint_pad_3;
+ /* 0x0110 */ float3 tint_pad_3;
/* 0x011c */ uint tint_pad_7;
/* 0x0120 */ float4 tint_pad_25;
/* 0x0130 */ uint tint_pad_5;
diff --git a/test/tint/buffer/storage/dynamic_index/read.wgsl.expected.msl b/test/tint/buffer/storage/dynamic_index/read.wgsl.expected.msl
index 549e70f..52e5e7d 100644
--- a/test/tint/buffer/storage/dynamic_index/read.wgsl.expected.msl
+++ b/test/tint/buffer/storage/dynamic_index/read.wgsl.expected.msl
@@ -2,16 +2,6 @@
using namespace metal;
-template<typename T, int N, int M>
-inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) {
- return lhs * vec<T, N>(rhs);
-}
-
-template<typename T, int N, int M>
-inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) {
- return vec<T, M>(lhs) * rhs;
-}
-
template<typename T, size_t N>
struct tint_array {
const constant T& operator[](size_t i) const constant { return elements[i]; }
@@ -42,11 +32,11 @@
};
void tint_symbol_inner(uint idx, const device S* const tint_symbol_1) {
- int3 const a = (*(tint_symbol_1)).arr[idx].a;
+ int3 const a = int3((*(tint_symbol_1)).arr[idx].a);
int const b = (*(tint_symbol_1)).arr[idx].b;
- uint3 const c = (*(tint_symbol_1)).arr[idx].c;
+ uint3 const c = uint3((*(tint_symbol_1)).arr[idx].c);
uint const d = (*(tint_symbol_1)).arr[idx].d;
- float3 const e = (*(tint_symbol_1)).arr[idx].e;
+ float3 const e = float3((*(tint_symbol_1)).arr[idx].e);
float const f = (*(tint_symbol_1)).arr[idx].f;
float2x3 const g = (*(tint_symbol_1)).arr[idx].g;
float3x2 const h = (*(tint_symbol_1)).arr[idx].h;
diff --git a/test/tint/buffer/storage/dynamic_index/write.wgsl.expected.msl b/test/tint/buffer/storage/dynamic_index/write.wgsl.expected.msl
index e2430df..bb82069 100644
--- a/test/tint/buffer/storage/dynamic_index/write.wgsl.expected.msl
+++ b/test/tint/buffer/storage/dynamic_index/write.wgsl.expected.msl
@@ -2,16 +2,6 @@
using namespace metal;
-template<typename T, int N, int M>
-inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) {
- return lhs * vec<T, N>(rhs);
-}
-
-template<typename T, int N, int M>
-inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) {
- return vec<T, M>(lhs) * rhs;
-}
-
template<typename T, size_t N>
struct tint_array {
const constant T& operator[](size_t i) const constant { return elements[i]; }
diff --git a/test/tint/buffer/storage/static_index/read.wgsl.expected.msl b/test/tint/buffer/storage/static_index/read.wgsl.expected.msl
index 8f891a2..db51912 100644
--- a/test/tint/buffer/storage/static_index/read.wgsl.expected.msl
+++ b/test/tint/buffer/storage/static_index/read.wgsl.expected.msl
@@ -2,16 +2,6 @@
using namespace metal;
-template<typename T, int N, int M>
-inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) {
- return lhs * vec<T, N>(rhs);
-}
-
-template<typename T, int N, int M>
-inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) {
- return vec<T, M>(lhs) * rhs;
-}
-
template<typename T, size_t N>
struct tint_array {
const constant T& operator[](size_t i) const constant { return elements[i]; }
@@ -43,11 +33,11 @@
};
kernel void tint_symbol(const device S* tint_symbol_1 [[buffer(0)]]) {
- int3 const a = (*(tint_symbol_1)).a;
+ int3 const a = int3((*(tint_symbol_1)).a);
int const b = (*(tint_symbol_1)).b;
- uint3 const c = (*(tint_symbol_1)).c;
+ uint3 const c = uint3((*(tint_symbol_1)).c);
uint const d = (*(tint_symbol_1)).d;
- float3 const e = (*(tint_symbol_1)).e;
+ float3 const e = float3((*(tint_symbol_1)).e);
float const f = (*(tint_symbol_1)).f;
float2x3 const g = (*(tint_symbol_1)).g;
float3x2 const h = (*(tint_symbol_1)).h;
diff --git a/test/tint/buffer/storage/static_index/write.wgsl.expected.msl b/test/tint/buffer/storage/static_index/write.wgsl.expected.msl
index 251e06f..1b21710 100644
--- a/test/tint/buffer/storage/static_index/write.wgsl.expected.msl
+++ b/test/tint/buffer/storage/static_index/write.wgsl.expected.msl
@@ -2,16 +2,6 @@
using namespace metal;
-template<typename T, int N, int M>
-inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) {
- return lhs * vec<T, N>(rhs);
-}
-
-template<typename T, int N, int M>
-inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) {
- return vec<T, M>(lhs) * rhs;
-}
-
template<typename T, size_t N>
struct tint_array {
const constant T& operator[](size_t i) const constant { return elements[i]; }
diff --git a/test/tint/buffer/uniform/dynamic_index/read.wgsl.expected.msl b/test/tint/buffer/uniform/dynamic_index/read.wgsl.expected.msl
index e361022..37817c3 100644
--- a/test/tint/buffer/uniform/dynamic_index/read.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/dynamic_index/read.wgsl.expected.msl
@@ -2,16 +2,6 @@
using namespace metal;
-template<typename T, int N, int M>
-inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) {
- return lhs * vec<T, N>(rhs);
-}
-
-template<typename T, int N, int M>
-inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) {
- return vec<T, M>(lhs) * rhs;
-}
-
template<typename T, size_t N>
struct tint_array {
const constant T& operator[](size_t i) const constant { return elements[i]; }
@@ -44,11 +34,11 @@
};
void tint_symbol_inner(uint idx, const constant S* const tint_symbol_1) {
- int3 const a = (*(tint_symbol_1)).arr[idx].a;
+ int3 const a = int3((*(tint_symbol_1)).arr[idx].a);
int const b = (*(tint_symbol_1)).arr[idx].b;
- uint3 const c = (*(tint_symbol_1)).arr[idx].c;
+ uint3 const c = uint3((*(tint_symbol_1)).arr[idx].c);
uint const d = (*(tint_symbol_1)).arr[idx].d;
- float3 const e = (*(tint_symbol_1)).arr[idx].e;
+ float3 const e = float3((*(tint_symbol_1)).arr[idx].e);
float const f = (*(tint_symbol_1)).arr[idx].f;
int2 const g = (*(tint_symbol_1)).arr[idx].g;
int2 const h = (*(tint_symbol_1)).arr[idx].h;
diff --git a/test/tint/buffer/uniform/static_index/read.wgsl.expected.msl b/test/tint/buffer/uniform/static_index/read.wgsl.expected.msl
index 26497bd..02d091d 100644
--- a/test/tint/buffer/uniform/static_index/read.wgsl.expected.msl
+++ b/test/tint/buffer/uniform/static_index/read.wgsl.expected.msl
@@ -14,16 +14,6 @@
T elements[N];
};
-template<typename T, int N, int M>
-inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) {
- return lhs * vec<T, N>(rhs);
-}
-
-template<typename T, int N, int M>
-inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) {
- return vec<T, M>(lhs) * rhs;
-}
-
struct Inner {
/* 0x0000 */ int x;
/* 0x0004 */ tint_array<int8_t, 12> tint_pad;
@@ -46,11 +36,11 @@
};
kernel void tint_symbol(const constant S* tint_symbol_1 [[buffer(0)]]) {
- int3 const a = (*(tint_symbol_1)).a;
+ int3 const a = int3((*(tint_symbol_1)).a);
int const b = (*(tint_symbol_1)).b;
- uint3 const c = (*(tint_symbol_1)).c;
+ uint3 const c = uint3((*(tint_symbol_1)).c);
uint const d = (*(tint_symbol_1)).d;
- float3 const e = (*(tint_symbol_1)).e;
+ float3 const e = float3((*(tint_symbol_1)).e);
float const f = (*(tint_symbol_1)).f;
int2 const g = (*(tint_symbol_1)).g;
int2 const h = (*(tint_symbol_1)).h;
diff --git a/test/tint/bug/chromium/1273230.wgsl.expected.msl b/test/tint/bug/chromium/1273230.wgsl.expected.msl
index 08f7854..1e627d7 100644
--- a/test/tint/bug/chromium/1273230.wgsl.expected.msl
+++ b/test/tint/bug/chromium/1273230.wgsl.expected.msl
@@ -2,16 +2,6 @@
using namespace metal;
-template<typename T, int N, int M>
-inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) {
- return lhs * vec<T, N>(rhs);
-}
-
-template<typename T, int N, int M>
-inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) {
- return vec<T, M>(lhs) * rhs;
-}
-
template<typename T, size_t N>
struct tint_array {
const constant T& operator[](size_t i) const constant { return elements[i]; }
diff --git a/test/tint/bug/fxc/indexed_assign_to_array_in_struct/1206.wgsl.expected.msl b/test/tint/bug/fxc/indexed_assign_to_array_in_struct/1206.wgsl.expected.msl
index 6507f58..c63e9f1 100644
--- a/test/tint/bug/fxc/indexed_assign_to_array_in_struct/1206.wgsl.expected.msl
+++ b/test/tint/bug/fxc/indexed_assign_to_array_in_struct/1206.wgsl.expected.msl
@@ -14,16 +14,6 @@
T elements[N];
};
-template<typename T, int N, int M>
-inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) {
- return lhs * vec<T, N>(rhs);
-}
-
-template<typename T, int N, int M>
-inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) {
- return vec<T, M>(lhs) * rhs;
-}
-
struct Simulation {
/* 0x0000 */ uint i;
};
diff --git a/test/tint/bug/tint/1113.wgsl.expected.msl b/test/tint/bug/tint/1113.wgsl.expected.msl
index b62d4c5..bf546c1 100644
--- a/test/tint/bug/tint/1113.wgsl.expected.msl
+++ b/test/tint/bug/tint/1113.wgsl.expected.msl
@@ -2,16 +2,6 @@
using namespace metal;
-template<typename T, int N, int M>
-inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) {
- return lhs * vec<T, N>(rhs);
-}
-
-template<typename T, int N, int M>
-inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) {
- return vec<T, M>(lhs) * rhs;
-}
-
template<typename T, size_t N>
struct tint_array {
const constant T& operator[](size_t i) const constant { return elements[i]; }
diff --git a/test/tint/bug/tint/1118.wgsl.expected.msl b/test/tint/bug/tint/1118.wgsl.expected.msl
index 40e92e8..5539c67 100644
--- a/test/tint/bug/tint/1118.wgsl.expected.msl
+++ b/test/tint/bug/tint/1118.wgsl.expected.msl
@@ -1,17 +1,6 @@
#include <metal_stdlib>
using namespace metal;
-
-template<typename T, int N, int M>
-inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) {
- return lhs * vec<T, N>(rhs);
-}
-
-template<typename T, int N, int M>
-inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) {
- return vec<T, M>(lhs) * rhs;
-}
-
struct Scene {
/* 0x0000 */ float4 vEyePosition;
};
@@ -77,12 +66,12 @@
shadow = 1.0f;
refractionColor = float4(0.0f, 0.0f, 0.0f, 1.0f);
reflectionColor = float4(0.0f, 0.0f, 0.0f, 1.0f);
- float3 const x_94 = (*(tint_symbol_11)).vEmissiveColor;
+ float3 const x_94 = float3((*(tint_symbol_11)).vEmissiveColor);
emissiveColor = x_94;
float3 const x_96 = diffuseBase;
float3 const x_97 = diffuseColor;
float3 const x_99 = emissiveColor;
- float3 const x_103 = (*(tint_symbol_11)).vAmbientColor;
+ float3 const x_103 = float3((*(tint_symbol_11)).vAmbientColor);
float4 const x_108 = baseColor;
finalDiffuse = (clamp((((x_96 * x_97) + x_99) + x_103), float3(0.0f), float3(1.0f)) * float3(x_108[0], x_108[1], x_108[2]));
finalSpecular = float3(0.0f);
diff --git a/test/tint/bug/tint/1121.wgsl.expected.msl b/test/tint/bug/tint/1121.wgsl.expected.msl
index 34c70b2..22cc6dd 100644
--- a/test/tint/bug/tint/1121.wgsl.expected.msl
+++ b/test/tint/bug/tint/1121.wgsl.expected.msl
@@ -2,16 +2,6 @@
using namespace metal;
-template<typename T, int N, int M>
-inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) {
- return lhs * vec<T, N>(rhs);
-}
-
-template<typename T, int N, int M>
-inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) {
- return vec<T, M>(lhs) * rhs;
-}
-
template<typename T, size_t N>
struct tint_array {
const constant T& operator[](size_t i) const constant { return elements[i]; }
@@ -88,7 +78,7 @@
for(int x_1 = 0; (x_1 < TILE_COUNT_X); x_1 = as_type<int>((as_type<uint>(x_1) + as_type<uint>(1)))) {
int2 tilePixel0Idx = int2(as_type<int>((as_type<uint>(x_1) * as_type<uint>(TILE_SIZE))), as_type<int>((as_type<uint>(y_1) * as_type<uint>(TILE_SIZE))));
float2 floorCoord = (((2.0f * float2(tilePixel0Idx)) / float4((*(tint_symbol_3)).fullScreenSize).xy) - float2(1.0f));
- float2 ceilCoord = (((2.0f * float2(as_type<int2>((as_type<uint2>(int2(tilePixel0Idx)) + as_type<uint2>(int2(int2(TILE_SIZE))))))) / float4((*(tint_symbol_3)).fullScreenSize).xy) - float2(1.0f));
+ float2 ceilCoord = (((2.0f * float2(as_type<int2>((as_type<uint2>(tilePixel0Idx) + as_type<uint2>(int2(TILE_SIZE)))))) / float4((*(tint_symbol_3)).fullScreenSize).xy) - float2(1.0f));
float2 viewFloorCoord = float2((((-(viewNear) * floorCoord[0]) - (M[2][0] * viewNear)) / M[0][0]), (((-(viewNear) * floorCoord[1]) - (M[2][1] * viewNear)) / M[1][1]));
float2 viewCeilCoord = float2((((-(viewNear) * ceilCoord[0]) - (M[2][0] * viewNear)) / M[0][0]), (((-(viewNear) * ceilCoord[1]) - (M[2][1] * viewNear)) / M[1][1]));
frustumPlanes[0] = float4(1.0f, 0.0f, (-(viewFloorCoord[0]) / viewNear), 0.0f);
diff --git a/test/tint/bug/tint/1520.spvasm.expected.msl b/test/tint/bug/tint/1520.spvasm.expected.msl
index 3b8e4f7..d9ff17c 100644
--- a/test/tint/bug/tint/1520.spvasm.expected.msl
+++ b/test/tint/bug/tint/1520.spvasm.expected.msl
@@ -45,13 +45,13 @@
ok = x_41;
int4 const x_44 = int4(x_27, x_27, x_27, x_27);
val = x_44;
- int4 const x_47 = as_type<int4>((as_type<uint4>(int4(x_44)) + as_type<uint4>(int4(int4(1)))));
+ int4 const x_47 = as_type<int4>((as_type<uint4>(x_44) + as_type<uint4>(int4(1))));
val = x_47;
- int4 const x_48 = as_type<int4>((as_type<uint4>(int4(x_47)) - as_type<uint4>(int4(int4(1)))));
+ int4 const x_48 = as_type<int4>((as_type<uint4>(x_47) - as_type<uint4>(int4(1))));
val = x_48;
- int4 const x_49 = as_type<int4>((as_type<uint4>(int4(x_48)) + as_type<uint4>(int4(int4(1)))));
+ int4 const x_49 = as_type<int4>((as_type<uint4>(x_48) + as_type<uint4>(int4(1))));
val = x_49;
- int4 const x_50 = as_type<int4>((as_type<uint4>(int4(x_49)) - as_type<uint4>(int4(int4(1)))));
+ int4 const x_50 = as_type<int4>((as_type<uint4>(x_49) - as_type<uint4>(int4(1))));
val = x_50;
x_55 = false;
if (x_41) {
@@ -59,11 +59,11 @@
x_55 = x_54;
}
ok = x_55;
- int4 const x_58 = as_type<int4>((as_type<uint4>(int4(x_50)) * as_type<uint4>(int4(int4(2)))));
+ int4 const x_58 = as_type<int4>((as_type<uint4>(x_50) * as_type<uint4>(int4(2))));
val = x_58;
int4 const x_59 = (x_58 / int4(2));
val = x_59;
- int4 const x_60 = as_type<int4>((as_type<uint4>(int4(x_59)) * as_type<uint4>(int4(int4(2)))));
+ int4 const x_60 = as_type<int4>((as_type<uint4>(x_59) * as_type<uint4>(int4(2))));
val = x_60;
int4 const x_61 = (x_60 / int4(2));
val = x_61;
diff --git a/test/tint/bug/tint/1534.wgsl b/test/tint/bug/tint/1534.wgsl
new file mode 100644
index 0000000..1b0c2a6
--- /dev/null
+++ b/test/tint/bug/tint/1534.wgsl
@@ -0,0 +1,17 @@
+
+struct g {
+ a : vec3<u32>,
+}
+
+struct h {
+ a : u32,
+}
+
+@group(0) @binding(0) var<uniform> i : g;
+
+@group(0) @binding(1) var<storage, read_write> j : h;
+
+@compute @workgroup_size(1) fn main() {
+ let l = dot(i.a, i.a);
+ j.a = i.a.x;
+}
diff --git a/test/tint/bug/tint/1534.wgsl.expected.msl b/test/tint/bug/tint/1534.wgsl.expected.msl
new file mode 100644
index 0000000..6f8a3de
--- /dev/null
+++ b/test/tint/bug/tint/1534.wgsl.expected.msl
@@ -0,0 +1,35 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+ const constant T& operator[](size_t i) const constant { return elements[i]; }
+ device T& operator[](size_t i) device { return elements[i]; }
+ const device T& operator[](size_t i) const device { return elements[i]; }
+ thread T& operator[](size_t i) thread { return elements[i]; }
+ const thread T& operator[](size_t i) const thread { return elements[i]; }
+ threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+ const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+ T elements[N];
+};
+
+template<typename T>
+T tint_dot3(vec<T,3> a, vec<T,3> b) {
+ return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
+}
+struct g {
+ /* 0x0000 */ packed_uint3 a;
+ /* 0x000c */ tint_array<int8_t, 4> tint_pad;
+};
+
+struct h {
+ /* 0x0000 */ uint a;
+};
+
+kernel void tint_symbol(const constant g* tint_symbol_1 [[buffer(0)]], device h* tint_symbol_2 [[buffer(1)]]) {
+ uint const l = tint_dot3(uint3((*(tint_symbol_1)).a), uint3((*(tint_symbol_1)).a));
+ (*(tint_symbol_2)).a = (*(tint_symbol_1)).a[0];
+ return;
+}
+
diff --git a/test/tint/bug/tint/1677.wgsl.expected.msl b/test/tint/bug/tint/1677.wgsl.expected.msl
index 6ee8bbd..580eba4 100644
--- a/test/tint/bug/tint/1677.wgsl.expected.msl
+++ b/test/tint/bug/tint/1677.wgsl.expected.msl
@@ -20,7 +20,7 @@
};
void tint_symbol_inner(uint3 id, const device Input* const tint_symbol_1) {
- int3 const pos = as_type<int3>((as_type<uint3>(int3((*(tint_symbol_1)).position)) - as_type<uint3>(int3(int3(0)))));
+ int3 const pos = as_type<int3>((as_type<uint3>(int3((*(tint_symbol_1)).position)) - as_type<uint3>(int3(0))));
}
kernel void tint_symbol(const device Input* tint_symbol_2 [[buffer(0)]], uint3 id [[thread_position_in_grid]]) {
diff --git a/test/tint/bug/tint/948.wgsl.expected.msl b/test/tint/bug/tint/948.wgsl.expected.msl
index 6113640..e77abf2 100644
--- a/test/tint/bug/tint/948.wgsl.expected.msl
+++ b/test/tint/bug/tint/948.wgsl.expected.msl
@@ -14,16 +14,6 @@
T elements[N];
};
-template<typename T, int N, int M>
-inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) {
- return lhs * vec<T, N>(rhs);
-}
-
-template<typename T, int N, int M>
-inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) {
- return vec<T, M>(lhs) * rhs;
-}
-
struct LeftOver {
/* 0x0000 */ float time;
/* 0x0004 */ uint padding;
@@ -193,7 +183,7 @@
i = as_type<int>((as_type<uint>(x_304) + as_type<uint>(1)));
}
}
- float3 const x_310 = (*(tint_symbol_9)).colorMul;
+ float3 const x_310 = float3((*(tint_symbol_9)).colorMul);
float4 const x_311 = color;
float3 const x_313 = (float3(x_311[0], x_311[1], x_311[2]) * x_310);
float4 const x_314 = color;
diff --git a/test/tint/bug/tint/949.wgsl.expected.msl b/test/tint/bug/tint/949.wgsl.expected.msl
index c7bdad3..44f5320 100644
--- a/test/tint/bug/tint/949.wgsl.expected.msl
+++ b/test/tint/bug/tint/949.wgsl.expected.msl
@@ -14,16 +14,6 @@
T elements[N];
};
-template<typename T, int N, int M>
-inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) {
- return lhs * vec<T, N>(rhs);
-}
-
-template<typename T, int N, int M>
-inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) {
- return vec<T, M>(lhs) * rhs;
-}
-
struct lightingInfo {
float3 diffuse;
float3 specular;
@@ -248,7 +238,7 @@
float4 const x_264 = tempTextureRead;
float const x_273 = (*(tint_symbol_10)).textureInfoName;
rgb = (float3(x_264[0], x_264[1], x_264[2]) * x_273);
- float3 const x_279 = (*(tint_symbol_10)).u_cameraPosition;
+ float3 const x_279 = float3((*(tint_symbol_10)).u_cameraPosition);
float4 const x_282 = *(tint_symbol_11);
output5 = normalize((x_279 - float3(x_282[0], x_282[1], x_282[2])));
output4 = float4(0.0f);
@@ -380,7 +370,7 @@
tempTextureRead1 = x_475;
float4 const x_477 = tempTextureRead1;
rgb1 = float3(x_477[0], x_477[1], x_477[2]);
- float3 const x_481 = (*(tint_symbol_10)).u_cameraPosition;
+ float3 const x_481 = float3((*(tint_symbol_10)).u_cameraPosition);
float4 const x_482 = *(tint_symbol_11);
viewDirectionW_1 = normalize((x_481 - float3(x_482[0], x_482[1], x_482[2])));
shadow = 1.0f;
@@ -400,7 +390,7 @@
param_14 = float3(x_510[0], x_510[1], x_510[2]);
float4 const x_514 = (*(tint_symbol_17)).vLightSpecular;
param_15 = float3(x_514[0], x_514[1], x_514[2]);
- float3 const x_518 = (*(tint_symbol_17)).vLightGround;
+ float3 const x_518 = float3((*(tint_symbol_17)).vLightGround);
param_16 = x_518;
float const x_520 = glossiness_1;
param_17 = x_520;
diff --git a/test/tint/bug/tint/980.wgsl.expected.msl b/test/tint/bug/tint/980.wgsl.expected.msl
index 2e23ef1..36cce9d 100644
--- a/test/tint/bug/tint/980.wgsl.expected.msl
+++ b/test/tint/bug/tint/980.wgsl.expected.msl
@@ -1,17 +1,6 @@
#include <metal_stdlib>
using namespace metal;
-
-template<typename T, int N, int M>
-inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) {
- return lhs * vec<T, N>(rhs);
-}
-
-template<typename T, int N, int M>
-inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) {
- return vec<T, M>(lhs) * rhs;
-}
-
float3 Bad(uint index, float3 rd) {
float3 normal = float3(0.0f);
normal[index] = -(sign(rd[index]));
@@ -24,7 +13,7 @@
};
void tint_symbol_inner(uint idx, device S* const tint_symbol_2) {
- float3 const tint_symbol_1 = Bad((*(tint_symbol_2)).i, (*(tint_symbol_2)).v);
+ float3 const tint_symbol_1 = Bad((*(tint_symbol_2)).i, float3((*(tint_symbol_2)).v));
(*(tint_symbol_2)).v = tint_symbol_1;
}
diff --git a/test/tint/expressions/binary/add/scalar-vec3/i32.wgsl.expected.msl b/test/tint/expressions/binary/add/scalar-vec3/i32.wgsl.expected.msl
index 8658c03..46f1909 100644
--- a/test/tint/expressions/binary/add/scalar-vec3/i32.wgsl.expected.msl
+++ b/test/tint/expressions/binary/add/scalar-vec3/i32.wgsl.expected.msl
@@ -4,7 +4,7 @@
kernel void f() {
int const a = 4;
int3 const b = int3(1, 2, 3);
- int3 const r = as_type<int3>((as_type<uint>(a) + as_type<uint3>(int3(b))));
+ int3 const r = as_type<int3>((as_type<uint>(a) + as_type<uint3>(b)));
return;
}
diff --git a/test/tint/expressions/binary/add/vec3-scalar/i32.wgsl.expected.msl b/test/tint/expressions/binary/add/vec3-scalar/i32.wgsl.expected.msl
index de4195f..89306cc 100644
--- a/test/tint/expressions/binary/add/vec3-scalar/i32.wgsl.expected.msl
+++ b/test/tint/expressions/binary/add/vec3-scalar/i32.wgsl.expected.msl
@@ -4,7 +4,7 @@
kernel void f() {
int3 const a = int3(1, 2, 3);
int const b = 4;
- int3 const r = as_type<int3>((as_type<uint3>(int3(a)) + as_type<uint>(b)));
+ int3 const r = as_type<int3>((as_type<uint3>(a) + as_type<uint>(b)));
return;
}
diff --git a/test/tint/expressions/binary/add/vec3-vec3/i32.wgsl.expected.msl b/test/tint/expressions/binary/add/vec3-vec3/i32.wgsl.expected.msl
index 009e87e..54d88c7 100644
--- a/test/tint/expressions/binary/add/vec3-vec3/i32.wgsl.expected.msl
+++ b/test/tint/expressions/binary/add/vec3-vec3/i32.wgsl.expected.msl
@@ -4,7 +4,7 @@
kernel void f() {
int3 const a = int3(1, 2, 3);
int3 const b = int3(4, 5, 6);
- int3 const r = as_type<int3>((as_type<uint3>(int3(a)) + as_type<uint3>(int3(b))));
+ int3 const r = as_type<int3>((as_type<uint3>(a) + as_type<uint3>(b)));
return;
}
diff --git a/test/tint/expressions/binary/div_by_zero/by_expression/scalar-vec3/i32.wgsl.expected.msl b/test/tint/expressions/binary/div_by_zero/by_expression/scalar-vec3/i32.wgsl.expected.msl
index 6d2f8bc..72cb90c 100644
--- a/test/tint/expressions/binary/div_by_zero/by_expression/scalar-vec3/i32.wgsl.expected.msl
+++ b/test/tint/expressions/binary/div_by_zero/by_expression/scalar-vec3/i32.wgsl.expected.msl
@@ -4,7 +4,7 @@
kernel void f() {
int a = 4;
int3 b = int3(0, 2, 0);
- int3 const r = (a / as_type<int3>((as_type<uint3>(int3(b)) + as_type<uint3>(int3(b)))));
+ int3 const r = (a / as_type<int3>((as_type<uint3>(b) + as_type<uint3>(b))));
return;
}
diff --git a/test/tint/expressions/binary/div_by_zero/by_expression/vec3-vec3/i32.wgsl.expected.msl b/test/tint/expressions/binary/div_by_zero/by_expression/vec3-vec3/i32.wgsl.expected.msl
index c90c00e..e2a2a76 100644
--- a/test/tint/expressions/binary/div_by_zero/by_expression/vec3-vec3/i32.wgsl.expected.msl
+++ b/test/tint/expressions/binary/div_by_zero/by_expression/vec3-vec3/i32.wgsl.expected.msl
@@ -4,7 +4,7 @@
kernel void f() {
int3 a = int3(1, 2, 3);
int3 b = int3(0, 5, 0);
- int3 const r = (a / as_type<int3>((as_type<uint3>(int3(b)) + as_type<uint3>(int3(b)))));
+ int3 const r = (a / as_type<int3>((as_type<uint3>(b) + as_type<uint3>(b))));
return;
}
diff --git a/test/tint/expressions/binary/left-shift/vector-vector/i32.wgsl.expected.msl b/test/tint/expressions/binary/left-shift/vector-vector/i32.wgsl.expected.msl
index 1e4e146..f97db25 100644
--- a/test/tint/expressions/binary/left-shift/vector-vector/i32.wgsl.expected.msl
+++ b/test/tint/expressions/binary/left-shift/vector-vector/i32.wgsl.expected.msl
@@ -4,7 +4,7 @@
kernel void f() {
int3 const a = int3(1, 2, 3);
uint3 const b = uint3(4u, 5u, 6u);
- int3 const r = as_type<int3>((as_type<uint3>(int3(a)) << b));
+ int3 const r = as_type<int3>((as_type<uint3>(a) << b));
return;
}
diff --git a/test/tint/expressions/binary/mod_by_zero/by_expression/scalar-vec3/i32.wgsl.expected.msl b/test/tint/expressions/binary/mod_by_zero/by_expression/scalar-vec3/i32.wgsl.expected.msl
index 22f6994..12f1a72 100644
--- a/test/tint/expressions/binary/mod_by_zero/by_expression/scalar-vec3/i32.wgsl.expected.msl
+++ b/test/tint/expressions/binary/mod_by_zero/by_expression/scalar-vec3/i32.wgsl.expected.msl
@@ -4,7 +4,7 @@
kernel void f() {
int a = 4;
int3 b = int3(0, 2, 0);
- int3 const r = (a % as_type<int3>((as_type<uint3>(int3(b)) + as_type<uint3>(int3(b)))));
+ int3 const r = (a % as_type<int3>((as_type<uint3>(b) + as_type<uint3>(b))));
return;
}
diff --git a/test/tint/expressions/binary/mod_by_zero/by_expression/vec3-vec3/i32.wgsl.expected.msl b/test/tint/expressions/binary/mod_by_zero/by_expression/vec3-vec3/i32.wgsl.expected.msl
index 2d83cd3..61356dc 100644
--- a/test/tint/expressions/binary/mod_by_zero/by_expression/vec3-vec3/i32.wgsl.expected.msl
+++ b/test/tint/expressions/binary/mod_by_zero/by_expression/vec3-vec3/i32.wgsl.expected.msl
@@ -4,7 +4,7 @@
kernel void f() {
int3 a = int3(1, 2, 3);
int3 b = int3(0, 5, 0);
- int3 const r = (a % as_type<int3>((as_type<uint3>(int3(b)) + as_type<uint3>(int3(b)))));
+ int3 const r = (a % as_type<int3>((as_type<uint3>(b) + as_type<uint3>(b))));
return;
}
diff --git a/test/tint/expressions/binary/mul/mat3x2-vec3/f32.wgsl.expected.msl b/test/tint/expressions/binary/mul/mat3x2-vec3/f32.wgsl.expected.msl
index e210c3c..a36de59 100644
--- a/test/tint/expressions/binary/mul/mat3x2-vec3/f32.wgsl.expected.msl
+++ b/test/tint/expressions/binary/mul/mat3x2-vec3/f32.wgsl.expected.msl
@@ -14,16 +14,6 @@
T elements[N];
};
-template<typename T, int N, int M>
-inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) {
- return lhs * vec<T, N>(rhs);
-}
-
-template<typename T, int N, int M>
-inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) {
- return vec<T, M>(lhs) * rhs;
-}
-
struct S {
/* 0x0000 */ float3x2 tint_symbol;
/* 0x0018 */ tint_array<int8_t, 8> tint_pad;
@@ -32,7 +22,7 @@
};
fragment void tint_symbol_1(const constant S* tint_symbol_2 [[buffer(0)]]) {
- float2 const x = ((*(tint_symbol_2)).tint_symbol * (*(tint_symbol_2)).vector);
+ float2 const x = ((*(tint_symbol_2)).tint_symbol * float3((*(tint_symbol_2)).vector));
return;
}
diff --git a/test/tint/expressions/binary/mul/mat3x3-vec3/f32.wgsl.expected.msl b/test/tint/expressions/binary/mul/mat3x3-vec3/f32.wgsl.expected.msl
index 8f4ff55..79c3e09 100644
--- a/test/tint/expressions/binary/mul/mat3x3-vec3/f32.wgsl.expected.msl
+++ b/test/tint/expressions/binary/mul/mat3x3-vec3/f32.wgsl.expected.msl
@@ -2,16 +2,6 @@
using namespace metal;
-template<typename T, int N, int M>
-inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) {
- return lhs * vec<T, N>(rhs);
-}
-
-template<typename T, int N, int M>
-inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) {
- return vec<T, M>(lhs) * rhs;
-}
-
template<typename T, size_t N>
struct tint_array {
const constant T& operator[](size_t i) const constant { return elements[i]; }
@@ -31,7 +21,7 @@
};
fragment void tint_symbol_1(const constant S* tint_symbol_2 [[buffer(0)]]) {
- float3 const x = ((*(tint_symbol_2)).tint_symbol * (*(tint_symbol_2)).vector);
+ float3 const x = ((*(tint_symbol_2)).tint_symbol * float3((*(tint_symbol_2)).vector));
return;
}
diff --git a/test/tint/expressions/binary/mul/scalar-vec3/i32.wgsl.expected.msl b/test/tint/expressions/binary/mul/scalar-vec3/i32.wgsl.expected.msl
index 0a492f4..216de39 100644
--- a/test/tint/expressions/binary/mul/scalar-vec3/i32.wgsl.expected.msl
+++ b/test/tint/expressions/binary/mul/scalar-vec3/i32.wgsl.expected.msl
@@ -4,7 +4,7 @@
kernel void f() {
int const a = 4;
int3 const b = int3(1, 2, 3);
- int3 const r = as_type<int3>((as_type<uint>(a) * as_type<uint3>(int3(b))));
+ int3 const r = as_type<int3>((as_type<uint>(a) * as_type<uint3>(b)));
return;
}
diff --git a/test/tint/expressions/binary/mul/vec3-mat3x3/f32.wgsl.expected.msl b/test/tint/expressions/binary/mul/vec3-mat3x3/f32.wgsl.expected.msl
index d9fc80b..321a379 100644
--- a/test/tint/expressions/binary/mul/vec3-mat3x3/f32.wgsl.expected.msl
+++ b/test/tint/expressions/binary/mul/vec3-mat3x3/f32.wgsl.expected.msl
@@ -2,16 +2,6 @@
using namespace metal;
-template<typename T, int N, int M>
-inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) {
- return lhs * vec<T, N>(rhs);
-}
-
-template<typename T, int N, int M>
-inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) {
- return vec<T, M>(lhs) * rhs;
-}
-
template<typename T, size_t N>
struct tint_array {
const constant T& operator[](size_t i) const constant { return elements[i]; }
@@ -31,7 +21,7 @@
};
fragment void tint_symbol_1(const constant S* tint_symbol_2 [[buffer(0)]]) {
- float3 const x = ((*(tint_symbol_2)).vector * (*(tint_symbol_2)).tint_symbol);
+ float3 const x = (float3((*(tint_symbol_2)).vector) * (*(tint_symbol_2)).tint_symbol);
return;
}
diff --git a/test/tint/expressions/binary/mul/vec3-mat4x3/f32.wgsl.expected.msl b/test/tint/expressions/binary/mul/vec3-mat4x3/f32.wgsl.expected.msl
index 3f66659..b1f6165 100644
--- a/test/tint/expressions/binary/mul/vec3-mat4x3/f32.wgsl.expected.msl
+++ b/test/tint/expressions/binary/mul/vec3-mat4x3/f32.wgsl.expected.msl
@@ -2,16 +2,6 @@
using namespace metal;
-template<typename T, int N, int M>
-inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) {
- return lhs * vec<T, N>(rhs);
-}
-
-template<typename T, int N, int M>
-inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) {
- return vec<T, M>(lhs) * rhs;
-}
-
template<typename T, size_t N>
struct tint_array {
const constant T& operator[](size_t i) const constant { return elements[i]; }
@@ -31,7 +21,7 @@
};
fragment void tint_symbol_1(const constant S* tint_symbol_2 [[buffer(0)]]) {
- float4 const x = ((*(tint_symbol_2)).vector * (*(tint_symbol_2)).tint_symbol);
+ float4 const x = (float3((*(tint_symbol_2)).vector) * (*(tint_symbol_2)).tint_symbol);
return;
}
diff --git a/test/tint/expressions/binary/mul/vec3-scalar/i32.wgsl.expected.msl b/test/tint/expressions/binary/mul/vec3-scalar/i32.wgsl.expected.msl
index 134ba04..f320bd7 100644
--- a/test/tint/expressions/binary/mul/vec3-scalar/i32.wgsl.expected.msl
+++ b/test/tint/expressions/binary/mul/vec3-scalar/i32.wgsl.expected.msl
@@ -4,7 +4,7 @@
kernel void f() {
int3 const a = int3(1, 2, 3);
int const b = 4;
- int3 const r = as_type<int3>((as_type<uint3>(int3(a)) * as_type<uint>(b)));
+ int3 const r = as_type<int3>((as_type<uint3>(a) * as_type<uint>(b)));
return;
}
diff --git a/test/tint/expressions/binary/mul/vec3-vec3/i32.wgsl.expected.msl b/test/tint/expressions/binary/mul/vec3-vec3/i32.wgsl.expected.msl
index dbbcac5..f4511b2 100644
--- a/test/tint/expressions/binary/mul/vec3-vec3/i32.wgsl.expected.msl
+++ b/test/tint/expressions/binary/mul/vec3-vec3/i32.wgsl.expected.msl
@@ -4,7 +4,7 @@
kernel void f() {
int3 const a = int3(1, 2, 3);
int3 const b = int3(4, 5, 6);
- int3 const r = as_type<int3>((as_type<uint3>(int3(a)) * as_type<uint3>(int3(b))));
+ int3 const r = as_type<int3>((as_type<uint3>(a) * as_type<uint3>(b)));
return;
}
diff --git a/test/tint/expressions/binary/sub/scalar-vec3/i32.wgsl.expected.msl b/test/tint/expressions/binary/sub/scalar-vec3/i32.wgsl.expected.msl
index 5403240..8837be0 100644
--- a/test/tint/expressions/binary/sub/scalar-vec3/i32.wgsl.expected.msl
+++ b/test/tint/expressions/binary/sub/scalar-vec3/i32.wgsl.expected.msl
@@ -4,7 +4,7 @@
kernel void f() {
int const a = 4;
int3 const b = int3(1, 2, 3);
- int3 const r = as_type<int3>((as_type<uint>(a) - as_type<uint3>(int3(b))));
+ int3 const r = as_type<int3>((as_type<uint>(a) - as_type<uint3>(b)));
return;
}
diff --git a/test/tint/expressions/binary/sub/vec3-scalar/i32.wgsl.expected.msl b/test/tint/expressions/binary/sub/vec3-scalar/i32.wgsl.expected.msl
index 9e59fcd..6149a0c 100644
--- a/test/tint/expressions/binary/sub/vec3-scalar/i32.wgsl.expected.msl
+++ b/test/tint/expressions/binary/sub/vec3-scalar/i32.wgsl.expected.msl
@@ -4,7 +4,7 @@
kernel void f() {
int3 const a = int3(1, 2, 3);
int const b = 4;
- int3 const r = as_type<int3>((as_type<uint3>(int3(a)) - as_type<uint>(b)));
+ int3 const r = as_type<int3>((as_type<uint3>(a) - as_type<uint>(b)));
return;
}
diff --git a/test/tint/expressions/binary/sub/vec3-vec3/i32.wgsl.expected.msl b/test/tint/expressions/binary/sub/vec3-vec3/i32.wgsl.expected.msl
index a42ec6c..142bb72 100644
--- a/test/tint/expressions/binary/sub/vec3-vec3/i32.wgsl.expected.msl
+++ b/test/tint/expressions/binary/sub/vec3-vec3/i32.wgsl.expected.msl
@@ -4,7 +4,7 @@
kernel void f() {
int3 const a = int3(1, 2, 3);
int3 const b = int3(4, 5, 6);
- int3 const r = as_type<int3>((as_type<uint3>(int3(a)) - as_type<uint3>(int3(b))));
+ int3 const r = as_type<int3>((as_type<uint3>(a) - as_type<uint3>(b)));
return;
}
diff --git a/test/tint/expressions/swizzle/read/packed_vec3/f32.wgsl.expected.msl b/test/tint/expressions/swizzle/read/packed_vec3/f32.wgsl.expected.msl
index e2bbca3..1974ac0 100644
--- a/test/tint/expressions/swizzle/read/packed_vec3/f32.wgsl.expected.msl
+++ b/test/tint/expressions/swizzle/read/packed_vec3/f32.wgsl.expected.msl
@@ -2,16 +2,6 @@
using namespace metal;
-template<typename T, int N, int M>
-inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) {
- return lhs * vec<T, N>(rhs);
-}
-
-template<typename T, int N, int M>
-inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) {
- return vec<T, M>(lhs) * rhs;
-}
-
template<typename T, size_t N>
struct tint_array {
const constant T& operator[](size_t i) const constant { return elements[i]; }
@@ -30,7 +20,7 @@
};
void f(const constant S* const tint_symbol) {
- float3 v = (*(tint_symbol)).v;
+ float3 v = float3((*(tint_symbol)).v);
float x = (*(tint_symbol)).v[0];
float y = (*(tint_symbol)).v[1];
float z = (*(tint_symbol)).v[2];
diff --git a/test/tint/expressions/swizzle/read/packed_vec3/i32.wgsl.expected.msl b/test/tint/expressions/swizzle/read/packed_vec3/i32.wgsl.expected.msl
index 7a93a59..cfabec5 100644
--- a/test/tint/expressions/swizzle/read/packed_vec3/i32.wgsl.expected.msl
+++ b/test/tint/expressions/swizzle/read/packed_vec3/i32.wgsl.expected.msl
@@ -20,7 +20,7 @@
};
void f(const constant S* const tint_symbol) {
- int3 v = (*(tint_symbol)).v;
+ int3 v = int3((*(tint_symbol)).v);
int x = (*(tint_symbol)).v[0];
int y = (*(tint_symbol)).v[1];
int z = (*(tint_symbol)).v[2];
diff --git a/test/tint/expressions/swizzle/read/packed_vec3/u32.wgsl.expected.msl b/test/tint/expressions/swizzle/read/packed_vec3/u32.wgsl.expected.msl
index 7444f75..3f1899c 100644
--- a/test/tint/expressions/swizzle/read/packed_vec3/u32.wgsl.expected.msl
+++ b/test/tint/expressions/swizzle/read/packed_vec3/u32.wgsl.expected.msl
@@ -20,7 +20,7 @@
};
void f(const constant S* const tint_symbol) {
- uint3 v = (*(tint_symbol)).v;
+ uint3 v = uint3((*(tint_symbol)).v);
uint x = (*(tint_symbol)).v[0];
uint y = (*(tint_symbol)).v[1];
uint z = (*(tint_symbol)).v[2];
diff --git a/test/tint/expressions/swizzle/write/packed_vec3/f32.wgsl.expected.msl b/test/tint/expressions/swizzle/write/packed_vec3/f32.wgsl.expected.msl
index 7599cbc..8640cf6 100644
--- a/test/tint/expressions/swizzle/write/packed_vec3/f32.wgsl.expected.msl
+++ b/test/tint/expressions/swizzle/write/packed_vec3/f32.wgsl.expected.msl
@@ -2,16 +2,6 @@
using namespace metal;
-template<typename T, int N, int M>
-inline vec<T, M> operator*(matrix<T, N, M> lhs, packed_vec<T, N> rhs) {
- return lhs * vec<T, N>(rhs);
-}
-
-template<typename T, int N, int M>
-inline vec<T, N> operator*(packed_vec<T, M> lhs, matrix<T, N, M> rhs) {
- return vec<T, M>(lhs) * rhs;
-}
-
template<typename T, size_t N>
struct tint_array {
const constant T& operator[](size_t i) const constant { return elements[i]; }
diff --git a/test/tint/statements/compound_assign/vector/minus.wgsl.expected.msl b/test/tint/statements/compound_assign/vector/minus.wgsl.expected.msl
index d6ddc12..1a225d3 100644
--- a/test/tint/statements/compound_assign/vector/minus.wgsl.expected.msl
+++ b/test/tint/statements/compound_assign/vector/minus.wgsl.expected.msl
@@ -6,6 +6,6 @@
};
void foo(device S* const tint_symbol) {
- (*(tint_symbol)).a = as_type<int4>((as_type<uint4>(int4((*(tint_symbol)).a)) - as_type<uint4>(int4(int4(2)))));
+ (*(tint_symbol)).a = as_type<int4>((as_type<uint4>((*(tint_symbol)).a) - as_type<uint4>(int4(2))));
}
diff --git a/test/tint/statements/compound_assign/vector/plus.wgsl.expected.msl b/test/tint/statements/compound_assign/vector/plus.wgsl.expected.msl
index 455e61d..7ea366b 100644
--- a/test/tint/statements/compound_assign/vector/plus.wgsl.expected.msl
+++ b/test/tint/statements/compound_assign/vector/plus.wgsl.expected.msl
@@ -6,6 +6,6 @@
};
void foo(device S* const tint_symbol) {
- (*(tint_symbol)).a = as_type<int4>((as_type<uint4>(int4((*(tint_symbol)).a)) + as_type<uint4>(int4(int4(2)))));
+ (*(tint_symbol)).a = as_type<int4>((as_type<uint4>((*(tint_symbol)).a) + as_type<uint4>(int4(2))));
}
diff --git a/test/tint/statements/compound_assign/vector/shift_left.wgsl.expected.msl b/test/tint/statements/compound_assign/vector/shift_left.wgsl.expected.msl
index 84a60be..2dd819c 100644
--- a/test/tint/statements/compound_assign/vector/shift_left.wgsl.expected.msl
+++ b/test/tint/statements/compound_assign/vector/shift_left.wgsl.expected.msl
@@ -6,6 +6,6 @@
};
void foo(device S* const tint_symbol) {
- (*(tint_symbol)).a = as_type<int4>((as_type<uint4>(int4((*(tint_symbol)).a)) << uint4(2u)));
+ (*(tint_symbol)).a = as_type<int4>((as_type<uint4>((*(tint_symbol)).a) << uint4(2u)));
}
diff --git a/test/tint/statements/compound_assign/vector/times.wgsl.expected.msl b/test/tint/statements/compound_assign/vector/times.wgsl.expected.msl
index 3dfa83f..ef7fd06 100644
--- a/test/tint/statements/compound_assign/vector/times.wgsl.expected.msl
+++ b/test/tint/statements/compound_assign/vector/times.wgsl.expected.msl
@@ -6,6 +6,6 @@
};
void foo(device S* const tint_symbol) {
- (*(tint_symbol)).a = as_type<int4>((as_type<uint4>(int4((*(tint_symbol)).a)) * as_type<uint4>(int4(int4(2)))));
+ (*(tint_symbol)).a = as_type<int4>((as_type<uint4>((*(tint_symbol)).a) * as_type<uint4>(int4(2))));
}