blob: 0f5c92e82ab2a7ed4e986d849766a4e8d65bd343 [file] [log] [blame] [edit]
// Copyright 2022 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/tint/transform/packed_vec3.h"
#include <string>
#include <utility>
#include <vector>
#include "src/tint/transform/test_helper.h"
#include "src/tint/utils/string.h"
namespace tint::transform {
namespace {
using PackedVec3Test = TransformTest;
TEST_F(PackedVec3Test, ShouldRun_EmptyModule) {
auto* src = R"()";
EXPECT_FALSE(ShouldRun<PackedVec3>(src));
}
TEST_F(PackedVec3Test, ShouldRun_NonHostSharableStruct) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
fn f() {
var v : S; // function address-space - not host sharable
}
)";
EXPECT_FALSE(ShouldRun<PackedVec3>(src));
}
TEST_F(PackedVec3Test, ShouldRun_Vec4Vec2) {
auto* src = R"(
struct S {
v4 : vec4<f32>,
v2 : vec2<f32>,
}
@group(0) @binding(0) var<uniform> P : S; // Host sharable
)";
EXPECT_FALSE(ShouldRun<PackedVec3>(src));
}
TEST_F(PackedVec3Test, ShouldRun_HostSharableStruct) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<uniform> P : S; // Host sharable
)";
EXPECT_TRUE(ShouldRun<PackedVec3>(src));
}
TEST_F(PackedVec3Test, UniformAddressSpace) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<uniform> P : S;
fn f() {
let x = P.v;
}
)";
auto* expect = R"(
struct S {
@internal(packed_vector)
v : vec3<f32>,
}
@group(0) @binding(0) var<uniform> P : S;
fn f() {
let x = vec3<f32>(P.v);
}
)";
DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, StorageAddressSpace) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P.v;
}
)";
auto* expect = R"(
struct S {
@internal(packed_vector)
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = vec3<f32>(P.v);
}
)";
DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ExistingMemberAttributes) {
auto* src = R"(
struct S {
@align(32) @size(64) v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P.v;
}
)";
auto* expect = R"(
struct S {
@internal(packed_vector) @align(32) @size(64)
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = vec3<f32>(P.v);
}
)";
DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, MultipleVectors) {
auto* src = R"(
struct S {
v2_a : vec2<f32>,
v3_a : vec3<f32>,
v4_a : vec4<f32>,
v2_b : vec2<f32>,
v3_b : vec3<f32>,
v4_b : vec4<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let v2_a = P.v2_a;
let v3_a = P.v3_a;
let v4_a = P.v4_a;
let v2_b = P.v2_b;
let v3_b = P.v3_b;
let v4_b = P.v4_b;
}
)";
auto* expect = R"(
struct S {
v2_a : vec2<f32>,
@internal(packed_vector)
v3_a : vec3<f32>,
v4_a : vec4<f32>,
v2_b : vec2<f32>,
@internal(packed_vector)
v3_b : vec3<f32>,
v4_b : vec4<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let v2_a = P.v2_a;
let v3_a = vec3<f32>(P.v3_a);
let v4_a = P.v4_a;
let v2_b = P.v2_b;
let v3_b = vec3<f32>(P.v3_b);
let v4_b = P.v4_b;
}
)";
DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, MixedAddressSpace) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
var f : S;
let x = f.v;
}
)";
auto* expect = R"(
struct S {
@internal(packed_vector)
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
var f : S;
let x = vec3<f32>(f.v);
}
)";
DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ReadMemberAccessChain) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P.v.yz.x;
}
)";
auto* expect = R"(
struct S {
@internal(packed_vector)
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P.v.yz.x;
}
)";
DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ReadVector) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P.v;
}
)";
auto* expect = R"(
struct S {
@internal(packed_vector)
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = vec3<f32>(P.v);
}
)";
DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ReadIndexAccessor) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P.v[1];
}
)";
auto* expect = R"(
struct S {
@internal(packed_vector)
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P.v[1];
}
)";
DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ReadViaStructPtrDirect) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = (*(&(*(&P)))).v;
}
)";
auto* expect = R"(
struct S {
@internal(packed_vector)
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = vec3<f32>((*(&(*(&(P))))).v);
}
)";
DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ReadViaVectorPtrDirect) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = *(&(*(&(P.v))));
}
)";
auto* expect = R"(
struct S {
@internal(packed_vector)
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = vec3<f32>(*(&(*(&(P.v)))));
}
)";
DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ReadViaStructPtrViaLet) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let p0 = &P;
let p1 = &(*(p0));
let a = (*p1).v;
let p2 = &(*(p1));
let b = (*p2).v;
let c = (*p2).v;
}
)";
auto* expect = R"(
struct S {
@internal(packed_vector)
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let p0 = &(P);
let p1 = &(*(p0));
let a = vec3<f32>((*(p1)).v);
let p2 = &(*(p1));
let b = vec3<f32>((*(p2)).v);
let c = vec3<f32>((*(p2)).v);
}
)";
DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ReadViaVectorPtrViaLet) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let p0 = &(P.v);
let p1 = &(*(p0));
let a = *p1;
let p2 = &(*(p1));
let b = *p2;
let c = *p2;
}
)";
auto* expect = R"(
struct S {
@internal(packed_vector)
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let p0 = &(P.v);
let p1 = &(*(p0));
let a = vec3<f32>(*(p1));
let p2 = &(*(p1));
let b = vec3<f32>(*(p2));
let c = vec3<f32>(*(p2));
}
)";
DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ReadUnaryOp) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = -P.v;
}
)";
auto* expect = R"(
struct S {
@internal(packed_vector)
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = -(vec3<f32>(P.v));
}
)";
DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, ReadBinaryOp) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = P.v + P.v;
}
)";
auto* expect = R"(
struct S {
@internal(packed_vector)
v : vec3<f32>,
}
@group(0) @binding(0) var<storage> P : S;
fn f() {
let x = (vec3<f32>(P.v) + vec3<f32>(P.v));
}
)";
DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, WriteVector) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P.v = vec3(1.23);
}
)";
auto* expect = R"(
struct S {
@internal(packed_vector)
v : vec3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P.v = vec3(1.23);
}
)";
DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, WriteMemberAccess) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P.v.y = 1.23;
}
)";
auto* expect = R"(
struct S {
@internal(packed_vector)
v : vec3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P.v.y = 1.23;
}
)";
DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(PackedVec3Test, WriteIndexAccessor) {
auto* src = R"(
struct S {
v : vec3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P.v[1] = 1.23;
}
)";
auto* expect = R"(
struct S {
@internal(packed_vector)
v : vec3<f32>,
}
@group(0) @binding(0) var<storage, read_write> P : S;
fn f() {
P.v[1] = 1.23;
}
)";
DataMap data;
auto got = Run<PackedVec3>(src, data);
EXPECT_EQ(expect, str(got));
}
} // namespace
} // namespace tint::transform