mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-13 23:26:24 +00:00
wgsl: Replace [[decoration]] with @decoration
Deprecate the old syntax. Migrate everything to the new syntax. Bug: tint:1382 Change-Id: Ide12b2e927b17dc93b9714c7049090864cc568d3 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/77260 Reviewed-by: James Price <jrprice@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: David Neto <dneto@google.com> Commit-Queue: David Neto <dneto@google.com>
This commit is contained in:
committed by
Tint LUCI CQ
parent
8f1d5224ee
commit
01e4b6fc18
@@ -27,7 +27,7 @@ using ResolverAssignmentValidationTest = ResolverTest;
|
||||
|
||||
TEST_F(ResolverAssignmentValidationTest, ReadOnlyBuffer) {
|
||||
// [[block]] struct S { m : i32 };
|
||||
// [[group(0), binding(0)]]
|
||||
// @group(0) @binding(0)
|
||||
// var<storage,read> a : S;
|
||||
auto* s = Structure("S", {Member("m", ty.i32())},
|
||||
{create<ast::StructBlockDecoration>()});
|
||||
@@ -251,7 +251,7 @@ TEST_F(ResolverAssignmentValidationTest, AssignNonConstructible_Handle) {
|
||||
|
||||
TEST_F(ResolverAssignmentValidationTest, AssignNonConstructible_Atomic) {
|
||||
// [[block]] struct S { a : atomic<i32>; };
|
||||
// [[group(0), binding(0)]] var<storage, read_write> v : S;
|
||||
// @group(0) @binding(0) var<storage, read_write> v : S;
|
||||
// v.a = v.a;
|
||||
|
||||
auto* s = Structure("S", {Member("a", ty.atomic(ty.i32()))},
|
||||
@@ -273,7 +273,7 @@ TEST_F(ResolverAssignmentValidationTest, AssignNonConstructible_Atomic) {
|
||||
|
||||
TEST_F(ResolverAssignmentValidationTest, AssignNonConstructible_RuntimeArray) {
|
||||
// [[block]] struct S { a : array<f32>; };
|
||||
// [[group(0), binding(0)]] var<storage, read_write> v : S;
|
||||
// @group(0) @binding(0) var<storage, read_write> v : S;
|
||||
// v.a = v.a;
|
||||
|
||||
auto* s = Structure("S", {Member("a", ty.array(ty.f32()))},
|
||||
@@ -299,7 +299,7 @@ TEST_F(ResolverAssignmentValidationTest,
|
||||
// struct S {
|
||||
// arr: array<i32>;
|
||||
// };
|
||||
// [[group(0), binding(0)]] var<storage, read_write> s : S;
|
||||
// @group(0) @binding(0) var<storage, read_write> s : S;
|
||||
// fn f() {
|
||||
// _ = s;
|
||||
// }
|
||||
@@ -320,7 +320,7 @@ TEST_F(ResolverAssignmentValidationTest, AssignToPhony_DynamicArray_Fail) {
|
||||
// struct S {
|
||||
// arr: array<i32>;
|
||||
// };
|
||||
// [[group(0), binding(0)]] var<storage, read_write> s : S;
|
||||
// @group(0) @binding(0) var<storage, read_write> s : S;
|
||||
// fn f() {
|
||||
// _ = s.arr;
|
||||
// }
|
||||
@@ -347,10 +347,10 @@ TEST_F(ResolverAssignmentValidationTest, AssignToPhony_Pass) {
|
||||
// struct U {
|
||||
// i: i32;
|
||||
// };
|
||||
// [[group(0), binding(0)]] var tex texture_2d;
|
||||
// [[group(0), binding(1)]] var smp sampler;
|
||||
// [[group(0), binding(2)]] var<uniform> u : U;
|
||||
// [[group(0), binding(3)]] var<storage, read_write> s : S;
|
||||
// @group(0) @binding(0) var tex texture_2d;
|
||||
// @group(0) @binding(1) var smp sampler;
|
||||
// @group(0) @binding(2) var<uniform> u : U;
|
||||
// @group(0) @binding(3) var<storage, read_write> s : S;
|
||||
// var<workgroup> wg : array<f32, 10>
|
||||
// fn f() {
|
||||
// _ = 1;
|
||||
|
||||
@@ -201,10 +201,10 @@ INSTANTIATE_TEST_SUITE_P(ResolverBuiltinsValidationTest,
|
||||
testing::ValuesIn(cases));
|
||||
|
||||
TEST_F(ResolverBuiltinsValidationTest, FragDepthIsInput_Fail) {
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn fs_main(
|
||||
// [[builtin(frag_depth)]] fd: f32,
|
||||
// ) -> [[location(0)]] f32 { return 1.0; }
|
||||
// @builtin(frag_depth) fd: f32,
|
||||
// ) -> @location(0) f32 { return 1.0; }
|
||||
auto* fd = Param(
|
||||
"fd", ty.f32(),
|
||||
ast::DecorationList{Builtin(Source{{12, 34}}, ast::Builtin::kFragDepth)});
|
||||
@@ -219,10 +219,10 @@ TEST_F(ResolverBuiltinsValidationTest, FragDepthIsInput_Fail) {
|
||||
|
||||
TEST_F(ResolverBuiltinsValidationTest, FragDepthIsInputStruct_Fail) {
|
||||
// struct MyInputs {
|
||||
// [[builtin(frag_depth)]] ff: f32;
|
||||
// @builtin(frag_depth) ff: f32;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// fn fragShader(arg: MyInputs) -> [[location(0)]] f32 { return 1.0; }
|
||||
// @stage(fragment)
|
||||
// fn fragShader(arg: MyInputs) -> @location(0) f32 { return 1.0; }
|
||||
|
||||
auto* s = Structure(
|
||||
"MyInputs", {Member("frag_depth", ty.f32(),
|
||||
@@ -240,9 +240,9 @@ TEST_F(ResolverBuiltinsValidationTest, FragDepthIsInputStruct_Fail) {
|
||||
|
||||
TEST_F(ResolverBuiltinsValidationTest, StructBuiltinInsideEntryPoint_Ignored) {
|
||||
// struct S {
|
||||
// [[builtin(vertex_index)]] idx: u32;
|
||||
// @builtin(vertex_index) idx: u32;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn fragShader() { var s : S; }
|
||||
|
||||
Structure("S",
|
||||
@@ -257,10 +257,10 @@ TEST_F(ResolverBuiltinsValidationTest, StructBuiltinInsideEntryPoint_Ignored) {
|
||||
|
||||
TEST_F(ResolverBuiltinsValidationTest, PositionNotF32_Struct_Fail) {
|
||||
// struct MyInputs {
|
||||
// [[builtin(kPosition)]] p: vec4<u32>;
|
||||
// @builtin(kPosition) p: vec4<u32>;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// fn fragShader(is_front: MyInputs) -> [[location(0)]] f32 { return 1.0; }
|
||||
// @stage(fragment)
|
||||
// fn fragShader(is_front: MyInputs) -> @location(0) f32 { return 1.0; }
|
||||
|
||||
auto* m = Member(
|
||||
"position", ty.vec4<u32>(),
|
||||
@@ -275,8 +275,8 @@ TEST_F(ResolverBuiltinsValidationTest, PositionNotF32_Struct_Fail) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverBuiltinsValidationTest, PositionNotF32_ReturnType_Fail) {
|
||||
// [[stage(vertex)]]
|
||||
// fn main() -> [[builtin(position)]] f32 { return 1.0; }
|
||||
// @stage(vertex)
|
||||
// fn main() -> @builtin(position) f32 { return 1.0; }
|
||||
Func("main", {}, ty.f32(), {Return(1.0f)},
|
||||
{Stage(ast::PipelineStage::kVertex)},
|
||||
{Builtin(Source{{12, 34}}, ast::Builtin::kPosition)});
|
||||
@@ -288,10 +288,10 @@ TEST_F(ResolverBuiltinsValidationTest, PositionNotF32_ReturnType_Fail) {
|
||||
|
||||
TEST_F(ResolverBuiltinsValidationTest, FragDepthNotF32_Struct_Fail) {
|
||||
// struct MyInputs {
|
||||
// [[builtin(kFragDepth)]] p: i32;
|
||||
// @builtin(kFragDepth) p: i32;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// fn fragShader(is_front: MyInputs) -> [[location(0)]] f32 { return 1.0; }
|
||||
// @stage(fragment)
|
||||
// fn fragShader(is_front: MyInputs) -> @location(0) f32 { return 1.0; }
|
||||
|
||||
auto* m = Member(
|
||||
"frag_depth", ty.i32(),
|
||||
@@ -307,10 +307,10 @@ TEST_F(ResolverBuiltinsValidationTest, FragDepthNotF32_Struct_Fail) {
|
||||
|
||||
TEST_F(ResolverBuiltinsValidationTest, SampleMaskNotU32_Struct_Fail) {
|
||||
// struct MyInputs {
|
||||
// [[builtin(sample_mask)]] m: f32;
|
||||
// @builtin(sample_mask) m: f32;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// fn fragShader(is_front: MyInputs) -> [[location(0)]] f32 { return 1.0; }
|
||||
// @stage(fragment)
|
||||
// fn fragShader(is_front: MyInputs) -> @location(0) f32 { return 1.0; }
|
||||
|
||||
auto* s = Structure(
|
||||
"MyInputs", {Member("m", ty.f32(),
|
||||
@@ -325,8 +325,8 @@ TEST_F(ResolverBuiltinsValidationTest, SampleMaskNotU32_Struct_Fail) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverBuiltinsValidationTest, SampleMaskNotU32_ReturnType_Fail) {
|
||||
// [[stage(fragment)]]
|
||||
// fn main() -> [[builtin(sample_mask)]] i32 { return 1; }
|
||||
// @stage(fragment)
|
||||
// fn main() -> @builtin(sample_mask) i32 { return 1; }
|
||||
Func("main", {}, ty.i32(), {Return(1)},
|
||||
{Stage(ast::PipelineStage::kFragment)},
|
||||
{Builtin(Source{{12, 34}}, ast::Builtin::kSampleMask)});
|
||||
@@ -337,10 +337,10 @@ TEST_F(ResolverBuiltinsValidationTest, SampleMaskNotU32_ReturnType_Fail) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverBuiltinsValidationTest, SampleMaskIsNotU32_Fail) {
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn fs_main(
|
||||
// [[builtin(sample_mask)]] arg: bool
|
||||
// ) -> [[location(0)]] f32 { return 1.0; }
|
||||
// @builtin(sample_mask) arg: bool
|
||||
// ) -> @location(0) f32 { return 1.0; }
|
||||
auto* arg = Param("arg", ty.bool_(),
|
||||
ast::DecorationList{
|
||||
Builtin(Source{{12, 34}}, ast::Builtin::kSampleMask)});
|
||||
@@ -354,10 +354,10 @@ TEST_F(ResolverBuiltinsValidationTest, SampleMaskIsNotU32_Fail) {
|
||||
|
||||
TEST_F(ResolverBuiltinsValidationTest, SampleIndexIsNotU32_Struct_Fail) {
|
||||
// struct MyInputs {
|
||||
// [[builtin(sample_index)]] m: f32;
|
||||
// @builtin(sample_index) m: f32;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// fn fragShader(is_front: MyInputs) -> [[location(0)]] f32 { return 1.0; }
|
||||
// @stage(fragment)
|
||||
// fn fragShader(is_front: MyInputs) -> @location(0) f32 { return 1.0; }
|
||||
|
||||
auto* s = Structure(
|
||||
"MyInputs", {Member("m", ty.f32(),
|
||||
@@ -372,10 +372,10 @@ TEST_F(ResolverBuiltinsValidationTest, SampleIndexIsNotU32_Struct_Fail) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverBuiltinsValidationTest, SampleIndexIsNotU32_Fail) {
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn fs_main(
|
||||
// [[builtin(sample_index)]] arg: bool
|
||||
// ) -> [[location(0)]] f32 { return 1.0; }
|
||||
// @builtin(sample_index) arg: bool
|
||||
// ) -> @location(0) f32 { return 1.0; }
|
||||
auto* arg = Param("arg", ty.bool_(),
|
||||
ast::DecorationList{
|
||||
Builtin(Source{{12, 34}}, ast::Builtin::kSampleIndex)});
|
||||
@@ -388,10 +388,10 @@ TEST_F(ResolverBuiltinsValidationTest, SampleIndexIsNotU32_Fail) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverBuiltinsValidationTest, PositionIsNotF32_Fail) {
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn fs_main(
|
||||
// [[builtin(kPosition)]] p: vec3<f32>,
|
||||
// ) -> [[location(0)]] f32 { return 1.0; }
|
||||
// @builtin(kPosition) p: vec3<f32>,
|
||||
// ) -> @location(0) f32 { return 1.0; }
|
||||
auto* p = Param(
|
||||
"p", ty.vec3<f32>(),
|
||||
ast::DecorationList{Builtin(Source{{12, 34}}, ast::Builtin::kPosition)});
|
||||
@@ -404,8 +404,8 @@ TEST_F(ResolverBuiltinsValidationTest, PositionIsNotF32_Fail) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverBuiltinsValidationTest, FragDepthIsNotF32_Fail) {
|
||||
// [[stage(fragment)]]
|
||||
// fn fs_main() -> [[builtin(kFragDepth)]] f32 { var fd: i32; return fd; }
|
||||
// @stage(fragment)
|
||||
// fn fs_main() -> @builtin(kFragDepth) f32 { var fd: i32; return fd; }
|
||||
auto* fd = Var("fd", ty.i32());
|
||||
Func(
|
||||
"fs_main", {}, ty.i32(), {Decl(fd), Return(fd)},
|
||||
@@ -417,11 +417,11 @@ TEST_F(ResolverBuiltinsValidationTest, FragDepthIsNotF32_Fail) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverBuiltinsValidationTest, VertexIndexIsNotU32_Fail) {
|
||||
// [[stage(vertex)]]
|
||||
// @stage(vertex)
|
||||
// fn main(
|
||||
// [[builtin(kVertexIndex)]] vi : f32,
|
||||
// [[builtin(kPosition)]] p :vec4<f32>
|
||||
// ) -> [[builtin(kPosition)]] vec4<f32> { return vec4<f32>(); }
|
||||
// @builtin(kVertexIndex) vi : f32,
|
||||
// @builtin(kPosition) p :vec4<f32>
|
||||
// ) -> @builtin(kPosition) vec4<f32> { return vec4<f32>(); }
|
||||
auto* p = Param("p", ty.vec4<f32>(),
|
||||
ast::DecorationList{Builtin(ast::Builtin::kPosition)});
|
||||
auto* vi = Param("vi", ty.f32(),
|
||||
@@ -436,11 +436,11 @@ TEST_F(ResolverBuiltinsValidationTest, VertexIndexIsNotU32_Fail) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverBuiltinsValidationTest, InstanceIndexIsNotU32) {
|
||||
// [[stage(vertex)]]
|
||||
// @stage(vertex)
|
||||
// fn main(
|
||||
// [[builtin(kInstanceIndex)]] ii : f32,
|
||||
// [[builtin(kPosition)]] p :vec4<f32>
|
||||
// ) -> [[builtin(kPosition)]] vec4<f32> { return vec4<f32>(); }
|
||||
// @builtin(kInstanceIndex) ii : f32,
|
||||
// @builtin(kPosition) p :vec4<f32>
|
||||
// ) -> @builtin(kPosition) vec4<f32> { return vec4<f32>(); }
|
||||
auto* p = Param("p", ty.vec4<f32>(),
|
||||
ast::DecorationList{Builtin(ast::Builtin::kPosition)});
|
||||
auto* ii = Param("ii", ty.f32(),
|
||||
@@ -455,13 +455,13 @@ TEST_F(ResolverBuiltinsValidationTest, InstanceIndexIsNotU32) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverBuiltinsValidationTest, FragmentBuiltin_Pass) {
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn fs_main(
|
||||
// [[builtin(kPosition)]] p: vec4<f32>,
|
||||
// [[builtin(front_facing)]] ff: bool,
|
||||
// [[builtin(sample_index)]] si: u32,
|
||||
// [[builtin(sample_mask)]] sm : u32
|
||||
// ) -> [[builtin(frag_depth)]] f32 { var fd: f32; return fd; }
|
||||
// @builtin(kPosition) p: vec4<f32>,
|
||||
// @builtin(front_facing) ff: bool,
|
||||
// @builtin(sample_index) si: u32,
|
||||
// @builtin(sample_mask) sm : u32
|
||||
// ) -> @builtin(frag_depth) f32 { var fd: f32; return fd; }
|
||||
auto* p = Param("p", ty.vec4<f32>(),
|
||||
ast::DecorationList{Builtin(ast::Builtin::kPosition)});
|
||||
auto* ff = Param("ff", ty.bool_(),
|
||||
@@ -479,11 +479,11 @@ TEST_F(ResolverBuiltinsValidationTest, FragmentBuiltin_Pass) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverBuiltinsValidationTest, VertexBuiltin_Pass) {
|
||||
// [[stage(vertex)]]
|
||||
// @stage(vertex)
|
||||
// fn main(
|
||||
// [[builtin(vertex_index)]] vi : u32,
|
||||
// [[builtin(instance_index)]] ii : u32,
|
||||
// ) -> [[builtin(position)]] vec4<f32> { var p :vec4<f32>; return p; }
|
||||
// @builtin(vertex_index) vi : u32,
|
||||
// @builtin(instance_index) ii : u32,
|
||||
// ) -> @builtin(position) vec4<f32> { var p :vec4<f32>; return p; }
|
||||
auto* vi = Param("vi", ty.u32(),
|
||||
ast::DecorationList{
|
||||
Builtin(Source{{12, 34}}, ast::Builtin::kVertexIndex)});
|
||||
@@ -504,13 +504,13 @@ TEST_F(ResolverBuiltinsValidationTest, VertexBuiltin_Pass) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverBuiltinsValidationTest, ComputeBuiltin_Pass) {
|
||||
// [[stage(compute), workgroup_size(1)]]
|
||||
// @stage(compute) @workgroup_size(1)
|
||||
// fn main(
|
||||
// [[builtin(local_invocationId)]] li_id: vec3<u32>,
|
||||
// [[builtin(local_invocationIndex)]] li_index: u32,
|
||||
// [[builtin(global_invocationId)]] gi: vec3<u32>,
|
||||
// [[builtin(workgroup_id)]] wi: vec3<u32>,
|
||||
// [[builtin(num_workgroups)]] nwgs: vec3<u32>,
|
||||
// @builtin(local_invocationId) li_id: vec3<u32>,
|
||||
// @builtin(local_invocationIndex) li_index: u32,
|
||||
// @builtin(global_invocationId) gi: vec3<u32>,
|
||||
// @builtin(workgroup_id) wi: vec3<u32>,
|
||||
// @builtin(num_workgroups) nwgs: vec3<u32>,
|
||||
// ) {}
|
||||
|
||||
auto* li_id =
|
||||
@@ -618,13 +618,13 @@ TEST_F(ResolverBuiltinsValidationTest,
|
||||
|
||||
TEST_F(ResolverBuiltinsValidationTest, FragmentBuiltinStruct_Pass) {
|
||||
// Struct MyInputs {
|
||||
// [[builtin(kPosition)]] p: vec4<f32>;
|
||||
// [[builtin(frag_depth)]] fd: f32;
|
||||
// [[builtin(sample_index)]] si: u32;
|
||||
// [[builtin(sample_mask)]] sm : u32;;
|
||||
// @builtin(kPosition) p: vec4<f32>;
|
||||
// @builtin(frag_depth) fd: f32;
|
||||
// @builtin(sample_index) si: u32;
|
||||
// @builtin(sample_mask) sm : u32;;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// fn fragShader(arg: MyInputs) -> [[location(0)]] f32 { return 1.0; }
|
||||
// @stage(fragment)
|
||||
// fn fragShader(arg: MyInputs) -> @location(0) f32 { return 1.0; }
|
||||
|
||||
auto* s = Structure(
|
||||
"MyInputs",
|
||||
@@ -642,10 +642,10 @@ TEST_F(ResolverBuiltinsValidationTest, FragmentBuiltinStruct_Pass) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverBuiltinsValidationTest, FrontFacingParamIsNotBool_Fail) {
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn fs_main(
|
||||
// [[builtin(front_facing)]] is_front: i32;
|
||||
// ) -> [[location(0)]] f32 { return 1.0; }
|
||||
// @builtin(front_facing) is_front: i32;
|
||||
// ) -> @location(0) f32 { return 1.0; }
|
||||
|
||||
auto* is_front = Param("is_front", ty.i32(),
|
||||
ast::DecorationList{Builtin(
|
||||
@@ -661,10 +661,10 @@ TEST_F(ResolverBuiltinsValidationTest, FrontFacingParamIsNotBool_Fail) {
|
||||
|
||||
TEST_F(ResolverBuiltinsValidationTest, FrontFacingMemberIsNotBool_Fail) {
|
||||
// struct MyInputs {
|
||||
// [[builtin(front_facing)]] pos: f32;
|
||||
// @builtin(front_facing) pos: f32;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// fn fragShader(is_front: MyInputs) -> [[location(0)]] f32 { return 1.0; }
|
||||
// @stage(fragment)
|
||||
// fn fragShader(is_front: MyInputs) -> @location(0) f32 { return 1.0; }
|
||||
|
||||
auto* s = Structure(
|
||||
"MyInputs", {Member("pos", ty.f32(),
|
||||
|
||||
@@ -172,7 +172,7 @@ TEST_F(ResolverCallValidationTest, PointerArgument_FunctionParamWithMain) {
|
||||
// fn bar(p: ptr<function, i32>) {
|
||||
// foo(p);
|
||||
// }
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn main() {
|
||||
// var v: i32;
|
||||
// bar(&v);
|
||||
@@ -195,7 +195,7 @@ TEST_F(ResolverCallValidationTest, PointerArgument_FunctionParamWithMain) {
|
||||
|
||||
TEST_F(ResolverCallValidationTest, LetPointer) {
|
||||
// fn x(p : ptr<function, i32>) -> i32 {}
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn main() {
|
||||
// var v: i32;
|
||||
// let p: ptr<function, i32> = &v;
|
||||
@@ -227,7 +227,7 @@ TEST_F(ResolverCallValidationTest, LetPointerPrivate) {
|
||||
// let p: ptr<private, i32> = &v;
|
||||
// fn foo(p : ptr<private, i32>) -> i32 {}
|
||||
// var v: i32;
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn main() {
|
||||
// var c: i32 = foo(p);
|
||||
// }
|
||||
|
||||
@@ -973,9 +973,9 @@ TEST_F(ResourceDecorationTest, UniformBufferMissingBinding) {
|
||||
Global(Source{{12, 34}}, "G", ty.Of(s), ast::StorageClass::kUniform);
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
"12:34 error: resource variables require [[group]] and [[binding]] "
|
||||
"decorations");
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(12:34 error: resource variables require @group and @binding decorations)");
|
||||
}
|
||||
|
||||
TEST_F(ResourceDecorationTest, StorageBufferMissingBinding) {
|
||||
@@ -985,9 +985,9 @@ TEST_F(ResourceDecorationTest, StorageBufferMissingBinding) {
|
||||
ast::Access::kRead);
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
"12:34 error: resource variables require [[group]] and [[binding]] "
|
||||
"decorations");
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(12:34 error: resource variables require @group and @binding decorations)");
|
||||
}
|
||||
|
||||
TEST_F(ResourceDecorationTest, TextureMissingBinding) {
|
||||
@@ -995,9 +995,9 @@ TEST_F(ResourceDecorationTest, TextureMissingBinding) {
|
||||
ast::StorageClass::kNone);
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
"12:34 error: resource variables require [[group]] and [[binding]] "
|
||||
"decorations");
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(12:34 error: resource variables require @group and @binding decorations)");
|
||||
}
|
||||
|
||||
TEST_F(ResourceDecorationTest, SamplerMissingBinding) {
|
||||
@@ -1005,9 +1005,9 @@ TEST_F(ResourceDecorationTest, SamplerMissingBinding) {
|
||||
ast::StorageClass::kNone);
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
"12:34 error: resource variables require [[group]] and [[binding]] "
|
||||
"decorations");
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(12:34 error: resource variables require @group and @binding decorations)");
|
||||
}
|
||||
|
||||
TEST_F(ResourceDecorationTest, BindingPairMissingBinding) {
|
||||
@@ -1018,9 +1018,9 @@ TEST_F(ResourceDecorationTest, BindingPairMissingBinding) {
|
||||
});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
"12:34 error: resource variables require [[group]] and [[binding]] "
|
||||
"decorations");
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(12:34 error: resource variables require @group and @binding decorations)");
|
||||
}
|
||||
|
||||
TEST_F(ResourceDecorationTest, BindingPairMissingGroup) {
|
||||
@@ -1031,9 +1031,9 @@ TEST_F(ResourceDecorationTest, BindingPairMissingGroup) {
|
||||
});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
"12:34 error: resource variables require [[group]] and [[binding]] "
|
||||
"decorations");
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(12:34 error: resource variables require @group and @binding decorations)");
|
||||
}
|
||||
|
||||
TEST_F(ResourceDecorationTest, BindingPointUsedTwiceByEntryPoint) {
|
||||
@@ -1064,7 +1064,7 @@ TEST_F(ResourceDecorationTest, BindingPointUsedTwiceByEntryPoint) {
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(56:78 error: entry point 'F' references multiple variables that use the same resource binding [[group(2), binding(1)]]
|
||||
R"(56:78 error: entry point 'F' references multiple variables that use the same resource binding @group(2), @binding(1)
|
||||
12:34 note: first resource binding usage declared here)");
|
||||
}
|
||||
|
||||
@@ -1108,9 +1108,9 @@ TEST_F(ResourceDecorationTest, BindingPointOnNonResource) {
|
||||
});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
"12:34 error: non-resource variables must not have [[group]] or "
|
||||
"[[binding]] decorations");
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(12:34 error: non-resource variables must not have @group or @binding decorations)");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -1368,9 +1368,9 @@ TEST_F(InterpolateTest, MissingLocationAttribute_Parameter) {
|
||||
ast::DecorationList{Stage(ast::PipelineStage::kFragment)});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
"12:34 error: interpolate attribute must only be used with "
|
||||
"[[location]]");
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(12:34 error: interpolate attribute must only be used with @location)");
|
||||
}
|
||||
|
||||
TEST_F(InterpolateTest, MissingLocationAttribute_ReturnType) {
|
||||
@@ -1381,9 +1381,9 @@ TEST_F(InterpolateTest, MissingLocationAttribute_ReturnType) {
|
||||
ast::InterpolationSampling::kNone)});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
"12:34 error: interpolate attribute must only be used with "
|
||||
"[[location]]");
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(12:34 error: interpolate attribute must only be used with @location)");
|
||||
}
|
||||
|
||||
TEST_F(InterpolateTest, MissingLocationAttribute_Struct) {
|
||||
@@ -1393,9 +1393,9 @@ TEST_F(InterpolateTest, MissingLocationAttribute_Struct) {
|
||||
ast::InterpolationSampling::kNone)})});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
"12:34 error: interpolate attribute must only be used with "
|
||||
"[[location]]");
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(12:34 error: interpolate attribute must only be used with @location)");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -51,8 +51,8 @@ class ResolverEntryPointValidationTest : public TestHelper,
|
||||
public testing::Test {};
|
||||
|
||||
TEST_F(ResolverEntryPointValidationTest, ReturnTypeAttribute_Location) {
|
||||
// [[stage(fragment)]]
|
||||
// fn main() -> [[location(0)]] f32 { return 1.0; }
|
||||
// @stage(fragment)
|
||||
// fn main() -> @location(0) f32 { return 1.0; }
|
||||
Func(Source{{12, 34}}, "main", {}, ty.f32(), {Return(1.0f)},
|
||||
{Stage(ast::PipelineStage::kFragment)}, {Location(0)});
|
||||
|
||||
@@ -60,8 +60,8 @@ TEST_F(ResolverEntryPointValidationTest, ReturnTypeAttribute_Location) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverEntryPointValidationTest, ReturnTypeAttribute_Builtin) {
|
||||
// [[stage(vertex)]]
|
||||
// fn main() -> [[builtin(position)]] vec4<f32> { return vec4<f32>(); }
|
||||
// @stage(vertex)
|
||||
// fn main() -> @builtin(position) vec4<f32> { return vec4<f32>(); }
|
||||
Func(Source{{12, 34}}, "main", {}, ty.vec4<f32>(),
|
||||
{Return(Construct(ty.vec4<f32>()))},
|
||||
{Stage(ast::PipelineStage::kVertex)},
|
||||
@@ -71,7 +71,7 @@ TEST_F(ResolverEntryPointValidationTest, ReturnTypeAttribute_Builtin) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverEntryPointValidationTest, ReturnTypeAttribute_Missing) {
|
||||
// [[stage(vertex)]]
|
||||
// @stage(vertex)
|
||||
// fn main() -> f32 {
|
||||
// return 1.0;
|
||||
// }
|
||||
@@ -85,8 +85,8 @@ TEST_F(ResolverEntryPointValidationTest, ReturnTypeAttribute_Missing) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverEntryPointValidationTest, ReturnTypeAttribute_Multiple) {
|
||||
// [[stage(vertex)]]
|
||||
// fn main() -> [[location(0)]] [[builtin(position)]] vec4<f32> {
|
||||
// @stage(vertex)
|
||||
// fn main() -> @location(0) @builtin(position) vec4<f32> {
|
||||
// return vec4<f32>();
|
||||
// }
|
||||
Func(Source{{12, 34}}, "main", {}, ty.vec4<f32>(),
|
||||
@@ -102,10 +102,10 @@ TEST_F(ResolverEntryPointValidationTest, ReturnTypeAttribute_Multiple) {
|
||||
|
||||
TEST_F(ResolverEntryPointValidationTest, ReturnType_Struct_Valid) {
|
||||
// struct Output {
|
||||
// [[location(0)]] a : f32;
|
||||
// [[builtin(frag_depth)]] b : f32;
|
||||
// @location(0) a : f32;
|
||||
// @builtin(frag_depth) b : f32;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn main() -> Output {
|
||||
// return Output();
|
||||
// }
|
||||
@@ -122,9 +122,9 @@ TEST_F(ResolverEntryPointValidationTest, ReturnType_Struct_Valid) {
|
||||
TEST_F(ResolverEntryPointValidationTest,
|
||||
ReturnType_Struct_MemberMultipleAttributes) {
|
||||
// struct Output {
|
||||
// [[location(0)]] [[builtin(frag_depth)]] a : f32;
|
||||
// @location(0) @builtin(frag_depth) a : f32;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn main() -> Output {
|
||||
// return Output();
|
||||
// }
|
||||
@@ -146,10 +146,10 @@ TEST_F(ResolverEntryPointValidationTest,
|
||||
TEST_F(ResolverEntryPointValidationTest,
|
||||
ReturnType_Struct_MemberMissingAttribute) {
|
||||
// struct Output {
|
||||
// [[location(0)]] a : f32;
|
||||
// @location(0) a : f32;
|
||||
// b : f32;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn main() -> Output {
|
||||
// return Output();
|
||||
// }
|
||||
@@ -168,10 +168,10 @@ TEST_F(ResolverEntryPointValidationTest,
|
||||
|
||||
TEST_F(ResolverEntryPointValidationTest, ReturnType_Struct_DuplicateBuiltins) {
|
||||
// struct Output {
|
||||
// [[builtin(frag_depth)]] a : f32;
|
||||
// [[builtin(frag_depth)]] b : f32;
|
||||
// @builtin(frag_depth) a : f32;
|
||||
// @builtin(frag_depth) b : f32;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn main() -> Output {
|
||||
// return Output();
|
||||
// }
|
||||
@@ -190,8 +190,8 @@ TEST_F(ResolverEntryPointValidationTest, ReturnType_Struct_DuplicateBuiltins) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverEntryPointValidationTest, ParameterAttribute_Location) {
|
||||
// [[stage(fragment)]]
|
||||
// fn main([[location(0)]] param : f32) {}
|
||||
// @stage(fragment)
|
||||
// fn main(@location(0) param : f32) {}
|
||||
auto* param = Param("param", ty.f32(), {Location(0)});
|
||||
Func(Source{{12, 34}}, "main", {param}, ty.void_(), {},
|
||||
{Stage(ast::PipelineStage::kFragment)});
|
||||
@@ -200,7 +200,7 @@ TEST_F(ResolverEntryPointValidationTest, ParameterAttribute_Location) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverEntryPointValidationTest, ParameterAttribute_Missing) {
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn main(param : f32) {}
|
||||
auto* param = Param(Source{{13, 43}}, "param", ty.vec4<f32>());
|
||||
Func(Source{{12, 34}}, "main", {param}, ty.void_(), {},
|
||||
@@ -212,8 +212,8 @@ TEST_F(ResolverEntryPointValidationTest, ParameterAttribute_Missing) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverEntryPointValidationTest, ParameterAttribute_Multiple) {
|
||||
// [[stage(fragment)]]
|
||||
// fn main([[location(0)]] [[builtin(sample_index)]] param : u32) {}
|
||||
// @stage(fragment)
|
||||
// fn main(@location(0) @builtin(sample_index) param : u32) {}
|
||||
auto* param = Param("param", ty.u32(),
|
||||
{Location(Source{{13, 43}}, 0),
|
||||
Builtin(Source{{14, 52}}, ast::Builtin::kSampleIndex)});
|
||||
@@ -227,10 +227,10 @@ TEST_F(ResolverEntryPointValidationTest, ParameterAttribute_Multiple) {
|
||||
|
||||
TEST_F(ResolverEntryPointValidationTest, Parameter_Struct_Valid) {
|
||||
// struct Input {
|
||||
// [[location(0)]] a : f32;
|
||||
// [[builtin(sample_index)]] b : u32;
|
||||
// @location(0) a : f32;
|
||||
// @builtin(sample_index) b : u32;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn main(param : Input) {}
|
||||
auto* input = Structure(
|
||||
"Input", {Member("a", ty.f32(), {Location(0)}),
|
||||
@@ -245,9 +245,9 @@ TEST_F(ResolverEntryPointValidationTest, Parameter_Struct_Valid) {
|
||||
TEST_F(ResolverEntryPointValidationTest,
|
||||
Parameter_Struct_MemberMultipleAttributes) {
|
||||
// struct Input {
|
||||
// [[location(0)]] [[builtin(sample_index)]] a : u32;
|
||||
// @location(0) @builtin(sample_index) a : u32;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn main(param : Input) {}
|
||||
auto* input = Structure(
|
||||
"Input",
|
||||
@@ -267,10 +267,10 @@ TEST_F(ResolverEntryPointValidationTest,
|
||||
TEST_F(ResolverEntryPointValidationTest,
|
||||
Parameter_Struct_MemberMissingAttribute) {
|
||||
// struct Input {
|
||||
// [[location(0)]] a : f32;
|
||||
// @location(0) a : f32;
|
||||
// b : f32;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn main(param : Input) {}
|
||||
auto* input = Structure(
|
||||
"Input", {Member(Source{{13, 43}}, "a", ty.f32(), {Location(0)}),
|
||||
@@ -285,9 +285,9 @@ TEST_F(ResolverEntryPointValidationTest,
|
||||
}
|
||||
|
||||
TEST_F(ResolverEntryPointValidationTest, Parameter_DuplicateBuiltins) {
|
||||
// [[stage(fragment)]]
|
||||
// fn main([[builtin(sample_index)]] param_a : u32,
|
||||
// [[builtin(sample_index)]] param_b : u32) {}
|
||||
// @stage(fragment)
|
||||
// fn main(@builtin(sample_index) param_a : u32,
|
||||
// @builtin(sample_index) param_b : u32) {}
|
||||
auto* param_a =
|
||||
Param("param_a", ty.u32(), {Builtin(ast::Builtin::kSampleIndex)});
|
||||
auto* param_b =
|
||||
@@ -304,12 +304,12 @@ TEST_F(ResolverEntryPointValidationTest, Parameter_DuplicateBuiltins) {
|
||||
|
||||
TEST_F(ResolverEntryPointValidationTest, Parameter_Struct_DuplicateBuiltins) {
|
||||
// struct InputA {
|
||||
// [[builtin(sample_index)]] a : u32;
|
||||
// @builtin(sample_index) a : u32;
|
||||
// };
|
||||
// struct InputB {
|
||||
// [[builtin(sample_index)]] a : u32;
|
||||
// @builtin(sample_index) a : u32;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn main(param_a : InputA, param_b : InputB) {}
|
||||
auto* input_a = Structure(
|
||||
"InputA", {Member("a", ty.u32(), {Builtin(ast::Builtin::kSampleIndex)})});
|
||||
@@ -328,7 +328,7 @@ TEST_F(ResolverEntryPointValidationTest, Parameter_Struct_DuplicateBuiltins) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverEntryPointValidationTest, VertexShaderMustReturnPosition) {
|
||||
// [[stage(vertex)]]
|
||||
// @stage(vertex)
|
||||
// fn main() {}
|
||||
Func(Source{{12, 34}}, "main", {}, ty.void_(), {},
|
||||
{Stage(ast::PipelineStage::kVertex)});
|
||||
@@ -370,8 +370,8 @@ static constexpr Params cases[] = {
|
||||
};
|
||||
|
||||
TEST_P(TypeValidationTest, BareInputs) {
|
||||
// [[stage(fragment)]]
|
||||
// fn main([[location(0)]] a : *) {}
|
||||
// @stage(fragment)
|
||||
// fn main(@location(0) a : *) {}
|
||||
auto params = GetParam();
|
||||
auto* a = Param("a", params.create_ast_type(*this), {Location(0)});
|
||||
Func(Source{{12, 34}}, "main", {a}, ty.void_(), {},
|
||||
@@ -386,9 +386,9 @@ TEST_P(TypeValidationTest, BareInputs) {
|
||||
|
||||
TEST_P(TypeValidationTest, StructInputs) {
|
||||
// struct Input {
|
||||
// [[location(0)]] a : *;
|
||||
// @location(0) a : *;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn main(a : Input) {}
|
||||
auto params = GetParam();
|
||||
auto* input = Structure(
|
||||
@@ -405,8 +405,8 @@ TEST_P(TypeValidationTest, StructInputs) {
|
||||
}
|
||||
|
||||
TEST_P(TypeValidationTest, BareOutputs) {
|
||||
// [[stage(fragment)]]
|
||||
// fn main() -> [[location(0)]] * {
|
||||
// @stage(fragment)
|
||||
// fn main() -> @location(0) * {
|
||||
// return *();
|
||||
// }
|
||||
auto params = GetParam();
|
||||
@@ -423,9 +423,9 @@ TEST_P(TypeValidationTest, BareOutputs) {
|
||||
|
||||
TEST_P(TypeValidationTest, StructOutputs) {
|
||||
// struct Output {
|
||||
// [[location(0)]] a : *;
|
||||
// @location(0) a : *;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn main() -> Output {
|
||||
// return Output();
|
||||
// }
|
||||
@@ -453,8 +453,8 @@ namespace {
|
||||
using LocationDecorationTests = ResolverTest;
|
||||
|
||||
TEST_F(LocationDecorationTests, Pass) {
|
||||
// [[stage(fragment)]]
|
||||
// fn frag_main([[location(0)]] a: i32) {}
|
||||
// @stage(fragment)
|
||||
// fn frag_main(@location(0) a: i32) {}
|
||||
|
||||
auto* p = Param(Source{{12, 34}}, "a", ty.i32(), {Location(0)});
|
||||
Func("frag_main", {p}, ty.void_(), {},
|
||||
@@ -464,8 +464,8 @@ TEST_F(LocationDecorationTests, Pass) {
|
||||
}
|
||||
|
||||
TEST_F(LocationDecorationTests, BadType_Input_bool) {
|
||||
// [[stage(fragment)]]
|
||||
// fn frag_main([[location(0)]] a: bool) {}
|
||||
// @stage(fragment)
|
||||
// fn frag_main(@location(0) a: bool) {}
|
||||
|
||||
auto* p =
|
||||
Param(Source{{12, 34}}, "a", ty.bool_(), {Location(Source{{34, 56}}, 0)});
|
||||
@@ -481,8 +481,8 @@ TEST_F(LocationDecorationTests, BadType_Input_bool) {
|
||||
}
|
||||
|
||||
TEST_F(LocationDecorationTests, BadType_Output_Array) {
|
||||
// [[stage(fragment)]]
|
||||
// fn frag_main()->[[location(0)]] array<f32, 2> { return array<f32, 2>(); }
|
||||
// @stage(fragment)
|
||||
// fn frag_main()->@location(0) array<f32, 2> { return array<f32, 2>(); }
|
||||
|
||||
Func(Source{{12, 34}}, "frag_main", {}, ty.array<f32, 2>(),
|
||||
{Return(Construct(ty.array<f32, 2>()))},
|
||||
@@ -500,8 +500,8 @@ TEST_F(LocationDecorationTests, BadType_Input_Struct) {
|
||||
// struct Input {
|
||||
// a : f32;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// fn main([[location(0)]] param : Input) {}
|
||||
// @stage(fragment)
|
||||
// fn main(@location(0) param : Input) {}
|
||||
auto* input = Structure("Input", {Member("a", ty.f32())});
|
||||
auto* param = Param(Source{{12, 34}}, "param", ty.Of(input),
|
||||
{Location(Source{{13, 43}}, 0)});
|
||||
@@ -518,12 +518,12 @@ TEST_F(LocationDecorationTests, BadType_Input_Struct) {
|
||||
|
||||
TEST_F(LocationDecorationTests, BadType_Input_Struct_NestedStruct) {
|
||||
// struct Inner {
|
||||
// [[location(0)]] b : f32;
|
||||
// @location(0) b : f32;
|
||||
// };
|
||||
// struct Input {
|
||||
// a : Inner;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn main(param : Input) {}
|
||||
auto* inner = Structure(
|
||||
"Inner", {Member(Source{{13, 43}}, "a", ty.f32(), {Location(0)})});
|
||||
@@ -542,9 +542,9 @@ TEST_F(LocationDecorationTests, BadType_Input_Struct_NestedStruct) {
|
||||
TEST_F(LocationDecorationTests, BadType_Input_Struct_RuntimeArray) {
|
||||
// [[block]]
|
||||
// struct Input {
|
||||
// [[location(0)]] a : array<f32>;
|
||||
// @location(0) a : array<f32>;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn main(param : Input) {}
|
||||
auto* input = Structure(
|
||||
"Input",
|
||||
@@ -564,8 +564,8 @@ TEST_F(LocationDecorationTests, BadType_Input_Struct_RuntimeArray) {
|
||||
|
||||
TEST_F(LocationDecorationTests, BadMemberType_Input) {
|
||||
// [[block]]
|
||||
// struct S { [[location(0)]] m: array<i32>; };
|
||||
// [[stage(fragment)]]
|
||||
// struct S { @location(0) m: array<i32>; };
|
||||
// @stage(fragment)
|
||||
// fn frag_main( a: S) {}
|
||||
|
||||
auto* m = Member(Source{{34, 56}}, "m", ty.array<i32>(),
|
||||
@@ -585,8 +585,8 @@ TEST_F(LocationDecorationTests, BadMemberType_Input) {
|
||||
}
|
||||
|
||||
TEST_F(LocationDecorationTests, BadMemberType_Output) {
|
||||
// struct S { [[location(0)]] m: atomic<i32>; };
|
||||
// [[stage(fragment)]]
|
||||
// struct S { @location(0) m: atomic<i32>; };
|
||||
// @stage(fragment)
|
||||
// fn frag_main() -> S {}
|
||||
auto* m = Member(Source{{34, 56}}, "m", ty.atomic<i32>(),
|
||||
ast::DecorationList{Location(Source{{12, 34}}, 0u)});
|
||||
@@ -604,7 +604,7 @@ TEST_F(LocationDecorationTests, BadMemberType_Output) {
|
||||
}
|
||||
|
||||
TEST_F(LocationDecorationTests, BadMemberType_Unused) {
|
||||
// struct S { [[location(0)]] m: mat3x2<f32>; };
|
||||
// struct S { @location(0) m: mat3x2<f32>; };
|
||||
|
||||
auto* m = Member(Source{{34, 56}}, "m", ty.mat3x2<f32>(),
|
||||
ast::DecorationList{Location(Source{{12, 34}}, 0u)});
|
||||
@@ -620,10 +620,10 @@ TEST_F(LocationDecorationTests, BadMemberType_Unused) {
|
||||
|
||||
TEST_F(LocationDecorationTests, ReturnType_Struct_Valid) {
|
||||
// struct Output {
|
||||
// [[location(0)]] a : f32;
|
||||
// [[builtin(frag_depth)]] b : f32;
|
||||
// @location(0) a : f32;
|
||||
// @builtin(frag_depth) b : f32;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn main() -> Output {
|
||||
// return Output();
|
||||
// }
|
||||
@@ -641,8 +641,8 @@ TEST_F(LocationDecorationTests, ReturnType_Struct) {
|
||||
// struct Output {
|
||||
// a : f32;
|
||||
// };
|
||||
// [[stage(vertex)]]
|
||||
// fn main() -> [[location(0)]] Output {
|
||||
// @stage(vertex)
|
||||
// fn main() -> @location(0) Output {
|
||||
// return Output();
|
||||
// }
|
||||
auto* output = Structure("Output", {Member("a", ty.f32())});
|
||||
@@ -660,12 +660,12 @@ TEST_F(LocationDecorationTests, ReturnType_Struct) {
|
||||
|
||||
TEST_F(LocationDecorationTests, ReturnType_Struct_NestedStruct) {
|
||||
// struct Inner {
|
||||
// [[location(0)]] b : f32;
|
||||
// @location(0) b : f32;
|
||||
// };
|
||||
// struct Output {
|
||||
// a : Inner;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn main() -> Output { return Output(); }
|
||||
auto* inner = Structure(
|
||||
"Inner", {Member(Source{{13, 43}}, "a", ty.f32(), {Location(0)})});
|
||||
@@ -684,9 +684,9 @@ TEST_F(LocationDecorationTests, ReturnType_Struct_NestedStruct) {
|
||||
TEST_F(LocationDecorationTests, ReturnType_Struct_RuntimeArray) {
|
||||
// [[block]]
|
||||
// struct Output {
|
||||
// [[location(0)]] a : array<f32>;
|
||||
// @location(0) a : array<f32>;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn main() -> Output {
|
||||
// return Output();
|
||||
// }
|
||||
@@ -760,9 +760,9 @@ TEST_F(LocationDecorationTests, ComputeShaderLocationStructMember_Input) {
|
||||
}
|
||||
|
||||
TEST_F(LocationDecorationTests, Duplicate_input) {
|
||||
// [[stage(fragment)]]
|
||||
// fn main([[location(1)]] param_a : f32,
|
||||
// [[location(1)]] param_b : f32) {}
|
||||
// @stage(fragment)
|
||||
// fn main(@location(1) param_a : f32,
|
||||
// @location(1) param_b : f32) {}
|
||||
auto* param_a = Param("param_a", ty.f32(), {Location(1)});
|
||||
auto* param_b = Param("param_b", ty.f32(), {Location(Source{{12, 34}}, 1)});
|
||||
Func(Source{{12, 34}}, "main", {param_a, param_b}, ty.void_(), {},
|
||||
@@ -775,12 +775,12 @@ TEST_F(LocationDecorationTests, Duplicate_input) {
|
||||
|
||||
TEST_F(LocationDecorationTests, Duplicate_struct) {
|
||||
// struct InputA {
|
||||
// [[location(1)]] a : f32;
|
||||
// @location(1) a : f32;
|
||||
// };
|
||||
// struct InputB {
|
||||
// [[location(1)]] a : f32;
|
||||
// @location(1) a : f32;
|
||||
// };
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn main(param_a : InputA, param_b : InputB) {}
|
||||
auto* input_a = Structure("InputA", {Member("a", ty.f32(), {Location(1)})});
|
||||
auto* input_b = Structure(
|
||||
|
||||
@@ -353,7 +353,7 @@ TEST_F(ResolverFunctionValidationTest,
|
||||
}
|
||||
|
||||
TEST_F(ResolverFunctionValidationTest, CannotCallEntryPoint) {
|
||||
// [[stage(compute), workgroup_size(1)]] fn entrypoint() {}
|
||||
// @stage(compute) @workgroup_size(1) fn entrypoint() {}
|
||||
// fn func() { return entrypoint(); }
|
||||
Func("entrypoint", ast::VariableList{}, ty.void_(), {},
|
||||
{Stage(ast::PipelineStage::kCompute), WorkgroupSize(1)});
|
||||
@@ -371,8 +371,8 @@ TEST_F(ResolverFunctionValidationTest, CannotCallEntryPoint) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverFunctionValidationTest, PipelineStage_MustBeUnique_Fail) {
|
||||
// [[stage(fragment)]]
|
||||
// [[stage(vertex)]]
|
||||
// @stage(fragment)
|
||||
// @stage(vertex)
|
||||
// fn main() { return; }
|
||||
Func(Source{{12, 34}}, "main", ast::VariableList{}, ty.void_(),
|
||||
ast::StatementList{
|
||||
@@ -440,7 +440,7 @@ TEST_F(ResolverFunctionValidationTest, FunctionParamsConst) {
|
||||
TEST_F(ResolverFunctionValidationTest, WorkgroupSize_GoodType_ConstU32) {
|
||||
// let x = 4u;
|
||||
// let x = 8u;
|
||||
// [[stage(compute), workgroup_size(x, y, 16u)]]
|
||||
// @stage(compute) @workgroup_size(x, y, 16u)
|
||||
// fn main() {}
|
||||
auto* x = GlobalConst("x", ty.u32(), Expr(4u));
|
||||
auto* y = GlobalConst("y", ty.u32(), Expr(8u));
|
||||
|
||||
@@ -36,7 +36,7 @@ TEST_F(ResolverIntrinsicValidationTest,
|
||||
}
|
||||
|
||||
TEST_F(ResolverIntrinsicValidationTest, InvalidPipelineStageDirect) {
|
||||
// [[stage(compute), workgroup_size(1)]] fn func { return dpdx(1.0); }
|
||||
// @stage(compute) @workgroup_size(1) fn func { return dpdx(1.0); }
|
||||
|
||||
auto* dpdx = create<ast::CallExpression>(Source{{3, 4}}, Expr("dpdx"),
|
||||
ast::ExpressionList{Expr(1.0f)});
|
||||
@@ -53,7 +53,7 @@ TEST_F(ResolverIntrinsicValidationTest, InvalidPipelineStageIndirect) {
|
||||
// fn f0 { return dpdx(1.0); }
|
||||
// fn f1 { f0(); }
|
||||
// fn f2 { f1(); }
|
||||
// [[stage(compute), workgroup_size(1)]] fn main { return f2(); }
|
||||
// @stage(compute) @workgroup_size(1) fn main { return f2(); }
|
||||
|
||||
auto* dpdx = create<ast::CallExpression>(Source{{3, 4}}, Expr("dpdx"),
|
||||
ast::ExpressionList{Expr(1.0f)});
|
||||
|
||||
@@ -53,7 +53,7 @@ TEST_F(ResolverPtrRefValidationTest, AddressOfLet) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverPtrRefValidationTest, AddressOfHandle) {
|
||||
// [[group(0), binding(0)]] var t: texture_3d<f32>;
|
||||
// @group(0) @binding(0) var t: texture_3d<f32>;
|
||||
// &t
|
||||
Global("t", ty.sampled_texture(ast::TextureDimension::k3d, ty.f32()),
|
||||
GroupAndBinding(0u, 0u));
|
||||
@@ -95,7 +95,7 @@ TEST_F(ResolverPtrRefValidationTest, AddressOfVectorComponent_IndexAccessor) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverPtrRefValidationTest, IndirectOfAddressOfHandle) {
|
||||
// [[group(0), binding(0)]] var t: texture_3d<f32>;
|
||||
// @group(0) @binding(0) var t: texture_3d<f32>;
|
||||
// *&t
|
||||
Global("t", ty.sampled_texture(ast::TextureDimension::k3d, ty.f32()),
|
||||
GroupAndBinding(0u, 0u));
|
||||
@@ -142,7 +142,7 @@ TEST_F(ResolverPtrRefValidationTest, InferredPtrAccessMismatch) {
|
||||
// [[block]] struct S {
|
||||
// inner: Inner;
|
||||
// }
|
||||
// [[group(0), binding(0)]] var<storage, read_write> s : S;
|
||||
// @group(0) @binding(0) var<storage, read_write> s : S;
|
||||
// fn f() {
|
||||
// let p : pointer<storage, i32> = &s.inner.arr[2];
|
||||
// }
|
||||
|
||||
@@ -2151,7 +2151,7 @@ sem::Array* Resolver::Array(const ast::Array* arr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Look for explicit stride via [[stride(n)]] decoration
|
||||
// Look for explicit stride via @stride(n) decoration
|
||||
uint32_t explicit_stride = 0;
|
||||
for (auto* deco : arr->decorations) {
|
||||
Mark(deco);
|
||||
|
||||
@@ -920,7 +920,7 @@ TEST_F(ResolverTest, Function_CallSites) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverTest, Function_WorkgroupSize_NotSet) {
|
||||
// [[stage(compute), workgroup_size(1)]]
|
||||
// @stage(compute) @workgroup_size(1)
|
||||
// fn main() {}
|
||||
auto* func = Func("main", ast::VariableList{}, ty.void_(), {}, {});
|
||||
|
||||
@@ -938,7 +938,7 @@ TEST_F(ResolverTest, Function_WorkgroupSize_NotSet) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverTest, Function_WorkgroupSize_Literals) {
|
||||
// [[stage(compute), workgroup_size(8, 2, 3)]]
|
||||
// @stage(compute) @workgroup_size(8, 2, 3)
|
||||
// fn main() {}
|
||||
auto* func =
|
||||
Func("main", ast::VariableList{}, ty.void_(), {},
|
||||
@@ -961,7 +961,7 @@ TEST_F(ResolverTest, Function_WorkgroupSize_Consts) {
|
||||
// let width = 16;
|
||||
// let height = 8;
|
||||
// let depth = 2;
|
||||
// [[stage(compute), workgroup_size(width, height, depth)]]
|
||||
// @stage(compute) @workgroup_size(width, height, depth)
|
||||
// fn main() {}
|
||||
GlobalConst("width", ty.i32(), Expr(16));
|
||||
GlobalConst("height", ty.i32(), Expr(8));
|
||||
@@ -986,7 +986,7 @@ TEST_F(ResolverTest, Function_WorkgroupSize_Consts) {
|
||||
TEST_F(ResolverTest, Function_WorkgroupSize_Consts_NestedInitializer) {
|
||||
// let width = i32(i32(i32(8)));
|
||||
// let height = i32(i32(i32(4)));
|
||||
// [[stage(compute), workgroup_size(width, height)]]
|
||||
// @stage(compute) @workgroup_size(width, height)
|
||||
// fn main() {}
|
||||
GlobalConst("width", ty.i32(),
|
||||
Construct(ty.i32(), Construct(ty.i32(), Construct(ty.i32(), 8))));
|
||||
@@ -1010,10 +1010,10 @@ TEST_F(ResolverTest, Function_WorkgroupSize_Consts_NestedInitializer) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverTest, Function_WorkgroupSize_OverridableConsts) {
|
||||
// [[override(0)]] let width = 16;
|
||||
// [[override(1)]] let height = 8;
|
||||
// [[override(2)]] let depth = 2;
|
||||
// [[stage(compute), workgroup_size(width, height, depth)]]
|
||||
// @override(0) let width = 16;
|
||||
// @override(1) let height = 8;
|
||||
// @override(2) let depth = 2;
|
||||
// @stage(compute) @workgroup_size(width, height, depth)
|
||||
// fn main() {}
|
||||
auto* width = GlobalConst("width", ty.i32(), Expr(16), {Override(0)});
|
||||
auto* height = GlobalConst("height", ty.i32(), Expr(8), {Override(1)});
|
||||
@@ -1036,10 +1036,10 @@ TEST_F(ResolverTest, Function_WorkgroupSize_OverridableConsts) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverTest, Function_WorkgroupSize_OverridableConsts_NoInit) {
|
||||
// [[override(0)]] let width : i32;
|
||||
// [[override(1)]] let height : i32;
|
||||
// [[override(2)]] let depth : i32;
|
||||
// [[stage(compute), workgroup_size(width, height, depth)]]
|
||||
// @override(0) let width : i32;
|
||||
// @override(1) let height : i32;
|
||||
// @override(2) let depth : i32;
|
||||
// @stage(compute) @workgroup_size(width, height, depth)
|
||||
// fn main() {}
|
||||
auto* width = GlobalConst("width", ty.i32(), nullptr, {Override(0)});
|
||||
auto* height = GlobalConst("height", ty.i32(), nullptr, {Override(1)});
|
||||
@@ -1062,9 +1062,9 @@ TEST_F(ResolverTest, Function_WorkgroupSize_OverridableConsts_NoInit) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverTest, Function_WorkgroupSize_Mixed) {
|
||||
// [[override(1)]] let height = 2;
|
||||
// @override(1) let height = 2;
|
||||
// let depth = 3;
|
||||
// [[stage(compute), workgroup_size(8, height, depth)]]
|
||||
// @stage(compute) @workgroup_size(8, height, depth)
|
||||
// fn main() {}
|
||||
auto* height = GlobalConst("height", ty.i32(), Expr(2), {Override(0)});
|
||||
GlobalConst("depth", ty.i32(), Expr(3));
|
||||
@@ -1816,8 +1816,8 @@ TEST_F(ResolverTest, Access_SetForStorageBuffer) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverTest, BindingPoint_SetForResources) {
|
||||
// [[group(1), binding(2)]] var s1 : sampler;
|
||||
// [[group(3), binding(4)]] var s2 : sampler;
|
||||
// @group(1) @binding(2) var s1 : sampler;
|
||||
// @group(3) @binding(4) var s2 : sampler;
|
||||
auto* s1 = Global(Sym(), ty.sampler(ast::SamplerKind::kSampler),
|
||||
ast::DecorationList{create<ast::GroupDecoration>(1),
|
||||
create<ast::BindingDecoration>(2)});
|
||||
|
||||
@@ -271,8 +271,8 @@ bool Resolver::ValidateStorageClassLayout(const sem::Struct* str,
|
||||
"' must be a multiple of " + std::to_string(required_align) +
|
||||
" bytes, but '" + member_name_of(m) +
|
||||
"' is currently at offset " + std::to_string(m->Offset()) +
|
||||
". Consider setting [[align(" +
|
||||
std::to_string(required_align) + ")]] on this member",
|
||||
". Consider setting @align(" +
|
||||
std::to_string(required_align) + ") on this member",
|
||||
m->Declaration()->source);
|
||||
|
||||
AddNote("see layout of struct:\n" + str->Layout(builder_->Symbols()),
|
||||
@@ -299,7 +299,7 @@ bool Resolver::ValidateStorageClassLayout(const sem::Struct* str,
|
||||
"member be a multiple of 16 bytes, but there are currently " +
|
||||
std::to_string(prev_to_curr_offset) + " bytes between '" +
|
||||
member_name_of(prev_member) + "' and '" + member_name_of(m) +
|
||||
"'. Consider setting [[align(16)]] on this member",
|
||||
"'. Consider setting @align(16) on this member",
|
||||
m->Declaration()->source);
|
||||
|
||||
AddNote("see layout of struct:\n" + str->Layout(builder_->Symbols()),
|
||||
@@ -326,10 +326,10 @@ bool Resolver::ValidateStorageClassLayout(const sem::Struct* str,
|
||||
"bytes, but array stride of '" +
|
||||
member_name_of(m) + "' is currently " +
|
||||
std::to_string(arr->Stride()) +
|
||||
". Consider setting [[stride(" +
|
||||
". Consider setting @stride(" +
|
||||
std::to_string(
|
||||
utils::RoundUp(required_align, arr->Stride())) +
|
||||
")]] on the array type",
|
||||
") on the array type",
|
||||
m->Declaration()->type->source);
|
||||
AddNote("see layout of struct:\n" + str->Layout(builder_->Symbols()),
|
||||
str->Declaration()->source);
|
||||
@@ -429,7 +429,7 @@ bool Resolver::ValidateGlobalVariable(const sem::Variable* var) {
|
||||
// attributes.
|
||||
if (!binding_point) {
|
||||
AddError(
|
||||
"resource variables require [[group]] and [[binding]] "
|
||||
"resource variables require @group and @binding "
|
||||
"decorations",
|
||||
decl->source);
|
||||
return false;
|
||||
@@ -441,7 +441,7 @@ bool Resolver::ValidateGlobalVariable(const sem::Variable* var) {
|
||||
// https://gpuweb.github.io/gpuweb/wgsl/#attribute-binding
|
||||
// Must only be applied to a resource variable
|
||||
AddError(
|
||||
"non-resource variables must not have [[group]] or [[binding]] "
|
||||
"non-resource variables must not have @group or @binding "
|
||||
"decorations",
|
||||
decl->source);
|
||||
return false;
|
||||
@@ -1037,7 +1037,7 @@ bool Resolver::ValidateEntryPoint(const sem::Function* func) {
|
||||
if (interpolate_attribute) {
|
||||
if (!pipeline_io_attribute ||
|
||||
!pipeline_io_attribute->Is<ast::LocationDecoration>()) {
|
||||
AddError("interpolate attribute must only be used with [[location]]",
|
||||
AddError("interpolate attribute must only be used with @location",
|
||||
interpolate_attribute->source);
|
||||
return false;
|
||||
}
|
||||
@@ -1167,9 +1167,9 @@ bool Resolver::ValidateEntryPoint(const sem::Function* func) {
|
||||
auto func_name = builder_->Symbols().NameFor(decl->symbol);
|
||||
AddError("entry point '" + func_name +
|
||||
"' references multiple variables that use the "
|
||||
"same resource binding [[group(" +
|
||||
std::to_string(bp.group) + "), binding(" +
|
||||
std::to_string(bp.binding) + ")]]",
|
||||
"same resource binding @group(" +
|
||||
std::to_string(bp.group) + "), @binding(" +
|
||||
std::to_string(bp.binding) + ")",
|
||||
var_decl->source);
|
||||
AddNote("first resource binding usage declared here",
|
||||
res.first->second->source);
|
||||
@@ -2035,7 +2035,7 @@ bool Resolver::ValidateStructure(const sem::Struct* str) {
|
||||
}
|
||||
|
||||
if (interpolate_attribute && !has_location) {
|
||||
AddError("interpolate attribute must only be used with [[location]]",
|
||||
AddError("interpolate attribute must only be used with @location",
|
||||
interpolate_attribute->source);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -28,10 +28,10 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
StorageBuffer_UnalignedMember) {
|
||||
// [[block]]
|
||||
// struct S {
|
||||
// [[size(5)]] a : f32;
|
||||
// [[align(1)]] b : f32;
|
||||
// @size(5) a : f32;
|
||||
// @align(1) b : f32;
|
||||
// };
|
||||
// [[group(0), binding(0)]]
|
||||
// @group(0) @binding(0)
|
||||
// var<storage> a : S;
|
||||
|
||||
Structure(Source{{12, 34}}, "S",
|
||||
@@ -45,7 +45,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
ASSERT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(34:56 error: the offset of a struct member of type 'f32' in storage class 'storage' must be a multiple of 4 bytes, but 'b' is currently at offset 5. Consider setting [[align(4)]] on this member
|
||||
R"(34:56 error: the offset of a struct member of type 'f32' in storage class 'storage' must be a multiple of 4 bytes, but 'b' is currently at offset 5. Consider setting @align(4) on this member
|
||||
12:34 note: see layout of struct:
|
||||
/* align(4) size(12) */ struct S {
|
||||
/* offset(0) align(4) size( 5) */ a : f32;
|
||||
@@ -59,10 +59,10 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
StorageBuffer_UnalignedMember_SuggestedFix) {
|
||||
// [[block]]
|
||||
// struct S {
|
||||
// [[size(5)]] a : f32;
|
||||
// [[align(4)]] b : f32;
|
||||
// @size(5) a : f32;
|
||||
// @align(4) b : f32;
|
||||
// };
|
||||
// [[group(0), binding(0)]]
|
||||
// @group(0) @binding(0)
|
||||
// var<storage> a : S;
|
||||
|
||||
Structure(Source{{12, 34}}, "S",
|
||||
@@ -89,7 +89,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
// inner : Inner;
|
||||
// };
|
||||
//
|
||||
// [[group(0), binding(0)]]
|
||||
// @group(0) @binding(0)
|
||||
// var<uniform> a : Outer;
|
||||
|
||||
Structure(Source{{12, 34}}, "Inner", {Member("scalar", ty.i32())});
|
||||
@@ -107,7 +107,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
ASSERT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(56:78 error: the offset of a struct member of type 'Inner' in storage class 'uniform' must be a multiple of 16 bytes, but 'inner' is currently at offset 4. Consider setting [[align(16)]] on this member
|
||||
R"(56:78 error: the offset of a struct member of type 'Inner' in storage class 'uniform' must be a multiple of 16 bytes, but 'inner' is currently at offset 4. Consider setting @align(16) on this member
|
||||
34:56 note: see layout of struct:
|
||||
/* align(4) size(8) */ struct Outer {
|
||||
/* offset(0) align(4) size(4) */ scalar : f32;
|
||||
@@ -129,10 +129,10 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
// [[block]]
|
||||
// struct Outer {
|
||||
// scalar : f32;
|
||||
// [[align(16)]] inner : Inner;
|
||||
// @align(16) inner : Inner;
|
||||
// };
|
||||
//
|
||||
// [[group(0), binding(0)]]
|
||||
// @group(0) @binding(0)
|
||||
// var<uniform> a : Outer;
|
||||
|
||||
Structure(Source{{12, 34}}, "Inner", {Member("scalar", ty.i32())});
|
||||
@@ -154,7 +154,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
// Detect unaligned array member for uniform buffers
|
||||
TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
UniformBuffer_UnalignedMember_Array) {
|
||||
// type Inner = [[stride(16)]] array<f32, 10>;
|
||||
// type Inner = @stride(16) array<f32, 10>;
|
||||
//
|
||||
// [[block]]
|
||||
// struct Outer {
|
||||
@@ -162,7 +162,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
// inner : Inner;
|
||||
// };
|
||||
//
|
||||
// [[group(0), binding(0)]]
|
||||
// @group(0) @binding(0)
|
||||
// var<uniform> a : Outer;
|
||||
Alias("Inner", ty.array(ty.f32(), 10, 16));
|
||||
|
||||
@@ -179,26 +179,26 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
ASSERT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(56:78 error: the offset of a struct member of type '[[stride(16)]] array<f32, 10>' in storage class 'uniform' must be a multiple of 16 bytes, but 'inner' is currently at offset 4. Consider setting [[align(16)]] on this member
|
||||
R"(56:78 error: the offset of a struct member of type '@stride(16) array<f32, 10>' in storage class 'uniform' must be a multiple of 16 bytes, but 'inner' is currently at offset 4. Consider setting @align(16) on this member
|
||||
12:34 note: see layout of struct:
|
||||
/* align(4) size(164) */ struct Outer {
|
||||
/* offset( 0) align(4) size( 4) */ scalar : f32;
|
||||
/* offset( 4) align(4) size(160) */ inner : [[stride(16)]] array<f32, 10>;
|
||||
/* offset( 4) align(4) size(160) */ inner : @stride(16) array<f32, 10>;
|
||||
/* */ };
|
||||
78:90 note: see declaration of variable)");
|
||||
}
|
||||
|
||||
TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
UniformBuffer_UnalignedMember_Array_SuggestedFix) {
|
||||
// type Inner = [[stride(16)]] array<f32, 10>;
|
||||
// type Inner = @stride(16) array<f32, 10>;
|
||||
//
|
||||
// [[block]]
|
||||
// struct Outer {
|
||||
// scalar : f32;
|
||||
// [[align(16)]] inner : Inner;
|
||||
// @align(16) inner : Inner;
|
||||
// };
|
||||
//
|
||||
// [[group(0), binding(0)]]
|
||||
// @group(0) @binding(0)
|
||||
// var<uniform> a : Outer;
|
||||
Alias("Inner", ty.array(ty.f32(), 10, 16));
|
||||
|
||||
@@ -221,7 +221,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
UniformBuffer_MembersOffsetNotMultipleOf16) {
|
||||
// struct Inner {
|
||||
// [[align(1), size(5)]] scalar : i32;
|
||||
// @align(1) @size(5) scalar : i32;
|
||||
// };
|
||||
//
|
||||
// [[block]]
|
||||
@@ -230,7 +230,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
// scalar : i32;
|
||||
// };
|
||||
//
|
||||
// [[group(0), binding(0)]]
|
||||
// @group(0) @binding(0)
|
||||
// var<uniform> a : Outer;
|
||||
|
||||
Structure(Source{{12, 34}}, "Inner",
|
||||
@@ -249,7 +249,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
ASSERT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(78:90 error: uniform storage requires that the number of bytes between the start of the previous member of type struct and the current member be a multiple of 16 bytes, but there are currently 8 bytes between 'inner' and 'scalar'. Consider setting [[align(16)]] on this member
|
||||
R"(78:90 error: uniform storage requires that the number of bytes between the start of the previous member of type struct and the current member be a multiple of 16 bytes, but there are currently 8 bytes between 'inner' and 'scalar'. Consider setting @align(16) on this member
|
||||
34:56 note: see layout of struct:
|
||||
/* align(4) size(12) */ struct Outer {
|
||||
/* offset( 0) align(1) size( 5) */ inner : Inner;
|
||||
@@ -270,7 +270,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
// a : i32;
|
||||
// b : i32;
|
||||
// c : i32;
|
||||
// [[align(1), size(5)]] scalar : i32;
|
||||
// @align(1) @size(5) scalar : i32;
|
||||
// };
|
||||
//
|
||||
// [[block]]
|
||||
@@ -279,7 +279,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
// scalar : i32;
|
||||
// };
|
||||
//
|
||||
// [[group(0), binding(0)]]
|
||||
// @group(0) @binding(0)
|
||||
// var<uniform> a : Outer;
|
||||
|
||||
Structure(Source{{12, 34}}, "Inner",
|
||||
@@ -303,7 +303,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
ASSERT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(78:90 error: uniform storage requires that the number of bytes between the start of the previous member of type struct and the current member be a multiple of 16 bytes, but there are currently 20 bytes between 'inner' and 'scalar'. Consider setting [[align(16)]] on this member
|
||||
R"(78:90 error: uniform storage requires that the number of bytes between the start of the previous member of type struct and the current member be a multiple of 16 bytes, but there are currently 20 bytes between 'inner' and 'scalar'. Consider setting @align(16) on this member
|
||||
34:56 note: see layout of struct:
|
||||
/* align(4) size(24) */ struct Outer {
|
||||
/* offset( 0) align(4) size(20) */ inner : Inner;
|
||||
@@ -323,16 +323,16 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
UniformBuffer_MembersOffsetNotMultipleOf16_SuggestedFix) {
|
||||
// struct Inner {
|
||||
// [[align(1), size(5)]] scalar : i32;
|
||||
// @align(1) @size(5) scalar : i32;
|
||||
// };
|
||||
//
|
||||
// [[block]]
|
||||
// struct Outer {
|
||||
// [[align(16)]] inner : Inner;
|
||||
// @align(16) inner : Inner;
|
||||
// scalar : i32;
|
||||
// };
|
||||
//
|
||||
// [[group(0), binding(0)]]
|
||||
// @group(0) @binding(0)
|
||||
// var<uniform> a : Outer;
|
||||
|
||||
Structure(Source{{12, 34}}, "Inner",
|
||||
@@ -360,7 +360,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
// v : vec3<f32>;
|
||||
// s : f32;
|
||||
// };
|
||||
// [[group(0), binding(0)]]
|
||||
// @group(0) @binding(0)
|
||||
// var<uniform> a : ScalarPackedAtEndOfVec3;
|
||||
|
||||
Structure("ScalarPackedAtEndOfVec3",
|
||||
@@ -379,7 +379,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
// Detect array stride must be a multiple of 16 bytes for uniform buffers
|
||||
TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
UniformBuffer_InvalidArrayStride) {
|
||||
// type Inner = [[stride(8)]] array<f32, 10>;
|
||||
// type Inner = @stride(8) array<f32, 10>;
|
||||
//
|
||||
// [[block]]
|
||||
// struct Outer {
|
||||
@@ -387,7 +387,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
// scalar : i32;
|
||||
// };
|
||||
//
|
||||
// [[group(0), binding(0)]]
|
||||
// @group(0) @binding(0)
|
||||
// var<uniform> a : Outer;
|
||||
|
||||
Alias("Inner", ty.array(ty.f32(), 10, 8));
|
||||
@@ -405,10 +405,10 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
ASSERT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(34:56 error: uniform storage requires that array elements be aligned to 16 bytes, but array stride of 'inner' is currently 8. Consider setting [[stride(16)]] on the array type
|
||||
R"(34:56 error: uniform storage requires that array elements be aligned to 16 bytes, but array stride of 'inner' is currently 8. Consider setting @stride(16) on the array type
|
||||
12:34 note: see layout of struct:
|
||||
/* align(4) size(84) */ struct Outer {
|
||||
/* offset( 0) align(4) size(80) */ inner : [[stride(8)]] array<f32, 10>;
|
||||
/* offset( 0) align(4) size(80) */ inner : @stride(8) array<f32, 10>;
|
||||
/* offset(80) align(4) size( 4) */ scalar : i32;
|
||||
/* */ };
|
||||
78:90 note: see declaration of variable)");
|
||||
@@ -416,7 +416,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
|
||||
TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
UniformBuffer_InvalidArrayStride_SuggestedFix) {
|
||||
// type Inner = [[stride(16)]] array<f32, 10>;
|
||||
// type Inner = @stride(16) array<f32, 10>;
|
||||
//
|
||||
// [[block]]
|
||||
// struct Outer {
|
||||
@@ -424,7 +424,7 @@ TEST_F(ResolverStorageClassLayoutValidationTest,
|
||||
// scalar : i32;
|
||||
// };
|
||||
//
|
||||
// [[group(0), binding(0)]]
|
||||
// @group(0) @binding(0)
|
||||
// var<uniform> a : Outer;
|
||||
|
||||
Alias("Inner", ty.array(ty.f32(), 10, 16));
|
||||
|
||||
@@ -226,7 +226,7 @@ TEST_F(ResolverStorageClassValidationTest, StorageBufferNoError_Aliases) {
|
||||
|
||||
TEST_F(ResolverStorageClassValidationTest, UniformBuffer_Struct_Runtime) {
|
||||
// [[block]] struct S { m: array<f32>; };
|
||||
// [[group(0), binding(0)]] var<uniform, > svar : S;
|
||||
// @group(0) @binding(0) var<uniform, > svar : S;
|
||||
|
||||
auto* s = Structure(Source{{12, 34}}, "S", {Member("m", ty.array<i32>())},
|
||||
{create<ast::StructBlockDecoration>()});
|
||||
|
||||
@@ -79,7 +79,7 @@ TEST_F(ResolverTypeValidationTest, VariableDeclNoConstructor_Pass) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, GlobalConstantNoConstructor_Pass) {
|
||||
// [[override(0)]] let a :i32;
|
||||
// @override(0) let a :i32;
|
||||
GlobalConst(Source{{12, 34}}, "a", ty.i32(), nullptr,
|
||||
ast::DecorationList{create<ast::OverrideDecoration>(0)});
|
||||
|
||||
@@ -336,7 +336,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_TooBig_ImplicitStride) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, ArraySize_TooBig_ExplicitStride) {
|
||||
// var<private> a : [[stride(8)]] array<f32, 0x20000000>;
|
||||
// var<private> a : @stride(8) array<f32, 0x20000000>;
|
||||
Global("a", ty.array(Source{{12, 34}}, ty.f32(), 0x20000000, 8),
|
||||
ast::StorageClass::kPrivate);
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
@@ -396,7 +396,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_InvalidExpr) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, RuntimeArrayInFunction_Fail) {
|
||||
/// [[stage(vertex)]]
|
||||
/// @stage(vertex)
|
||||
// fn func() { var a : array<i32>; }
|
||||
|
||||
auto* var =
|
||||
@@ -594,7 +594,7 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayAsLocalVariable) {
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, RuntimeArrayAsParameter_Fail) {
|
||||
// fn func(a : array<u32>) {}
|
||||
// [[stage(vertex)]] fn main() {}
|
||||
// @stage(vertex) fn main() {}
|
||||
|
||||
auto* param = Param(Source{{12, 34}}, "a", ty.array<i32>());
|
||||
|
||||
@@ -855,7 +855,7 @@ static constexpr DimensionParams Dimension_cases[] = {
|
||||
|
||||
using StorageTextureDimensionTest = ResolverTestWithParam<DimensionParams>;
|
||||
TEST_P(StorageTextureDimensionTest, All) {
|
||||
// [[group(0), binding(0)]]
|
||||
// @group(0) @binding(0)
|
||||
// var a : texture_storage_*<ru32int, write>;
|
||||
auto& params = GetParam();
|
||||
|
||||
@@ -905,13 +905,13 @@ static constexpr FormatParams format_cases[] = {
|
||||
using StorageTextureFormatTest = ResolverTestWithParam<FormatParams>;
|
||||
TEST_P(StorageTextureFormatTest, All) {
|
||||
auto& params = GetParam();
|
||||
// [[group(0), binding(0)]]
|
||||
// @group(0) @binding(0)
|
||||
// var a : texture_storage_1d<*, write>;
|
||||
// [[group(0), binding(1)]]
|
||||
// @group(0) @binding(1)
|
||||
// var b : texture_storage_2d<*, write>;
|
||||
// [[group(0), binding(2)]]
|
||||
// @group(0) @binding(2)
|
||||
// var c : texture_storage_2d_array<*, write>;
|
||||
// [[group(0), binding(3)]]
|
||||
// @group(0) @binding(3)
|
||||
// var d : texture_storage_3d<*, write>;
|
||||
|
||||
auto* st_a = ty.storage_texture(Source{{12, 34}}, ast::TextureDimension::k1d,
|
||||
@@ -951,7 +951,7 @@ INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
|
||||
using StorageTextureAccessTest = ResolverTest;
|
||||
|
||||
TEST_F(StorageTextureAccessTest, MissingAccess_Fail) {
|
||||
// [[group(0), binding(0)]]
|
||||
// @group(0) @binding(0)
|
||||
// var a : texture_storage_1d<ru32int>;
|
||||
|
||||
auto* st =
|
||||
@@ -967,7 +967,7 @@ TEST_F(StorageTextureAccessTest, MissingAccess_Fail) {
|
||||
}
|
||||
|
||||
TEST_F(StorageTextureAccessTest, RWAccess_Fail) {
|
||||
// [[group(0), binding(0)]]
|
||||
// @group(0) @binding(0)
|
||||
// var a : texture_storage_1d<ru32int, read_write>;
|
||||
|
||||
auto* st =
|
||||
@@ -984,7 +984,7 @@ TEST_F(StorageTextureAccessTest, RWAccess_Fail) {
|
||||
}
|
||||
|
||||
TEST_F(StorageTextureAccessTest, ReadOnlyAccess_Fail) {
|
||||
// [[group(0), binding(0)]]
|
||||
// @group(0) @binding(0)
|
||||
// var a : texture_storage_1d<ru32int, read>;
|
||||
|
||||
auto* st = ty.storage_texture(Source{{12, 34}}, ast::TextureDimension::k1d,
|
||||
@@ -1000,7 +1000,7 @@ TEST_F(StorageTextureAccessTest, ReadOnlyAccess_Fail) {
|
||||
}
|
||||
|
||||
TEST_F(StorageTextureAccessTest, WriteOnlyAccess_Pass) {
|
||||
// [[group(0), binding(0)]]
|
||||
// @group(0) @binding(0)
|
||||
// var a : texture_storage_1d<ru32int, write>;
|
||||
|
||||
auto* st =
|
||||
|
||||
@@ -80,7 +80,7 @@ TEST_F(ResolverValidationTest, WorkgroupMemoryUsedInFragmentStage) {
|
||||
// var<workgroup> dst : vec4<f32>;
|
||||
// fn f2(){ dst = wg; }
|
||||
// fn f1() { f2(); }
|
||||
// [[stage(fragment)]]
|
||||
// @stage(fragment)
|
||||
// fn f0() {
|
||||
// f1();
|
||||
//}
|
||||
|
||||
@@ -288,7 +288,7 @@ TEST_F(ResolverVarLetTest, LetInheritsAccessFromOriginatingVariable) {
|
||||
// [[block]] struct S {
|
||||
// inner: Inner;
|
||||
// }
|
||||
// [[group(0), binding(0)]] var<storage, read_write> s : S;
|
||||
// @group(0) @binding(0) var<storage, read_write> s : S;
|
||||
// fn f() {
|
||||
// let p = &s.inner.arr[2];
|
||||
// }
|
||||
|
||||
@@ -79,7 +79,7 @@ TEST_F(ResolverVarLetValidationTest, VarTypeNotStorable) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverVarLetValidationTest, LetTypeNotConstructible) {
|
||||
// [[group(0), binding(0)]] var t1 : texture_2d<f32>;
|
||||
// @group(0) @binding(0) var t1 : texture_2d<f32>;
|
||||
// let t2 : t1;
|
||||
auto* t1 =
|
||||
Global("t1", ty.sampled_texture(ast::TextureDimension::k2d, ty.f32()),
|
||||
@@ -223,7 +223,7 @@ TEST_F(ResolverVarLetValidationTest, InferredPtrStorageAccessMismatch) {
|
||||
// [[block]] struct S {
|
||||
// inner: Inner;
|
||||
// }
|
||||
// [[group(0), binding(0)]] var<storage> s : S;
|
||||
// @group(0) @binding(0) var<storage> s : S;
|
||||
// fn f() {
|
||||
// let p : pointer<storage, i32, read_write> = &s.inner.arr[2];
|
||||
// }
|
||||
@@ -286,7 +286,7 @@ TEST_F(ResolverVarLetValidationTest, NonConstructibleType_Struct_WithAtomic) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverVarLetValidationTest, NonConstructibleType_InferredType) {
|
||||
// [[group(0), binding(0)]] var s : sampler;
|
||||
// @group(0) @binding(0) var s : sampler;
|
||||
// fn foo() {
|
||||
// var v = s;
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user