Import Tint changes from Dawn
Changes:
- c8fb20b38ba33dcaf4a7d688c5508a4b729033d0 [tint][msl] Fix doxygen warning / error by Ben Clayton <bclayton@google.com>
- f0057a56feedf3c617c9544a65416460c4f4aa9d Add inspector helper for texture information. by dan sinclair <dsinclair@chromium.org>
- ffd485c685040edb1e678165dcbf0e841cfa0298 [tint][msl] Replace volatile loop conditional with outer ... by Ben Clayton <bclayton@google.com>
- 267845cb1db12737854d8b12e900711d10830b45 [spirv-reader] Parse IO struct member decorations by James Price <jrprice@google.com>
- a3cad6827d5ce6d6d437ae36dd5dce7924d5dee9 [spirv-reader] Parse Invariant decoration on var by James Price <jrprice@google.com>
- 3d63299556a1899ef84df2d7d811caf02a855349 [spirv-reader] Parse user-defined IO decorations by James Price <jrprice@google.com>
- fe068476847cba50af47c04d50065bc9ac22c3ec [spirv-reader] Parse input/output builtins by James Price <jrprice@google.com>
- 9be037cf1bcbd4a37d083d079f4e457e2b7f5182 [tint][msl]: Use a volatile bool to control loop preserva... by Ben Clayton <bclayton@google.com>
- 9cfc80a7865ae17e71631cfe481a8d067a3dcc85 [spirv-reader] Handle StorageBuffer storage class by James Price <jrprice@google.com>
- ea0fda3e68e565d4f4610b4521f6cafe663bfa84 [ast,msl]: packed_vec3: Unroll loop for small composite c... by David Neto <dneto@google.com>
GitOrigin-RevId: c8fb20b38ba33dcaf4a7d688c5508a4b729033d0
Change-Id: Ia9dd2769bf321ad75f64b6397bd8f163c7c67ccf
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/170521
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/lang/core/type/manager.h b/src/tint/lang/core/type/manager.h
index 0e8b324..6c12a6c 100644
--- a/src/tint/lang/core/type/manager.h
+++ b/src/tint/lang/core/type/manager.h
@@ -65,13 +65,13 @@
/// @returns the default access control for a memory view with the given address space.
static constexpr inline core::Access DefaultAccessFor(core::AddressSpace space) {
switch (space) {
+ case core::AddressSpace::kIn:
case core::AddressSpace::kPushConstant:
case core::AddressSpace::kUniform:
case core::AddressSpace::kHandle:
return core::Access::kRead;
case core::AddressSpace::kUndefined:
- case core::AddressSpace::kIn:
case core::AddressSpace::kOut:
case core::AddressSpace::kFunction:
case core::AddressSpace::kPixelLocal:
diff --git a/src/tint/lang/msl/writer/ast_printer/ast_printer.cc b/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
index 63dcf81..718770e 100644
--- a/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
@@ -2122,8 +2122,7 @@
};
TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
- Line() << "while (true) {";
- EmitLoopPreserver();
+ Line() << IsolateUB() << " while(true) {";
{
ScopedIndent si(this);
if (!EmitStatements(stmt->body->statements)) {
@@ -2193,8 +2192,7 @@
};
TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
- Line() << "while (true) {";
- EmitLoopPreserver();
+ Line() << IsolateUB() << " while(true) {";
IncrementIndent();
TINT_DEFER({
DecrementIndent();
@@ -2217,7 +2215,7 @@
// For-loop can be generated.
{
auto out = Line();
- out << "for";
+ out << IsolateUB() << " for";
{
ScopedParen sp(out);
@@ -2235,7 +2233,6 @@
}
out << " {";
}
- EmitLoopPreserver();
{
auto emit_continuing = [] { return true; };
TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
@@ -2268,8 +2265,7 @@
// as a regular while in MSL. Instead we need to generate a `while(true)` loop.
bool emit_as_loop = cond_pre.lines.size() > 0;
if (emit_as_loop) {
- Line() << "while (true) {";
- EmitLoopPreserver();
+ Line() << IsolateUB() << " while(true) {";
IncrementIndent();
TINT_DEFER({
DecrementIndent();
@@ -2283,16 +2279,7 @@
}
} else {
// While can be generated.
- {
- auto out = Line();
- out << "while";
- {
- ScopedParen sp(out);
- out << cond_buf.str();
- }
- out << " {";
- }
- EmitLoopPreserver();
+ Line() << IsolateUB() << " while(" << cond_buf.str() << ") {";
if (!EmitStatementsWithIndent(stmt->body->statements)) {
return false;
}
@@ -3031,32 +3018,16 @@
return true;
}
-void ASTPrinter::EmitLoopPreserver() {
- IncrementIndent();
- // This statement prevents the MSL compiler from erasing a loop during
- // optimizations. In the AIR dialiect of LLVM IR, WGSL loops should compile
- // to a loop that contains an 'asm' call with a 'sideeffect' annotation.
- //
- // For example, compile a WGSL file with a trivial while(1) loop to 'a.metal',
- // then compile that to AIR (LLVM IR dialect):
- //
- // xcrun metal a.metal -S -o -
- //
- // The loop in the AIR should look something like this:
- //
- // 1: ...
- // br label %2
- //
- // 2: ; preds = %1, %2
- // tail call void asm sideeffect "", ""() #1, !srcloc !27
- // br label %2, !llvm.loop !28
- //
- // It is important that the 'sideeffect' annotation exist. That tells the
- // optimizer that the instruction has side effects invisible to the
- // optimizer, and therefore the loop should not be eliminated.
- Line() << R"(__asm__("");)";
-
- DecrementIndent();
+std::string_view ASTPrinter::IsolateUB() {
+ if (isolate_ub_macro_name_.empty()) {
+ isolate_ub_macro_name_ = UniqueIdentifier("TINT_ISOLATE_UB");
+ auto volatile_true = UniqueIdentifier("tint_volatile_true");
+ Line(&helpers_) << "#define " << isolate_ub_macro_name_ << " \\";
+ Line(&helpers_) << " if (volatile bool " << volatile_true << " = true; " << volatile_true
+ << ")";
+ Line(&helpers_);
+ }
+ return isolate_ub_macro_name_;
}
template <typename F>
diff --git a/src/tint/lang/msl/writer/ast_printer/ast_printer.h b/src/tint/lang/msl/writer/ast_printer/ast_printer.h
index af251db..70269c9 100644
--- a/src/tint/lang/msl/writer/ast_printer/ast_printer.h
+++ b/src/tint/lang/msl/writer/ast_printer/ast_printer.h
@@ -378,9 +378,10 @@
const ast::CallExpression* expr,
const sem::BuiltinFn* builtin);
- /// Emits a code sequence that preserves a loop during
- /// optimizations even if the loop is infinite.
- void EmitLoopPreserver();
+ /// Lazilly generates the TINT_ISOLATE_UB macro, used to prevent UB statements from affecting
+ /// later logic.
+ /// @return the unique name of the TINT_ISOLATE_UB macro.
+ std::string_view IsolateUB();
/// Handles generating a builtin name
/// @param builtin the semantic info for the builtin
@@ -437,6 +438,10 @@
std::function<bool()> emit_continuing_;
+ /// The name of the macro used to prevent UB affecting later control flow.
+ /// Do not use this directly, instead call IsolateUB().
+ std::string isolate_ub_macro_name_;
+
/// Name of atomicCompareExchangeWeak() helper for the given pointer storage
/// class and struct return type
using ACEWKeyType =
diff --git a/src/tint/lang/msl/writer/ast_printer/ast_printer_test.cc b/src/tint/lang/msl/writer/ast_printer/ast_printer_test.cc
index 0477e48..74d8fdd 100644
--- a/src/tint/lang/msl/writer/ast_printer/ast_printer_test.cc
+++ b/src/tint/lang/msl/writer/ast_printer/ast_printer_test.cc
@@ -226,13 +226,15 @@
T elements[N];
};
+#define TINT_ISOLATE_UB \
+ if (volatile bool tint_volatile_true = true; tint_volatile_true)
+
struct tint_symbol_3 {
tint_array<float2x2, 4> m;
};
void comp_main_inner(uint local_invocation_index, threadgroup tint_array<float2x2, 4>* const tint_symbol) {
- for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
- __asm__("");
+ TINT_ISOLATE_UB for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
uint const i = idx;
(*(tint_symbol))[i] = float2x2(float2(0.0f), float2(0.0f));
}
diff --git a/src/tint/lang/msl/writer/ast_printer/continue_test.cc b/src/tint/lang/msl/writer/ast_printer/continue_test.cc
index a79ddc3..727f05c 100644
--- a/src/tint/lang/msl/writer/ast_printer/continue_test.cc
+++ b/src/tint/lang/msl/writer/ast_printer/continue_test.cc
@@ -39,16 +39,24 @@
ASTPrinter& gen = Build();
- gen.IncrementIndent();
+ ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
+ EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
- ASSERT_TRUE(gen.EmitStatement(loop)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( while (true) {
- __asm__("");
+using namespace metal;
+
+#define TINT_ISOLATE_UB \
+ if (volatile bool tint_volatile_true = true; tint_volatile_true)
+
+kernel void test_function() {
+ TINT_ISOLATE_UB while(true) {
if (false) {
break;
}
continue;
}
+ return;
+}
+
)");
}
diff --git a/src/tint/lang/msl/writer/ast_printer/loop_test.cc b/src/tint/lang/msl/writer/ast_printer/loop_test.cc
index 450592b..7aed227 100644
--- a/src/tint/lang/msl/writer/ast_printer/loop_test.cc
+++ b/src/tint/lang/msl/writer/ast_printer/loop_test.cc
@@ -46,13 +46,21 @@
ASTPrinter& gen = Build();
- gen.IncrementIndent();
+ ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
+ EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
- ASSERT_TRUE(gen.EmitStatement(l)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( while (true) {
- __asm__("");
+using namespace metal;
+
+#define TINT_ISOLATE_UB \
+ if (volatile bool tint_volatile_true = true; tint_volatile_true)
+
+fragment void F() {
+ TINT_ISOLATE_UB while(true) {
break;
}
+ return;
+}
+
)");
}
@@ -67,16 +75,27 @@
ASTPrinter& gen = Build();
- gen.IncrementIndent();
+ ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
+ EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
- ASSERT_TRUE(gen.EmitStatement(l)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( while (true) {
- __asm__("");
+using namespace metal;
+
+#define TINT_ISOLATE_UB \
+ if (volatile bool tint_volatile_true = true; tint_volatile_true)
+
+void a_statement() {
+}
+
+fragment void F() {
+ TINT_ISOLATE_UB while(true) {
break;
{
a_statement();
}
}
+ return;
+}
+
)");
}
@@ -91,17 +110,28 @@
ASTPrinter& gen = Build();
- gen.IncrementIndent();
+ ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
+ EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
- ASSERT_TRUE(gen.EmitStatement(l)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( while (true) {
- __asm__("");
+using namespace metal;
+
+#define TINT_ISOLATE_UB \
+ if (volatile bool tint_volatile_true = true; tint_volatile_true)
+
+void a_statement() {
+}
+
+fragment void F() {
+ TINT_ISOLATE_UB while(true) {
break;
{
a_statement();
if (true) { break; }
}
}
+ return;
+}
+
)");
}
@@ -125,23 +155,19 @@
ASTPrinter& gen = Build();
- gen.IncrementIndent();
-
ASSERT_TRUE(gen.EmitStatement(outer)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( while (true) {
- __asm__("");
- while (true) {
- __asm__("");
- break;
- {
- a_statement();
- }
- }
+ EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB while(true) {
+ TINT_ISOLATE_UB while(true) {
+ break;
{
- lhs = rhs;
- if (true) { break; }
+ a_statement();
}
}
+ {
+ lhs = rhs;
+ if (true) { break; }
+ }
+}
)");
}
@@ -167,18 +193,15 @@
ASTPrinter& gen = Build();
- gen.IncrementIndent();
-
ASSERT_TRUE(gen.EmitStatement(outer)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( while (true) {
- __asm__("");
- float lhs = 2.5f;
- float other = 0.0f;
- break;
- {
- lhs = rhs;
- }
+ EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB while(true) {
+ float lhs = 2.5f;
+ float other = 0.0f;
+ break;
+ {
+ lhs = rhs;
}
+}
)");
}
@@ -193,13 +216,10 @@
ASTPrinter& gen = Build();
- gen.IncrementIndent();
-
ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( for(; ; ) {
- __asm__("");
- return;
- }
+ EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB for(; ; ) {
+ return;
+}
)");
}
@@ -214,13 +234,10 @@
ASTPrinter& gen = Build();
- gen.IncrementIndent();
-
ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( for(int i = 0; ; ) {
- __asm__("");
- return;
- }
+ EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB for(int i = 0; ; ) {
+ return;
+}
)");
}
@@ -243,19 +260,16 @@
ASTPrinter& gen = Build();
- gen.IncrementIndent();
-
ASSERT_TRUE(gen.EmitStatement(loop)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( {
- {
- f(1);
- f(2);
- }
- for(; ; ) {
- __asm__("");
- return;
- }
+ EXPECT_EQ(gen.Result(), R"({
+ {
+ f(1);
+ f(2);
}
+ TINT_ISOLATE_UB for(; ; ) {
+ return;
+ }
+}
)");
}
@@ -270,13 +284,10 @@
ASTPrinter& gen = Build();
- gen.IncrementIndent();
-
ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( for(; true; ) {
- __asm__("");
- return;
- }
+ EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB for(; true; ) {
+ return;
+}
)");
}
@@ -292,14 +303,11 @@
ASTPrinter& gen = Build();
- gen.IncrementIndent();
-
ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
EXPECT_EQ(gen.Result(),
- R"( for(; ; i = as_type<int>((as_type<uint>(i) + as_type<uint>(1)))) {
- __asm__("");
- return;
- }
+ R"(TINT_ISOLATE_UB for(; ; i = as_type<int>((as_type<uint>(i) + as_type<uint>(1)))) {
+ return;
+}
)");
}
@@ -322,17 +330,14 @@
ASTPrinter& gen = Build();
- gen.IncrementIndent();
-
ASSERT_TRUE(gen.EmitStatement(loop)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( while (true) {
- __asm__("");
- return;
- {
- f(1);
- f(2);
- }
+ EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB while(true) {
+ return;
+ {
+ f(1);
+ f(2);
}
+}
)");
}
@@ -349,14 +354,12 @@
ASTPrinter& gen = Build();
- gen.IncrementIndent();
-
ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(),
- R"( for(int i = 0; true; i = as_type<int>((as_type<uint>(i) + as_type<uint>(1)))) {
- __asm__("");
- a_statement();
- }
+ EXPECT_EQ(
+ gen.Result(),
+ R"(TINT_ISOLATE_UB for(int i = 0; true; i = as_type<int>((as_type<uint>(i) + as_type<uint>(1)))) {
+ a_statement();
+}
)");
}
@@ -380,24 +383,21 @@
ASTPrinter& gen = Build();
- gen.IncrementIndent();
-
ASSERT_TRUE(gen.EmitStatement(loop)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( {
+ EXPECT_EQ(gen.Result(), R"({
+ {
+ f(1);
+ f(2);
+ }
+ TINT_ISOLATE_UB while(true) {
+ if (!(true)) { break; }
+ return;
{
- f(1);
- f(2);
- }
- while (true) {
- __asm__("");
- if (!(true)) { break; }
- return;
- {
- f(3);
- f(4);
- }
+ f(3);
+ f(4);
}
}
+}
)");
}
@@ -411,13 +411,10 @@
ASTPrinter& gen = Build();
- gen.IncrementIndent();
-
ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( while(true) {
- __asm__("");
- return;
- }
+ EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB while(true) {
+ return;
+}
)");
}
@@ -431,13 +428,10 @@
ASTPrinter& gen = Build();
- gen.IncrementIndent();
-
ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( while(true) {
- __asm__("");
- continue;
- }
+ EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB while(true) {
+ continue;
+}
)");
}
@@ -454,13 +448,10 @@
ASTPrinter& gen = Build();
- gen.IncrementIndent();
-
ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( while((t && false)) {
- __asm__("");
- return;
- }
+ EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB while((t && false)) {
+ return;
+}
)");
}
diff --git a/src/tint/lang/msl/writer/ast_raise/packed_vec3.cc b/src/tint/lang/msl/writer/ast_raise/packed_vec3.cc
index 9d651c6..a61e3f8 100644
--- a/src/tint/lang/msl/writer/ast_raise/packed_vec3.cc
+++ b/src/tint/lang/msl/writer/ast_raise/packed_vec3.cc
@@ -58,6 +58,10 @@
namespace tint::msl::writer {
+/// Arrays larger than this will be packed/unpacked with a for loop.
+/// Arrays up to this size will be packed/unpacked with a sequence of statements.
+static constexpr uint32_t kMaxSeriallyUnpackedArraySize = 8;
+
/// PIMPL state for the transform
struct PackedVec3::State {
/// Constructor
@@ -242,7 +246,6 @@
const std::function<ast::Type()>& out_type) {
// Allocate a variable to hold the return value of the function.
tint::Vector<const ast::Statement*, 4> statements;
- statements.Push(b.Decl(b.Var("result", out_type())));
// Helper that generates a loop to copy and pack/unpack elements of an array to the result:
// for (var i = 0u; i < num_elements; i = i + 1) {
@@ -250,15 +253,28 @@
// }
auto copy_array_elements = [&](uint32_t num_elements,
const core::type::Type* element_type) {
- // Generate an expression for packing or unpacking an element of the array.
- auto* element = pack_or_unpack_element(b.IndexAccessor("in", "i"), element_type);
- statements.Push(b.For( //
- b.Decl(b.Var("i", b.ty.u32())), //
- b.LessThan("i", u32(num_elements)), //
- b.Assign("i", b.Add("i", 1_a)), //
- b.Block(tint::Vector{
- b.Assign(b.IndexAccessor("result", "i"), element),
- })));
+ // Generate code for unpacking the array.
+ if (num_elements <= kMaxSeriallyUnpackedArraySize) {
+ // Generate a variable with an explicit initializer.
+ tint::Vector<const ast::Expression*, 8> elements;
+ for (uint32_t i = 0; i < num_elements; i++) {
+ elements.Push(pack_or_unpack_element(
+ b.IndexAccessor("in", b.Expr(core::AInt(i))), element_type));
+ }
+ statements.Push(b.Decl(b.Var("result", b.Call(out_type(), b.ExprList(elements)))));
+ } else {
+ statements.Push(b.Decl(b.Var("result", out_type())));
+ // Generate a for loop.
+ // Generate an expression for packing or unpacking an element of the array.
+ auto* element = pack_or_unpack_element(b.IndexAccessor("in", "i"), element_type);
+ statements.Push(b.For( //
+ b.Decl(b.Var("i", b.ty.u32())), //
+ b.LessThan("i", u32(num_elements)), //
+ b.Assign("i", b.Add("i", 1_a)), //
+ b.Block(tint::Vector{
+ b.Assign(b.IndexAccessor("result", "i"), element),
+ })));
+ }
};
// Copy the elements of the value over to the result.
@@ -272,6 +288,7 @@
copy_array_elements(mat->columns(), mat->ColumnType());
},
[&](const core::type::Struct* str) {
+ statements.Push(b.Decl(b.Var("result", out_type())));
// Copy the struct members over one at a time, packing/unpacking as necessary.
for (auto* member : str->Members()) {
const ast::Expression* element =
diff --git a/src/tint/lang/msl/writer/ast_raise/packed_vec3_test.cc b/src/tint/lang/msl/writer/ast_raise/packed_vec3_test.cc
index 220dabb..cc002ba 100644
--- a/src/tint/lang/msl/writer/ast_raise/packed_vec3_test.cc
+++ b/src/tint/lang/msl/writer/ast_raise/packed_vec3_test.cc
@@ -502,7 +502,7 @@
EXPECT_EQ(expect, str(got));
}
-TEST_F(PackedVec3Test, ArrayOfVec3_ReadArray) {
+TEST_F(PackedVec3Test, ArrayOfVec3_ReadArray_Small) {
auto* src = R"(
@group(0) @binding(0) var<storage> arr : array<vec3<f32>, 4>;
@@ -520,14 +520,49 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result : array<vec3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
+ var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
+ return result;
+}
+
+@group(0) @binding(0) var<storage> arr : array<tint_packed_vec3_f32_array_element, 4u>;
+
+fn f() {
+ let x = tint_unpack_vec3_in_composite(arr);
+}
+)";
+
+ ast::transform::DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfVec3_ReadArray_Large) {
+ auto* src = R"(
+@group(0) @binding(0) var<storage> arr : array<vec3<f32>, 9>;
+
+fn f() {
+ let x = arr;
+}
+)";
+
+ auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+ @align(16)
+ elements : __packed_vec3<f32>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 9u>) -> array<vec3<f32>, 9u> {
+ var result : array<vec3<f32>, 9u>;
+ for(var i : u32; (i < 9u); i = (i + 1)) {
result[i] = vec3<f32>(in[i].elements);
}
return result;
}
-@group(0) @binding(0) var<storage> arr : array<tint_packed_vec3_f32_array_element, 4u>;
+@group(0) @binding(0) var<storage> arr : array<tint_packed_vec3_f32_array_element, 9u>;
fn f() {
let x = tint_unpack_vec3_in_composite(arr);
@@ -630,7 +665,7 @@
EXPECT_EQ(expect, str(got));
}
-TEST_F(PackedVec3Test, ArrayOfVec3_WriteArray_ValueRHS) {
+TEST_F(PackedVec3Test, ArrayOfVec3_WriteArray_ValueRHS_Small) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 2>;
@@ -648,10 +683,7 @@
}
fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 2u>) -> array<tint_packed_vec3_f32_array_element, 2u> {
- var result : array<tint_packed_vec3_f32_array_element, 2u>;
- for(var i : u32; (i < 2u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 2u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])));
return result;
}
@@ -668,6 +700,52 @@
EXPECT_EQ(expect, str(got));
}
+TEST_F(PackedVec3Test, ArrayOfVec3_WriteArray_ValueRHS_Large) {
+ auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 9>;
+
+fn f() {
+ arr = array(vec3(1.5, 2.5, 3.5),
+ vec3(4.5, 5.5, 6.5),
+ vec3(7.5, 8.5, 9.5),
+ vec3(7.5, 8.5, 9.5),
+ vec3(7.5, 8.5, 9.5),
+ vec3(7.5, 8.5, 9.5),
+ vec3(7.5, 8.5, 9.5),
+ vec3(7.5, 8.5, 9.5),
+ vec3(7.5, 8.5, 9.5));
+}
+)";
+
+ auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+ @align(16)
+ elements : __packed_vec3<f32>,
+}
+
+fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 9u>) -> array<tint_packed_vec3_f32_array_element, 9u> {
+ var result : array<tint_packed_vec3_f32_array_element, 9u>;
+ for(var i : u32; (i < 9u); i = (i + 1)) {
+ result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+ }
+ return result;
+}
+
+@group(0) @binding(0) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 9u>;
+
+fn f() {
+ arr = tint_pack_vec3_in_composite(array(vec3(1.5, 2.5, 3.5), vec3(4.5, 5.5, 6.5), vec3(7.5, 8.5, 9.5), vec3(7.5, 8.5, 9.5), vec3(7.5, 8.5, 9.5), vec3(7.5, 8.5, 9.5), vec3(7.5, 8.5, 9.5), vec3(7.5, 8.5, 9.5), vec3(7.5, 8.5, 9.5)));
+}
+)";
+
+ ast::transform::DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
TEST_F(PackedVec3Test, ArrayOfVec3_WriteArray_RefRHS) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 2>;
@@ -731,7 +809,7 @@
EXPECT_EQ(expect, str(got));
}
-TEST_F(PackedVec3Test, ArrayOfVec3_WriteVector_RefRHS) {
+TEST_F(PackedVec3Test, ArrayOfVec3_WriteVector_RefRHS_Small) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 4>;
@group(0) @binding(1) var<uniform> in_arr : array<vec3<f32>, 4>;
@@ -769,6 +847,44 @@
EXPECT_EQ(expect, str(got));
}
+TEST_F(PackedVec3Test, ArrayOfVec3_WriteVector_RefRHS_Large) {
+ auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 9>;
+@group(0) @binding(1) var<uniform> in_arr : array<vec3<f32>, 9>;
+@group(0) @binding(2) var<uniform> in_vec : vec3<f32>;
+
+fn f() {
+ arr[0] = in_arr[0];
+ arr[1] = in_vec;
+}
+)";
+
+ auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+ @align(16)
+ elements : __packed_vec3<f32>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 9u>;
+
+@group(0) @binding(1) var<uniform> in_arr : array<tint_packed_vec3_f32_array_element, 9u>;
+
+@group(0) @binding(2) var<uniform> in_vec : __packed_vec3<f32>;
+
+fn f() {
+ arr[0].elements = in_arr[0].elements;
+ arr[1].elements = in_vec;
+}
+)";
+
+ ast::transform::DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
TEST_F(PackedVec3Test, ArrayOfVec3_WriteComponent_MemberAccessor) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 4>;
@@ -847,10 +963,7 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
@@ -975,10 +1088,7 @@
}
fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result : array<tint_packed_vec3_f32_array_element, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
return result;
}
@@ -1156,7 +1266,7 @@
EXPECT_EQ(expect, str(got));
}
-TEST_F(PackedVec3Test, ArrayOfMatrix_ReadArray) {
+TEST_F(PackedVec3Test, ArrayOfMatrix_ReadArray_Small) {
auto* src = R"(
@group(0) @binding(0) var<storage> arr : array<mat3x3<f32>, 4>;
@@ -1174,22 +1284,59 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result : array<mat3x3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
+ var result = array<mat3x3<f32>, 4u>(tint_unpack_vec3_in_composite(in[0]), tint_unpack_vec3_in_composite(in[1]), tint_unpack_vec3_in_composite(in[2]), tint_unpack_vec3_in_composite(in[3]));
+ return result;
+}
+
+@group(0) @binding(0) var<storage> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+
+fn f() {
+ let x = tint_unpack_vec3_in_composite_1(arr);
+}
+)";
+
+ ast::transform::DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, ArrayOfMatrix_ReadArray_Large) {
+ auto* src = R"(
+@group(0) @binding(0) var<storage> arr : array<mat3x3<f32>, 9>;
+
+fn f() {
+ let x = arr;
+}
+)";
+
+ auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+ @align(16)
+ elements : __packed_vec3<f32>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
+ return result;
+}
+
+fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>) -> array<mat3x3<f32>, 9u> {
+ var result : array<mat3x3<f32>, 9u>;
+ for(var i : u32; (i < 9u); i = (i + 1)) {
result[i] = tint_unpack_vec3_in_composite(in[i]);
}
return result;
}
-@group(0) @binding(0) var<storage> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
+@group(0) @binding(0) var<storage> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>;
fn f() {
let x = tint_unpack_vec3_in_composite_1(arr);
@@ -1220,10 +1367,7 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
@@ -1330,7 +1474,7 @@
EXPECT_EQ(expect, str(got));
}
-TEST_F(PackedVec3Test, ArrayOfMatrix_WriteArray_ValueRHS) {
+TEST_F(PackedVec3Test, ArrayOfMatrix_WriteArray_ValueRHS_Small) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 2>;
@@ -1348,18 +1492,12 @@
}
fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result : array<tint_packed_vec3_f32_array_element, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
return result;
}
fn tint_pack_vec3_in_composite_1(in : array<mat3x3<f32>, 2u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 2u> {
- var result : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>;
- for(var i : u32; (i < 2u); i = (i + 1)) {
- result[i] = tint_pack_vec3_in_composite(in[i]);
- }
+ var result = array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>(tint_pack_vec3_in_composite(in[0]), tint_pack_vec3_in_composite(in[1]));
return result;
}
@@ -1376,6 +1514,57 @@
EXPECT_EQ(expect, str(got));
}
+TEST_F(PackedVec3Test, ArrayOfMatrix_WriteArray_ValueRHS_Large) {
+ auto* src = R"(
+@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 9>;
+
+fn f() {
+ arr = array(mat3x3<f32>(),
+ mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5),
+ mat3x3f(),
+ mat3x3f(),
+ mat3x3f(),
+ mat3x3f(),
+ mat3x3f(),
+ mat3x3f(),
+ mat3x3f());
+}
+)";
+
+ auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+ @align(16)
+ elements : __packed_vec3<f32>,
+}
+
+fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
+ var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
+ return result;
+}
+
+fn tint_pack_vec3_in_composite_1(in : array<mat3x3<f32>, 9u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 9u> {
+ var result : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>;
+ for(var i : u32; (i < 9u); i = (i + 1)) {
+ result[i] = tint_pack_vec3_in_composite(in[i]);
+ }
+ return result;
+}
+
+@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>;
+
+fn f() {
+ arr = tint_pack_vec3_in_composite_1(array(mat3x3<f32>(), mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5), mat3x3f(), mat3x3f(), mat3x3f(), mat3x3f(), mat3x3f(), mat3x3f(), mat3x3f()));
+}
+)";
+
+ ast::transform::DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
TEST_F(PackedVec3Test, ArrayOfMatrix_WriteArray_RefRHS) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 2>;
@@ -1427,10 +1616,7 @@
}
fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result : array<tint_packed_vec3_f32_array_element, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
return result;
}
@@ -2025,7 +2211,7 @@
EXPECT_EQ(expect, str(got));
}
-TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_ReadStruct) {
+TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_ReadStruct_Small) {
auto* src = R"(
struct S {
arr : array<vec3<f32>, 4>,
@@ -2052,10 +2238,7 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result : array<vec3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
return result;
}
@@ -2082,7 +2265,64 @@
EXPECT_EQ(expect, str(got));
}
-TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_ReadArray) {
+TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_ReadStruct_Large) {
+ auto* src = R"(
+struct S {
+ arr : array<vec3<f32>, 9>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let x = P;
+}
+)";
+
+ auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+ @align(16)
+ elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+ @align(16)
+ arr : array<tint_packed_vec3_f32_array_element, 9u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 9u>) -> array<vec3<f32>, 9u> {
+ var result : array<vec3<f32>, 9u>;
+ for(var i : u32; (i < 9u); i = (i + 1)) {
+ result[i] = vec3<f32>(in[i].elements);
+ }
+ return result;
+}
+
+fn tint_unpack_vec3_in_composite_1(in : S_tint_packed_vec3) -> S {
+ var result : S;
+ result.arr = tint_unpack_vec3_in_composite(in.arr);
+ return result;
+}
+
+struct S {
+ arr : array<vec3<f32>, 9>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+ let x = tint_unpack_vec3_in_composite_1(P);
+}
+)";
+
+ ast::transform::DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_ReadArray_Small) {
auto* src = R"(
struct S {
arr : array<vec3<f32>, 4>,
@@ -2109,15 +2349,63 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result : array<vec3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
+ var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
+ return result;
+}
+
+struct S {
+ arr : array<vec3<f32>, 4>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+ let x = tint_unpack_vec3_in_composite(P.arr);
+}
+)";
+
+ ast::transform::DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_ReadArray_Large) {
+ auto* src = R"(
+struct S {
+ arr : array<vec3<f32>, 9>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let x = P.arr;
+}
+)";
+
+ auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+ @align(16)
+ elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+ @align(16)
+ arr : array<tint_packed_vec3_f32_array_element, 9u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 9u>) -> array<vec3<f32>, 9u> {
+ var result : array<vec3<f32>, 9u>;
+ for(var i : u32; (i < 9u); i = (i + 1)) {
result[i] = vec3<f32>(in[i].elements);
}
return result;
}
struct S {
- arr : array<vec3<f32>, 4>,
+ arr : array<vec3<f32>, 9>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
@@ -2262,7 +2550,7 @@
EXPECT_EQ(expect, str(got));
}
-TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteStruct_ValueRHS) {
+TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteStruct_ValueRHS_Small) {
auto* src = R"(
struct S {
arr : array<vec3<f32>, 2>,
@@ -2290,10 +2578,7 @@
}
fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 2u>) -> array<tint_packed_vec3_f32_array_element, 2u> {
- var result : array<tint_packed_vec3_f32_array_element, 2u>;
- for(var i : u32; (i < 2u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 2u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])));
return result;
}
@@ -2320,6 +2605,72 @@
EXPECT_EQ(expect, str(got));
}
+TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteStruct_ValueRHS_Large) {
+ auto* src = R"(
+struct S {
+ arr : array<vec3<f32>, 9>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+ P = S(array(vec3(1.5, 4.5, 7.5),
+ vec3(9.5, 6.5, 3.5),
+ vec3(9.5, 6.5, 3.5),
+ vec3(9.5, 6.5, 3.5),
+ vec3(9.5, 6.5, 3.5),
+ vec3(9.5, 6.5, 3.5),
+ vec3(9.5, 6.5, 3.5),
+ vec3(9.5, 6.5, 3.5),
+ vec3(9.5, 6.5, 3.5)));
+}
+)";
+
+ auto* expect =
+ R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+ @align(16)
+ elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+ @align(16)
+ arr : array<tint_packed_vec3_f32_array_element, 9u>,
+}
+
+fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 9u>) -> array<tint_packed_vec3_f32_array_element, 9u> {
+ var result : array<tint_packed_vec3_f32_array_element, 9u>;
+ for(var i : u32; (i < 9u); i = (i + 1)) {
+ result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+ }
+ return result;
+}
+
+fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
+ var result : S_tint_packed_vec3;
+ result.arr = tint_pack_vec3_in_composite(in.arr);
+ return result;
+}
+
+struct S {
+ arr : array<vec3<f32>, 9>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+ P = tint_pack_vec3_in_composite_1(S(array(vec3(1.5, 4.5, 7.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5))));
+}
+)";
+
+ ast::transform::DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteStruct_RefRHS) {
auto* src = R"(
struct S {
@@ -2366,7 +2717,7 @@
EXPECT_EQ(expect, str(got));
}
-TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteArray_ValueRHS) {
+TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteArray_ValueRHS_Small) {
auto* src = R"(
struct S {
arr : array<vec3<f32>, 2>,
@@ -2393,10 +2744,7 @@
}
fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 2u>) -> array<tint_packed_vec3_f32_array_element, 2u> {
- var result : array<tint_packed_vec3_f32_array_element, 2u>;
- for(var i : u32; (i < 2u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 2u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])));
return result;
}
@@ -2417,6 +2765,65 @@
EXPECT_EQ(expect, str(got));
}
+TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteArray_ValueRHS_Large) {
+ auto* src = R"(
+struct S {
+ arr : array<vec3<f32>, 9>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S;
+
+fn f() {
+ P.arr = array(vec3(1.5, 4.5, 7.5),
+ vec3(9.5, 6.5, 3.5),
+ vec3(9.5, 6.5, 3.5),
+ vec3(9.5, 6.5, 3.5),
+ vec3(9.5, 6.5, 3.5),
+ vec3(9.5, 6.5, 3.5),
+ vec3(9.5, 6.5, 3.5),
+ vec3(9.5, 6.5, 3.5),
+ vec3(9.5, 6.5, 3.5));
+}
+)";
+
+ auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+ @align(16)
+ elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+ @align(16)
+ arr : array<tint_packed_vec3_f32_array_element, 9u>,
+}
+
+fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 9u>) -> array<tint_packed_vec3_f32_array_element, 9u> {
+ var result : array<tint_packed_vec3_f32_array_element, 9u>;
+ for(var i : u32; (i < 9u); i = (i + 1)) {
+ result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
+ }
+ return result;
+}
+
+struct S {
+ arr : array<vec3<f32>, 9>,
+}
+
+@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
+
+fn f() {
+ P.arr = tint_pack_vec3_in_composite(array(vec3(1.5, 4.5, 7.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5)));
+}
+)";
+
+ ast::transform::DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteArray_RefRHS) {
auto* src = R"(
struct S {
@@ -2684,10 +3091,7 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
@@ -2741,10 +3145,7 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
@@ -2922,10 +3323,7 @@
}
fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result : array<tint_packed_vec3_f32_array_element, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
return result;
}
@@ -3025,10 +3423,7 @@
}
fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result : array<tint_packed_vec3_f32_array_element, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
return result;
}
@@ -3289,7 +3684,7 @@
EXPECT_EQ(expect, str(got));
}
-TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_ReadStruct) {
+TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_ReadStruct_Small) {
auto* src = R"(
struct S {
arr : array<mat3x3<f32>, 4>,
@@ -3316,18 +3711,12 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result : array<mat3x3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite(in[i]);
- }
+ var result = array<mat3x3<f32>, 4u>(tint_unpack_vec3_in_composite(in[0]), tint_unpack_vec3_in_composite(in[1]), tint_unpack_vec3_in_composite(in[2]), tint_unpack_vec3_in_composite(in[3]));
return result;
}
@@ -3354,10 +3743,72 @@
EXPECT_EQ(expect, str(got));
}
+TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_ReadStruct_Large) {
+ auto* src = R"(
+struct S {
+ arr : array<mat3x3<f32>, 9>,
+}
+
+@group(0) @binding(0) var<storage> P : S;
+
+fn f() {
+ let x = P;
+}
+)";
+
+ auto* expect = R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+ @align(16)
+ elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+ @align(16)
+ arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
+ return result;
+}
+
+fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>) -> array<mat3x3<f32>, 9u> {
+ var result : array<mat3x3<f32>, 9u>;
+ for(var i : u32; (i < 9u); i = (i + 1)) {
+ result[i] = tint_unpack_vec3_in_composite(in[i]);
+ }
+ return result;
+}
+
+fn tint_unpack_vec3_in_composite_2(in : S_tint_packed_vec3) -> S {
+ var result : S;
+ result.arr = tint_unpack_vec3_in_composite_1(in.arr);
+ return result;
+}
+
+struct S {
+ arr : array<mat3x3<f32>, 9>,
+}
+
+@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
+
+fn f() {
+ let x = tint_unpack_vec3_in_composite_2(P);
+}
+)";
+
+ ast::transform::DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_ReadArray) {
auto* src = R"(
struct S {
- arr : array<mat3x3<f32>, 4>,
+ arr : array<mat3x3<f32>, 9>,
}
@group(0) @binding(0) var<storage> P : S;
@@ -3377,27 +3828,24 @@
struct S_tint_packed_vec3 {
@align(16)
- arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
+ arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>,
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
-fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result : array<mat3x3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
+fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>) -> array<mat3x3<f32>, 9u> {
+ var result : array<mat3x3<f32>, 9u>;
+ for(var i : u32; (i < 9u); i = (i + 1)) {
result[i] = tint_unpack_vec3_in_composite(in[i]);
}
return result;
}
struct S {
- arr : array<mat3x3<f32>, 4>,
+ arr : array<mat3x3<f32>, 9>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
@@ -3440,10 +3888,7 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
@@ -3621,18 +4066,12 @@
}
fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result : array<tint_packed_vec3_f32_array_element, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
return result;
}
fn tint_pack_vec3_in_composite_1(in : array<mat3x3<f32>, 2u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 2u> {
- var result : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>;
- for(var i : u32; (i < 2u); i = (i + 1)) {
- result[i] = tint_pack_vec3_in_composite(in[i]);
- }
+ var result = array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>(tint_pack_vec3_in_composite(in[0]), tint_pack_vec3_in_composite(in[1]));
return result;
}
@@ -3732,18 +4171,12 @@
}
fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result : array<tint_packed_vec3_f32_array_element, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
return result;
}
fn tint_pack_vec3_in_composite_1(in : array<mat3x3<f32>, 2u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 2u> {
- var result : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>;
- for(var i : u32; (i < 2u); i = (i + 1)) {
- result[i] = tint_pack_vec3_in_composite(in[i]);
- }
+ var result = array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>(tint_pack_vec3_in_composite(in[0]), tint_pack_vec3_in_composite(in[1]));
return result;
}
@@ -3846,10 +4279,7 @@
}
fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result : array<tint_packed_vec3_f32_array_element, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
return result;
}
@@ -4510,10 +4940,7 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result : array<vec3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
return result;
}
@@ -4528,10 +4955,7 @@
}
fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
- var result : array<tint_packed_vec3_f32_array_element, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 4u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[3])));
return result;
}
@@ -4759,10 +5183,7 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result : array<vec3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
return result;
}
@@ -4965,18 +5386,12 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result : array<tint_packed_vec3_f32_array_element, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
return result;
}
@@ -5047,18 +5462,12 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result : array<vec3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
return result;
}
fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
- var result : array<tint_packed_vec3_f32_array_element, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 4u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[3])));
return result;
}
@@ -5120,34 +5529,22 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result : array<mat3x3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite(in[i]);
- }
+ var result = array<mat3x3<f32>, 4u>(tint_unpack_vec3_in_composite(in[0]), tint_unpack_vec3_in_composite(in[1]), tint_unpack_vec3_in_composite(in[2]), tint_unpack_vec3_in_composite(in[3]));
return result;
}
fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result : array<tint_packed_vec3_f32_array_element, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
return result;
}
fn tint_pack_vec3_in_composite_1(in : array<mat3x3<f32>, 4u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 4u> {
- var result : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_pack_vec3_in_composite(in[i]);
- }
+ var result = array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>(tint_pack_vec3_in_composite(in[0]), tint_pack_vec3_in_composite(in[1]), tint_pack_vec3_in_composite(in[2]), tint_pack_vec3_in_composite(in[3]));
return result;
}
@@ -5213,26 +5610,17 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
fn tint_unpack_vec3_in_composite_1(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result : array<vec3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
return result;
}
fn tint_unpack_vec3_in_composite_2(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result : array<mat3x3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite(in[i]);
- }
+ var result = array<mat3x3<f32>, 4u>(tint_unpack_vec3_in_composite(in[0]), tint_unpack_vec3_in_composite(in[1]), tint_unpack_vec3_in_composite(in[2]), tint_unpack_vec3_in_composite(in[3]));
return result;
}
@@ -5246,26 +5634,17 @@
}
fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result : array<tint_packed_vec3_f32_array_element, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
return result;
}
fn tint_pack_vec3_in_composite_1(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
- var result : array<tint_packed_vec3_f32_array_element, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 4u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[3])));
return result;
}
fn tint_pack_vec3_in_composite_2(in : array<mat3x3<f32>, 4u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 4u> {
- var result : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_pack_vec3_in_composite(in[i]);
- }
+ var result = array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>(tint_pack_vec3_in_composite(in[0]), tint_pack_vec3_in_composite(in[1]), tint_pack_vec3_in_composite(in[2]), tint_pack_vec3_in_composite(in[3]));
return result;
}
@@ -5460,18 +5839,12 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result : array<tint_packed_vec3_f32_array_element, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
return result;
}
@@ -5551,18 +5924,12 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result : array<vec3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
return result;
}
fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
- var result : array<tint_packed_vec3_f32_array_element, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 4u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[3])));
return result;
}
@@ -5635,34 +6002,22 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result : array<mat3x3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite(in[i]);
- }
+ var result = array<mat3x3<f32>, 4u>(tint_unpack_vec3_in_composite(in[0]), tint_unpack_vec3_in_composite(in[1]), tint_unpack_vec3_in_composite(in[2]), tint_unpack_vec3_in_composite(in[3]));
return result;
}
fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result : array<tint_packed_vec3_f32_array_element, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
return result;
}
fn tint_pack_vec3_in_composite_1(in : array<mat3x3<f32>, 4u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 4u> {
- var result : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_pack_vec3_in_composite(in[i]);
- }
+ var result = array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>(tint_pack_vec3_in_composite(in[0]), tint_pack_vec3_in_composite(in[1]), tint_pack_vec3_in_composite(in[2]), tint_pack_vec3_in_composite(in[3]));
return result;
}
@@ -5741,26 +6096,17 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
fn tint_unpack_vec3_in_composite_1(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result : array<vec3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
return result;
}
fn tint_unpack_vec3_in_composite_2(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result : array<mat3x3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite(in[i]);
- }
+ var result = array<mat3x3<f32>, 4u>(tint_unpack_vec3_in_composite(in[0]), tint_unpack_vec3_in_composite(in[1]), tint_unpack_vec3_in_composite(in[2]), tint_unpack_vec3_in_composite(in[3]));
return result;
}
@@ -5774,26 +6120,17 @@
}
fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result : array<tint_packed_vec3_f32_array_element, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
return result;
}
fn tint_pack_vec3_in_composite_1(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
- var result : array<tint_packed_vec3_f32_array_element, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 4u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[3])));
return result;
}
fn tint_pack_vec3_in_composite_2(in : array<mat3x3<f32>, 4u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 4u> {
- var result : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_pack_vec3_in_composite(in[i]);
- }
+ var result = array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>(tint_pack_vec3_in_composite(in[0]), tint_pack_vec3_in_composite(in[1]), tint_pack_vec3_in_composite(in[2]), tint_pack_vec3_in_composite(in[3]));
return result;
}
@@ -5868,10 +6205,7 @@
}
fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
- var result : array<tint_packed_vec3_f32_array_element, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 4u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[3])));
return result;
}
@@ -5947,10 +6281,7 @@
}
fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
- var result : array<tint_packed_vec3_f32_array_element, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 4u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[3])));
return result;
}
@@ -6041,10 +6372,7 @@
}
fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
- var result : array<tint_packed_vec3_f32_array_element, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 4u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[3])));
return result;
}
@@ -6133,26 +6461,17 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
fn tint_unpack_vec3_in_composite_1(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result : array<vec3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
return result;
}
fn tint_unpack_vec3_in_composite_2(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result : array<mat3x3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite(in[i]);
- }
+ var result = array<mat3x3<f32>, 4u>(tint_unpack_vec3_in_composite(in[0]), tint_unpack_vec3_in_composite(in[1]), tint_unpack_vec3_in_composite(in[2]), tint_unpack_vec3_in_composite(in[3]));
return result;
}
@@ -6239,26 +6558,17 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
fn tint_unpack_vec3_in_composite_1(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result : array<vec3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
return result;
}
fn tint_unpack_vec3_in_composite_2(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result : array<mat3x3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite(in[i]);
- }
+ var result = array<mat3x3<f32>, 4u>(tint_unpack_vec3_in_composite(in[0]), tint_unpack_vec3_in_composite(in[1]), tint_unpack_vec3_in_composite(in[2]), tint_unpack_vec3_in_composite(in[3]));
return result;
}
@@ -6484,10 +6794,7 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
@@ -6706,10 +7013,7 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
@@ -6933,10 +7237,7 @@
}
fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
- var result : array<tint_packed_vec3_f32_array_element, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 4u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[3])));
return result;
}
@@ -7000,18 +7301,12 @@
}
fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
- var result : array<tint_packed_vec3_f32_array_element, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 4u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[3])));
return result;
}
fn tint_pack_vec3_in_composite_1(in : array<array<vec3<f32>, 4u>, 4u>) -> array<array<tint_packed_vec3_f32_array_element, 4u>, 4u> {
- var result : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_pack_vec3_in_composite(in[i]);
- }
+ var result = array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>(tint_pack_vec3_in_composite(in[0]), tint_pack_vec3_in_composite(in[1]), tint_pack_vec3_in_composite(in[2]), tint_pack_vec3_in_composite(in[3]));
return result;
}
@@ -7075,10 +7370,7 @@
}
fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result : array<tint_packed_vec3_f32_array_element, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
return result;
}
@@ -7140,18 +7432,12 @@
}
fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result : array<tint_packed_vec3_f32_array_element, 3u>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
+ var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
return result;
}
fn tint_pack_vec3_in_composite_1(in : array<mat3x3<f32>, 4u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 4u> {
- var result : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_pack_vec3_in_composite(in[i]);
- }
+ var result = array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>(tint_pack_vec3_in_composite(in[0]), tint_pack_vec3_in_composite(in[1]), tint_pack_vec3_in_composite(in[2]), tint_pack_vec3_in_composite(in[3]));
return result;
}
@@ -7222,42 +7508,27 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result : array<vec3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
return result;
}
fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>) -> array<array<vec3<f32>, 4u>, 4u> {
- var result : array<array<vec3<f32>, 4u>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite(in[i]);
- }
+ var result = array<array<vec3<f32>, 4u>, 4u>(tint_unpack_vec3_in_composite(in[0]), tint_unpack_vec3_in_composite(in[1]), tint_unpack_vec3_in_composite(in[2]), tint_unpack_vec3_in_composite(in[3]));
return result;
}
fn tint_unpack_vec3_in_composite_2(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
fn tint_unpack_vec3_in_composite_3(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result : array<mat3x3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite_2(in[i]);
- }
+ var result = array<mat3x3<f32>, 4u>(tint_unpack_vec3_in_composite_2(in[0]), tint_unpack_vec3_in_composite_2(in[1]), tint_unpack_vec3_in_composite_2(in[2]), tint_unpack_vec3_in_composite_2(in[3]));
return result;
}
fn tint_unpack_vec3_in_composite_4(in : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, 4u>) -> array<array<mat3x3<f32>, 4u>, 4u> {
- var result : array<array<mat3x3<f32>, 4u>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite_3(in[i]);
- }
+ var result = array<array<mat3x3<f32>, 4u>, 4u>(tint_unpack_vec3_in_composite_3(in[0]), tint_unpack_vec3_in_composite_3(in[1]), tint_unpack_vec3_in_composite_3(in[2]), tint_unpack_vec3_in_composite_3(in[3]));
return result;
}
@@ -7269,10 +7540,7 @@
}
fn tint_unpack_vec3_in_composite_6(in : array<S_tint_packed_vec3, 4u>) -> array<S, 4u> {
- var result : array<S, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite_5(in[i]);
- }
+ var result = array<S, 4u>(tint_unpack_vec3_in_composite_5(in[0]), tint_unpack_vec3_in_composite_5(in[1]), tint_unpack_vec3_in_composite_5(in[2]), tint_unpack_vec3_in_composite_5(in[3]));
return result;
}
@@ -7304,7 +7572,7 @@
EXPECT_EQ(expect, str(got));
}
-TEST_F(PackedVec3Test, NestedArrays_VarInit) {
+TEST_F(PackedVec3Test, NestedArrays_VarInit_Small) {
auto* src = R"(
struct S {
arr_v : array<array<vec3<f32>, 4>, 4>,
@@ -7345,42 +7613,27 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result : array<vec3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
return result;
}
fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>) -> array<array<vec3<f32>, 4u>, 4u> {
- var result : array<array<vec3<f32>, 4u>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite(in[i]);
- }
+ var result = array<array<vec3<f32>, 4u>, 4u>(tint_unpack_vec3_in_composite(in[0]), tint_unpack_vec3_in_composite(in[1]), tint_unpack_vec3_in_composite(in[2]), tint_unpack_vec3_in_composite(in[3]));
return result;
}
fn tint_unpack_vec3_in_composite_2(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
fn tint_unpack_vec3_in_composite_3(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result : array<mat3x3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite_2(in[i]);
- }
+ var result = array<mat3x3<f32>, 4u>(tint_unpack_vec3_in_composite_2(in[0]), tint_unpack_vec3_in_composite_2(in[1]), tint_unpack_vec3_in_composite_2(in[2]), tint_unpack_vec3_in_composite_2(in[3]));
return result;
}
fn tint_unpack_vec3_in_composite_4(in : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, 4u>) -> array<array<mat3x3<f32>, 4u>, 4u> {
- var result : array<array<mat3x3<f32>, 4u>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite_3(in[i]);
- }
+ var result = array<array<mat3x3<f32>, 4u>, 4u>(tint_unpack_vec3_in_composite_3(in[0]), tint_unpack_vec3_in_composite_3(in[1]), tint_unpack_vec3_in_composite_3(in[2]), tint_unpack_vec3_in_composite_3(in[3]));
return result;
}
@@ -7392,10 +7645,7 @@
}
fn tint_unpack_vec3_in_composite_6(in : array<S_tint_packed_vec3, 4u>) -> array<S, 4u> {
- var result : array<S, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite_5(in[i]);
- }
+ var result = array<S, 4u>(tint_unpack_vec3_in_composite_5(in[0]), tint_unpack_vec3_in_composite_5(in[1]), tint_unpack_vec3_in_composite_5(in[2]), tint_unpack_vec3_in_composite_5(in[3]));
return result;
}
@@ -7427,7 +7677,127 @@
EXPECT_EQ(expect, str(got));
}
-TEST_F(PackedVec3Test, NestedArrays_VarAssignment) {
+TEST_F(PackedVec3Test, NestedArrays_VarInit_Large) {
+ auto* src = R"(
+struct S {
+ arr_v : array<array<vec3<f32>, 9>, 9>,
+ arr_m : array<array<mat3x3<f32>, 9>, 9>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr_s : array<S, 9>;
+
+fn f() {
+ var full_var : array<S, 9> = arr_s;
+ var struct_var : S = arr_s[0];
+ var outer_arr_v_var : array<array<vec3<f32>, 9>, 9> = arr_s[0].arr_v;
+ var inner_arr_v_var : array<vec3<f32>, 9> = arr_s[0].arr_v[1];
+ var v_var : vec3<f32> = arr_s[0].arr_v[1][2];
+ var v_element_var : f32 = arr_s[0].arr_v[1][2].y;
+ var outer_arr_m_var : array<array<mat3x3<f32>, 9>, 9> = arr_s[0].arr_m;
+ var inner_arr_m_var : array<mat3x3<f32>, 9> = arr_s[0].arr_m[1];
+ var m_var : mat3x3<f32> = arr_s[0].arr_m[1][2];
+ var m_col_var : vec3<f32> = arr_s[0].arr_m[1][2][0];
+ var m_element_var : f32 = arr_s[0].arr_m[1][2][0].y;
+}
+)";
+
+ auto* expect =
+ R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+ @align(16)
+ elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+ @align(16)
+ arr_v : array<array<tint_packed_vec3_f32_array_element, 9u>, 9u>,
+ @align(16)
+ arr_m : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>, 9u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 9u>) -> array<vec3<f32>, 9u> {
+ var result : array<vec3<f32>, 9u>;
+ for(var i : u32; (i < 9u); i = (i + 1)) {
+ result[i] = vec3<f32>(in[i].elements);
+ }
+ return result;
+}
+
+fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 9u>, 9u>) -> array<array<vec3<f32>, 9u>, 9u> {
+ var result : array<array<vec3<f32>, 9u>, 9u>;
+ for(var i : u32; (i < 9u); i = (i + 1)) {
+ result[i] = tint_unpack_vec3_in_composite(in[i]);
+ }
+ return result;
+}
+
+fn tint_unpack_vec3_in_composite_2(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
+ return result;
+}
+
+fn tint_unpack_vec3_in_composite_3(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>) -> array<mat3x3<f32>, 9u> {
+ var result : array<mat3x3<f32>, 9u>;
+ for(var i : u32; (i < 9u); i = (i + 1)) {
+ result[i] = tint_unpack_vec3_in_composite_2(in[i]);
+ }
+ return result;
+}
+
+fn tint_unpack_vec3_in_composite_4(in : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>, 9u>) -> array<array<mat3x3<f32>, 9u>, 9u> {
+ var result : array<array<mat3x3<f32>, 9u>, 9u>;
+ for(var i : u32; (i < 9u); i = (i + 1)) {
+ result[i] = tint_unpack_vec3_in_composite_3(in[i]);
+ }
+ return result;
+}
+
+fn tint_unpack_vec3_in_composite_5(in : S_tint_packed_vec3) -> S {
+ var result : S;
+ result.arr_v = tint_unpack_vec3_in_composite_1(in.arr_v);
+ result.arr_m = tint_unpack_vec3_in_composite_4(in.arr_m);
+ return result;
+}
+
+fn tint_unpack_vec3_in_composite_6(in : array<S_tint_packed_vec3, 9u>) -> array<S, 9u> {
+ var result : array<S, 9u>;
+ for(var i : u32; (i < 9u); i = (i + 1)) {
+ result[i] = tint_unpack_vec3_in_composite_5(in[i]);
+ }
+ return result;
+}
+
+struct S {
+ arr_v : array<array<vec3<f32>, 9>, 9>,
+ arr_m : array<array<mat3x3<f32>, 9>, 9>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr_s : array<S_tint_packed_vec3, 9u>;
+
+fn f() {
+ var full_var : array<S, 9> = tint_unpack_vec3_in_composite_6(arr_s);
+ var struct_var : S = tint_unpack_vec3_in_composite_5(arr_s[0]);
+ var outer_arr_v_var : array<array<vec3<f32>, 9>, 9> = tint_unpack_vec3_in_composite_1(arr_s[0].arr_v);
+ var inner_arr_v_var : array<vec3<f32>, 9> = tint_unpack_vec3_in_composite(arr_s[0].arr_v[1]);
+ var v_var : vec3<f32> = vec3<f32>(arr_s[0].arr_v[1][2].elements);
+ var v_element_var : f32 = arr_s[0].arr_v[1][2].elements.y;
+ var outer_arr_m_var : array<array<mat3x3<f32>, 9>, 9> = tint_unpack_vec3_in_composite_4(arr_s[0].arr_m);
+ var inner_arr_m_var : array<mat3x3<f32>, 9> = tint_unpack_vec3_in_composite_3(arr_s[0].arr_m[1]);
+ var m_var : mat3x3<f32> = tint_unpack_vec3_in_composite_2(arr_s[0].arr_m[1][2]);
+ var m_col_var : vec3<f32> = vec3<f32>(arr_s[0].arr_m[1][2][0].elements);
+ var m_element_var : f32 = arr_s[0].arr_m[1][2][0].elements.y;
+}
+)";
+
+ ast::transform::DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(PackedVec3Test, NestedArrays_VarAssignment_Small) {
auto* src = R"(
struct S {
arr_v : array<array<vec3<f32>, 4>, 4>,
@@ -7480,42 +7850,27 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result : array<vec3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
return result;
}
fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>) -> array<array<vec3<f32>, 4u>, 4u> {
- var result : array<array<vec3<f32>, 4u>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite(in[i]);
- }
+ var result = array<array<vec3<f32>, 4u>, 4u>(tint_unpack_vec3_in_composite(in[0]), tint_unpack_vec3_in_composite(in[1]), tint_unpack_vec3_in_composite(in[2]), tint_unpack_vec3_in_composite(in[3]));
return result;
}
fn tint_unpack_vec3_in_composite_2(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
fn tint_unpack_vec3_in_composite_3(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result : array<mat3x3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite_2(in[i]);
- }
+ var result = array<mat3x3<f32>, 4u>(tint_unpack_vec3_in_composite_2(in[0]), tint_unpack_vec3_in_composite_2(in[1]), tint_unpack_vec3_in_composite_2(in[2]), tint_unpack_vec3_in_composite_2(in[3]));
return result;
}
fn tint_unpack_vec3_in_composite_4(in : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, 4u>) -> array<array<mat3x3<f32>, 4u>, 4u> {
- var result : array<array<mat3x3<f32>, 4u>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite_3(in[i]);
- }
+ var result = array<array<mat3x3<f32>, 4u>, 4u>(tint_unpack_vec3_in_composite_3(in[0]), tint_unpack_vec3_in_composite_3(in[1]), tint_unpack_vec3_in_composite_3(in[2]), tint_unpack_vec3_in_composite_3(in[3]));
return result;
}
@@ -7527,10 +7882,7 @@
}
fn tint_unpack_vec3_in_composite_6(in : array<S_tint_packed_vec3, 4u>) -> array<S, 4u> {
- var result : array<S, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite_5(in[i]);
- }
+ var result = array<S, 4u>(tint_unpack_vec3_in_composite_5(in[0]), tint_unpack_vec3_in_composite_5(in[1]), tint_unpack_vec3_in_composite_5(in[2]), tint_unpack_vec3_in_composite_5(in[3]));
return result;
}
@@ -7573,6 +7925,149 @@
EXPECT_EQ(expect, str(got));
}
+TEST_F(PackedVec3Test, NestedArrays_VarAssignment_Large) {
+ auto* src = R"(
+struct S {
+ arr_v : array<array<vec3<f32>, 9>, 9>,
+ arr_m : array<array<mat3x3<f32>, 9>, 9>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr_s : array<S, 9>;
+
+fn f() {
+ var full_var : array<S, 9>;
+ var struct_var : S;
+ var outer_arr_v_var : array<array<vec3<f32>, 9>, 9>;
+ var inner_arr_v_var : array<vec3<f32>, 9>;
+ var v_var : vec3<f32>;
+ var v_element_var : f32;
+ var outer_arr_m_var : array<array<mat3x3<f32>, 9>, 9>;
+ var inner_arr_m_var : array<mat3x3<f32>, 9>;
+ var m_var : mat3x3<f32>;
+ var m_col_var : vec3<f32>;
+ var m_element_var : f32;
+
+ full_var = arr_s;
+ struct_var = arr_s[0];
+ outer_arr_v_var = arr_s[0].arr_v;
+ inner_arr_v_var = arr_s[0].arr_v[1];
+ v_var = arr_s[0].arr_v[1][2];
+ v_element_var = arr_s[0].arr_v[1][2].y;
+ outer_arr_m_var = arr_s[0].arr_m;
+ inner_arr_m_var = arr_s[0].arr_m[1];
+ m_var = arr_s[0].arr_m[1][2];
+ m_col_var = arr_s[0].arr_m[1][2][0];
+ m_element_var = arr_s[0].arr_m[1][2][0].y;
+}
+)";
+
+ auto* expect =
+ R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+ @align(16)
+ elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+ @align(16)
+ arr_v : array<array<tint_packed_vec3_f32_array_element, 9u>, 9u>,
+ @align(16)
+ arr_m : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>, 9u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 9u>) -> array<vec3<f32>, 9u> {
+ var result : array<vec3<f32>, 9u>;
+ for(var i : u32; (i < 9u); i = (i + 1)) {
+ result[i] = vec3<f32>(in[i].elements);
+ }
+ return result;
+}
+
+fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 9u>, 9u>) -> array<array<vec3<f32>, 9u>, 9u> {
+ var result : array<array<vec3<f32>, 9u>, 9u>;
+ for(var i : u32; (i < 9u); i = (i + 1)) {
+ result[i] = tint_unpack_vec3_in_composite(in[i]);
+ }
+ return result;
+}
+
+fn tint_unpack_vec3_in_composite_2(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
+ return result;
+}
+
+fn tint_unpack_vec3_in_composite_3(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>) -> array<mat3x3<f32>, 9u> {
+ var result : array<mat3x3<f32>, 9u>;
+ for(var i : u32; (i < 9u); i = (i + 1)) {
+ result[i] = tint_unpack_vec3_in_composite_2(in[i]);
+ }
+ return result;
+}
+
+fn tint_unpack_vec3_in_composite_4(in : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>, 9u>) -> array<array<mat3x3<f32>, 9u>, 9u> {
+ var result : array<array<mat3x3<f32>, 9u>, 9u>;
+ for(var i : u32; (i < 9u); i = (i + 1)) {
+ result[i] = tint_unpack_vec3_in_composite_3(in[i]);
+ }
+ return result;
+}
+
+fn tint_unpack_vec3_in_composite_5(in : S_tint_packed_vec3) -> S {
+ var result : S;
+ result.arr_v = tint_unpack_vec3_in_composite_1(in.arr_v);
+ result.arr_m = tint_unpack_vec3_in_composite_4(in.arr_m);
+ return result;
+}
+
+fn tint_unpack_vec3_in_composite_6(in : array<S_tint_packed_vec3, 9u>) -> array<S, 9u> {
+ var result : array<S, 9u>;
+ for(var i : u32; (i < 9u); i = (i + 1)) {
+ result[i] = tint_unpack_vec3_in_composite_5(in[i]);
+ }
+ return result;
+}
+
+struct S {
+ arr_v : array<array<vec3<f32>, 9>, 9>,
+ arr_m : array<array<mat3x3<f32>, 9>, 9>,
+}
+
+@group(0) @binding(0) var<storage, read_write> arr_s : array<S_tint_packed_vec3, 9u>;
+
+fn f() {
+ var full_var : array<S, 9>;
+ var struct_var : S;
+ var outer_arr_v_var : array<array<vec3<f32>, 9>, 9>;
+ var inner_arr_v_var : array<vec3<f32>, 9>;
+ var v_var : vec3<f32>;
+ var v_element_var : f32;
+ var outer_arr_m_var : array<array<mat3x3<f32>, 9>, 9>;
+ var inner_arr_m_var : array<mat3x3<f32>, 9>;
+ var m_var : mat3x3<f32>;
+ var m_col_var : vec3<f32>;
+ var m_element_var : f32;
+ full_var = tint_unpack_vec3_in_composite_6(arr_s);
+ struct_var = tint_unpack_vec3_in_composite_5(arr_s[0]);
+ outer_arr_v_var = tint_unpack_vec3_in_composite_1(arr_s[0].arr_v);
+ inner_arr_v_var = tint_unpack_vec3_in_composite(arr_s[0].arr_v[1]);
+ v_var = vec3<f32>(arr_s[0].arr_v[1][2].elements);
+ v_element_var = arr_s[0].arr_v[1][2].elements.y;
+ outer_arr_m_var = tint_unpack_vec3_in_composite_4(arr_s[0].arr_m);
+ inner_arr_m_var = tint_unpack_vec3_in_composite_3(arr_s[0].arr_m[1]);
+ m_var = tint_unpack_vec3_in_composite_2(arr_s[0].arr_m[1][2]);
+ m_col_var = vec3<f32>(arr_s[0].arr_m[1][2][0].elements);
+ m_element_var = arr_s[0].arr_m[1][2][0].elements.y;
+}
+)";
+
+ ast::transform::DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
TEST_F(PackedVec3Test, RuntimeSizedArray) {
auto* src = R"(
struct S {
@@ -7817,10 +8312,7 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
@@ -7939,10 +8431,7 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result : mat3x3<f32>;
- for(var i : u32; (i < 3u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
return result;
}
@@ -8048,7 +8537,7 @@
EXPECT_EQ(expect, str(got));
}
-TEST_F(PackedVec3Test, Aliases) {
+TEST_F(PackedVec3Test, Aliases_Small) {
auto* src = R"(
alias VecArray = array<vec3<f32>, 4>;
alias MatArray = array<mat3x3<f32>, 4>;
@@ -8097,10 +8586,7 @@
}
fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result : array<vec3<f32>, 4u>;
- for(var i : u32; (i < 4u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
+ var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
return result;
}
@@ -8142,6 +8628,100 @@
EXPECT_EQ(expect, str(got));
}
+TEST_F(PackedVec3Test, Aliases_Large) {
+ auto* src = R"(
+alias VecArray = array<vec3<f32>, 9>;
+alias MatArray = array<mat3x3<f32>, 9>;
+alias NestedArray = array<VecArray, 9>;
+
+struct S {
+ v : VecArray,
+ m : MatArray,
+ n : NestedArray,
+}
+
+@group(0) @binding(0) var<storage, read_write> s : S;
+@group(0) @binding(1) var<storage, read_write> arr_v : VecArray;
+@group(0) @binding(2) var<storage, read_write> arr_m : MatArray;
+@group(0) @binding(3) var<storage, read_write> arr_n : NestedArray;
+
+fn g(p : ptr<function, VecArray>) {
+}
+
+fn f() {
+ var f_arr_v : VecArray = s.v;
+ g(&f_arr_v);
+
+ arr_v = s.v;
+ arr_m[0] = s.m[0];
+ arr_n[1][2] = s.n[1][2];
+}
+)";
+
+ auto* expect =
+ R"(
+enable chromium_internal_relaxed_uniform_layout;
+
+struct tint_packed_vec3_f32_array_element {
+ @align(16)
+ elements : __packed_vec3<f32>,
+}
+
+struct S_tint_packed_vec3 {
+ @align(16)
+ v : array<tint_packed_vec3_f32_array_element, 9u>,
+ @align(16)
+ m : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>,
+ @align(16)
+ n : array<array<tint_packed_vec3_f32_array_element, 9u>, 9u>,
+}
+
+fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 9u>) -> array<vec3<f32>, 9u> {
+ var result : array<vec3<f32>, 9u>;
+ for(var i : u32; (i < 9u); i = (i + 1)) {
+ result[i] = vec3<f32>(in[i].elements);
+ }
+ return result;
+}
+
+alias VecArray = array<vec3<f32>, 9>;
+
+alias MatArray = array<mat3x3<f32>, 9>;
+
+alias NestedArray = array<VecArray, 9>;
+
+struct S {
+ v : VecArray,
+ m : MatArray,
+ n : NestedArray,
+}
+
+@group(0) @binding(0) var<storage, read_write> s : S_tint_packed_vec3;
+
+@group(0) @binding(1) var<storage, read_write> arr_v : array<tint_packed_vec3_f32_array_element, 9u>;
+
+@group(0) @binding(2) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>;
+
+@group(0) @binding(3) var<storage, read_write> arr_n : array<array<tint_packed_vec3_f32_array_element, 9u>, 9u>;
+
+fn g(p : ptr<function, VecArray>) {
+}
+
+fn f() {
+ var f_arr_v : VecArray = tint_unpack_vec3_in_composite(s.v);
+ g(&(f_arr_v));
+ arr_v = s.v;
+ arr_m[0] = s.m[0];
+ arr_n[1][2].elements = s.n[1][2].elements;
+}
+)";
+
+ ast::transform::DataMap data;
+ auto got = Run<PackedVec3>(src, data);
+
+ EXPECT_EQ(expect, str(got));
+}
+
TEST_F(PackedVec3Test, Vec3Bool) {
// Make sure that we don't rewrite vec3<bool> types, as the `packed_bool<n>` types are reserved
// in MSL and might not be supported everywhere.
diff --git a/src/tint/lang/spirv/reader/parser/memory_test.cc b/src/tint/lang/spirv/reader/parser/memory_test.cc
index 9f8c75f..acb3972 100644
--- a/src/tint/lang/spirv/reader/parser/memory_test.cc
+++ b/src/tint/lang/spirv/reader/parser/memory_test.cc
@@ -760,5 +760,59 @@
)");
}
+TEST_F(SpirvParserTest, StorageBufferAccessMode) {
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpExtension "SPV_KHR_storage_buffer_storage_class"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main"
+ OpExecutionMode %main LocalSize 1 1 1
+ OpDecorate %str Block
+ OpMemberDecorate %str 0 Offset 0
+ OpDecorate %ro_var NonWritable
+ OpDecorate %ro_var DescriptorSet 1
+ OpDecorate %ro_var Binding 2
+ OpDecorate %rw_var DescriptorSet 1
+ OpDecorate %rw_var Binding 3
+ %void = OpTypeVoid
+ %u32 = OpTypeInt 32 0
+ %str = OpTypeStruct %u32
+ %u32_ptr = OpTypePointer StorageBuffer %u32
+ %str_ptr = OpTypePointer StorageBuffer %str
+ %ep_type = OpTypeFunction %void
+ %u32_0 = OpConstant %u32 0
+ %ro_var = OpVariable %str_ptr StorageBuffer
+ %rw_var = OpVariable %str_ptr StorageBuffer
+ %main = OpFunction %void None %ep_type
+ %main_start = OpLabel
+ %ro_access = OpAccessChain %u32_ptr %ro_var %u32_0
+ %rw_access = OpAccessChain %u32_ptr %rw_var %u32_0
+ %load = OpLoad %u32 %ro_access
+ OpStore %rw_access %load
+ OpReturn
+ OpFunctionEnd
+)",
+ R"(
+tint_symbol_1 = struct @align(4) {
+ tint_symbol:u32 @offset(0)
+}
+
+%b1 = block { # root
+ %1:ptr<storage, tint_symbol_1, read> = var @binding_point(1, 2)
+ %2:ptr<storage, tint_symbol_1, read_write> = var @binding_point(1, 3)
+}
+
+%main = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
+ %b2 = block {
+ %4:ptr<storage, u32, read> = access %1, 0u
+ %5:ptr<storage, u32, read_write> = access %2, 0u
+ %6:u32 = load %4
+ store %5, %6
+ ret
+ }
+}
+)");
+}
+
} // namespace
} // namespace tint::spirv::reader
diff --git a/src/tint/lang/spirv/reader/parser/parser.cc b/src/tint/lang/spirv/reader/parser/parser.cc
index 6fe4eb9..cfbc8cc 100644
--- a/src/tint/lang/spirv/reader/parser/parser.cc
+++ b/src/tint/lang/spirv/reader/parser/parser.cc
@@ -76,6 +76,14 @@
return Failure("failed to build the internal representation of the module");
}
+ // Check for unsupported extensions.
+ for (const auto& ext : spirv_context_->extensions()) {
+ auto name = ext.GetOperand(0).AsString();
+ if (name != "SPV_KHR_storage_buffer_storage_class") {
+ return Failure("SPIR-V extension '" + name + "' is not supported");
+ }
+ }
+
{
TINT_SCOPED_ASSIGNMENT(current_block_, ir_.root_block);
EmitModuleScopeVariables();
@@ -95,10 +103,16 @@
/// @returns the Tint address space for a SPIR-V storage class
core::AddressSpace AddressSpace(spv::StorageClass sc) {
switch (sc) {
+ case spv::StorageClass::Input:
+ return core::AddressSpace::kIn;
+ case spv::StorageClass::Output:
+ return core::AddressSpace::kOut;
case spv::StorageClass::Function:
return core::AddressSpace::kFunction;
case spv::StorageClass::Private:
return core::AddressSpace::kPrivate;
+ case spv::StorageClass::StorageBuffer:
+ return core::AddressSpace::kStorage;
case spv::StorageClass::Uniform:
return core::AddressSpace::kUniform;
default:
@@ -108,10 +122,50 @@
}
}
+ /// @param b a SPIR-V BuiltIn
+ /// @returns the Tint builtin value for a SPIR-V BuiltIn decoration
+ core::BuiltinValue Builtin(spv::BuiltIn b) {
+ switch (b) {
+ case spv::BuiltIn::FragCoord:
+ return core::BuiltinValue::kPosition;
+ case spv::BuiltIn::FragDepth:
+ return core::BuiltinValue::kFragDepth;
+ case spv::BuiltIn::FrontFacing:
+ return core::BuiltinValue::kFrontFacing;
+ case spv::BuiltIn::GlobalInvocationId:
+ return core::BuiltinValue::kGlobalInvocationId;
+ case spv::BuiltIn::InstanceIndex:
+ return core::BuiltinValue::kInstanceIndex;
+ case spv::BuiltIn::LocalInvocationId:
+ return core::BuiltinValue::kLocalInvocationId;
+ case spv::BuiltIn::LocalInvocationIndex:
+ return core::BuiltinValue::kLocalInvocationIndex;
+ case spv::BuiltIn::NumWorkgroups:
+ return core::BuiltinValue::kNumWorkgroups;
+ case spv::BuiltIn::PointSize:
+ return core::BuiltinValue::kPointSize;
+ case spv::BuiltIn::Position:
+ return core::BuiltinValue::kPosition;
+ case spv::BuiltIn::SampleId:
+ return core::BuiltinValue::kSampleIndex;
+ case spv::BuiltIn::SampleMask:
+ return core::BuiltinValue::kSampleMask;
+ case spv::BuiltIn::VertexIndex:
+ return core::BuiltinValue::kVertexIndex;
+ case spv::BuiltIn::WorkgroupId:
+ return core::BuiltinValue::kWorkgroupId;
+ default:
+ TINT_UNIMPLEMENTED() << "unhandled SPIR-V BuiltIn: " << static_cast<uint32_t>(b);
+ return core::BuiltinValue::kUndefined;
+ }
+ }
+
/// @param type a SPIR-V type object
+ /// @param access_mode an optional access mode (for pointers)
/// @returns a Tint type object
- const core::type::Type* Type(const spvtools::opt::analysis::Type* type) {
- return types_.GetOrCreate(type, [&]() -> const core::type::Type* {
+ const core::type::Type* Type(const spvtools::opt::analysis::Type* type,
+ core::Access access_mode = core::Access::kUndefined) {
+ return types_.GetOrCreate(TypeKey{type, access_mode}, [&]() -> const core::type::Type* {
switch (type->kind()) {
case spvtools::opt::analysis::Type::kVoid:
return ty_.void_();
@@ -156,7 +210,7 @@
case spvtools::opt::analysis::Type::kPointer: {
auto* ptr_ty = type->AsPointer();
return ty_.ptr(AddressSpace(ptr_ty->storage_class()),
- Type(ptr_ty->pointee_type()));
+ Type(ptr_ty->pointee_type()), access_mode);
}
default:
TINT_UNIMPLEMENTED() << "unhandled SPIR-V type: " << type->str();
@@ -166,9 +220,10 @@
}
/// @param id a SPIR-V result ID for a type declaration instruction
+ /// @param access_mode an optional access mode (for pointers)
/// @returns a Tint type object
- const core::type::Type* Type(uint32_t id) {
- return Type(spirv_context_->get_type_mgr()->GetType(id));
+ const core::type::Type* Type(uint32_t id, core::Access access_mode = core::Access::kUndefined) {
+ return Type(spirv_context_->get_type_mgr()->GetType(id), access_mode);
}
/// @param arr_ty a SPIR-V array object
@@ -209,6 +264,15 @@
uint32_t align = std::max<uint32_t>(member_ty->Align(), 1u);
uint32_t offset = tint::RoundUp(align, current_size);
core::type::StructMemberAttributes attributes;
+ auto interpolation = [&]() -> core::Interpolation& {
+ // Create the interpolation field with the default values on first call.
+ if (!attributes.interpolation.has_value()) {
+ attributes.interpolation =
+ core::Interpolation{core::InterpolationType::kPerspective,
+ core::InterpolationSampling::kCenter};
+ }
+ return attributes.interpolation.value();
+ };
// Handle member decorations that affect layout or attributes.
if (struct_ty->element_decorations().count(i)) {
@@ -217,6 +281,28 @@
case spv::Decoration::Offset:
offset = deco[1];
break;
+ case spv::Decoration::BuiltIn:
+ attributes.builtin = Builtin(spv::BuiltIn(deco[1]));
+ break;
+ case spv::Decoration::Invariant:
+ attributes.invariant = true;
+ break;
+ case spv::Decoration::Location:
+ attributes.location = deco[1];
+ break;
+ case spv::Decoration::NoPerspective:
+ interpolation().type = core::InterpolationType::kLinear;
+ break;
+ case spv::Decoration::Flat:
+ interpolation().type = core::InterpolationType::kFlat;
+ break;
+ case spv::Decoration::Centroid:
+ interpolation().sampling = core::InterpolationSampling::kCentroid;
+ break;
+ case spv::Decoration::Sample:
+ interpolation().sampling = core::InterpolationSampling::kSample;
+ break;
+
default:
TINT_UNIMPLEMENTED() << "unhandled member decoration: " << deco[0];
break;
@@ -459,7 +545,14 @@
indices.Push(Value(inst.GetSingleWordOperand(i)));
}
auto* base = Value(inst.GetSingleWordOperand(2));
- auto* access = b_.Access(Type(inst.type_id()), base, std::move(indices));
+
+ // Propagate the access mode of the base object.
+ auto access_mode = core::Access::kUndefined;
+ if (auto* ptr = base->Type()->As<core::type::Pointer>()) {
+ access_mode = ptr->Access();
+ }
+
+ auto* access = b_.Access(Type(inst.type_id(), access_mode), base, std::move(indices));
Emit(access, inst.result_id());
}
@@ -496,19 +589,25 @@
/// @param inst the SPIR-V instruction for OpVariable
void EmitVar(const spvtools::opt::Instruction& inst) {
- auto* var = b_.Var(Type(inst.type_id())->As<core::type::Pointer>());
- if (inst.NumOperands() > 3) {
- var->SetInitializer(Value(inst.GetSingleWordOperand(3)));
- }
-
// Handle decorations.
std::optional<uint32_t> group;
std::optional<uint32_t> binding;
+ core::Access access_mode = core::Access::kUndefined;
+ core::ir::IOAttributes io_attributes;
+ auto interpolation = [&]() -> core::Interpolation& {
+ // Create the interpolation field with the default values on first call.
+ if (!io_attributes.interpolation.has_value()) {
+ io_attributes.interpolation = core::Interpolation{
+ core::InterpolationType::kPerspective, core::InterpolationSampling::kCenter};
+ }
+ return io_attributes.interpolation.value();
+ };
for (auto* deco :
spirv_context_->get_decoration_mgr()->GetDecorationsFor(inst.result_id(), false)) {
auto d = deco->GetSingleWordOperand(1);
switch (spv::Decoration(d)) {
case spv::Decoration::NonWritable:
+ access_mode = core::Access::kRead;
break;
case spv::Decoration::DescriptorSet:
group = deco->GetSingleWordOperand(2);
@@ -516,20 +615,70 @@
case spv::Decoration::Binding:
binding = deco->GetSingleWordOperand(2);
break;
+ case spv::Decoration::BuiltIn:
+ io_attributes.builtin = Builtin(spv::BuiltIn(deco->GetSingleWordOperand(2)));
+ break;
+ case spv::Decoration::Invariant:
+ io_attributes.invariant = true;
+ break;
+ case spv::Decoration::Location:
+ io_attributes.location = deco->GetSingleWordOperand(2);
+ break;
+ case spv::Decoration::NoPerspective:
+ interpolation().type = core::InterpolationType::kLinear;
+ break;
+ case spv::Decoration::Flat:
+ interpolation().type = core::InterpolationType::kFlat;
+ break;
+ case spv::Decoration::Centroid:
+ interpolation().sampling = core::InterpolationSampling::kCentroid;
+ break;
+ case spv::Decoration::Sample:
+ interpolation().sampling = core::InterpolationSampling::kSample;
+ break;
default:
TINT_UNIMPLEMENTED() << "unhandled decoration " << d;
break;
}
}
+
+ auto* var = b_.Var(Type(inst.type_id(), access_mode)->As<core::type::Pointer>());
+ if (inst.NumOperands() > 3) {
+ var->SetInitializer(Value(inst.GetSingleWordOperand(3)));
+ }
+
if (group || binding) {
TINT_ASSERT(group && binding);
var->SetBindingPoint(group.value(), binding.value());
}
+ var->SetAttributes(std::move(io_attributes));
Emit(var, inst.result_id());
}
private:
+ /// TypeKey describes a SPIR-V type with an access mode.
+ struct TypeKey {
+ /// The SPIR-V type object.
+ const spvtools::opt::analysis::Type* type;
+ /// The access mode.
+ core::Access access_mode;
+
+ // Equality operator for TypeKey.
+ bool operator==(const TypeKey& other) const {
+ return type == other.type && access_mode == other.access_mode;
+ }
+
+ /// Hasher provides a hash function for the TypeKey.
+ struct Hasher {
+ /// @param tk the TypeKey to create a hash for
+ /// @return the hash value
+ inline std::size_t operator()(const TypeKey& tk) const {
+ return HashCombine(Hash(tk.type), tk.access_mode);
+ }
+ };
+ };
+
/// The generated IR module.
core::ir::Module ir_;
/// The Tint IR builder.
@@ -541,8 +690,8 @@
core::ir::Function* current_function_ = nullptr;
/// The Tint IR block that is currently being emitted.
core::ir::Block* current_block_ = nullptr;
- /// A map from a SPIR-V type declaration result ID to the corresponding Tint type object.
- Hashmap<const spvtools::opt::analysis::Type*, const core::type::Type*, 16> types_;
+ /// A map from a SPIR-V type declaration to the corresponding Tint type object.
+ Hashmap<TypeKey, const core::type::Type*, 16, TypeKey::Hasher> types_;
/// A map from a SPIR-V function definition result ID to the corresponding Tint function object.
Hashmap<uint32_t, core::ir::Function*, 8> functions_;
/// A map from a SPIR-V result ID to the corresponding Tint value object.
diff --git a/src/tint/lang/spirv/reader/parser/struct_test.cc b/src/tint/lang/spirv/reader/parser/struct_test.cc
index afbaa39..bedb4e2 100644
--- a/src/tint/lang/spirv/reader/parser/struct_test.cc
+++ b/src/tint/lang/spirv/reader/parser/struct_test.cc
@@ -229,4 +229,132 @@
)");
}
+TEST_F(SpirvParserTest, Struct_Builtin) {
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpCapability SampleRateShading
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main"
+ OpExecutionMode %main OriginUpperLeft
+ OpMemberDecorate %str 0 BuiltIn Position
+ %void = OpTypeVoid
+ %f32 = OpTypeFloat 32
+ %vec4f = OpTypeVector %f32 4
+ %str = OpTypeStruct %vec4f
+ %fn_type = OpTypeFunction %void
+
+%_ptr_Output = OpTypePointer Output %str
+ %var = OpVariable %_ptr_Output Output
+
+ %main = OpFunction %void None %fn_type
+ %main_start = OpLabel
+ OpReturn
+ OpFunctionEnd
+)",
+ R"(
+tint_symbol_1 = struct @align(16) {
+ tint_symbol:vec4<f32> @offset(0), @builtin(position)
+}
+)");
+}
+
+TEST_F(SpirvParserTest, Struct_Builtin_WithInvariant) {
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpCapability SampleRateShading
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main"
+ OpExecutionMode %main OriginUpperLeft
+ OpMemberDecorate %str 0 BuiltIn Position
+ OpMemberDecorate %str 0 Invariant
+ %void = OpTypeVoid
+ %f32 = OpTypeFloat 32
+ %vec4f = OpTypeVector %f32 4
+ %str = OpTypeStruct %vec4f
+ %fn_type = OpTypeFunction %void
+
+%_ptr_Output = OpTypePointer Output %str
+ %var = OpVariable %_ptr_Output Output
+
+ %main = OpFunction %void None %fn_type
+ %main_start = OpLabel
+ OpReturn
+ OpFunctionEnd
+)",
+ R"(
+tint_symbol_1 = struct @align(16) {
+ tint_symbol:vec4<f32> @offset(0), @invariant, @builtin(position)
+}
+)");
+}
+
+struct LocationCase {
+ std::string spirv_decorations;
+ std::string ir;
+};
+
+using LocationStructTest = SpirvParserTestWithParam<LocationCase>;
+
+TEST_P(LocationStructTest, MemberDecorations) {
+ auto params = GetParam();
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpCapability SampleRateShading
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main"
+ OpExecutionMode %main OriginUpperLeft
+ )" + params.spirv_decorations +
+ R"(
+ %void = OpTypeVoid
+ %f32 = OpTypeFloat 32
+ %vec4f = OpTypeVector %f32 4
+ %str = OpTypeStruct %vec4f
+ %fn_type = OpTypeFunction %void
+
+%_ptr_Input = OpTypePointer Input %str
+ %var = OpVariable %_ptr_Input Input
+
+ %main = OpFunction %void None %fn_type
+ %main_start = OpLabel
+ OpReturn
+ OpFunctionEnd
+)",
+ params.ir);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ SpirvParser,
+ LocationStructTest,
+ testing::Values(
+ LocationCase{
+ "OpMemberDecorate %str 0 Location 1 ",
+ "tint_symbol:vec4<f32> @offset(0), @location(1)",
+ },
+ LocationCase{
+ "OpMemberDecorate %str 0 Location 2 "
+ "OpMemberDecorate %str 0 NoPerspective ",
+ "tint_symbol:vec4<f32> @offset(0), @location(2), @interpolate(linear, center)",
+ },
+ LocationCase{
+ "OpMemberDecorate %str 0 Location 3 "
+ "OpMemberDecorate %str 0 Flat ",
+ "tint_symbol:vec4<f32> @offset(0), @location(3), @interpolate(flat, center)",
+ },
+ LocationCase{
+ "OpMemberDecorate %str 0 Location 4 "
+ "OpMemberDecorate %str 0 Centroid ",
+ "tint_symbol:vec4<f32> @offset(0), @location(4), @interpolate(perspective, centroid)",
+ },
+ LocationCase{
+ "OpMemberDecorate %str 0 Location 5 "
+ "OpMemberDecorate %str 0 Sample ",
+ "tint_symbol:vec4<f32> @offset(0), @location(5), @interpolate(perspective, sample)",
+ },
+ LocationCase{
+ "OpMemberDecorate %str 0 Location 6 "
+ "OpMemberDecorate %str 0 NoPerspective "
+ "OpMemberDecorate %str 0 Centroid ",
+ "tint_symbol:vec4<f32> @offset(0), @location(6), @interpolate(linear, centroid)",
+ }));
+
} // namespace tint::spirv::reader
diff --git a/src/tint/lang/spirv/reader/parser/var_test.cc b/src/tint/lang/spirv/reader/parser/var_test.cc
index 88a6347..f524b23 100644
--- a/src/tint/lang/spirv/reader/parser/var_test.cc
+++ b/src/tint/lang/spirv/reader/parser/var_test.cc
@@ -142,6 +142,129 @@
)");
}
+TEST_F(SpirvParserTest, StorageVar_ReadOnly) {
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpExtension "SPV_KHR_storage_buffer_storage_class"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %1 "main"
+ OpExecutionMode %1 LocalSize 1 1 1
+ OpDecorate %str Block
+ OpMemberDecorate %str 0 Offset 0
+ OpDecorate %6 NonWritable
+ OpDecorate %6 DescriptorSet 1
+ OpDecorate %6 Binding 2
+ %void = OpTypeVoid
+ %uint = OpTypeInt 32 0
+ %str = OpTypeStruct %uint
+%_ptr_StorageBuffer_str = OpTypePointer StorageBuffer %str
+ %5 = OpTypeFunction %void
+ %6 = OpVariable %_ptr_StorageBuffer_str StorageBuffer
+ %1 = OpFunction %void None %5
+ %7 = OpLabel
+ OpReturn
+ OpFunctionEnd
+)",
+ R"(
+tint_symbol_1 = struct @align(4) {
+ tint_symbol:u32 @offset(0)
+}
+
+%b1 = block { # root
+ %1:ptr<storage, tint_symbol_1, read> = var @binding_point(1, 2)
+}
+
+%main = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
+ %b2 = block {
+ ret
+ }
+}
+)");
+}
+
+TEST_F(SpirvParserTest, StorageVar_ReadWrite) {
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpExtension "SPV_KHR_storage_buffer_storage_class"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %1 "main"
+ OpExecutionMode %1 LocalSize 1 1 1
+ OpDecorate %str Block
+ OpMemberDecorate %str 0 Offset 0
+ OpDecorate %6 DescriptorSet 1
+ OpDecorate %6 Binding 2
+ %void = OpTypeVoid
+ %uint = OpTypeInt 32 0
+ %str = OpTypeStruct %uint
+%_ptr_StorageBuffer_str = OpTypePointer StorageBuffer %str
+ %5 = OpTypeFunction %void
+ %6 = OpVariable %_ptr_StorageBuffer_str StorageBuffer
+ %1 = OpFunction %void None %5
+ %7 = OpLabel
+ OpReturn
+ OpFunctionEnd
+)",
+ R"(
+tint_symbol_1 = struct @align(4) {
+ tint_symbol:u32 @offset(0)
+}
+
+%b1 = block { # root
+ %1:ptr<storage, tint_symbol_1, read_write> = var @binding_point(1, 2)
+}
+
+%main = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
+ %b2 = block {
+ ret
+ }
+}
+)");
+}
+
+TEST_F(SpirvParserTest, StorageVar_ReadOnly_And_ReadWrite) {
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpExtension "SPV_KHR_storage_buffer_storage_class"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %1 "main"
+ OpExecutionMode %1 LocalSize 1 1 1
+ OpDecorate %str Block
+ OpMemberDecorate %str 0 Offset 0
+ OpDecorate %6 NonWritable
+ OpDecorate %6 DescriptorSet 1
+ OpDecorate %6 Binding 2
+ OpDecorate %7 DescriptorSet 1
+ OpDecorate %7 Binding 3
+ %void = OpTypeVoid
+ %uint = OpTypeInt 32 0
+ %str = OpTypeStruct %uint
+%_ptr_StorageBuffer_str = OpTypePointer StorageBuffer %str
+ %5 = OpTypeFunction %void
+ %6 = OpVariable %_ptr_StorageBuffer_str StorageBuffer
+ %7 = OpVariable %_ptr_StorageBuffer_str StorageBuffer
+ %1 = OpFunction %void None %5
+ %8 = OpLabel
+ OpReturn
+ OpFunctionEnd
+)",
+ R"(
+tint_symbol_1 = struct @align(4) {
+ tint_symbol:u32 @offset(0)
+}
+
+%b1 = block { # root
+ %1:ptr<storage, tint_symbol_1, read> = var @binding_point(1, 2)
+ %2:ptr<storage, tint_symbol_1, read_write> = var @binding_point(1, 3)
+}
+
+%main = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
+ %b2 = block {
+ ret
+ }
+}
+)");
+}
+
TEST_F(SpirvParserTest, UniformVar) {
EXPECT_IR(R"(
OpCapability Shader
@@ -181,5 +304,278 @@
)");
}
+struct BuiltinCase {
+ std::string spirv_type;
+ std::string spirv_builtin;
+ std::string ir;
+};
+std::string PrintBuiltinCase(testing::TestParamInfo<BuiltinCase> bc) {
+ return bc.param.spirv_builtin;
+}
+
+using BuiltinInputTest = SpirvParserTestWithParam<BuiltinCase>;
+
+TEST_P(BuiltinInputTest, Enum) {
+ auto params = GetParam();
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpCapability SampleRateShading
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main"
+ OpExecutionMode %main LocalSize 1 1 1
+ OpDecorate %var BuiltIn )" +
+ params.spirv_builtin + R"(
+ %void = OpTypeVoid
+ %bool = OpTypeBool
+ %u32 = OpTypeInt 32 0
+ %vec3u = OpTypeVector %u32 3
+ %f32 = OpTypeFloat 32
+ %vec4f = OpTypeVector %f32 4
+ %u32_1 = OpConstant %u32 1
+ %arr_u32_1 = OpTypeArray %u32 %u32_1
+ %fn_type = OpTypeFunction %void
+
+ %_ptr_Input = OpTypePointer Input %)" +
+ params.spirv_type + R"(
+ %var = OpVariable %_ptr_Input Input
+
+ %main = OpFunction %void None %fn_type
+ %main_start = OpLabel
+ OpReturn
+ OpFunctionEnd
+)",
+ params.ir);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ SpirvParser,
+ BuiltinInputTest,
+ testing::Values(
+ BuiltinCase{
+ "vec4f",
+ "FragCoord",
+ "%1:ptr<__in, vec4<f32>, read> = var @builtin(position)",
+ },
+ BuiltinCase{
+ "bool",
+ "FrontFacing",
+ "%1:ptr<__in, bool, read> = var @builtin(front_facing)",
+ },
+ BuiltinCase{
+ "vec3u",
+ "GlobalInvocationId",
+ "%1:ptr<__in, vec3<u32>, read> = var @builtin(global_invocation_id)",
+ },
+ BuiltinCase{
+ "u32",
+ "InstanceIndex",
+ "%1:ptr<__in, u32, read> = var @builtin(instance_index)",
+ },
+ BuiltinCase{
+ "vec3u",
+ "LocalInvocationId",
+ "%1:ptr<__in, vec3<u32>, read> = var @builtin(local_invocation_id)",
+ },
+ BuiltinCase{
+ "u32",
+ "LocalInvocationIndex",
+ "%1:ptr<__in, u32, read> = var @builtin(local_invocation_index)",
+ },
+ BuiltinCase{
+ "vec3u",
+ "NumWorkgroups",
+ "%1:ptr<__in, vec3<u32>, read> = var @builtin(num_workgroups)",
+ },
+ BuiltinCase{
+ "u32",
+ "SampleId",
+ "%1:ptr<__in, u32, read> = var @builtin(sample_index)",
+ },
+ BuiltinCase{
+ "arr_u32_1",
+ "SampleMask",
+ "%1:ptr<__in, array<u32, 1>, read> = var @builtin(sample_mask)",
+ },
+ BuiltinCase{
+ "u32",
+ "VertexIndex",
+ "%1:ptr<__in, u32, read> = var @builtin(vertex_index)",
+ },
+ BuiltinCase{
+ "vec3u",
+ "WorkgroupId",
+ "%1:ptr<__in, vec3<u32>, read> = var @builtin(workgroup_id)",
+ }),
+ PrintBuiltinCase);
+
+using BuiltinOutputTest = SpirvParserTestWithParam<BuiltinCase>;
+
+TEST_P(BuiltinOutputTest, Enum) {
+ auto params = GetParam();
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main"
+ OpExecutionMode %main LocalSize 1 1 1
+ OpDecorate %var BuiltIn )" +
+ params.spirv_builtin + R"(
+ %void = OpTypeVoid
+ %u32 = OpTypeInt 32 0
+ %f32 = OpTypeFloat 32
+ %vec4f = OpTypeVector %f32 4
+ %u32_1 = OpConstant %u32 1
+ %arr_u32_1 = OpTypeArray %u32 %u32_1
+ %fn_type = OpTypeFunction %void
+
+%_ptr_Output = OpTypePointer Output %)" +
+ params.spirv_type + R"(
+ %var = OpVariable %_ptr_Output Output
+
+ %main = OpFunction %void None %fn_type
+ %main_start = OpLabel
+ OpReturn
+ OpFunctionEnd
+)",
+ params.ir);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ SpirvParser,
+ BuiltinOutputTest,
+ testing::Values(
+ BuiltinCase{
+ "f32",
+ "PointSize",
+ "%1:ptr<__out, f32, read_write> = var @builtin(__point_size)",
+ },
+ BuiltinCase{
+ "vec4f",
+ "Position",
+ "%1:ptr<__out, vec4<f32>, read_write> = var @builtin(position)",
+ },
+ BuiltinCase{
+ "arr_u32_1",
+ "SampleMask",
+ "%1:ptr<__out, array<u32, 1>, read_write> = var @builtin(sample_mask)",
+ }),
+ PrintBuiltinCase);
+
+TEST_F(SpirvParserTest, Invariant_OnVariable) {
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main"
+ OpExecutionMode %main LocalSize 1 1 1
+ OpDecorate %var BuiltIn Position
+ OpDecorate %var Invariant
+ %void = OpTypeVoid
+ %f32 = OpTypeFloat 32
+ %vec4f = OpTypeVector %f32 4
+ %fn_type = OpTypeFunction %void
+
+%_ptr_Output = OpTypePointer Output %vec4f
+ %var = OpVariable %_ptr_Output Output
+
+ %main = OpFunction %void None %fn_type
+ %main_start = OpLabel
+ OpReturn
+ OpFunctionEnd
+)",
+ "%1:ptr<__out, vec4<f32>, read_write> = var @invariant @builtin(position)");
+}
+
+struct LocationCase {
+ std::string spirv_decorations;
+ std::string ir;
+};
+
+using LocationVarTest = SpirvParserTestWithParam<LocationCase>;
+
+TEST_P(LocationVarTest, Input) {
+ auto params = GetParam();
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpCapability SampleRateShading
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main"
+ OpExecutionMode %main LocalSize 1 1 1
+ )" + params.spirv_decorations +
+ R"(
+ %void = OpTypeVoid
+ %f32 = OpTypeFloat 32
+ %vec4f = OpTypeVector %f32 4
+ %fn_type = OpTypeFunction %void
+
+%_ptr_Input = OpTypePointer Input %vec4f
+ %var = OpVariable %_ptr_Input Input
+
+ %main = OpFunction %void None %fn_type
+ %main_start = OpLabel
+ OpReturn
+ OpFunctionEnd
+)",
+ "%1:ptr<__in, vec4<f32>, read> = " + params.ir);
+}
+
+TEST_P(LocationVarTest, Output) {
+ auto params = GetParam();
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpCapability SampleRateShading
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main"
+ OpExecutionMode %main LocalSize 1 1 1
+ )" + params.spirv_decorations +
+ R"(
+ %void = OpTypeVoid
+ %f32 = OpTypeFloat 32
+ %vec4f = OpTypeVector %f32 4
+ %fn_type = OpTypeFunction %void
+
+%_ptr_Output = OpTypePointer Output %vec4f
+ %var = OpVariable %_ptr_Output Output
+
+ %main = OpFunction %void None %fn_type
+ %main_start = OpLabel
+ OpReturn
+ OpFunctionEnd
+)",
+ "%1:ptr<__out, vec4<f32>, read_write> = " + params.ir);
+}
+
+INSTANTIATE_TEST_SUITE_P(SpirvParser,
+ LocationVarTest,
+ testing::Values(
+ LocationCase{
+ "OpDecorate %var Location 1 ",
+ "var @location(1)",
+ },
+ LocationCase{
+ "OpDecorate %var Location 2 "
+ "OpDecorate %var NoPerspective ",
+ "var @location(2) @interpolate(linear, center)",
+ },
+ LocationCase{
+ "OpDecorate %var Location 3 "
+ "OpDecorate %var Flat ",
+ "var @location(3) @interpolate(flat, center)",
+ },
+ LocationCase{
+ "OpDecorate %var Location 4 "
+ "OpDecorate %var Centroid ",
+ "var @location(4) @interpolate(perspective, centroid)",
+ },
+ LocationCase{
+ "OpDecorate %var Location 5 "
+ "OpDecorate %var Sample ",
+ "var @location(5) @interpolate(perspective, sample)",
+ },
+ LocationCase{
+ "OpDecorate %var Location 6 "
+ "OpDecorate %var NoPerspective "
+ "OpDecorate %var Centroid ",
+ "var @location(6) @interpolate(linear, centroid)",
+ }));
+
} // namespace
} // namespace tint::spirv::reader
diff --git a/src/tint/lang/spirv/reader/reader_test.cc b/src/tint/lang/spirv/reader/reader_test.cc
index 1a086a8..5313aaf 100644
--- a/src/tint/lang/spirv/reader/reader_test.cc
+++ b/src/tint/lang/spirv/reader/reader_test.cc
@@ -68,6 +68,25 @@
}
};
+TEST_F(SpirvReaderTest, UnsupportedExtension) {
+ auto got = Run(R"(
+ OpCapability Shader
+ OpExtension "SPV_KHR_variable_pointers"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main"
+ OpExecutionMode %main LocalSize 1 1 1
+ %void = OpTypeVoid
+ %ep_type = OpTypeFunction %void
+ %main = OpFunction %void None %ep_type
+ %main_start = OpLabel
+ OpReturn
+ OpFunctionEnd
+)");
+ ASSERT_NE(got, Success);
+ EXPECT_EQ(got.Failure().reason.str(),
+ "error: SPIR-V extension 'SPV_KHR_variable_pointers' is not supported");
+}
+
TEST_F(SpirvReaderTest, Load_VectorComponent) {
auto got = Run(R"(
OpCapability Shader
diff --git a/src/tint/lang/wgsl/inspector/inspector.cc b/src/tint/lang/wgsl/inspector/inspector.cc
index 630ef0f..d7fe564 100644
--- a/src/tint/lang/wgsl/inspector/inspector.cc
+++ b/src/tint/lang/wgsl/inspector/inspector.cc
@@ -27,7 +27,7 @@
#include "src/tint/lang/wgsl/inspector/inspector.h"
-#include <limits>
+#include <unordered_set>
#include <utility>
#include "src/tint/lang/core/builtin_value.h"
@@ -1009,4 +1009,139 @@
}
}
+std::vector<Inspector::LevelSampleInfo> Inspector::GetTextureQueries(const std::string& ep_name) {
+ std::vector<LevelSampleInfo> res;
+
+ std::unordered_set<BindingPoint> seen = {};
+
+ auto sample_type_for_call_and_type = [](wgsl::BuiltinFn builtin, const core::type::Type* ty) {
+ if (builtin == wgsl::BuiltinFn::kTextureNumLevels) {
+ return TextureQueryType::kTextureNumLevels;
+ }
+ if (builtin == wgsl::BuiltinFn::kTextureLoad) {
+ if (!ty->UnwrapRef()
+ ->IsAnyOf<core::type::MultisampledTexture,
+ core::type::DepthMultisampledTexture>()) {
+ return TextureQueryType::kTextureNumLevels;
+ }
+ }
+
+ return TextureQueryType::kTextureNumSamples;
+ };
+
+ Hashmap<const sem::Function*, Hashmap<const ast::Parameter*, TextureQueryType, 4>, 8>
+ fn_to_data;
+
+ auto record_function_param = [&fn_to_data](const sem::Function* func,
+ const ast::Parameter* param, TextureQueryType type) {
+ auto& param_to_type = *fn_to_data.GetOrZero(func);
+
+ auto entry = param_to_type.Get(param);
+ if (entry.has_value()) {
+ return;
+ }
+
+ param_to_type.Add(param, type);
+ };
+
+ auto save_if_needed = [&res, &seen](const sem::GlobalVariable* global, TextureQueryType type) {
+ auto binding = global->Attributes().binding_point.value();
+ if (seen.insert(binding).second) {
+ res.emplace_back(LevelSampleInfo{type, binding.group, binding.binding});
+ }
+ };
+
+ auto& sem = program_.Sem();
+
+ const auto* ep = FindEntryPointByName(ep_name);
+ if (!ep) {
+ return {};
+ }
+
+ // This works in dependency order such that we'll see the texture call first and can record
+ // any function parameter information and then as we walk up the function chain we can look
+ // the call data.
+ for (auto* fn_decl : sem.Module()->DependencyOrderedDeclarations()) {
+ auto* fn = sem.Get<sem::Function>(fn_decl);
+ if (!fn) {
+ continue;
+ }
+
+ // This is an entrypoint, make sure it's the requested entry point
+ if (fn->Declaration()->IsEntryPoint()) {
+ if (fn->Declaration() != ep) {
+ continue;
+ }
+ } else {
+ // Not an entry point, make sure it was called from the requested entry point
+ if (!fn->HasAncestorEntryPoint(ep->name->symbol)) {
+ continue;
+ }
+ }
+
+ for (auto* call : fn->DirectCalls()) {
+ // Builtin function call, record the texture information. If the used texture maps
+ // back up to a function parameter just store the type of the call and we'll track the
+ // function callback up in the `sem::Function` branch.
+ tint::Switch(
+ call->Target(),
+ [&](const sem::BuiltinFn* builtin) {
+ if (builtin->Fn() != wgsl::BuiltinFn::kTextureNumLevels &&
+ builtin->Fn() != wgsl::BuiltinFn::kTextureNumSamples &&
+ builtin->Fn() != wgsl::BuiltinFn::kTextureLoad) {
+ return;
+ }
+
+ auto* texture_expr = call->Declaration()->args[0];
+ auto* texture_sem = sem.GetVal(texture_expr)->RootIdentifier();
+ TINT_ASSERT(texture_sem);
+
+ auto type = sample_type_for_call_and_type(builtin->Fn(), texture_sem->Type());
+
+ tint::Switch(
+ texture_sem, //
+ [&](const sem::GlobalVariable* global) { save_if_needed(global, type); },
+ [&](const sem::Parameter* param) {
+ record_function_param(fn, param->Declaration(), type);
+ },
+ TINT_ICE_ON_NO_MATCH);
+ },
+ [&](const sem::Function* func) {
+ // A function call, check to see if any params needed to be tracked back to a
+ // global texture.
+
+ auto param_to_type = fn_to_data.Find(func);
+ if (!param_to_type) {
+ return;
+ }
+ TINT_ASSERT(call->Arguments().Length() == func->Declaration()->params.Length());
+
+ for (size_t i = 0; i < call->Arguments().Length(); i++) {
+ auto param = func->Declaration()->params[i];
+
+ // Determine if this had a texture we cared about
+ auto type = param_to_type->Get(param);
+ if (!type.has_value()) {
+ continue;
+ }
+
+ auto* arg = call->Arguments()[i];
+ auto* texture_sem = arg->RootIdentifier();
+
+ tint::Switch(
+ texture_sem,
+ [&](const sem::GlobalVariable* global) {
+ save_if_needed(global, type.value());
+ },
+ [&](const sem::Parameter* p) {
+ record_function_param(fn, p->Declaration(), type.value());
+ },
+ TINT_ICE_ON_NO_MATCH);
+ }
+ });
+ }
+ }
+ return res;
+}
+
} // namespace tint::inspector
diff --git a/src/tint/lang/wgsl/inspector/inspector.h b/src/tint/lang/wgsl/inspector/inspector.h
index 14c5ef6..6604832 100644
--- a/src/tint/lang/wgsl/inspector/inspector.h
+++ b/src/tint/lang/wgsl/inspector/inspector.h
@@ -156,6 +156,31 @@
/// extension.
std::vector<std::pair<std::string, Source>> GetEnableDirectives();
+ /// The information needed to be supplied.
+ enum class TextureQueryType : uint8_t {
+ /// Texture Num Levels
+ kTextureNumLevels,
+ /// Texture Num Samples
+ kTextureNumSamples,
+ };
+ /// Information on level and sample calls by a given texture binding point
+ struct LevelSampleInfo {
+ /// The type of function
+ TextureQueryType type = TextureQueryType::kTextureNumLevels;
+ /// The group number
+ uint32_t group = 0;
+ /// The binding number
+ uint32_t binding = 0;
+ };
+
+ /// @param ep the entry point ot get the information for
+ /// @returns a vector of information for textures which call textureNumLevels and
+ /// textureNumSamples for backends which require additional support for those methods. Each
+ /// binding point will only be returned once regardless of the number of calls made. The
+ /// texture types for `textureNumSamples` is disjoint from the texture types in
+ /// `textureNumLevels` so the binding point will always be one or the other.
+ std::vector<LevelSampleInfo> GetTextureQueries(const std::string& ep);
+
private:
const Program& program_;
diag::List diagnostics_;
diff --git a/src/tint/lang/wgsl/inspector/inspector_test.cc b/src/tint/lang/wgsl/inspector/inspector_test.cc
index c33f950..76d514e 100644
--- a/src/tint/lang/wgsl/inspector/inspector_test.cc
+++ b/src/tint/lang/wgsl/inspector/inspector_test.cc
@@ -3701,5 +3701,286 @@
inspector.GetSamplerTextureUses("main");
}
+class InspectorTextureTest : public InspectorRunner, public testing::Test {};
+
+TEST_F(InspectorTextureTest, TextureLevelInEP) {
+ std::string shader = R"(
+@group(2) @binding(3) var myTexture: texture_2d<f32>;
+
+@compute @workgroup_size(1)
+fn main() {
+ let num = textureNumLevels(myTexture);
+})";
+
+ Inspector& inspector = Initialize(shader);
+ auto info = inspector.GetTextureQueries("main");
+
+ ASSERT_EQ(1u, info.size());
+ EXPECT_EQ(Inspector::TextureQueryType::kTextureNumLevels, info[0].type);
+ EXPECT_EQ(2u, info[0].group);
+ EXPECT_EQ(3u, info[0].binding);
+}
+
+TEST_F(InspectorTextureTest, TextureLevelInEPNoDups) {
+ std::string shader = R"(
+@group(0) @binding(0) var myTexture: texture_2d<f32>;
+
+@compute @workgroup_size(1)
+fn main() {
+ let num1 = textureNumLevels(myTexture);
+ let num2 = textureNumLevels(myTexture);
+})";
+
+ Inspector& inspector = Initialize(shader);
+ auto info = inspector.GetTextureQueries("main");
+
+ ASSERT_EQ(1u, info.size());
+}
+
+TEST_F(InspectorTextureTest, TextureLevelInEPMultiple) {
+ std::string shader = R"(
+@group(2) @binding(3) var tex1: texture_2d<f32>;
+@group(1) @binding(2) var tex2: texture_2d<f32>;
+
+@compute @workgroup_size(1)
+fn main() {
+ let num1 = textureNumLevels(tex1);
+ let num2 = textureNumLevels(tex2);
+})";
+
+ Inspector& inspector = Initialize(shader);
+ auto info = inspector.GetTextureQueries("main");
+
+ ASSERT_EQ(2u, info.size());
+
+ EXPECT_EQ(Inspector::TextureQueryType::kTextureNumLevels, info[0].type);
+ EXPECT_EQ(2u, info[0].group);
+ EXPECT_EQ(3u, info[0].binding);
+
+ EXPECT_EQ(Inspector::TextureQueryType::kTextureNumLevels, info[1].type);
+ EXPECT_EQ(1u, info[1].group);
+ EXPECT_EQ(2u, info[1].binding);
+}
+
+TEST_F(InspectorTextureTest, TextureSamplesInEP) {
+ std::string shader = R"(
+@group(2) @binding(3) var myTexture: texture_multisampled_2d<f32>;
+
+@compute @workgroup_size(1)
+fn main() {
+ let num = textureNumSamples(myTexture);
+})";
+
+ Inspector& inspector = Initialize(shader);
+ auto info = inspector.GetTextureQueries("main");
+
+ ASSERT_EQ(1u, info.size());
+ EXPECT_EQ(Inspector::TextureQueryType::kTextureNumSamples, info[0].type);
+ EXPECT_EQ(2u, info[0].group);
+ EXPECT_EQ(3u, info[0].binding);
+}
+
+TEST_F(InspectorTextureTest, TextureSamplesInEPNoDups) {
+ std::string shader = R"(
+@group(0) @binding(0) var myTexture: texture_multisampled_2d<f32>;
+
+@compute @workgroup_size(1)
+fn main() {
+ let num1 = textureNumSamples(myTexture);
+ let num2 = textureNumSamples(myTexture);
+})";
+
+ Inspector& inspector = Initialize(shader);
+ auto info = inspector.GetTextureQueries("main");
+
+ ASSERT_EQ(1u, info.size());
+}
+
+TEST_F(InspectorTextureTest, TextureSamplesInEPMultiple) {
+ std::string shader = R"(
+@group(2) @binding(3) var tex1: texture_multisampled_2d<f32>;
+@group(1) @binding(2) var tex2: texture_multisampled_2d<f32>;
+
+@compute @workgroup_size(1)
+fn main() {
+ let num1 = textureNumSamples(tex1);
+ let num2 = textureNumSamples(tex2);
+})";
+
+ Inspector& inspector = Initialize(shader);
+ auto info = inspector.GetTextureQueries("main");
+
+ ASSERT_EQ(2u, info.size());
+
+ EXPECT_EQ(Inspector::TextureQueryType::kTextureNumSamples, info[0].type);
+ EXPECT_EQ(2u, info[0].group);
+ EXPECT_EQ(3u, info[0].binding);
+
+ EXPECT_EQ(Inspector::TextureQueryType::kTextureNumSamples, info[1].type);
+ EXPECT_EQ(1u, info[1].group);
+ EXPECT_EQ(2u, info[1].binding);
+}
+
+TEST_F(InspectorTextureTest, TextureLoadInEP) {
+ std::string shader = R"(
+@group(2) @binding(3) var tex1: texture_2d<f32>;
+
+@compute @workgroup_size(1)
+fn main() {
+ let num1 = textureLoad(tex1, vec2(0, 0), 0);
+})";
+
+ Inspector& inspector = Initialize(shader);
+ auto info = inspector.GetTextureQueries("main");
+
+ ASSERT_EQ(1u, info.size());
+
+ EXPECT_EQ(Inspector::TextureQueryType::kTextureNumLevels, info[0].type);
+ EXPECT_EQ(2u, info[0].group);
+ EXPECT_EQ(3u, info[0].binding);
+}
+
+TEST_F(InspectorTextureTest, TextureLoadMultisampledInEP) {
+ std::string shader = R"(
+@group(2) @binding(3) var tex1: texture_multisampled_2d<f32>;
+
+@compute @workgroup_size(1)
+fn main() {
+ let num1 = textureLoad(tex1, vec2(0, 0), 0);
+})";
+
+ Inspector& inspector = Initialize(shader);
+ auto info = inspector.GetTextureQueries("main");
+
+ ASSERT_EQ(1u, info.size());
+
+ EXPECT_EQ(Inspector::TextureQueryType::kTextureNumSamples, info[0].type);
+ EXPECT_EQ(2u, info[0].group);
+ EXPECT_EQ(3u, info[0].binding);
+}
+
+TEST_F(InspectorTextureTest, TextureLoadMultipleInEP) {
+ std::string shader = R"(
+@group(2) @binding(3) var tex1: texture_2d<f32>;
+@group(1) @binding(4) var tex2: texture_multisampled_2d<f32>;
+
+@compute @workgroup_size(1)
+fn main() {
+ let num1 = textureLoad(tex1, vec2(0, 0), 0);
+ let num2 = textureLoad(tex2, vec2(0, 0), 0);
+})";
+
+ Inspector& inspector = Initialize(shader);
+ auto info = inspector.GetTextureQueries("main");
+
+ ASSERT_EQ(2u, info.size());
+
+ EXPECT_EQ(Inspector::TextureQueryType::kTextureNumLevels, info[0].type);
+ EXPECT_EQ(2u, info[0].group);
+ EXPECT_EQ(3u, info[0].binding);
+ EXPECT_EQ(Inspector::TextureQueryType::kTextureNumSamples, info[1].type);
+ EXPECT_EQ(1u, info[1].group);
+ EXPECT_EQ(4u, info[1].binding);
+}
+
+TEST_F(InspectorTextureTest, TextureInSubfunction) {
+ std::string shader = R"(
+@group(2) @binding(3) var tex1: texture_2d<f32>;
+@group(1) @binding(4) var tex2: texture_multisampled_2d<f32>;
+@group(1) @binding(3) var tex3: texture_2d<f32>;
+
+fn b(tx1: texture_2d<f32>, tx2: texture_multisampled_2d<f32>, tx3: texture_2d<f32>, tx4: texture_2d<f32>) {
+ let v1 = textureNumLevels(tx1);
+ let v2 = textureNumSamples(tx2);
+ let v3 = textureLoad(tx3, vec2(0, 0), 0);
+ let v4 = textureNumLevels(tx4);
+}
+
+fn a(tx1: texture_2d<f32>, tx2: texture_multisampled_2d<f32>, tx3: texture_2d<f32>) {
+ b(tx1, tx2, tx3, tx1);
+}
+
+@compute @workgroup_size(1)
+fn main() {
+ a(tex1, tex2, tex3);
+})";
+
+ Inspector& inspector = Initialize(shader);
+ auto info = inspector.GetTextureQueries("main");
+
+ ASSERT_EQ(3u, info.size());
+
+ EXPECT_EQ(Inspector::TextureQueryType::kTextureNumLevels, info[0].type);
+ EXPECT_EQ(2u, info[0].group);
+ EXPECT_EQ(3u, info[0].binding);
+ EXPECT_EQ(Inspector::TextureQueryType::kTextureNumSamples, info[1].type);
+ EXPECT_EQ(1u, info[1].group);
+ EXPECT_EQ(4u, info[1].binding);
+ EXPECT_EQ(Inspector::TextureQueryType::kTextureNumLevels, info[2].type);
+ EXPECT_EQ(1u, info[2].group);
+ EXPECT_EQ(3u, info[2].binding);
+}
+
+TEST_F(InspectorTextureTest, TextureMultipleEPs) {
+ std::string shader = R"(
+@group(0) @binding(0) var<storage, read_write> dstBuf : array<u32>;
+@group(0) @binding(1) var tex1 : texture_2d_array<f32>;
+@group(0) @binding(4) var tex2 : texture_multisampled_2d<f32>;
+@group(1) @binding(3) var tex3 : texture_2d_array<f32>;
+
+@compute @workgroup_size(1, 1, 1) fn main1() {
+ dstBuf[0] = textureNumLayers(tex1);
+ dstBuf[1] = textureNumLevels(tex1);
+ dstBuf[2] = textureNumSamples(tex2);
+ dstBuf[3] = textureNumLevels(tex3);
+}
+
+@compute @workgroup_size(1, 1, 1) fn main2() {
+ dstBuf[0] = textureNumLayers(tex1);
+ dstBuf[1] = textureNumLevels(tex1);
+ dstBuf[2] = textureNumSamples(tex2);
+}
+ )";
+ Inspector& inspector = Initialize(shader);
+ {
+ auto info1 = inspector.GetTextureQueries("main1");
+ ASSERT_EQ(3u, info1.size());
+
+ EXPECT_EQ(Inspector::TextureQueryType::kTextureNumLevels, info1[0].type);
+ EXPECT_EQ(0u, info1[0].group);
+ EXPECT_EQ(1u, info1[0].binding);
+ EXPECT_EQ(Inspector::TextureQueryType::kTextureNumSamples, info1[1].type);
+ EXPECT_EQ(0u, info1[1].group);
+ EXPECT_EQ(4u, info1[1].binding);
+ EXPECT_EQ(Inspector::TextureQueryType::kTextureNumLevels, info1[2].type);
+ EXPECT_EQ(1u, info1[2].group);
+ EXPECT_EQ(3u, info1[2].binding);
+ }
+ {
+ auto info2 = inspector.GetTextureQueries("main2");
+ ASSERT_EQ(2u, info2.size());
+
+ EXPECT_EQ(Inspector::TextureQueryType::kTextureNumLevels, info2[0].type);
+ EXPECT_EQ(0u, info2[0].group);
+ EXPECT_EQ(1u, info2[0].binding);
+ EXPECT_EQ(Inspector::TextureQueryType::kTextureNumSamples, info2[1].type);
+ EXPECT_EQ(0u, info2[1].group);
+ EXPECT_EQ(4u, info2[1].binding);
+ }
+}
+
} // namespace
+
+static std::ostream& operator<<(std::ostream& out, const Inspector::TextureQueryType& ty) {
+ switch (ty) {
+ case Inspector::TextureQueryType::kTextureNumLevels:
+ out << "textureNumLevels";
+ break;
+ case Inspector::TextureQueryType::kTextureNumSamples:
+ out << "textureNumSamples";
+ break;
+ }
+ return out;
+}
+
} // namespace tint::inspector