validation: invariant attribute on struct members
Bug: tint:1008 Change-Id: If3c398b01952f6b482c60cf86ab8ddf724d385a9 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/59060 Auto-Submit: Sarah Mashayekhi <sarahmashay@google.com> Commit-Queue: James Price <jrprice@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: James Price <jrprice@google.com>
This commit is contained in:
parent
f3fffdaded
commit
a4696681eb
|
@ -197,7 +197,6 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
TestParams{DecorationKind::kBuiltin, true},
|
TestParams{DecorationKind::kBuiltin, true},
|
||||||
TestParams{DecorationKind::kGroup, false},
|
TestParams{DecorationKind::kGroup, false},
|
||||||
TestParams{DecorationKind::kInterpolate, true},
|
TestParams{DecorationKind::kInterpolate, true},
|
||||||
// TODO(crbug.com/tint/1008)
|
|
||||||
// kInvariant tested separately (requires position builtin)
|
// kInvariant tested separately (requires position builtin)
|
||||||
TestParams{DecorationKind::kLocation, true},
|
TestParams{DecorationKind::kLocation, true},
|
||||||
TestParams{DecorationKind::kOverride, false},
|
TestParams{DecorationKind::kOverride, false},
|
||||||
|
@ -252,6 +251,34 @@ TEST_F(EntryPointParameterDecorationTest, ComputeShaderLocation) {
|
||||||
"parameters");
|
"parameters");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(EntryPointParameterDecorationTest, InvariantWithPosition) {
|
||||||
|
auto* param = Param("p", ty.vec4<f32>(),
|
||||||
|
{Invariant(Source{{12, 34}}),
|
||||||
|
Builtin(Source{{56, 78}}, ast::Builtin::kPosition)});
|
||||||
|
Func("main", ast::VariableList{param}, ty.vec4<f32>(),
|
||||||
|
ast::StatementList{Return(Construct(ty.vec4<f32>()))},
|
||||||
|
ast::DecorationList{Stage(ast::PipelineStage::kFragment)},
|
||||||
|
ast::DecorationList{
|
||||||
|
Location(0),
|
||||||
|
});
|
||||||
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(EntryPointParameterDecorationTest, InvariantWithoutPosition) {
|
||||||
|
auto* param =
|
||||||
|
Param("p", ty.vec4<f32>(), {Invariant(Source{{12, 34}}), Location(0)});
|
||||||
|
Func("main", ast::VariableList{param}, ty.vec4<f32>(),
|
||||||
|
ast::StatementList{Return(Construct(ty.vec4<f32>()))},
|
||||||
|
ast::DecorationList{Stage(ast::PipelineStage::kFragment)},
|
||||||
|
ast::DecorationList{
|
||||||
|
Location(0),
|
||||||
|
});
|
||||||
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
EXPECT_EQ(r()->error(),
|
||||||
|
"12:34 error: invariant attribute must only be applied to a "
|
||||||
|
"position builtin");
|
||||||
|
}
|
||||||
|
|
||||||
using FunctionReturnTypeDecorationTest = TestWithParams;
|
using FunctionReturnTypeDecorationTest = TestWithParams;
|
||||||
TEST_P(FunctionReturnTypeDecorationTest, IsValid) {
|
TEST_P(FunctionReturnTypeDecorationTest, IsValid) {
|
||||||
auto& params = GetParam();
|
auto& params = GetParam();
|
||||||
|
@ -359,7 +386,7 @@ TEST_F(EntryPointReturnTypeDecorationTest, InvariantWithPosition) {
|
||||||
TEST_F(EntryPointReturnTypeDecorationTest, InvariantWithoutPosition) {
|
TEST_F(EntryPointReturnTypeDecorationTest, InvariantWithoutPosition) {
|
||||||
Func("main", ast::VariableList{}, ty.vec4<f32>(),
|
Func("main", ast::VariableList{}, ty.vec4<f32>(),
|
||||||
ast::StatementList{Return(Construct(ty.vec4<f32>()))},
|
ast::StatementList{Return(Construct(ty.vec4<f32>()))},
|
||||||
ast::DecorationList{Stage(ast::PipelineStage::kFragment)},
|
ast::DecorationList{Stage(ast::PipelineStage::kVertex)},
|
||||||
ast::DecorationList{
|
ast::DecorationList{
|
||||||
Invariant(Source{{12, 34}}),
|
Invariant(Source{{12, 34}}),
|
||||||
Location(Source{{56, 78}}, 0),
|
Location(Source{{56, 78}}, 0),
|
||||||
|
@ -501,7 +528,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
TestParams{DecorationKind::kBuiltin, true},
|
TestParams{DecorationKind::kBuiltin, true},
|
||||||
TestParams{DecorationKind::kGroup, false},
|
TestParams{DecorationKind::kGroup, false},
|
||||||
TestParams{DecorationKind::kInterpolate, true},
|
TestParams{DecorationKind::kInterpolate, true},
|
||||||
TestParams{DecorationKind::kInvariant, true},
|
// kInvariant tested separately (requires position builtin)
|
||||||
TestParams{DecorationKind::kLocation, true},
|
TestParams{DecorationKind::kLocation, true},
|
||||||
TestParams{DecorationKind::kOverride, false},
|
TestParams{DecorationKind::kOverride, false},
|
||||||
TestParams{DecorationKind::kOffset, true},
|
TestParams{DecorationKind::kOffset, true},
|
||||||
|
@ -531,6 +558,34 @@ TEST_F(StructMemberDecorationTest, DuplicateDecoration) {
|
||||||
12:34 note: first decoration declared here)");
|
12:34 note: first decoration declared here)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(StructMemberDecorationTest, InvariantDecorationWithPosition) {
|
||||||
|
Structure("mystruct", {
|
||||||
|
Member("a", ty.vec4<f32>(),
|
||||||
|
{
|
||||||
|
Invariant(),
|
||||||
|
Builtin(ast::Builtin::kPosition),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
WrapInFunction();
|
||||||
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(StructMemberDecorationTest, InvariantDecorationWithoutPosition) {
|
||||||
|
Structure("mystruct", {
|
||||||
|
Member("a", ty.vec4<f32>(),
|
||||||
|
{
|
||||||
|
Invariant(Source{{12, 34}}),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
WrapInFunction();
|
||||||
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
EXPECT_EQ(r()->error(),
|
||||||
|
"12:34 error: invariant attribute must only be applied to a "
|
||||||
|
"position builtin");
|
||||||
|
}
|
||||||
|
|
||||||
using VariableDecorationTest = TestWithParams;
|
using VariableDecorationTest = TestWithParams;
|
||||||
TEST_P(VariableDecorationTest, IsValid) {
|
TEST_P(VariableDecorationTest, IsValid) {
|
||||||
auto& params = GetParam();
|
auto& params = GetParam();
|
||||||
|
|
|
@ -1149,7 +1149,7 @@ bool Resolver::ValidateFunctionParameter(const ast::Function* func,
|
||||||
deco->source());
|
deco->source());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (!deco->IsAnyOf<ast::BuiltinDecoration,
|
} else if (!deco->IsAnyOf<ast::BuiltinDecoration, ast::InvariantDecoration,
|
||||||
ast::InternalDecoration>() &&
|
ast::InternalDecoration>() &&
|
||||||
(IsValidationEnabled(
|
(IsValidationEnabled(
|
||||||
info->declaration->decorations(),
|
info->declaration->decorations(),
|
||||||
|
@ -3896,6 +3896,8 @@ bool Resolver::ValidateStructure(const sem::Struct* str) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto has_position = false;
|
||||||
|
ast::InvariantDecoration* invariant_attribute = nullptr;
|
||||||
for (auto* deco : member->Declaration()->decorations()) {
|
for (auto* deco : member->Declaration()->decorations()) {
|
||||||
if (!(deco->Is<ast::BuiltinDecoration>() ||
|
if (!(deco->Is<ast::BuiltinDecoration>() ||
|
||||||
deco->Is<ast::InterpolateDecoration>() ||
|
deco->Is<ast::InterpolateDecoration>() ||
|
||||||
|
@ -3908,10 +3910,16 @@ bool Resolver::ValidateStructure(const sem::Struct* str) {
|
||||||
deco->source());
|
deco->source());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (auto* invariant = deco->As<ast::InvariantDecoration>()) {
|
||||||
|
invariant_attribute = invariant;
|
||||||
|
}
|
||||||
if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
|
if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
|
||||||
if (!ValidateBuiltinDecoration(builtin, member->Type())) {
|
if (!ValidateBuiltinDecoration(builtin, member->Type())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (builtin->value() == ast::Builtin::kPosition) {
|
||||||
|
has_position = true;
|
||||||
|
}
|
||||||
} else if (auto* interpolate = deco->As<ast::InterpolateDecoration>()) {
|
} else if (auto* interpolate = deco->As<ast::InterpolateDecoration>()) {
|
||||||
if (!ValidateInterpolateDecoration(interpolate, member->Type())) {
|
if (!ValidateInterpolateDecoration(interpolate, member->Type())) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -3919,6 +3927,12 @@ bool Resolver::ValidateStructure(const sem::Struct* str) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (invariant_attribute && !has_position) {
|
||||||
|
AddError("invariant attribute must only be applied to a position builtin",
|
||||||
|
invariant_attribute->source());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (auto* member_struct_type = member->Type()->As<sem::Struct>()) {
|
if (auto* member_struct_type = member->Type()->As<sem::Struct>()) {
|
||||||
if (auto* member_struct_type_block_decoration =
|
if (auto* member_struct_type_block_decoration =
|
||||||
ast::GetDecoration<ast::StructBlockDecoration>(
|
ast::GetDecoration<ast::StructBlockDecoration>(
|
||||||
|
|
Loading…
Reference in New Issue