blob: 220dabbc9b664c30f421b66a52b34084f9e0215b [file] [log] [blame]
// Copyright 2022 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "src/tint/lang/msl/writer/ast_raise/packed_vec3.h"
#include <string>
#include <utility>
#include <vector>
#include "src/tint/lang/core/fluent_types.h"
#include "src/tint/lang/core/type/array.h"
#include "src/tint/lang/wgsl/ast/module.h"
#include "src/tint/lang/wgsl/ast/transform/helper_test.h"
#include "src/tint/lang/wgsl/program/program_builder.h"
#include "src/tint/lang/wgsl/resolver/resolve.h"
#include "src/tint/lang/wgsl/sem/struct.h"
#include "src/tint/lang/wgsl/sem/variable.h"
#include "src/tint/utils/text/string.h"
using namespace tint::core::fluent_types; // NOLINT
namespace tint::msl::writer {
namespace {
using PackedVec3Test = ast::transform::TransformTest;
TEST_F(PackedVec3Test, ShouldRun_EmptyModule) {
auto* src = R"()";
EXPECT_FALSE(ShouldRun<PackedVec3>(src));
}
TEST_F(PackedVec3Test, ShouldRun_NoHostShareableVec3s) {
auto* src = R"(
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
a : array<vec3<f32>, 4>,
}
var<private> p_s : S;
var<private> p_v : vec3<f32>;
var<private> p_m : mat3x3<f32>;
var<private> p_a : array<vec3<f32>, 4>;
var<workgroup> w_s : S;
var<workgroup> w_v : vec3<f32>;
var<workgroup> w_m : mat3x3<f32>;
var<workgroup> w_a : array<vec3<f32>, 4>;
fn f() {
var f_s : S;
var f_v : vec3<f32>;
var f_m : mat3x3<f32>;
var f_a : array<vec3<f32>, 4>;
}
)";
EXPECT_FALSE(ShouldRun<PackedVec3>(src));
}
TEST_F(PackedVec3Test, ShouldRun_Vec4Vec2) {
auto* src = R"(
struct S {
v4 : vec4<f32>,
v2 : vec2<f32>,
}
@group(0) @binding(0) var<uniform> Ps : S; // Host sharable
@group(0) @binding(1) var<uniform> Pv4 : vec4<f32>; // Host sharable
@group(0) @binding(2) var<uniform> Pv2 : vec2<f32>; // Host sharable
)";
EXPECT_FALSE(ShouldRun<PackedVec3>(src));
}
TEST_F(PackedVec3Test, ShouldRun_OtherMatrices) {
auto* src = R"(
struct S {
m2x2 : mat2x2<f32>,
m2x4 : mat2x4<f32>,
m3x2 : mat3x2<f32>,
m3x4 : mat3x4<f32>,
m4x2 : mat4x2<f32>,
m4x4 : mat4x4<f32>,
}
@group(0) @binding(0) var<uniform> Ps : S; // Host sharable
@group(0) @binding(1) var<uniform> Pm2x2 : mat2x2<f32>; // Host sharable
@group(0) @binding(2) var<uniform> Pm2x4 : mat2x4<f32>; // Host sharable
@group(0) @binding(3) var<uniform> Pm3x2 : mat3x2<f32>; // Host sharable
@group(0) @binding(4) var<uniform> Pm3x4 : mat3x4<f32>; // Host sharable
@group(0) @binding(5) var<uniform> Pm4x2 : mat4x2<f32>; // Host sharable
@group(0) @binding(6) var<uniform> Pm4x4 : mat4x4<f32>; // Host sharable
)";
EXPECT_FALSE(ShouldRun<PackedVec3>(src));
}
TEST_F(PackedVec3Test, ShouldRun_ArrayOfNonVec3) {
auto* src = R"(
struct S {
arr_v : array<vec2<f32>, 4>,
arr_m : array<mat3x2<f32>, 4>,
}
@group(0) @binding(0) var<storage> Ps : S; // Host sharable
@group(0) @binding(1) var<storage> Parr_v : array<vec2<f32>, 4>; // Host sharable
@group(0) @binding(2) var<storage> Parr_m : array<mat3x2<f32>, 4>; // Host sharable
)";
EXPECT_FALSE(ShouldRun<PackedVec3>(src));
}
TEST_F(PackedVec3Test, ShouldRun_HostSharable_Vec3) {
auto* src = R"(
@group(0) @binding(0) var<uniform> P : vec3<f32>; // Host sharable
)";
EXPECT_TRUE(ShouldRun<PackedVec3>(src));
}
TEST_F(PackedVec3Test, ShouldRun_HostSharable_Mat3x3) {
auto* src = R"(
@group(0) @binding(0) var<uniform> P : mat3x3<f32>; // Host sharable
)";
EXPECT_TRUE(ShouldRun<PackedVec3>(src));
}
TEST_F(PackedVec3Test, ShouldRun_HostSharable_ArrayOfVec3) {
auto* src = R"(
@group(0) @binding(0) var<storage> P : array<vec3<f32>>; // Host sharable
)";
EXPECT_TRUE(ShouldRun<PackedVec3>(src));
}
TEST_F(PackedVec3Test, ShouldRun_HostSharable_ArrayOfMat3x3) {
auto* src = R"(
@group(0) @binding(0) var<storage> P : array<mat3x3<f32>>; // Host sharable
)";
EXPECT_TRUE(ShouldRun<PackedVec3>(src));
}
TEST_F(PackedVec3Test, ShouldRun_HostSharableStruct_Vec3) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<uniform> P : S; // Host sharable
)";
EXPECT_TRUE(ShouldRun<PackedVec3>(src));
}
TEST_F(PackedVec3Test, ShouldRun_HostSharableStruct_Mat3x3) {
auto* src = R"(
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<uniform> P : S; // Host sharable
)";
EXPECT_TRUE(ShouldRun<PackedVec3>(src));
}
TEST_F(PackedVec3Test, ShouldRun_HostSharableStruct_ArrayOfVec3) {
auto* src = R"(
struct S {
a : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<uniform> P : S; // Host sharable
)";
EXPECT_TRUE(ShouldRun<PackedVec3>(src));
}
TEST_F(PackedVec3Test, ShouldRun_HostSharableStruct_ArrayOfMat3x3) {
auto* src = R"(
struct S {
a : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<uniform> P : S; // Host sharable
)";
EXPECT_TRUE(ShouldRun<PackedVec3>(src));
}
TEST_F(PackedVec3Test, Vec3_ReadVector) {
auto* src = R"(
@group(0) @binding(0) var<storage> v : vec3<f32>;
fn f() {
let x = v;
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
@group(0) @binding(0) var<storage> v : __packed_vec3<f32>;
fn f() {
let x = vec3<f32>(v);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Vec3_ReadComponent_MemberAccessChain) {
auto* src = R"(
@group(0) @binding(0) var<storage> v : vec3<f32>;
fn f() {
let x = v.yz.x;
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
@group(0) @binding(0) var<storage> v : __packed_vec3<f32>;
fn f() {
let x = vec3<f32>(v).yz.x;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Vec3_ReadComponent_IndexAccessor) {
auto* src = R"(
@group(0) @binding(0) var<storage> v : vec3<f32>;
fn f() {
let x = v[1];
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
@group(0) @binding(0) var<storage> v : __packed_vec3<f32>;
fn f() {
let x = v[1];
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Vec3_ReadComponent_IndexAccessor_ViaDerefPointerIndex) {
auto* src = R"(
@group(0) @binding(0) var<storage> v : vec3<f32>;
fn f() {
let p = &v;
let x = (*p)[1];
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
@group(0) @binding(0) var<storage> v : __packed_vec3<f32>;
fn f() {
let p = &(v);
let x = (*(p))[1];
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Vec3_ReadComponent_IndexAccessor_ViaPointerIndex) {
auto* src = R"(
@group(0) @binding(0) var<storage> v : vec3<f32>;
fn f() {
let p = &v;
let x = p[1];
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
@group(0) @binding(0) var<storage> v : __packed_vec3<f32>;
fn f() {
let p = &(v);
let x = p[1];
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Vec3_WriteVector_ValueRHS) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
fn f() {
v = vec3(1.23);
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
fn f() {
v = __packed_vec3<f32>(vec3(1.22999999999999998224));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Vec3_WriteVector_RefRHS) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
@group(0) @binding(1) var<uniform> in : vec3<f32>;
fn f() {
v = in;
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
@group(0) @binding(1) var<uniform> in : __packed_vec3<f32>;
fn f() {
v = in;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Vec3_WriteComponent_MemberAccessor) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
fn f() {
v.y = 1.23;
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
fn f() {
v.y = 1.22999999999999998224;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Vec3_WriteComponent_MemberAccessor_ViaDerefPointerDot) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
fn f() {
let p = &v;
(*p).y = 1.23;
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
fn f() {
let p = &(v);
(*(p)).y = 1.22999999999999998224;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Vec3_WriteComponent_MemberAccessor_ViaPointerDot) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
fn f() {
let p = &v;
p.y = 1.23;
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
fn f() {
let p = &(v);
p.y = 1.22999999999999998224;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Vec3_WriteComponent_IndexAccessor) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
fn f() {
v[1] = 1.23;
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
fn f() {
v[1] = 1.22999999999999998224;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ArrayOfVec3_ReadArray) {
auto* src = R"(
@group(0) @binding(0) var<storage> arr : array<vec3<f32>, 4>;
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, 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);
}
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_ReadVector) {
auto* src = R"(
@group(0) @binding(0) var<storage> arr : array<vec3<f32>, 4>;
fn f() {
let x = arr[0];
}
)";
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> arr : array<tint_packed_vec3_f32_array_element, 4u>;
fn f() {
let x = vec3<f32>(arr[0].elements);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ArrayOfVec3_ReadComponent_MemberAccessor) {
auto* src = R"(
@group(0) @binding(0) var<storage> arr : array<vec3<f32>, 4>;
fn f() {
let x = arr[0].y;
}
)";
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> arr : array<tint_packed_vec3_f32_array_element, 4u>;
fn f() {
let x = arr[0].elements.y;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ArrayOfVec3_ReadComponent_IndexAccessor) {
auto* src = R"(
@group(0) @binding(0) var<storage> arr : array<vec3<f32>, 4>;
fn f() {
let x = arr[0][1];
}
)";
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> arr : array<tint_packed_vec3_f32_array_element, 4u>;
fn f() {
let x = arr[0].elements[1];
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ArrayOfVec3_WriteArray_ValueRHS) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 2>;
fn f() {
arr = array(vec3(1.5, 2.5, 3.5), vec3(4.5, 5.5, 6.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>, 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]));
}
return result;
}
@group(0) @binding(0) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 2u>;
fn f() {
arr = tint_pack_vec3_in_composite(array(vec3(1.5, 2.5, 3.5), vec3(4.5, 5.5, 6.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>;
@group(0) @binding(1) var<uniform> in : array<vec3<f32>, 2>;
fn f() {
arr = in;
}
)";
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, 2u>;
@group(0) @binding(1) var<uniform> in : array<tint_packed_vec3_f32_array_element, 2u>;
fn f() {
arr = in;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ArrayOfVec3_WriteVector_ValueRHS) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 4>;
fn f() {
arr[0] = vec3(1.23);
}
)";
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, 4u>;
fn f() {
arr[0].elements = __packed_vec3<f32>(vec3(1.22999999999999998224));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ArrayOfVec3_WriteVector_RefRHS) {
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>;
@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, 4u>;
@group(0) @binding(1) var<uniform> in_arr : array<tint_packed_vec3_f32_array_element, 4u>;
@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>;
fn f() {
arr[0].y = 1.23;
}
)";
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, 4u>;
fn f() {
arr[0].elements.y = 1.22999999999999998224;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ArrayOfVec3_WriteComponent_IndexAccessor) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 4>;
fn f() {
arr[0][1] = 1.23;
}
)";
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, 4u>;
fn f() {
arr[0].elements[1] = 1.22999999999999998224;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Matrix_ReadMatrix) {
auto* src = R"(
@group(0) @binding(0) var<storage> m : mat3x3<f32>;
fn f() {
let x = m;
}
)";
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>;
for(var i : u32; (i < 3u); i = (i + 1)) {
result[i] = vec3<f32>(in[i].elements);
}
return result;
}
@group(0) @binding(0) var<storage> m : array<tint_packed_vec3_f32_array_element, 3u>;
fn f() {
let x = tint_unpack_vec3_in_composite(m);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Matrix_ReadColumn) {
auto* src = R"(
@group(0) @binding(0) var<storage> m : mat3x3<f32>;
fn f() {
let x = m[1];
}
)";
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> m : array<tint_packed_vec3_f32_array_element, 3u>;
fn f() {
let x = vec3<f32>(m[1].elements);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Matrix_ReadComponent_MemberAccessChain) {
auto* src = R"(
@group(0) @binding(0) var<storage> m : mat3x3<f32>;
fn f() {
let x = m[1].yz.x;
}
)";
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> m : array<tint_packed_vec3_f32_array_element, 3u>;
fn f() {
let x = vec3<f32>(m[1].elements).yz.x;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Matrix_ReadComponent_IndexAccessor) {
auto* src = R"(
@group(0) @binding(0) var<storage> m : mat3x3<f32>;
fn f() {
let x = m[2][1];
}
)";
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> m : array<tint_packed_vec3_f32_array_element, 3u>;
fn f() {
let x = m[2].elements[1];
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Matrix_WriteMatrix_ValueRHS) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
fn f() {
m = mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 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 : 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]));
}
return result;
}
@group(0) @binding(0) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
fn f() {
m = tint_pack_vec3_in_composite(mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Matrix_WriteMatrix_RefRHS) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
@group(0) @binding(1) var<uniform> in : mat3x3<f32>;
fn f() {
m = in;
}
)";
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> m : array<tint_packed_vec3_f32_array_element, 3u>;
@group(0) @binding(1) var<uniform> in : array<tint_packed_vec3_f32_array_element, 3u>;
fn f() {
m = in;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Matrix_WriteColumn_ValueRHS) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
fn f() {
m[1] = vec3(1.23);
}
)";
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> m : array<tint_packed_vec3_f32_array_element, 3u>;
fn f() {
m[1].elements = __packed_vec3<f32>(vec3(1.22999999999999998224));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Matrix_WriteColumn_RefRHS) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
@group(0) @binding(1) var<uniform> in_mat : mat3x3<f32>;
@group(0) @binding(1) var<uniform> in_vec : vec3<f32>;
fn f() {
m[0] = in_mat[0];
m[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> m : array<tint_packed_vec3_f32_array_element, 3u>;
@group(0) @binding(1) var<uniform> in_mat : array<tint_packed_vec3_f32_array_element, 3u>;
@group(0) @binding(1) var<uniform> in_vec : __packed_vec3<f32>;
fn f() {
m[0].elements = in_mat[0].elements;
m[1].elements = in_vec;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Matrix_WriteComponent_MemberAccessor) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
fn f() {
m[1].y = 1.23;
}
)";
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> m : array<tint_packed_vec3_f32_array_element, 3u>;
fn f() {
m[1].elements.y = 1.22999999999999998224;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Matrix_WriteComponent_IndexAccessor) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
fn f() {
m[1][2] = 1.23;
}
)";
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> m : array<tint_packed_vec3_f32_array_element, 3u>;
fn f() {
m[1].elements[2] = 1.22999999999999998224;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ArrayOfMatrix_ReadArray) {
auto* src = R"(
@group(0) @binding(0) var<storage> arr : array<mat3x3<f32>, 4>;
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>;
for(var i : u32; (i < 3u); 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, 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]);
}
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_ReadMatrix) {
auto* src = R"(
@group(0) @binding(0) var<storage> arr : array<mat3x3<f32>, 4>;
fn f() {
let x = arr[0];
}
)";
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>;
for(var i : u32; (i < 3u); i = (i + 1)) {
result[i] = vec3<f32>(in[i].elements);
}
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(arr[0]);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ArrayOfMatrix_ReadColumn) {
auto* src = R"(
@group(0) @binding(0) var<storage> arr : array<mat3x3<f32>, 4>;
fn f() {
let x = arr[0][1];
}
)";
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> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
fn f() {
let x = vec3<f32>(arr[0][1].elements);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ArrayOfMatrix_ReadComponent_MemberAccessor) {
auto* src = R"(
@group(0) @binding(0) var<storage> arr : array<mat3x3<f32>, 4>;
fn f() {
let x = arr[0][1].y;
}
)";
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> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
fn f() {
let x = arr[0][1].elements.y;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ArrayOfMatrix_ReadComponent_IndexAccessor) {
auto* src = R"(
@group(0) @binding(0) var<storage> arr : array<mat3x3<f32>, 4>;
fn f() {
let x = arr[0][1][2];
}
)";
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> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
fn f() {
let x = arr[0][1].elements[2];
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ArrayOfMatrix_WriteArray_ValueRHS) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 2>;
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));
}
)";
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>;
for(var i : u32; (i < 3u); 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 : 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]);
}
return result;
}
@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>;
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)));
}
)";
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>;
@group(0) @binding(1) var<uniform> in : array<mat3x3<f32>, 2>;
fn f() {
arr = in;
}
)";
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<array<tint_packed_vec3_f32_array_element, 3u>, 2u>;
@group(0) @binding(1) var<uniform> in : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>;
fn f() {
arr = in;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ArrayOfMatrix_WriteMatrix_ValueRHS) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 4>;
fn f() {
arr[0] = mat3x3(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9);
}
)";
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>;
for(var i : u32; (i < 3u); 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<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
fn f() {
arr[0] = tint_pack_vec3_in_composite(mat3x3(1.10000000000000008882, 2.20000000000000017764, 3.29999999999999982236, 4.40000000000000035527, 5.5, 6.59999999999999964473, 7.70000000000000017764, 8.80000000000000071054, 9.90000000000000035527));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ArrayOfMatrix_WriteMatrix_RefRHS) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 4>;
@group(0) @binding(1) var<uniform> in_arr : array<mat3x3<f32>, 4>;
@group(0) @binding(2) var<uniform> in_mat : mat3x3<f32>;
fn f() {
arr[0] = in_arr[0];
arr[1] = in_mat;
}
)";
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<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
@group(0) @binding(1) var<uniform> in_arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
@group(0) @binding(2) var<uniform> in_mat : array<tint_packed_vec3_f32_array_element, 3u>;
fn f() {
arr[0] = in_arr[0];
arr[1] = in_mat;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ArrayOfMatrix_WriteVector_ValueRHS) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 4>;
fn f() {
arr[0][1] = vec3(1.23);
}
)";
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<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
fn f() {
arr[0][1].elements = __packed_vec3<f32>(vec3(1.22999999999999998224));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ArrayOfMatrix_WriteVector_RefRHS) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 4>;
@group(0) @binding(1) var<uniform> in_arr : array<mat3x3<f32>, 4>;
@group(0) @binding(2) var<uniform> in_mat : mat3x3<f32>;
@group(0) @binding(3) var<uniform> in_vec : vec3<f32>;
fn f() {
arr[0][0] = arr[0][1];
arr[0][1] = in_mat[2];
arr[0][2] = 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<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
@group(0) @binding(1) var<uniform> in_arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
@group(0) @binding(2) var<uniform> in_mat : array<tint_packed_vec3_f32_array_element, 3u>;
@group(0) @binding(3) var<uniform> in_vec : __packed_vec3<f32>;
fn f() {
arr[0][0].elements = arr[0][1].elements;
arr[0][1].elements = in_mat[2].elements;
arr[0][2].elements = in_vec;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ArrayOfMatrix_WriteComponent_MemberAccessor) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 4>;
fn f() {
arr[0][1].y = 1.23;
}
)";
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<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
fn f() {
arr[0][1].elements.y = 1.22999999999999998224;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ArrayOfMatrix_WriteComponent_IndexAccessor) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 4>;
fn f() {
arr[0][1][2] = 1.23;
}
)";
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<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
fn f() {
arr[0][1].elements[2] = 1.22999999999999998224;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_Vec3_ReadStruct) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P;
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
struct S_tint_packed_vec3 {
@align(16)
v : __packed_vec3<f32>,
}
fn tint_unpack_vec3_in_composite(in : S_tint_packed_vec3) -> S {
var result : S;
result.v = vec3<f32>(in.v);
return result;
}
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn f() {
let x = tint_unpack_vec3_in_composite(P);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_Vec3_ReadVector) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P.v;
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
struct S_tint_packed_vec3 {
@align(16)
v : __packed_vec3<f32>,
}
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn f() {
let x = vec3<f32>(P.v);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_Vec3_ReadComponent_MemberAccessChain) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P.v.yz.x;
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
struct S_tint_packed_vec3 {
@align(16)
v : __packed_vec3<f32>,
}
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn f() {
let x = vec3<f32>(P.v).yz.x;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_Vec3_ReadComponent_IndexAccessor) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P.v[1];
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
struct S_tint_packed_vec3 {
@align(16)
v : __packed_vec3<f32>,
}
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn f() {
let x = P.v[1];
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_Vec3_WriteStruct_ValueRHS) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P = S(vec3(1.23));
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
struct S_tint_packed_vec3 {
@align(16)
v : __packed_vec3<f32>,
}
fn tint_pack_vec3_in_composite(in : S) -> S_tint_packed_vec3 {
var result : S_tint_packed_vec3;
result.v = __packed_vec3<f32>(in.v);
return result;
}
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
P = tint_pack_vec3_in_composite(S(vec3(1.22999999999999998224)));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_Vec3_WriteStruct_RefRHS) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
@group(0) @binding(1) var<uniform> in : S;
fn f() {
P = in;
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
struct S_tint_packed_vec3 {
@align(16)
v : __packed_vec3<f32>,
}
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
@group(0) @binding(1) var<uniform> in : S_tint_packed_vec3;
fn f() {
P = in;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_Vec3_WriteVector_ValueRHS) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P.v = vec3(1.23);
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
struct S_tint_packed_vec3 {
@align(16)
v : __packed_vec3<f32>,
}
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
P.v = __packed_vec3<f32>(vec3(1.22999999999999998224));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_Vec3_WriteVector_RefRHS) {
auto* src = R"(
struct S {
v1 : vec3<f32>,
v2 : vec3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
@group(0) @binding(1) var<uniform> in_str : S;
@group(0) @binding(2) var<uniform> in_vec : vec3<f32>;
fn f() {
P.v1 = in_str.v1;
P.v2 = in_vec;
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
struct S_tint_packed_vec3 {
@align(16)
v1 : __packed_vec3<f32>,
@align(16)
v2 : __packed_vec3<f32>,
}
struct S {
v1 : vec3<f32>,
v2 : vec3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
@group(0) @binding(2) var<uniform> in_vec : __packed_vec3<f32>;
fn f() {
P.v1 = in_str.v1;
P.v2 = in_vec;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_Vec3_WriteComponent_MemberAccessor) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P.v.y = 1.23;
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
struct S_tint_packed_vec3 {
@align(16)
v : __packed_vec3<f32>,
}
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
P.v.y = 1.22999999999999998224;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_Vec3_WriteComponent_IndexAccessor) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P.v[1] = 1.23;
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
struct S_tint_packed_vec3 {
@align(16)
v : __packed_vec3<f32>,
}
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
P.v[1] = 1.22999999999999998224;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_ReadStruct) {
auto* src = R"(
struct S {
arr : array<vec3<f32>, 4>,
}
@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, 4u>,
}
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);
}
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>, 4>,
}
@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) {
auto* src = R"(
struct S {
arr : array<vec3<f32>, 4>,
}
@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, 4u>,
}
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);
}
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_ReadVector) {
auto* src = R"(
struct S {
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P.arr[0];
}
)";
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, 4u>,
}
struct S {
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn f() {
let x = vec3<f32>(P.arr[0].elements);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_ReadComponent_MemberAccessor) {
auto* src = R"(
struct S {
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P.arr[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 : array<tint_packed_vec3_f32_array_element, 4u>,
}
struct S {
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn f() {
let x = P.arr[0].elements.y;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_ReadComponent_IndexAccessor) {
auto* src = R"(
struct S {
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P.arr[0][1];
}
)";
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, 4u>,
}
struct S {
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn f() {
let x = P.arr[0].elements[1];
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteStruct_ValueRHS) {
auto* src = R"(
struct S {
arr : array<vec3<f32>, 2>,
}
@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)));
}
)";
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, 2u>,
}
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]));
}
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>, 2>,
}
@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))));
}
)";
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 {
arr : array<vec3<f32>, 2>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
@group(0) @binding(1) var<uniform> in : S;
fn f() {
P = in;
}
)";
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, 2u>,
}
struct S {
arr : array<vec3<f32>, 2>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
@group(0) @binding(1) var<uniform> in : S_tint_packed_vec3;
fn f() {
P = in;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteArray_ValueRHS) {
auto* src = R"(
struct S {
arr : array<vec3<f32>, 2>,
}
@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));
}
)";
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, 2u>,
}
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]));
}
return result;
}
struct S {
arr : array<vec3<f32>, 2>,
}
@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)));
}
)";
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 {
arr1 : array<vec3<f32>, 2>,
arr2 : array<vec3<f32>, 2>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
@group(0) @binding(1) var<uniform> in_str : S;
@group(0) @binding(2) var<uniform> in_arr : array<vec3<f32>, 2>;
fn f() {
P.arr1 = in_str.arr1;
P.arr2 = in_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)
arr1 : array<tint_packed_vec3_f32_array_element, 2u>,
@align(16)
arr2 : array<tint_packed_vec3_f32_array_element, 2u>,
}
struct S {
arr1 : array<vec3<f32>, 2>,
arr2 : array<vec3<f32>, 2>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
@group(0) @binding(2) var<uniform> in_arr : array<tint_packed_vec3_f32_array_element, 2u>;
fn f() {
P.arr1 = in_str.arr1;
P.arr2 = in_arr;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteVector_ValueRHS) {
auto* src = R"(
struct S {
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P.arr[0] = vec3(1.23);
}
)";
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, 4u>,
}
struct S {
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
P.arr[0].elements = __packed_vec3<f32>(vec3(1.22999999999999998224));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteVector_RefRHS) {
auto* src = R"(
struct S {
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
@group(0) @binding(1) var<uniform> in_str : S;
@group(0) @binding(2) var<uniform> in_arr : array<vec3<f32>, 4>;
@group(0) @binding(3) var<uniform> in_vec : vec3<f32>;
fn f() {
P.arr[0] = in_str.arr[0];
P.arr[1] = in_arr[1];
P.arr[2] = in_vec;
}
)";
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, 4u>,
}
struct S {
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
@group(0) @binding(2) var<uniform> in_arr : array<tint_packed_vec3_f32_array_element, 4u>;
@group(0) @binding(3) var<uniform> in_vec : __packed_vec3<f32>;
fn f() {
P.arr[0].elements = in_str.arr[0].elements;
P.arr[1].elements = in_arr[1].elements;
P.arr[2].elements = in_vec;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteComponent_MemberAccessor) {
auto* src = R"(
struct S {
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P.arr[0].y = 1.23;
}
)";
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, 4u>,
}
struct S {
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
P.arr[0].elements.y = 1.22999999999999998224;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteComponent_IndexAccessor) {
auto* src = R"(
struct S {
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P.arr[0][1] = 1.23;
}
)";
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, 4u>,
}
struct S {
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
P.arr[0].elements[1] = 1.22999999999999998224;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_Matrix_ReadStruct) {
auto* src = R"(
struct S {
m : mat3x3<f32>,
}
@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)
m : array<tint_packed_vec3_f32_array_element, 3u>,
}
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);
}
return result;
}
fn tint_unpack_vec3_in_composite_1(in : S_tint_packed_vec3) -> S {
var result : S;
result.m = tint_unpack_vec3_in_composite(in.m);
return result;
}
struct S {
m : mat3x3<f32>,
}
@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_Matrix_ReadMatrix) {
auto* src = R"(
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P.m;
}
)";
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)
m : array<tint_packed_vec3_f32_array_element, 3u>,
}
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);
}
return result;
}
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn f() {
let x = tint_unpack_vec3_in_composite(P.m);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_Matrix_ReadColumn) {
auto* src = R"(
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P.m[1];
}
)";
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)
m : array<tint_packed_vec3_f32_array_element, 3u>,
}
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn f() {
let x = vec3<f32>(P.m[1].elements);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_Matrix_ReadComponent_MemberAccessChain) {
auto* src = R"(
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P.m[1].yz.x;
}
)";
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)
m : array<tint_packed_vec3_f32_array_element, 3u>,
}
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn f() {
let x = vec3<f32>(P.m[1].elements).yz.x;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_Matrix_ReadComponent_IndexAccessor) {
auto* src = R"(
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P.m[2][1];
}
)";
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)
m : array<tint_packed_vec3_f32_array_element, 3u>,
}
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn f() {
let x = P.m[2].elements[1];
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_Matrix_WriteStruct_ValueRHS) {
auto* src = R"(
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P = S(mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 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>,
}
struct S_tint_packed_vec3 {
@align(16)
m : array<tint_packed_vec3_f32_array_element, 3u>,
}
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]));
}
return result;
}
fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
var result : S_tint_packed_vec3;
result.m = tint_pack_vec3_in_composite(in.m);
return result;
}
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
P = tint_pack_vec3_in_composite_1(S(mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5)));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_Matrix_WriteStruct_RefRHS) {
auto* src = R"(
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
@group(0) @binding(1) var<uniform> in : S;
fn f() {
P = in;
}
)";
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)
m : array<tint_packed_vec3_f32_array_element, 3u>,
}
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
@group(0) @binding(1) var<uniform> in : S_tint_packed_vec3;
fn f() {
P = in;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_Matrix_WriteMatrix_ValueRHS) {
auto* src = R"(
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P.m = mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 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>,
}
struct S_tint_packed_vec3 {
@align(16)
m : array<tint_packed_vec3_f32_array_element, 3u>,
}
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]));
}
return result;
}
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
P.m = tint_pack_vec3_in_composite(mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_Matrix_WriteMatrix_RefRHS) {
auto* src = R"(
struct S {
m1 : mat3x3<f32>,
m2 : mat3x3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
@group(0) @binding(1) var<uniform> in_str : S;
@group(0) @binding(2) var<uniform> in_mat : mat3x3<f32>;
fn f() {
P.m1 = in_str.m1;
P.m2 = in_mat;
}
)";
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)
m1 : array<tint_packed_vec3_f32_array_element, 3u>,
@align(16)
m2 : array<tint_packed_vec3_f32_array_element, 3u>,
}
struct S {
m1 : mat3x3<f32>,
m2 : mat3x3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
@group(0) @binding(2) var<uniform> in_mat : array<tint_packed_vec3_f32_array_element, 3u>;
fn f() {
P.m1 = in_str.m1;
P.m2 = in_mat;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_Matrix_WriteColumn_ValueRHS) {
auto* src = R"(
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P.m[1] = vec3(1.23);
}
)";
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)
m : array<tint_packed_vec3_f32_array_element, 3u>,
}
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
P.m[1].elements = __packed_vec3<f32>(vec3(1.22999999999999998224));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_Matrix_WriteColumn_RefRHS) {
auto* src = R"(
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
@group(0) @binding(1) var<uniform> in_str : S;
@group(0) @binding(2) var<uniform> in_mat : mat3x3<f32>;
@group(0) @binding(3) var<uniform> in_vec : vec3<f32>;
fn f() {
P.m[0] = in_str.m[0];
P.m[1] = in_mat[1];
P.m[2] = in_vec;
}
)";
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)
m : array<tint_packed_vec3_f32_array_element, 3u>,
}
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
@group(0) @binding(2) var<uniform> in_mat : array<tint_packed_vec3_f32_array_element, 3u>;
@group(0) @binding(3) var<uniform> in_vec : __packed_vec3<f32>;
fn f() {
P.m[0].elements = in_str.m[0].elements;
P.m[1].elements = in_mat[1].elements;
P.m[2].elements = in_vec;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_Matrix_WriteComponent_MemberAccessor) {
auto* src = R"(
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P.m[1].y = 1.23;
}
)";
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)
m : array<tint_packed_vec3_f32_array_element, 3u>,
}
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
P.m[1].elements.y = 1.22999999999999998224;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_Matrix_WriteComponent_IndexAccessor) {
auto* src = R"(
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P.m[1][2] = 1.23;
}
)";
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)
m : array<tint_packed_vec3_f32_array_element, 3u>,
}
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
P.m[1].elements[2] = 1.22999999999999998224;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_ReadStruct) {
auto* src = R"(
struct S {
arr : array<mat3x3<f32>, 4>,
}
@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>, 4u>,
}
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);
}
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]);
}
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>, 4>,
}
@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>,
}
@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<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
}
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);
}
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]);
}
return result;
}
struct S {
arr : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn f() {
let x = tint_unpack_vec3_in_composite_1(P.arr);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_ReadMatrix) {
auto* src = R"(
struct S {
arr : array<mat3x3<f32>, 4u>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P.arr[0];
}
)";
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>, 4u>,
}
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);
}
return result;
}
struct S {
arr : array<mat3x3<f32>, 4u>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn f() {
let x = tint_unpack_vec3_in_composite(P.arr[0]);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_ReadColumn) {
auto* src = R"(
struct S {
arr : array<mat3x3<f32>, 4u>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P.arr[0][1];
}
)";
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>, 4u>,
}
struct S {
arr : array<mat3x3<f32>, 4u>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn f() {
let x = vec3<f32>(P.arr[0][1].elements);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_ReadComponent_MemberAccessor) {
auto* src = R"(
struct S {
arr : array<mat3x3<f32>, 4u>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P.arr[0][1].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 : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
}
struct S {
arr : array<mat3x3<f32>, 4u>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn f() {
let x = P.arr[0][1].elements.y;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_ReadComponent_IndexAccessor) {
auto* src = R"(
struct S {
arr : array<mat3x3<f32>, 4u>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P.arr[0][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)
arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
}
struct S {
arr : array<mat3x3<f32>, 4u>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn f() {
let x = P.arr[0][1].elements[2];
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteStruct_ValueRHS) {
auto* src = R"(
struct S {
arr : array<mat3x3<f32>, 2>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P = S(array(mat3x3<f32>(), mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 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>,
}
struct S_tint_packed_vec3 {
@align(16)
arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>,
}
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]));
}
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]);
}
return result;
}
fn tint_pack_vec3_in_composite_2(in : S) -> S_tint_packed_vec3 {
var result : S_tint_packed_vec3;
result.arr = tint_pack_vec3_in_composite_1(in.arr);
return result;
}
struct S {
arr : array<mat3x3<f32>, 2>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
P = tint_pack_vec3_in_composite_2(S(array(mat3x3<f32>(), mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5))));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteStruct_RefRHS) {
auto* src = R"(
struct S {
arr : array<mat3x3<f32>, 2>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
@group(0) @binding(1) var<uniform> in : S;
fn f() {
P = in;
}
)";
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>, 2u>,
}
struct S {
arr : array<mat3x3<f32>, 2>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
@group(0) @binding(1) var<uniform> in : S_tint_packed_vec3;
fn f() {
P = in;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteArray_ValueRHS) {
auto* src = R"(
struct S {
arr : array<mat3x3<f32>, 2>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P.arr = array(mat3x3<f32>(), mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 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>,
}
struct S_tint_packed_vec3 {
@align(16)
arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>,
}
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]));
}
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]);
}
return result;
}
struct S {
arr : array<mat3x3<f32>, 2>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
P.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)));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteArray_RefRHS) {
auto* src = R"(
struct S {
arr1 : array<mat3x3<f32>, 2>,
arr2 : array<mat3x3<f32>, 2>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
@group(0) @binding(1) var<uniform> in_str : S;
@group(0) @binding(2) var<uniform> in_arr : array<mat3x3<f32>, 2>;
fn f() {
P.arr1 = in_str.arr1;
P.arr2 = in_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)
arr1 : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>,
@align(16)
arr2 : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>,
}
struct S {
arr1 : array<mat3x3<f32>, 2>,
arr2 : array<mat3x3<f32>, 2>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
@group(0) @binding(2) var<uniform> in_arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>;
fn f() {
P.arr1 = in_str.arr1;
P.arr2 = in_arr;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteMatrix_ValueRHS) {
auto* src = R"(
struct S {
arr : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P.arr[0] = mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 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>,
}
struct S_tint_packed_vec3 {
@align(16)
arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
}
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]));
}
return result;
}
struct S {
arr : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
P.arr[0] = tint_pack_vec3_in_composite(mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteMatrix_RefRHS) {
auto* src = R"(
struct S {
arr : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
@group(0) @binding(1) var<uniform> in_str : S;
@group(0) @binding(2) var<uniform> in_arr : array<mat3x3<f32>, 4>;
@group(0) @binding(3) var<uniform> in_mat : mat3x3<f32>;
fn f() {
P.arr[0] = in_str.arr[0];
P.arr[1] = in_arr[1];
P.arr[2] = in_mat;
}
)";
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>, 4u>,
}
struct S {
arr : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
@group(0) @binding(2) var<uniform> in_arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
@group(0) @binding(3) var<uniform> in_mat : array<tint_packed_vec3_f32_array_element, 3u>;
fn f() {
P.arr[0] = in_str.arr[0];
P.arr[1] = in_arr[1];
P.arr[2] = in_mat;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteVector_ValueRHS) {
auto* src = R"(
struct S {
arr : array<mat3x3<f32>, 4u>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P.arr[0][1] = vec3(1.23);
}
)";
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>, 4u>,
}
struct S {
arr : array<mat3x3<f32>, 4u>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
P.arr[0][1].elements = __packed_vec3<f32>(vec3(1.22999999999999998224));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteVector_RefRHS) {
auto* src = R"(
struct S {
arr : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
@group(0) @binding(1) var<uniform> in_str : S;
@group(0) @binding(2) var<uniform> in_arr : array<mat3x3<f32>, 4>;
@group(0) @binding(3) var<uniform> in_mat : mat3x3<f32>;
@group(0) @binding(4) var<uniform> in_vec : vec3<f32>;
fn f() {
P.arr[0][0] = in_str.arr[0][1];
P.arr[1][1] = in_arr[3][2];
P.arr[2][2] = in_mat[1];
P.arr[3][0] = in_vec;
}
)";
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>, 4u>,
}
struct S {
arr : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
@group(0) @binding(2) var<uniform> in_arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
@group(0) @binding(3) var<uniform> in_mat : array<tint_packed_vec3_f32_array_element, 3u>;
@group(0) @binding(4) var<uniform> in_vec : __packed_vec3<f32>;
fn f() {
P.arr[0][0].elements = in_str.arr[0][1].elements;
P.arr[1][1].elements = in_arr[3][2].elements;
P.arr[2][2].elements = in_mat[1].elements;
P.arr[3][0].elements = in_vec;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteComponent_MemberAccessor) {
auto* src = R"(
struct S {
arr : array<mat3x3<f32>, 4u>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P.arr[0][1].y = 1.23;
}
)";
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>, 4u>,
}
struct S {
arr : array<mat3x3<f32>, 4u>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
P.arr[0][1].elements.y = 1.22999999999999998224;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteComponent_IndexAccessor) {
auto* src = R"(
struct S {
arr : array<mat3x3<f32>, 4u>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P.arr[0][1][2] = 1.23;
}
)";
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>, 4u>,
}
struct S {
arr : array<mat3x3<f32>, 4u>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
P.arr[0][1].elements[2] = 1.22999999999999998224;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ExistingMemberAttributes) {
auto* src = R"(
struct S {
@align(32) @size(32) v : vec3<f32>,
@align(64) @size(64) arr : array<vec3<f32>, 4>,
@align(128) @size(128) x : u32,
}
@group(0) @binding(0) var<uniform> P : S;
fn f() {
let x = P.v[0];
}
)";
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(32) @size(32)
v : __packed_vec3<f32>,
@align(64) @size(64)
arr : array<tint_packed_vec3_f32_array_element, 4u>,
@align(128) @size(128)
x : u32,
}
struct S {
@align(32) @size(32)
v : vec3<f32>,
@align(64) @size(64)
arr : array<vec3<f32>, 4>,
@align(128) @size(128)
x : u32,
}
@group(0) @binding(0) var<uniform> P : S_tint_packed_vec3;
fn f() {
let x = P.v[0];
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ExistingMemberAttributes_SizeMatchesUnpackedVec3) {
// Test that the type we replace a vec3 with is not larger than it should be.
auto* src = R"(
struct S {
@size(12) v : vec3<f32>,
@size(64) arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<uniform> P : S;
fn f() {
let x = P.v[0];
}
)";
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 {
@size(12) @align(16)
v : __packed_vec3<f32>,
@size(64) @align(16)
arr : array<tint_packed_vec3_f32_array_element, 4u>,
}
struct S {
@size(12)
v : vec3<f32>,
@size(64)
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<uniform> P : S_tint_packed_vec3;
fn f() {
let x = P.v[0];
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ExistingMemberAttributes_AlignTooSmall) {
// Test that we add an @align() attribute when the new alignment of the packed vec3 struct would
// be too small.
auto* src = R"(
struct S {
a : u32,
v : vec3<f32>,
b : u32,
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<uniform> P : S;
fn f() {
let x = P.v[0];
}
)";
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 {
a : u32,
@align(16)
v : __packed_vec3<f32>,
b : u32,
@align(16)
arr : array<tint_packed_vec3_f32_array_element, 4u>,
}
struct S {
a : u32,
v : vec3<f32>,
b : u32,
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<uniform> P : S_tint_packed_vec3;
fn f() {
let x = P.v[0];
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructMember_ExistingMemberAttributes_ExplicitOffset) {
// Test that the we do not add an @align attribute if @offset is present.
// struct S {
// a : u32,
// @offset(32) v : vec3<f32>,
// b : u32,
// @offset(128) arr : array<vec3<f32>, 4>,
// }
//
// @group(0) @binding(0) var<uniform> P : S;
ProgramBuilder b;
b.Structure("S", tint::Vector{
b.Member("a", b.ty.u32()),
b.Member("v", b.ty.vec3<f32>(), tint::Vector{b.MemberOffset(AInt(32))}),
b.Member("b", b.ty.u32()),
b.Member("arr", b.ty.array(b.ty.vec3<f32>(), b.Expr(AInt(4))),
tint::Vector{b.MemberOffset(AInt(128))}),
});
b.GlobalVar("P", core::AddressSpace::kStorage, b.ty("S"),
tint::Vector{b.Group(AInt(0)), b.Binding(AInt(0))});
Program src(resolver::Resolve(b));
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 {
a : u32,
@size(28)
padding_0 : u32,
/* @offset(32) */
v : __packed_vec3<f32>,
b : u32,
@size(80)
padding_1 : u32,
/* @offset(128) */
arr : array<tint_packed_vec3_f32_array_element, 4u>,
}
struct S {
a : u32,
@size(16)
padding_0 : u32,
/* @offset(32) */
v : vec3<f32>,
b : u32,
@size(80)
padding_1 : u32,
/* @offset(128) */
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(std::move(src), data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructValueConstructor_ViaIndexAccessor) {
auto* src = R"(
struct S {
a : vec3<f32>,
b : vec3<f32>,
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage> s : S;
fn f() {
let value_arr : array<vec3<f32>, 4> = array<vec3<f32>, 4>();
let x = S(value_arr[0], s.arr[0], value_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)
a : __packed_vec3<f32>,
@align(16)
b : __packed_vec3<f32>,
@align(16)
arr : array<tint_packed_vec3_f32_array_element, 4u>,
}
struct S {
a : vec3<f32>,
b : vec3<f32>,
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage> s : S_tint_packed_vec3;
fn f() {
let value_arr : array<vec3<f32>, 4> = array<vec3<f32>, 4>();
let x = S(value_arr[0], vec3<f32>(s.arr[0].elements), value_arr);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, WrapperStructLayout_MixedUsage) {
// Test the layout of the generated wrapper struct(s) when vec3s are used in both structures and
// arrays.
auto* src = R"(
struct S {
v : vec3<f32>,
a : u32,
}
@group(0) @binding(0) var<storage, read_write> str : S;
@group(0) @binding(1) var<storage, read_write> arr : array<vec3<f32>, 4>;
fn main() {
str.v = arr[0];
arr[1] = str.v;
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
struct S_tint_packed_vec3 {
@align(16)
v : __packed_vec3<f32>,
a : u32,
}
struct tint_packed_vec3_f32_array_element {
@align(16)
elements : __packed_vec3<f32>,
}
struct S {
v : vec3<f32>,
a : u32,
}
@group(0) @binding(0) var<storage, read_write> str : S_tint_packed_vec3;
@group(0) @binding(1) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 4u>;
fn main() {
str.v = arr[0].elements;
arr[1].elements = str.v;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
auto& vars = got.program.AST().GlobalVariables();
ASSERT_EQ(vars.Length(), 2u);
{
// Check the layout of the struct type of "str".
// The first member should have an alignment of 16 bytes, a size of 12 bytes, and the second
// member should have an offset of 12 bytes.
auto* sem_str = got.program.Sem().Get(vars[0]);
auto* str_ty = sem_str->Type()->UnwrapRef()->As<core::type::Struct>();
ASSERT_NE(str_ty, nullptr);
ASSERT_EQ(str_ty->Members().Length(), 2u);
EXPECT_EQ(str_ty->Members()[0]->Align(), 16u);
EXPECT_EQ(str_ty->Members()[0]->Size(), 12u);
EXPECT_EQ(str_ty->Members()[1]->Offset(), 12u);
}
{
// Check the layout of the array type of "arr".
// The element stride should be 16 bytes.
auto* sem_arr = got.program.Sem().Get(vars[1]);
auto* arr_ty = sem_arr->Type()->UnwrapRef()->As<core::type::Array>();
ASSERT_NE(arr_ty, nullptr);
EXPECT_EQ(arr_ty->Stride(), 16u);
}
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, PackUnpackStructWithNonVec3Members) {
auto* src = R"(
struct S {
v : vec3<f32>,
arr : array<vec3<f32>, 4>,
a : u32,
b : vec4<f32>,
c : array<vec4<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
let x = P;
P = x;
}
)";
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 : __packed_vec3<f32>,
@align(16)
arr : array<tint_packed_vec3_f32_array_element, 4u>,
a : u32,
b : vec4<f32>,
c : array<vec4<f32>, 4>,
}
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);
}
return result;
}
fn tint_unpack_vec3_in_composite_1(in : S_tint_packed_vec3) -> S {
var result : S;
result.v = vec3<f32>(in.v);
result.arr = tint_unpack_vec3_in_composite(in.arr);
result.a = in.a;
result.b = in.b;
result.c = in.c;
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]));
}
return result;
}
fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
var result : S_tint_packed_vec3;
result.v = __packed_vec3<f32>(in.v);
result.arr = tint_pack_vec3_in_composite(in.arr);
result.a = in.a;
result.b = in.b;
result.c = in.c;
return result;
}
struct S {
v : vec3<f32>,
arr : array<vec3<f32>, 4>,
a : u32,
b : vec4<f32>,
c : array<vec4<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
let x = tint_unpack_vec3_in_composite_1(P);
P = tint_pack_vec3_in_composite_1(x);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Struct_ShaderIO) {
// Test that we do not modify structures that are used for shader IO.
auto* src = R"(
struct S1 {
@location(0) v : vec3<f32>,
}
struct S2 {
@location(0) v : vec3<f32>,
@builtin(position) pos : vec4<f32>,
}
@vertex
fn main(s1 : S1) -> S2 {
let v : vec3<f32> = s1.v;
var s2 : S2;
s2.v = v;
return s2;
}
)";
auto* expect = R"(
struct S1 {
@location(0)
v : vec3<f32>,
}
struct S2 {
@location(0)
v : vec3<f32>,
@builtin(position)
pos : vec4<f32>,
}
@vertex
fn main(s1 : S1) -> S2 {
let v : vec3<f32> = s1.v;
var s2 : S2;
s2.v = v;
return s2;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ModfReturnStruct) {
// Test that we do not try to modify accessors on the anonymous structure returned by modf.
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> output : vec3<f32>;
const values = array(modf(vec3(1.0, 2.0, 3.0)).fract);
@compute @workgroup_size(1)
fn main() {
output = values[0];
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
@group(0) @binding(0) var<storage, read_write> output : __packed_vec3<f32>;
const values = array(modf(vec3(1.0, 2.0, 3.0)).fract);
@compute @workgroup_size(1)
fn main() {
output = __packed_vec3<f32>(values[0]);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ModfReturnStruct_PointerToMember) {
// Test that we can pass a pointer to the vec3 member of the modf return struct to a function
// parameter to which we also pass a pointer to a vec3 member on a host-shareable struct.
auto* src = R"(
struct S {
v : vec3<f32>
}
@group(0) @binding(0) var<storage, read_write> output : S;
fn foo(p : ptr<function, vec3<f32>>) {
(*p) = vec3(1, 2, 3);
}
@compute @workgroup_size(1)
fn main() {
var f : S;
var modf_ret = modf(vec3(1.0, 2.0, 3.0));
foo(&f.v);
foo(&modf_ret.fract);
output.v = modf_ret.fract;
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
struct S_tint_packed_vec3 {
@align(16)
v : __packed_vec3<f32>,
}
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage, read_write> output : S_tint_packed_vec3;
fn foo(p : ptr<function, vec3<f32>>) {
*(p) = vec3(1, 2, 3);
}
@compute @workgroup_size(1)
fn main() {
var f : S;
var modf_ret = modf(vec3(1.0, 2.0, 3.0));
foo(&(f.v));
foo(&(modf_ret.fract));
output.v = __packed_vec3<f32>(modf_ret.fract);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, MultipleStructMembers) {
auto* src = R"(
struct S {
v2_a : vec2<f32>,
v3_a : vec3<f32>,
v4_a : vec4<f32>,
v2_b : vec2<f32>,
v3_b : vec3<f32>,
v4_b : vec4<f32>,
v2_arr : array<vec2<f32>, 4>,
v3_arr : array<vec3<f32>, 4>,
v4_arr : array<vec4<f32>, 4>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let v2_a = P.v2_a;
let v3_a = P.v3_a;
let v4_a = P.v4_a;
let v2_b = P.v2_b;
let v3_b = P.v3_b;
let v4_b = P.v4_b;
let v2_arr : array<vec2<f32>, 4> = P.v2_arr;
let v3_arr : array<vec3<f32>, 4> = P.v3_arr;
let v4_arr : array<vec4<f32>, 4> = P.v4_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 {
v2_a : vec2<f32>,
@align(16)
v3_a : __packed_vec3<f32>,
v4_a : vec4<f32>,
v2_b : vec2<f32>,
@align(16)
v3_b : __packed_vec3<f32>,
v4_b : vec4<f32>,
v2_arr : array<vec2<f32>, 4>,
@align(16)
v3_arr : array<tint_packed_vec3_f32_array_element, 4u>,
v4_arr : array<vec4<f32>, 4>,
}
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);
}
return result;
}
struct S {
v2_a : vec2<f32>,
v3_a : vec3<f32>,
v4_a : vec4<f32>,
v2_b : vec2<f32>,
v3_b : vec3<f32>,
v4_b : vec4<f32>,
v2_arr : array<vec2<f32>, 4>,
v3_arr : array<vec3<f32>, 4>,
v4_arr : array<vec4<f32>, 4>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn f() {
let v2_a = P.v2_a;
let v3_a = vec3<f32>(P.v3_a);
let v4_a = P.v4_a;
let v2_b = P.v2_b;
let v3_b = vec3<f32>(P.v3_b);
let v4_b = P.v4_b;
let v2_arr : array<vec2<f32>, 4> = P.v2_arr;
let v3_arr : array<vec3<f32>, 4> = tint_unpack_vec3_in_composite(P.v3_arr);
let v4_arr : array<vec4<f32>, 4> = P.v4_arr;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Vec3Pointers) {
auto* src = R"(
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
arr_v : array<vec3<f32>, 4>,
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
@group(0) @binding(1) var<storage, read_write> arr_v : array<vec3<f32>, 4>;
@group(0) @binding(2) var<storage, read_write> m : mat3x3<f32>;
@group(0) @binding(3) var<storage, read_write> arr_m : array<mat3x3<f32>, 4>;
@group(0) @binding(4) var<storage, read_write> str : S;
fn f() {
let p_v = &v;
let v = *p_v;
*p_v = v;
let p_arr_v = &arr_v[0];
let arr_v = *p_arr_v;
*p_arr_v = arr_v;
let p_m = &m[0];
let m = *p_m;
*p_m = m;
let p_arr_m = &arr_m[0][1];
let arr_m = *p_arr_m;
*p_arr_m = arr_m;
let p_str_v = &str.v;
let str_v = *p_str_v;
*p_str_v = str_v;
let p_str_arr_v = &str.arr_v[0];
let str_arr_v = *p_str_arr_v;
*p_str_arr_v = str_arr_v;
let p_str_m = &str.m[0];
let str_m = *p_str_m;
*p_str_m = str_m;
let p_str_arr_m = &str.arr_m[0][1];
let str_arr_m = *p_str_arr_m;
*p_str_arr_m = str_arr_m;
}
)";
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 : __packed_vec3<f32>,
@align(16)
m : array<tint_packed_vec3_f32_array_element, 3u>,
@align(16)
arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
@align(16)
arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
}
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
arr_v : array<vec3<f32>, 4>,
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
@group(0) @binding(1) var<storage, read_write> arr_v : array<tint_packed_vec3_f32_array_element, 4u>;
@group(0) @binding(2) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
@group(0) @binding(3) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
@group(0) @binding(4) var<storage, read_write> str : S_tint_packed_vec3;
fn f() {
let p_v = &(v);
let v = vec3<f32>(*(p_v));
*(p_v) = __packed_vec3<f32>(v);
let p_arr_v = &(arr_v[0].elements);
let arr_v = vec3<f32>(*(p_arr_v));
*(p_arr_v) = __packed_vec3<f32>(arr_v);
let p_m = &(m[0].elements);
let m = vec3<f32>(*(p_m));
*(p_m) = __packed_vec3<f32>(m);
let p_arr_m = &(arr_m[0][1].elements);
let arr_m = vec3<f32>(*(p_arr_m));
*(p_arr_m) = __packed_vec3<f32>(arr_m);
let p_str_v = &(str.v);
let str_v = vec3<f32>(*(p_str_v));
*(p_str_v) = __packed_vec3<f32>(str_v);
let p_str_arr_v = &(str.arr_v[0].elements);
let str_arr_v = vec3<f32>(*(p_str_arr_v));
*(p_str_arr_v) = __packed_vec3<f32>(str_arr_v);
let p_str_m = &(str.m[0].elements);
let str_m = vec3<f32>(*(p_str_m));
*(p_str_m) = __packed_vec3<f32>(str_m);
let p_str_arr_m = &(str.arr_m[0][1].elements);
let str_arr_m = vec3<f32>(*(p_str_arr_m));
*(p_str_arr_m) = __packed_vec3<f32>(str_arr_m);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, MatrixPointers) {
auto* src = R"(
struct S {
m : mat3x3<f32>,
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
@group(0) @binding(1) var<storage, read_write> arr_m : array<mat3x3<f32>, 4>;
@group(0) @binding(2) var<storage, read_write> str : S;
fn f() {
let p_m = &m;
let m = *p_m;
*p_m = m;
let p_arr_m = &arr_m[0];
let arr_m = *p_arr_m;
*p_arr_m = arr_m;
let p_str_m = &str.m;
let str_m = *p_str_m;
*p_str_m = str_m;
let p_str_arr_m = &str.arr_m[0];
let str_arr_m = *p_str_arr_m;
*p_str_arr_m = str_arr_m;
}
)";
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)
m : array<tint_packed_vec3_f32_array_element, 3u>,
@align(16)
arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
}
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);
}
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]));
}
return result;
}
struct S {
m : mat3x3<f32>,
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
@group(0) @binding(1) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
@group(0) @binding(2) var<storage, read_write> str : S_tint_packed_vec3;
fn f() {
let p_m = &(m);
let m = tint_unpack_vec3_in_composite(*(p_m));
*(p_m) = tint_pack_vec3_in_composite(m);
let p_arr_m = &(arr_m[0]);
let arr_m = tint_unpack_vec3_in_composite(*(p_arr_m));
*(p_arr_m) = tint_pack_vec3_in_composite(arr_m);
let p_str_m = &(str.m);
let str_m = tint_unpack_vec3_in_composite(*(p_str_m));
*(p_str_m) = tint_pack_vec3_in_composite(str_m);
let p_str_arr_m = &(str.arr_m[0]);
let str_arr_m = tint_unpack_vec3_in_composite(*(p_str_arr_m));
*(p_str_arr_m) = tint_pack_vec3_in_composite(str_arr_m);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ArrayOfVec3Pointers) {
auto* src = R"(
struct S {
arr_v : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> arr_v : array<vec3<f32>, 4>;
@group(0) @binding(1) var<storage, read_write> str : S;
fn f() {
let p_arr_v = &arr_v;
let arr_v = *p_arr_v;
*p_arr_v = arr_v;
let p_str_arr_v = &str.arr_v;
let str_arr_v = *p_str_arr_v;
*p_str_arr_v = str_arr_v;
}
)";
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<tint_packed_vec3_f32_array_element, 4u>,
}
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);
}
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]));
}
return result;
}
struct S {
arr_v : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> arr_v : array<tint_packed_vec3_f32_array_element, 4u>;
@group(0) @binding(1) var<storage, read_write> str : S_tint_packed_vec3;
fn f() {
let p_arr_v = &(arr_v);
let arr_v = tint_unpack_vec3_in_composite(*(p_arr_v));
*(p_arr_v) = tint_pack_vec3_in_composite(arr_v);
let p_str_arr_v = &(str.arr_v);
let str_arr_v = tint_unpack_vec3_in_composite(*(p_str_arr_v));
*(p_str_arr_v) = tint_pack_vec3_in_composite(str_arr_v);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ArrayOfMatrixPointers) {
auto* src = R"(
struct S {
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> arr_m : array<mat3x3<f32>, 4>;
@group(0) @binding(1) var<storage, read_write> str : S;
fn f() {
let p_arr_m = &arr_m;
let arr_m = *p_arr_m;
*p_arr_m = arr_m;
let p_str_arr_m = &str.arr_m;
let str_arr_m = *p_str_arr_m;
*p_str_arr_m = str_arr_m;
}
)";
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_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
}
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);
}
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]);
}
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]));
}
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]);
}
return result;
}
struct S {
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
@group(0) @binding(1) var<storage, read_write> str : S_tint_packed_vec3;
fn f() {
let p_arr_m = &(arr_m);
let arr_m = tint_unpack_vec3_in_composite_1(*(p_arr_m));
*(p_arr_m) = tint_pack_vec3_in_composite_1(arr_m);
let p_str_arr_m = &(str.arr_m);
let str_arr_m = tint_unpack_vec3_in_composite_1(*(p_str_arr_m));
*(p_str_arr_m) = tint_pack_vec3_in_composite_1(str_arr_m);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructPointers) {
auto* src = R"(
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
arr_v : array<vec3<f32>, 4>,
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> str : S;
fn f() {
let p_str = &str;
let str = *p_str;
*p_str = str;
}
)";
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 : __packed_vec3<f32>,
@align(16)
m : array<tint_packed_vec3_f32_array_element, 3u>,
@align(16)
arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
@align(16)
arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
}
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);
}
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);
}
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]);
}
return result;
}
fn tint_unpack_vec3_in_composite_3(in : S_tint_packed_vec3) -> S {
var result : S;
result.v = vec3<f32>(in.v);
result.m = tint_unpack_vec3_in_composite(in.m);
result.arr_v = tint_unpack_vec3_in_composite_1(in.arr_v);
result.arr_m = tint_unpack_vec3_in_composite_2(in.arr_m);
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]));
}
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]));
}
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]);
}
return result;
}
fn tint_pack_vec3_in_composite_3(in : S) -> S_tint_packed_vec3 {
var result : S_tint_packed_vec3;
result.v = __packed_vec3<f32>(in.v);
result.m = tint_pack_vec3_in_composite(in.m);
result.arr_v = tint_pack_vec3_in_composite_1(in.arr_v);
result.arr_m = tint_pack_vec3_in_composite_2(in.arr_m);
return result;
}
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
arr_v : array<vec3<f32>, 4>,
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> str : S_tint_packed_vec3;
fn f() {
let p_str = &(str);
let str = tint_unpack_vec3_in_composite_3(*(p_str));
*(p_str) = tint_pack_vec3_in_composite_3(str);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, VectorPointerParameters) {
auto* src = R"(
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
arr_v : array<vec3<f32>, 4>,
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
@group(0) @binding(1) var<storage, read_write> arr_v : array<vec3<f32>, 4>;
@group(0) @binding(2) var<storage, read_write> m : mat3x3<f32>;
@group(0) @binding(3) var<storage, read_write> arr_m : array<mat3x3<f32>, 4>;
@group(0) @binding(4) var<storage, read_write> str : S;
fn load(p : ptr<storage, vec3<f32>, read_write>) -> vec3<f32> {
return *p;
}
fn store(p : ptr<storage, vec3<f32>, read_write>) {
*p = vec3(1, 2, 3);
}
fn f() {
load(&v);
store(&v);
load(&arr_v[0]);
store(&arr_v[0]);
load(&m[0]);
store(&m[0]);
load(&arr_m[0][1]);
store(&arr_m[0][1]);
load(&str.v);
store(&str.v);
load(&str.arr_v[0]);
store(&str.arr_v[0]);
load(&str.m[0]);
store(&str.m[0]);
load(&str.arr_m[0][1]);
store(&str.arr_m[0][1]);
}
)";
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 : __packed_vec3<f32>,
@align(16)
m : array<tint_packed_vec3_f32_array_element, 3u>,
@align(16)
arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
@align(16)
arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
}
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
arr_v : array<vec3<f32>, 4>,
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
@group(0) @binding(1) var<storage, read_write> arr_v : array<tint_packed_vec3_f32_array_element, 4u>;
@group(0) @binding(2) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
@group(0) @binding(3) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
@group(0) @binding(4) var<storage, read_write> str : S_tint_packed_vec3;
fn load(p : ptr<storage, __packed_vec3<f32>, read_write>) -> vec3<f32> {
return vec3<f32>(*(p));
}
fn store(p : ptr<storage, __packed_vec3<f32>, read_write>) {
*(p) = __packed_vec3<f32>(vec3(1, 2, 3));
}
fn f() {
load(&(v));
store(&(v));
load(&(arr_v[0].elements));
store(&(arr_v[0].elements));
load(&(m[0].elements));
store(&(m[0].elements));
load(&(arr_m[0][1].elements));
store(&(arr_m[0][1].elements));
load(&(str.v));
store(&(str.v));
load(&(str.arr_v[0].elements));
store(&(str.arr_v[0].elements));
load(&(str.m[0].elements));
store(&(str.m[0].elements));
load(&(str.arr_m[0][1].elements));
store(&(str.arr_m[0][1].elements));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, MatrixPointerParameters) {
auto* src = R"(
struct S {
m : mat3x3<f32>,
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
@group(0) @binding(1) var<storage, read_write> arr_m : array<mat3x3<f32>, 4>;
@group(0) @binding(2) var<storage, read_write> str : S;
fn load(p : ptr<storage, mat3x3<f32>, read_write>) -> mat3x3<f32> {
return *p;
}
fn store(p : ptr<storage, mat3x3<f32>, read_write>) {
*p = mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9);
}
fn f() {
load(&m);
store(&m);
load(&arr_m[0]);
store(&arr_m[0]);
load(&str.m);
store(&str.m);
load(&str.arr_m[0]);
store(&str.arr_m[0]);
}
)";
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)
m : array<tint_packed_vec3_f32_array_element, 3u>,
@align(16)
arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
}
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);
}
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]));
}
return result;
}
struct S {
m : mat3x3<f32>,
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
@group(0) @binding(1) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
@group(0) @binding(2) var<storage, read_write> str : S_tint_packed_vec3;
fn load(p : ptr<storage, array<tint_packed_vec3_f32_array_element, 3u>, read_write>) -> mat3x3<f32> {
return tint_unpack_vec3_in_composite(*(p));
}
fn store(p : ptr<storage, array<tint_packed_vec3_f32_array_element, 3u>, read_write>) {
*(p) = tint_pack_vec3_in_composite(mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9));
}
fn f() {
load(&(m));
store(&(m));
load(&(arr_m[0]));
store(&(arr_m[0]));
load(&(str.m));
store(&(str.m));
load(&(str.arr_m[0]));
store(&(str.arr_m[0]));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ArrayOfVectorPointerParameters) {
auto* src = R"(
struct S {
arr_v : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> arr_v : array<vec3<f32>, 4>;
@group(0) @binding(1) var<storage, read_write> str : S;
fn load(p : ptr<storage, array<vec3<f32>, 4>, read_write>) -> array<vec3<f32>, 4> {
return *p;
}
fn store(p : ptr<storage, array<vec3<f32>, 4>, read_write>) {
*p = array(vec3(1.0), vec3(2.0), vec3(3.0), vec3(4.0));
}
fn f() {
load(&arr_v);
store(&arr_v);
load(&str.arr_v);
store(&str.arr_v);
}
)";
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<tint_packed_vec3_f32_array_element, 4u>,
}
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);
}
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]));
}
return result;
}
struct S {
arr_v : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> arr_v : array<tint_packed_vec3_f32_array_element, 4u>;
@group(0) @binding(1) var<storage, read_write> str : S_tint_packed_vec3;
fn load(p : ptr<storage, array<tint_packed_vec3_f32_array_element, 4u>, read_write>) -> array<vec3<f32>, 4> {
return tint_unpack_vec3_in_composite(*(p));
}
fn store(p : ptr<storage, array<tint_packed_vec3_f32_array_element, 4u>, read_write>) {
*(p) = tint_pack_vec3_in_composite(array(vec3(1.0), vec3(2.0), vec3(3.0), vec3(4.0)));
}
fn f() {
load(&(arr_v));
store(&(arr_v));
load(&(str.arr_v));
store(&(str.arr_v));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ArrayOfMatrixPointerParameters) {
auto* src = R"(
struct S {
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> arr_m : array<mat3x3<f32>, 4>;
@group(0) @binding(1) var<storage, read_write> str : S;
fn load(p : ptr<storage, array<mat3x3<f32>, 4>, read_write>) -> array<mat3x3<f32>, 4> {
return *p;
}
fn store(p : ptr<storage, array<mat3x3<f32>, 4>, read_write>) {
*p = array(mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>());
}
fn f() {
load(&arr_m);
store(&arr_m);
load(&str.arr_m);
store(&str.arr_m);
}
)";
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_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
}
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);
}
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]);
}
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]));
}
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]);
}
return result;
}
struct S {
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
@group(0) @binding(1) var<storage, read_write> str : S_tint_packed_vec3;
fn load(p : ptr<storage, array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, read_write>) -> array<mat3x3<f32>, 4> {
return tint_unpack_vec3_in_composite_1(*(p));
}
fn store(p : ptr<storage, array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, read_write>) {
*(p) = tint_pack_vec3_in_composite_1(array(mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>()));
}
fn f() {
load(&(arr_m));
store(&(arr_m));
load(&(str.arr_m));
store(&(str.arr_m));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StructPointerParameters) {
auto* src = R"(
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
arr_v : array<vec3<f32>, 4>,
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> str : S;
fn load(p : ptr<storage, S, read_write>) -> S {
return *p;
}
fn store(p : ptr<storage, S, read_write>) {
*p = S();
}
fn f() {
load(&str);
store(&str);
}
)";
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 : __packed_vec3<f32>,
@align(16)
m : array<tint_packed_vec3_f32_array_element, 3u>,
@align(16)
arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
@align(16)
arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
}
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);
}
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);
}
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]);
}
return result;
}
fn tint_unpack_vec3_in_composite_3(in : S_tint_packed_vec3) -> S {
var result : S;
result.v = vec3<f32>(in.v);
result.m = tint_unpack_vec3_in_composite(in.m);
result.arr_v = tint_unpack_vec3_in_composite_1(in.arr_v);
result.arr_m = tint_unpack_vec3_in_composite_2(in.arr_m);
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]));
}
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]));
}
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]);
}
return result;
}
fn tint_pack_vec3_in_composite_3(in : S) -> S_tint_packed_vec3 {
var result : S_tint_packed_vec3;
result.v = __packed_vec3<f32>(in.v);
result.m = tint_pack_vec3_in_composite(in.m);
result.arr_v = tint_pack_vec3_in_composite_1(in.arr_v);
result.arr_m = tint_pack_vec3_in_composite_2(in.arr_m);
return result;
}
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
arr_v : array<vec3<f32>, 4>,
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> str : S_tint_packed_vec3;
fn load(p : ptr<storage, S_tint_packed_vec3, read_write>) -> S {
return tint_unpack_vec3_in_composite_3(*(p));
}
fn store(p : ptr<storage, S_tint_packed_vec3, read_write>) {
*(p) = tint_pack_vec3_in_composite_3(S());
}
fn f() {
load(&(str));
store(&(str));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, MixedAddressSpace_Struct) {
auto* src = R"(
struct S {
v : vec3<f32>,
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
var f : S;
let v = f.v;
let arr = f.arr;
P = f;
}
)";
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 : __packed_vec3<f32>,
@align(16)
arr : array<tint_packed_vec3_f32_array_element, 4u>,
}
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]));
}
return result;
}
fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
var result : S_tint_packed_vec3;
result.v = __packed_vec3<f32>(in.v);
result.arr = tint_pack_vec3_in_composite(in.arr);
return result;
}
struct S {
v : vec3<f32>,
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
var f : S;
let v = f.v;
let arr = f.arr;
P = tint_pack_vec3_in_composite_1(f);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, MixedAddressSpace_NestedStruct) {
auto* src = R"(
struct S {
v : vec3<f32>,
arr : array<vec3<f32>, 4>,
}
struct Outer {
inner : S,
}
@group(0) @binding(0) var<storage, read_write> P : Outer;
fn f() {
var f : Outer;
let v = f.inner.v;
let arr = f.inner.arr;
P = f;
P.inner = f.inner;
P.inner.v = f.inner.v;
}
)";
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 : __packed_vec3<f32>,
@align(16)
arr : array<tint_packed_vec3_f32_array_element, 4u>,
}
struct Outer_tint_packed_vec3 {
@align(16)
inner : S_tint_packed_vec3,
}
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]));
}
return result;
}
fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
var result : S_tint_packed_vec3;
result.v = __packed_vec3<f32>(in.v);
result.arr = tint_pack_vec3_in_composite(in.arr);
return result;
}
fn tint_pack_vec3_in_composite_2(in : Outer) -> Outer_tint_packed_vec3 {
var result : Outer_tint_packed_vec3;
result.inner = tint_pack_vec3_in_composite_1(in.inner);
return result;
}
struct S {
v : vec3<f32>,
arr : array<vec3<f32>, 4>,
}
struct Outer {
inner : S,
}
@group(0) @binding(0) var<storage, read_write> P : Outer_tint_packed_vec3;
fn f() {
var f : Outer;
let v = f.inner.v;
let arr = f.inner.arr;
P = tint_pack_vec3_in_composite_2(f);
P.inner = tint_pack_vec3_in_composite_1(f.inner);
P.inner.v = __packed_vec3<f32>(f.inner.v);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, MixedAddressSpace_AnotherStructNotShared) {
// Test that we can pass a pointers to a members of both shared and non-shared structs to the
// same function.
auto* src = R"(
struct S {
v : vec3<f32>,
arr : array<vec3<f32>, 4>,
}
struct NotShared {
v : vec3<f32>,
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn g(p : ptr<function, vec3<f32>>) -> vec3<f32> {
return *p;
}
fn f() {
var f1 : S;
var f2 : NotShared;
g(&f1.v);
g(&f1.arr[0]);
g(&f2.v);
g(&f2.arr[0]);
P = f1;
}
)";
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 : __packed_vec3<f32>,
@align(16)
arr : array<tint_packed_vec3_f32_array_element, 4u>,
}
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]));
}
return result;
}
fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
var result : S_tint_packed_vec3;
result.v = __packed_vec3<f32>(in.v);
result.arr = tint_pack_vec3_in_composite(in.arr);
return result;
}
struct S {
v : vec3<f32>,
arr : array<vec3<f32>, 4>,
}
struct NotShared {
v : vec3<f32>,
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn g(p : ptr<function, vec3<f32>>) -> vec3<f32> {
return *(p);
}
fn f() {
var f1 : S;
var f2 : NotShared;
g(&(f1.v));
g(&(f1.arr[0]));
g(&(f2.v));
g(&(f2.arr[0]));
P = tint_pack_vec3_in_composite_1(f1);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, MixedAddressSpace_InitFromLoad_ExplicitVarType) {
auto* src = R"(
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
arr_v : array<vec3<f32>, 4>,
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
var f1 : S = P;
var f2 : vec3<f32> = P.v;
var f3 : mat3x3<f32> = P.m;
var f4 : array<vec3<f32>, 4> = P.arr_v;
var f5 : array<mat3x3<f32>, 4> = P.arr_m;
let v_1 = f1.v;
let v_2 = f2;
let v_3 = f3[0];
let v_4 = f4[1];
let v_5 = f5[2][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 : __packed_vec3<f32>,
@align(16)
m : array<tint_packed_vec3_f32_array_element, 3u>,
@align(16)
arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
@align(16)
arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
}
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);
}
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);
}
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]);
}
return result;
}
fn tint_unpack_vec3_in_composite_3(in : S_tint_packed_vec3) -> S {
var result : S;
result.v = vec3<f32>(in.v);
result.m = tint_unpack_vec3_in_composite(in.m);
result.arr_v = tint_unpack_vec3_in_composite_1(in.arr_v);
result.arr_m = tint_unpack_vec3_in_composite_2(in.arr_m);
return result;
}
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
arr_v : array<vec3<f32>, 4>,
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn f() {
var f1 : S = tint_unpack_vec3_in_composite_3(P);
var f2 : vec3<f32> = vec3<f32>(P.v);
var f3 : mat3x3<f32> = tint_unpack_vec3_in_composite(P.m);
var f4 : array<vec3<f32>, 4> = tint_unpack_vec3_in_composite_1(P.arr_v);
var f5 : array<mat3x3<f32>, 4> = tint_unpack_vec3_in_composite_2(P.arr_m);
let v_1 = f1.v;
let v_2 = f2;
let v_3 = f3[0];
let v_4 = f4[1];
let v_5 = f5[2][2];
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, MixedAddressSpace_InitFromLoad_InferredVarType) {
auto* src = R"(
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
arr_v : array<vec3<f32>, 4>,
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
var f1 = P;
var f2 = P.v;
var f3 = P.m;
var f4 = P.arr_v;
var f5 = P.arr_m;
let v_1 = f1.v;
let v_2 = f2;
let v_3 = f3[0];
let v_4 = f4[1];
let v_5 = f5[2][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 : __packed_vec3<f32>,
@align(16)
m : array<tint_packed_vec3_f32_array_element, 3u>,
@align(16)
arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
@align(16)
arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
}
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);
}
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);
}
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]);
}
return result;
}
fn tint_unpack_vec3_in_composite_3(in : S_tint_packed_vec3) -> S {
var result : S;
result.v = vec3<f32>(in.v);
result.m = tint_unpack_vec3_in_composite(in.m);
result.arr_v = tint_unpack_vec3_in_composite_1(in.arr_v);
result.arr_m = tint_unpack_vec3_in_composite_2(in.arr_m);
return result;
}
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
arr_v : array<vec3<f32>, 4>,
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn f() {
var f1 = tint_unpack_vec3_in_composite_3(P);
var f2 = vec3<f32>(P.v);
var f3 = tint_unpack_vec3_in_composite(P.m);
var f4 = tint_unpack_vec3_in_composite_1(P.arr_v);
var f5 = tint_unpack_vec3_in_composite_2(P.arr_m);
let v_1 = f1.v;
let v_2 = f2;
let v_3 = f3[0];
let v_4 = f4[1];
let v_5 = f5[2][2];
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, MixedAddressSpace_InitFromValue_ExplicitVarType) {
auto* src = R"(
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
arr_v : array<vec3<f32>, 4>,
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
var f1 : S = S();
var f2 : vec3<f32> = vec3<f32>();
var f3 : mat3x3<f32> = mat3x3<f32>();
var f4 : array<vec3<f32>, 4> = array(vec3<f32>(), vec3<f32>(), vec3<f32>(), vec3<f32>());
var f5 : array<mat3x3<f32>, 4> = array(mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>());
let v_1 = f1.v;
let v_2 = f2;
let v_3 = f3[0];
let v_4 = f4[1];
let v_5 = f5[2][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 : __packed_vec3<f32>,
@align(16)
m : array<tint_packed_vec3_f32_array_element, 3u>,
@align(16)
arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
@align(16)
arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
}
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
arr_v : array<vec3<f32>, 4>,
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn f() {
var f1 : S = S();
var f2 : vec3<f32> = vec3<f32>();
var f3 : mat3x3<f32> = mat3x3<f32>();
var f4 : array<vec3<f32>, 4> = array(vec3<f32>(), vec3<f32>(), vec3<f32>(), vec3<f32>());
var f5 : array<mat3x3<f32>, 4> = array(mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>());
let v_1 = f1.v;
let v_2 = f2;
let v_3 = f3[0];
let v_4 = f4[1];
let v_5 = f5[2][2];
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, MixedAddressSpace_InitFromValue_InferredVarType) {
auto* src = R"(
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
arr_v : array<vec3<f32>, 4>,
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
var f1 = S();
var f2 = vec3<f32>();
var f3 = mat3x3<f32>();
var f4 = array(vec3<f32>(), vec3<f32>(), vec3<f32>(), vec3<f32>());
var f5 = array(mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>());
let v_1 = f1.v;
let v_2 = f2;
let v_3 = f3[0];
let v_4 = f4[1];
let v_5 = f5[2][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 : __packed_vec3<f32>,
@align(16)
m : array<tint_packed_vec3_f32_array_element, 3u>,
@align(16)
arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
@align(16)
arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
}
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
arr_v : array<vec3<f32>, 4>,
arr_m : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn f() {
var f1 = S();
var f2 = vec3<f32>();
var f3 = mat3x3<f32>();
var f4 = array(vec3<f32>(), vec3<f32>(), vec3<f32>(), vec3<f32>());
var f5 = array(mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>());
let v_1 = f1.v;
let v_2 = f2;
let v_3 = f3[0];
let v_4 = f4[1];
let v_5 = f5[2][2];
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, MixedAddressSpace_Pointers_Function) {
auto* src = R"(
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
var f1 : S = P;
var f2 : vec3<f32> = P.v;
var f3 : array<vec3<f32>, 4>;
var f4 : mat3x3<f32> = P.m;
let pv_1 : ptr<function, vec3<f32>> = &f1.v;
let pv_2 : ptr<function, vec3<f32>> = &f2;
let pv_3 : ptr<function, vec3<f32>> = &f3[0];
let pv_4 : ptr<function, mat3x3<f32>> = &f1.m;
let pv_5 : ptr<function, mat3x3<f32>> = &f4;
}
)";
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 : __packed_vec3<f32>,
@align(16)
m : array<tint_packed_vec3_f32_array_element, 3u>,
}
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);
}
return result;
}
fn tint_unpack_vec3_in_composite_1(in : S_tint_packed_vec3) -> S {
var result : S;
result.v = vec3<f32>(in.v);
result.m = tint_unpack_vec3_in_composite(in.m);
return result;
}
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn f() {
var f1 : S = tint_unpack_vec3_in_composite_1(P);
var f2 : vec3<f32> = vec3<f32>(P.v);
var f3 : array<vec3<f32>, 4>;
var f4 : mat3x3<f32> = tint_unpack_vec3_in_composite(P.m);
let pv_1 : ptr<function, vec3<f32>> = &(f1.v);
let pv_2 : ptr<function, vec3<f32>> = &(f2);
let pv_3 : ptr<function, vec3<f32>> = &(f3[0]);
let pv_4 : ptr<function, mat3x3<f32>> = &(f1.m);
let pv_5 : ptr<function, mat3x3<f32>> = &(f4);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, MixedAddressSpace_Pointers_Private) {
auto* src = R"(
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
var<private> p1 : S;
var<private> p2 : vec3<f32>;
var<private> p3 : array<vec3<f32>, 4>;
var<private> p4 : mat3x3<f32>;
fn f() {
let pv_1 : ptr<private, vec3<f32>> = &p1.v;
let pv_2 : ptr<private, vec3<f32>> = &p2;
let pv_3 : ptr<private, vec3<f32>> = &p3[0];
let pv_4 : ptr<private, mat3x3<f32>> = &p1.m;
let pv_5 : ptr<private, mat3x3<f32>> = &p4;
}
)";
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 : __packed_vec3<f32>,
@align(16)
m : array<tint_packed_vec3_f32_array_element, 3u>,
}
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
var<private> p1 : S;
var<private> p2 : vec3<f32>;
var<private> p3 : array<vec3<f32>, 4>;
var<private> p4 : mat3x3<f32>;
fn f() {
let pv_1 : ptr<private, vec3<f32>> = &(p1.v);
let pv_2 : ptr<private, vec3<f32>> = &(p2);
let pv_3 : ptr<private, vec3<f32>> = &(p3[0]);
let pv_4 : ptr<private, mat3x3<f32>> = &(p1.m);
let pv_5 : ptr<private, mat3x3<f32>> = &(p4);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, MixedAddressSpace_Pointers_Workgroup) {
auto* src = R"(
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
var<workgroup> w1 : S;
var<workgroup> w2 : vec3<f32>;
var<workgroup> w3 : array<vec3<f32>, 4>;
var<workgroup> w4 : mat3x3<f32>;
fn f() {
let pv_1 : ptr<workgroup, vec3<f32>> = &w1.v;
let pv_2 : ptr<workgroup, vec3<f32>> = &w2;
let pv_3 : ptr<workgroup, vec3<f32>> = &w3[0];
let pv_4 : ptr<workgroup, mat3x3<f32>> = &w1.m;
let pv_5 : ptr<workgroup, mat3x3<f32>> = &w4;
}
)";
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 : __packed_vec3<f32>,
@align(16)
m : array<tint_packed_vec3_f32_array_element, 3u>,
}
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
var<workgroup> w1 : S;
var<workgroup> w2 : vec3<f32>;
var<workgroup> w3 : array<vec3<f32>, 4>;
var<workgroup> w4 : mat3x3<f32>;
fn f() {
let pv_1 : ptr<workgroup, vec3<f32>> = &(w1.v);
let pv_2 : ptr<workgroup, vec3<f32>> = &(w2);
let pv_3 : ptr<workgroup, vec3<f32>> = &(w3[0]);
let pv_4 : ptr<workgroup, mat3x3<f32>> = &(w1.m);
let pv_5 : ptr<workgroup, mat3x3<f32>> = &(w4);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, MixedAddressSpace_PointerParameters) {
auto* src = R"(
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn g_v(p : ptr<function, vec3<f32>>) -> vec3<f32> {
return *p;
}
fn g_m(p : ptr<function, mat3x3<f32>>) -> mat3x3<f32> {
return *p;
}
fn f() {
var f1 : S = P;
var f2 : vec3<f32> = P.v;
var f3 : array<vec3<f32>, 4>;
var f4 : mat3x3<f32> = P.m;
g_v(&f1.v);
g_v(&f2);
g_v(&f3[0]);
g_m(&f1.m);
g_m(&f4);
}
)";
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 : __packed_vec3<f32>,
@align(16)
m : array<tint_packed_vec3_f32_array_element, 3u>,
}
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);
}
return result;
}
fn tint_unpack_vec3_in_composite_1(in : S_tint_packed_vec3) -> S {
var result : S;
result.v = vec3<f32>(in.v);
result.m = tint_unpack_vec3_in_composite(in.m);
return result;
}
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
fn g_v(p : ptr<function, vec3<f32>>) -> vec3<f32> {
return *(p);
}
fn g_m(p : ptr<function, mat3x3<f32>>) -> mat3x3<f32> {
return *(p);
}
fn f() {
var f1 : S = tint_unpack_vec3_in_composite_1(P);
var f2 : vec3<f32> = vec3<f32>(P.v);
var f3 : array<vec3<f32>, 4>;
var f4 : mat3x3<f32> = tint_unpack_vec3_in_composite(P.m);
g_v(&(f1.v));
g_v(&(f2));
g_v(&(f3[0]));
g_m(&(f1.m));
g_m(&(f4));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, WriteVec3Swizzle_FromRef) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
fn f() {
v = v.zyx;
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
fn f() {
v = __packed_vec3<f32>(vec3<f32>(v).zyx);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, WriteVec3Swizzle_FromValue) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
fn f() {
v = vec3f(1, 2, 3).zyx;
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
fn f() {
v = __packed_vec3<f32>(vec3f(1, 2, 3).zyx);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, WriteVec3Component_FromPackedValueIndexAccessor) {
auto* src = R"(
struct S {
v : vec3<f32>
}
@group(0) @binding(0) var<storage, read_write> s : S;
fn g() -> S {
return S();
}
fn f() {
s.v[0] = g().v[1];
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
struct S_tint_packed_vec3 {
@align(16)
v : __packed_vec3<f32>,
}
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage, read_write> s : S_tint_packed_vec3;
fn g() -> S {
return S();
}
fn f() {
s.v[0] = g().v[1];
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ExtractVec3FromStructValueExpression) {
auto* src = R"(
struct S {
v : vec3<f32>
}
@group(0) @binding(0) var<storage, read_write> buffer : S;
fn f() {
var v_var : vec3<f32> = S().v;
let v_let : vec3<f32> = S().v;
v_var = S().v;
v_var = S().v * 2.0;
buffer = S(S().v);
}
)";
auto* expect = R"(
enable chromium_internal_relaxed_uniform_layout;
struct S_tint_packed_vec3 {
@align(16)
v : __packed_vec3<f32>,
}
fn tint_pack_vec3_in_composite(in : S) -> S_tint_packed_vec3 {
var result : S_tint_packed_vec3;
result.v = __packed_vec3<f32>(in.v);
return result;
}
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage, read_write> buffer : S_tint_packed_vec3;
fn f() {
var v_var : vec3<f32> = S().v;
let v_let : vec3<f32> = S().v;
v_var = S().v;
v_var = (S().v * 2.0);
buffer = tint_pack_vec3_in_composite(S(S().v));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ExtractArrayOfVec3FromStructValueExpression) {
auto* src = R"(
struct S {
arr : array<vec3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> buffer : S;
fn f() {
var arr_var : array<vec3<f32>, 4> = S().arr;
let arr_let : array<vec3<f32>, 4> = S().arr;
arr_var = S().arr;
arr_var[0] = S().arr[0] * 2.0;
buffer = S(S().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, 4u>,
}
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]));
}
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>, 4>,
}
@group(0) @binding(0) var<storage, read_write> buffer : S_tint_packed_vec3;
fn f() {
var arr_var : array<vec3<f32>, 4> = S().arr;
let arr_let : array<vec3<f32>, 4> = S().arr;
arr_var = S().arr;
arr_var[0] = (S().arr[0] * 2.0);
buffer = tint_pack_vec3_in_composite_1(S(S().arr));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ExtractNestedArrayFromStructValueExpression) {
auto* src = R"(
struct S {
arr : array<array<vec3<f32>, 4>, 4>,
}
@group(0) @binding(0) var<storage, read_write> buffer : S;
fn f() {
var arr_var : array<array<vec3<f32>, 4>, 4> = S().arr;
var inner_var : array<vec3<f32>, 4> = S().arr[0];
let arr_let : array<array<vec3<f32>, 4>, 4> = S().arr;
arr_var = S().arr;
inner_var = S().arr[0];
arr_var[0][0] = S().arr[0][0] * 2.0;
buffer = S(S().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<array<tint_packed_vec3_f32_array_element, 4u>, 4u>,
}
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]));
}
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]);
}
return result;
}
fn tint_pack_vec3_in_composite_2(in : S) -> S_tint_packed_vec3 {
var result : S_tint_packed_vec3;
result.arr = tint_pack_vec3_in_composite_1(in.arr);
return result;
}
struct S {
arr : array<array<vec3<f32>, 4>, 4>,
}
@group(0) @binding(0) var<storage, read_write> buffer : S_tint_packed_vec3;
fn f() {
var arr_var : array<array<vec3<f32>, 4>, 4> = S().arr;
var inner_var : array<vec3<f32>, 4> = S().arr[0];
let arr_let : array<array<vec3<f32>, 4>, 4> = S().arr;
arr_var = S().arr;
inner_var = S().arr[0];
arr_var[0][0] = (S().arr[0][0] * 2.0);
buffer = tint_pack_vec3_in_composite_2(S(S().arr));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ExtractMatrixFromStructValueExpression) {
auto* src = R"(
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage, read_write> buffer : S;
fn f() {
var m_var : mat3x3<f32> = S().m;
let m_let : mat3x3<f32> = S().m;
m_var = S().m;
m_var = S().m * 2.0;
buffer = S(S().m);
}
)";
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)
m : array<tint_packed_vec3_f32_array_element, 3u>,
}
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]));
}
return result;
}
fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
var result : S_tint_packed_vec3;
result.m = tint_pack_vec3_in_composite(in.m);
return result;
}
struct S {
m : mat3x3<f32>,
}
@group(0) @binding(0) var<storage, read_write> buffer : S_tint_packed_vec3;
fn f() {
var m_var : mat3x3<f32> = S().m;
let m_let : mat3x3<f32> = S().m;
m_var = S().m;
m_var = (S().m * 2.0);
buffer = tint_pack_vec3_in_composite_1(S(S().m));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ExtractArrayOfMatrixFromStructValueExpression) {
auto* src = R"(
struct S {
arr : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> buffer : S;
fn f() {
var arr_var : array<mat3x3<f32>, 4> = S().arr;
let arr_let : array<mat3x3<f32>, 4> = S().arr;
arr_var = S().arr;
arr_var[0] = S().arr[0] * 2.0;
buffer = S(S().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<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
}
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]));
}
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]);
}
return result;
}
fn tint_pack_vec3_in_composite_2(in : S) -> S_tint_packed_vec3 {
var result : S_tint_packed_vec3;
result.arr = tint_pack_vec3_in_composite_1(in.arr);
return result;
}
struct S {
arr : array<mat3x3<f32>, 4>,
}
@group(0) @binding(0) var<storage, read_write> buffer : S_tint_packed_vec3;
fn f() {
var arr_var : array<mat3x3<f32>, 4> = S().arr;
let arr_let : array<mat3x3<f32>, 4> = S().arr;
arr_var = S().arr;
arr_var[0] = (S().arr[0] * 2.0);
buffer = tint_pack_vec3_in_composite_2(S(S().arr));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, NestedArrays_Let) {
auto* src = R"(
struct S {
arr_v : array<array<vec3<f32>, 4>, 4>,
arr_m : array<array<mat3x3<f32>, 4>, 4>,
}
@group(0) @binding(0) var<storage, read_write> arr_s : array<S, 4>;
fn f() {
let full_let : array<S, 4> = arr_s;
let struct_let : S = arr_s[0];
let outer_arr_v_let : array<array<vec3<f32>, 4>, 4> = arr_s[0].arr_v;
let inner_arr_v_let : array<vec3<f32>, 4> = arr_s[0].arr_v[1];
let v_let : vec3<f32> = arr_s[0].arr_v[1][2];
let v_element_let : f32 = arr_s[0].arr_v[1][2].y;
let outer_arr_m_let : array<array<mat3x3<f32>, 4>, 4> = arr_s[0].arr_m;
let inner_arr_m_let : array<mat3x3<f32>, 4> = arr_s[0].arr_m[1];
let m_let : mat3x3<f32> = arr_s[0].arr_m[1][2];
let m_col_let : vec3<f32> = arr_s[0].arr_m[1][2][0];
let m_element_let : 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, 4u>, 4u>,
@align(16)
arr_m : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, 4u>,
}
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);
}
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]);
}
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);
}
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]);
}
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]);
}
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, 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]);
}
return result;
}
struct S {
arr_v : array<array<vec3<f32>, 4>, 4>,
arr_m : array<array<mat3x3<f32>, 4>, 4>,
}
@group(0) @binding(0) var<storage, read_write> arr_s : array<S_tint_packed_vec3, 4u>;
fn f() {
let full_let : array<S, 4> = tint_unpack_vec3_in_composite_6(arr_s);
let struct_let : S = tint_unpack_vec3_in_composite_5(arr_s[0]);
let outer_arr_v_let : array<array<vec3<f32>, 4>, 4> = tint_unpack_vec3_in_composite_1(arr_s[0].arr_v);
let inner_arr_v_let : array<vec3<f32>, 4> = tint_unpack_vec3_in_composite(arr_s[0].arr_v[1]);
let v_let : vec3<f32> = vec3<f32>(arr_s[0].arr_v[1][2].elements);
let v_element_let : f32 = arr_s[0].arr_v[1][2].elements.y;
let outer_arr_m_let : array<array<mat3x3<f32>, 4>, 4> = tint_unpack_vec3_in_composite_4(arr_s[0].arr_m);
let inner_arr_m_let : array<mat3x3<f32>, 4> = tint_unpack_vec3_in_composite_3(arr_s[0].arr_m[1]);
let m_let : mat3x3<f32> = tint_unpack_vec3_in_composite_2(arr_s[0].arr_m[1][2]);
let m_col_let : vec3<f32> = vec3<f32>(arr_s[0].arr_m[1][2][0].elements);
let m_element_let : 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_VarInit) {
auto* src = R"(
struct S {
arr_v : array<array<vec3<f32>, 4>, 4>,
arr_m : array<array<mat3x3<f32>, 4>, 4>,
}
@group(0) @binding(0) var<storage, read_write> arr_s : array<S, 4>;
fn f() {
var full_var : array<S, 4> = arr_s;
var struct_var : S = arr_s[0];
var outer_arr_v_var : array<array<vec3<f32>, 4>, 4> = arr_s[0].arr_v;
var inner_arr_v_var : array<vec3<f32>, 4> = 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>, 4>, 4> = arr_s[0].arr_m;
var inner_arr_m_var : array<mat3x3<f32>, 4> = 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, 4u>, 4u>,
@align(16)
arr_m : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, 4u>,
}
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);
}
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]);
}
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);
}
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]);
}
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]);
}
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, 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]);
}
return result;
}
struct S {
arr_v : array<array<vec3<f32>, 4>, 4>,
arr_m : array<array<mat3x3<f32>, 4>, 4>,
}
@group(0) @binding(0) var<storage, read_write> arr_s : array<S_tint_packed_vec3, 4u>;
fn f() {
var full_var : array<S, 4> = 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>, 4>, 4> = tint_unpack_vec3_in_composite_1(arr_s[0].arr_v);
var inner_arr_v_var : array<vec3<f32>, 4> = 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>, 4>, 4> = tint_unpack_vec3_in_composite_4(arr_s[0].arr_m);
var inner_arr_m_var : array<mat3x3<f32>, 4> = 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) {
auto* src = R"(
struct S {
arr_v : array<array<vec3<f32>, 4>, 4>,
arr_m : array<array<mat3x3<f32>, 4>, 4>,
}
@group(0) @binding(0) var<storage, read_write> arr_s : array<S, 4>;
fn f() {
var full_var : array<S, 4>;
var struct_var : S;
var outer_arr_v_var : array<array<vec3<f32>, 4>, 4>;
var inner_arr_v_var : array<vec3<f32>, 4>;
var v_var : vec3<f32>;
var v_element_var : f32;
var outer_arr_m_var : array<array<mat3x3<f32>, 4>, 4>;
var inner_arr_m_var : array<mat3x3<f32>, 4>;
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, 4u>, 4u>,
@align(16)
arr_m : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, 4u>,
}
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);
}
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]);
}
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);
}
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]);
}
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]);
}
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, 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]);
}
return result;
}
struct S {
arr_v : array<array<vec3<f32>, 4>, 4>,
arr_m : array<array<mat3x3<f32>, 4>, 4>,
}
@group(0) @binding(0) var<storage, read_write> arr_s : array<S_tint_packed_vec3, 4u>;
fn f() {
var full_var : array<S, 4>;
var struct_var : S;
var outer_arr_v_var : array<array<vec3<f32>, 4>, 4>;
var inner_arr_v_var : array<vec3<f32>, 4>;
var v_var : vec3<f32>;
var v_element_var : f32;
var outer_arr_m_var : array<array<mat3x3<f32>, 4>, 4>;
var inner_arr_m_var : array<mat3x3<f32>, 4>;
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 {
arr : array<vec3<f32>>,
}
@group(0) @binding(0) var<storage, read_write> arr_v : array<vec3<f32>>;
@group(0) @binding(1) var<storage, read_write> s : S;
fn main() {
s.arr[0] = arr_v[0];
}
)";
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>,
}
struct S {
arr : array<vec3<f32>>,
}
@group(0) @binding(0) var<storage, read_write> arr_v : array<tint_packed_vec3_f32_array_element>;
@group(0) @binding(1) var<storage, read_write> s : S_tint_packed_vec3;
fn main() {
s.arr[0].elements = arr_v[0].elements;
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Mat3x3_F16_Uniform) {
// Test that array element alignment validation rules do not trigger when we rewrite an f16
// matrix into an array of vec3s in uniform storage.
auto* src = R"(
enable f16;
@group(0) @binding(0) var<uniform> m : mat3x3<f16>;
fn g(p : ptr<uniform, mat3x3<f16>>) -> vec3<f16> {
return (*p)[0] + vec3<f16>(1);
}
fn f() {
let v = g(&m);
}
)";
auto* expect =
R"(
enable chromium_internal_relaxed_uniform_layout;
enable f16;
struct tint_packed_vec3_f16_array_element {
@align(8)
elements : __packed_vec3<f16>,
}
@group(0) @binding(0) var<uniform> m : array<tint_packed_vec3_f16_array_element, 3u>;
fn g(p : ptr<uniform, array<tint_packed_vec3_f16_array_element, 3u>>) -> vec3<f16> {
return (vec3<f16>((*(p))[0].elements) + vec3<f16>(1));
}
fn f() {
let v = g(&(m));
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, MultipleComponentTypes_StructMembers) {
auto* src = R"(
enable f16;
struct S {
f : vec3f,
h : vec3h,
i : vec3i,
u : vec3u,
}
@group(0) @binding(0) var<storage, read_write> s : S;
fn f() {
let f = s.f;
let h = s.h;
let i = s.i;
let u = s.u;
}
)";
auto* expect =
R"(
enable chromium_internal_relaxed_uniform_layout;
enable f16;
struct S_tint_packed_vec3 {
@align(16)
f : __packed_vec3<f32>,
@align(8)
h : __packed_vec3<f16>,
@align(16)
i : __packed_vec3<i32>,
@align(16)
u : __packed_vec3<u32>,
}
struct S {
f : vec3f,
h : vec3h,
i : vec3i,
u : vec3u,
}
@group(0) @binding(0) var<storage, read_write> s : S_tint_packed_vec3;
fn f() {
let f = vec3<f32>(s.f);
let h = vec3<f16>(s.h);
let i = vec3<i32>(s.i);
let u = vec3<u32>(s.u);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, MultipleComponentTypes_ArrayElement) {
auto* src = R"(
enable f16;
@group(0) @binding(0) var<storage, read_write> arr_f : array<vec3f>;
@group(0) @binding(1) var<storage, read_write> arr_h : array<vec3h>;
@group(0) @binding(2) var<storage, read_write> arr_i : array<vec3i>;
@group(0) @binding(3) var<storage, read_write> arr_u : array<vec3u>;
fn main() {
let f = arr_f[0];
let h = arr_h[0];
let i = arr_i[0];
let u = arr_u[0];
}
)";
auto* expect =
R"(
enable chromium_internal_relaxed_uniform_layout;
enable f16;
struct tint_packed_vec3_f32_array_element {
@align(16)
elements : __packed_vec3<f32>,
}
struct tint_packed_vec3_f16_array_element {
@align(8)
elements : __packed_vec3<f16>,
}
struct tint_packed_vec3_i32_array_element {
@align(16)
elements : __packed_vec3<i32>,
}
struct tint_packed_vec3_u32_array_element {
@align(16)
elements : __packed_vec3<u32>,
}
@group(0) @binding(0) var<storage, read_write> arr_f : array<tint_packed_vec3_f32_array_element>;
@group(0) @binding(1) var<storage, read_write> arr_h : array<tint_packed_vec3_f16_array_element>;
@group(0) @binding(2) var<storage, read_write> arr_i : array<tint_packed_vec3_i32_array_element>;
@group(0) @binding(3) var<storage, read_write> arr_u : array<tint_packed_vec3_u32_array_element>;
fn main() {
let f = vec3<f32>(arr_f[0].elements);
let h = vec3<f16>(arr_h[0].elements);
let i = vec3<i32>(arr_i[0].elements);
let u = vec3<u32>(arr_u[0].elements);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Arithmetic_FromRef) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> buffer_v : vec3<f32>;
@group(0) @binding(1) var<storage, read_write> buffer_m : mat3x3<f32>;
@group(0) @binding(2) var<storage, read_write> buffer_arr_v : array<vec3<f32>, 4>;
@group(0) @binding(3) var<storage, read_write> buffer_arr_m : array<mat3x3<f32>, 4>;
@group(0) @binding(4) var<storage, read_write> buffer_nested_arr_v : array<array<vec3<f32>, 4>, 4>;
fn f() {
var v : vec3<f32> = buffer_v * 2;
v = -v;
v = buffer_m * v;
v = buffer_m[0] + v;
v = buffer_arr_v[0] + v;
v = buffer_arr_m[0] * v;
v = buffer_arr_m[0][1] + v;
v = buffer_nested_arr_v[0][0] + v;
}
)";
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>;
for(var i : u32; (i < 3u); i = (i + 1)) {
result[i] = vec3<f32>(in[i].elements);
}
return result;
}
@group(0) @binding(0) var<storage, read_write> buffer_v : __packed_vec3<f32>;
@group(0) @binding(1) var<storage, read_write> buffer_m : array<tint_packed_vec3_f32_array_element, 3u>;
@group(0) @binding(2) var<storage, read_write> buffer_arr_v : array<tint_packed_vec3_f32_array_element, 4u>;
@group(0) @binding(3) var<storage, read_write> buffer_arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
@group(0) @binding(4) var<storage, read_write> buffer_nested_arr_v : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>;
fn f() {
var v : vec3<f32> = (vec3<f32>(buffer_v) * 2);
v = -(v);
v = (tint_unpack_vec3_in_composite(buffer_m) * v);
v = (vec3<f32>(buffer_m[0].elements) + v);
v = (vec3<f32>(buffer_arr_v[0].elements) + v);
v = (tint_unpack_vec3_in_composite(buffer_arr_m[0]) * v);
v = (vec3<f32>(buffer_arr_m[0][1].elements) + v);
v = (vec3<f32>(buffer_nested_arr_v[0][0].elements) + v);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Arithmetic_FromValue) {
auto* src = R"(
@group(0) @binding(0) var<storage, read_write> buffer_v : vec3f;
fn f() {
var v : vec3f = buffer_v;
v = -vec3f(1, 2, 3);
v = mat3x3f() * v;
v = mat3x3f()[0] + v;
v = array<vec3f, 4>()[0] + v;
v = array<mat3x3f, 4>()[0] * v;
v = array<mat3x3f, 4>()[0][1] + v;
v = array<array<vec3f, 4>, 4>()[0][0] + v;
}
)";
auto* expect =
R"(
enable chromium_internal_relaxed_uniform_layout;
@group(0) @binding(0) var<storage, read_write> buffer_v : __packed_vec3<f32>;
fn f() {
var v : vec3f = vec3<f32>(buffer_v);
v = -(vec3f(1, 2, 3));
v = (mat3x3f() * v);
v = (mat3x3f()[0] + v);
v = (array<vec3f, 4>()[0] + v);
v = (array<mat3x3f, 4>()[0] * v);
v = (array<mat3x3f, 4>()[0][1] + v);
v = (array<array<vec3f, 4>, 4>()[0][0] + v);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Arithmetic_FromRefStruct) {
auto* src = R"(
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
arr_v : array<vec3<f32>, 4>,
arr_m : array<mat3x3<f32>, 4>,
nested_arr_v : array<array<vec3<f32>, 4>, 4>,
}
@group(0) @binding(0) var<storage, read_write> buffer : S;
fn f() {
var v : vec3<f32> = buffer.v * 2;
v = -v;
v = buffer.m * v;
v = buffer.m[0] + v;
v = buffer.arr_v[0] + v;
v = buffer.arr_m[0] * v;
v = buffer.arr_m[0][1] + v;
v = buffer.nested_arr_v[0][0] + v;
}
)";
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 : __packed_vec3<f32>,
@align(16)
m : array<tint_packed_vec3_f32_array_element, 3u>,
@align(16)
arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
@align(16)
arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
@align(16)
nested_arr_v : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>,
}
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);
}
return result;
}
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
arr_v : array<vec3<f32>, 4>,
arr_m : array<mat3x3<f32>, 4>,
nested_arr_v : array<array<vec3<f32>, 4>, 4>,
}
@group(0) @binding(0) var<storage, read_write> buffer : S_tint_packed_vec3;
fn f() {
var v : vec3<f32> = (vec3<f32>(buffer.v) * 2);
v = -(v);
v = (tint_unpack_vec3_in_composite(buffer.m) * v);
v = (vec3<f32>(buffer.m[0].elements) + v);
v = (vec3<f32>(buffer.arr_v[0].elements) + v);
v = (tint_unpack_vec3_in_composite(buffer.arr_m[0]) * v);
v = (vec3<f32>(buffer.arr_m[0][1].elements) + v);
v = (vec3<f32>(buffer.nested_arr_v[0][0].elements) + v);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Arithmetic_FromValueStruct) {
auto* src = R"(
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
arr_v : array<vec3<f32>, 4>,
arr_m : array<mat3x3<f32>, 4>,
nested_arr_v : array<array<vec3<f32>, 4>, 4>,
}
@group(0) @binding(0) var<storage, read_write> buffer : S;
fn f() {
var v : vec3<f32> = S().v;
v = -S().v;
v = S().m * v;
v = S().m[0] + v;
v = S().arr_v[0] + v;
v = S().arr_m[0] * v;
v = S().arr_m[0][1] + v;
v = S().nested_arr_v[0][0] + v;
}
)";
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 : __packed_vec3<f32>,
@align(16)
m : array<tint_packed_vec3_f32_array_element, 3u>,
@align(16)
arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
@align(16)
arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
@align(16)
nested_arr_v : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>,
}
struct S {
v : vec3<f32>,
m : mat3x3<f32>,
arr_v : array<vec3<f32>, 4>,
arr_m : array<mat3x3<f32>, 4>,
nested_arr_v : array<array<vec3<f32>, 4>, 4>,
}
@group(0) @binding(0) var<storage, read_write> buffer : S_tint_packed_vec3;
fn f() {
var v : vec3<f32> = S().v;
v = -(S().v);
v = (S().m * v);
v = (S().m[0] + v);
v = (S().arr_v[0] + v);
v = (S().arr_m[0] * v);
v = (S().arr_m[0][1] + v);
v = (S().nested_arr_v[0][0] + v);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, Aliases) {
auto* src = R"(
alias VecArray = array<vec3<f32>, 4>;
alias MatArray = array<mat3x3<f32>, 4>;
alias NestedArray = array<VecArray, 4>;
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, 4u>,
@align(16)
m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
@align(16)
n : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>,
}
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);
}
return result;
}
alias VecArray = array<vec3<f32>, 4>;
alias MatArray = array<mat3x3<f32>, 4>;
alias NestedArray = array<VecArray, 4>;
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, 4u>;
@group(0) @binding(2) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
@group(0) @binding(3) var<storage, read_write> arr_n : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>;
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.
auto* src = R"(
struct S {
vf : vec3<f32>,
af : array<vec3<f32>, 4>,
vb : vec3<bool>,
ab : array<vec3<bool>, 4>,
}
// Create a vec3 storage buffer so that the transform is not skipped.
@group(0) @binding(0) var<storage, read_write> buffer : vec3<f32>;
fn f() {
var f : S;
f.vf = buffer;
buffer = f.af[0];
}
)";
auto* expect =
R"(
enable chromium_internal_relaxed_uniform_layout;
struct S {
vf : vec3<f32>,
af : array<vec3<f32>, 4>,
vb : vec3<bool>,
ab : array<vec3<bool>, 4>,
}
@group(0) @binding(0) var<storage, read_write> buffer : __packed_vec3<f32>;
fn f() {
var f : S;
f.vf = vec3<f32>(buffer);
buffer = __packed_vec3<f32>(f.af[0]);
}
)";
ast::transform::DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
} // namespace
} // namespace tint::msl::writer