validation: Validate invariant attribute
This is only valid on structure members and entry point return types. Additionally, this can only be applied to a position builtin. Bug: tint:772 Change-Id: Iffd774ca768ab66373678ecf0eb57c766767e92b Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/57641 Commit-Queue: Ben Clayton <bclayton@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
2e6fefb858
commit
508d2491d0
|
@ -39,6 +39,7 @@
|
|||
#include "src/ast/i32.h"
|
||||
#include "src/ast/if_statement.h"
|
||||
#include "src/ast/interpolate_decoration.h"
|
||||
#include "src/ast/invariant_decoration.h"
|
||||
#include "src/ast/loop_statement.h"
|
||||
#include "src/ast/matrix.h"
|
||||
#include "src/ast/member_accessor_expression.h"
|
||||
|
@ -2042,6 +2043,19 @@ class ProgramBuilder {
|
|||
return create<ast::InterpolateDecoration>(source_, type, sampling);
|
||||
}
|
||||
|
||||
/// Creates an ast::InvariantDecoration
|
||||
/// @param source the source information
|
||||
/// @returns the invariant decoration pointer
|
||||
ast::InvariantDecoration* Invariant(const Source& source) {
|
||||
return create<ast::InvariantDecoration>(source);
|
||||
}
|
||||
|
||||
/// Creates an ast::InvariantDecoration
|
||||
/// @returns the invariant decoration pointer
|
||||
ast::InvariantDecoration* Invariant() {
|
||||
return create<ast::InvariantDecoration>(source_);
|
||||
}
|
||||
|
||||
/// Creates an ast::LocationDecoration
|
||||
/// @param source the source information
|
||||
/// @param location the location value
|
||||
|
|
|
@ -62,6 +62,7 @@ enum class DecorationKind {
|
|||
kBuiltin,
|
||||
kGroup,
|
||||
kInterpolate,
|
||||
kInvariant,
|
||||
kLocation,
|
||||
kOverride,
|
||||
kOffset,
|
||||
|
@ -107,6 +108,8 @@ static ast::DecorationList createDecorations(const Source& source,
|
|||
return {builder.Interpolate(source, ast::InterpolationType::kLinear,
|
||||
ast::InterpolationSampling::kCenter),
|
||||
builder.Location(0)};
|
||||
case DecorationKind::kInvariant:
|
||||
return {builder.Invariant(source)};
|
||||
case DecorationKind::kLocation:
|
||||
return {builder.Location(source, 1)};
|
||||
case DecorationKind::kOverride:
|
||||
|
@ -157,6 +160,7 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{DecorationKind::kBuiltin, false},
|
||||
TestParams{DecorationKind::kGroup, false},
|
||||
TestParams{DecorationKind::kInterpolate, false},
|
||||
TestParams{DecorationKind::kInvariant, false},
|
||||
TestParams{DecorationKind::kLocation, false},
|
||||
TestParams{DecorationKind::kOverride, false},
|
||||
TestParams{DecorationKind::kOffset, false},
|
||||
|
@ -193,6 +197,7 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{DecorationKind::kBuiltin, true},
|
||||
TestParams{DecorationKind::kGroup, false},
|
||||
TestParams{DecorationKind::kInterpolate, true},
|
||||
TestParams{DecorationKind::kInvariant, false},
|
||||
TestParams{DecorationKind::kLocation, true},
|
||||
TestParams{DecorationKind::kOverride, false},
|
||||
TestParams{DecorationKind::kOffset, false},
|
||||
|
@ -257,6 +262,7 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{DecorationKind::kBuiltin, false},
|
||||
TestParams{DecorationKind::kGroup, false},
|
||||
TestParams{DecorationKind::kInterpolate, false},
|
||||
TestParams{DecorationKind::kInvariant, false},
|
||||
TestParams{DecorationKind::kLocation, false},
|
||||
TestParams{DecorationKind::kOverride, false},
|
||||
TestParams{DecorationKind::kOffset, false},
|
||||
|
@ -293,6 +299,7 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{DecorationKind::kBuiltin, true},
|
||||
TestParams{DecorationKind::kGroup, false},
|
||||
TestParams{DecorationKind::kInterpolate, true},
|
||||
// kInvariant tested separately (requires position builtin)
|
||||
TestParams{DecorationKind::kLocation, true},
|
||||
TestParams{DecorationKind::kOverride, false},
|
||||
TestParams{DecorationKind::kOffset, false},
|
||||
|
@ -317,6 +324,32 @@ TEST_F(EntryPointReturnTypeDecorationTest, DuplicateDecoration) {
|
|||
12:34 note: first decoration declared here)");
|
||||
}
|
||||
|
||||
TEST_F(EntryPointReturnTypeDecorationTest, InvariantWithPosition) {
|
||||
Func("main", ast::VariableList{}, ty.vec4<f32>(),
|
||||
ast::StatementList{Return(Construct(ty.vec4<f32>()))},
|
||||
ast::DecorationList{Stage(ast::PipelineStage::kVertex)},
|
||||
ast::DecorationList{
|
||||
Invariant(Source{{12, 34}}),
|
||||
Builtin(Source{{56, 78}}, ast::Builtin::kPosition),
|
||||
});
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
}
|
||||
|
||||
TEST_F(EntryPointReturnTypeDecorationTest, InvariantWithoutPosition) {
|
||||
Func("main", ast::VariableList{}, ty.vec4<f32>(),
|
||||
ast::StatementList{Return(Construct(ty.vec4<f32>()))},
|
||||
ast::DecorationList{Stage(ast::PipelineStage::kFragment)},
|
||||
ast::DecorationList{
|
||||
Invariant(Source{{12, 34}}),
|
||||
Location(Source{{56, 78}}, 0),
|
||||
});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
"12:34 error: invariant attribute must only be applied to a "
|
||||
"position builtin");
|
||||
}
|
||||
|
||||
using ArrayDecorationTest = TestWithParams;
|
||||
TEST_P(ArrayDecorationTest, IsValid) {
|
||||
auto& params = GetParam();
|
||||
|
@ -347,6 +380,7 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{DecorationKind::kBuiltin, false},
|
||||
TestParams{DecorationKind::kGroup, false},
|
||||
TestParams{DecorationKind::kInterpolate, false},
|
||||
TestParams{DecorationKind::kInvariant, false},
|
||||
TestParams{DecorationKind::kLocation, false},
|
||||
TestParams{DecorationKind::kOverride, false},
|
||||
TestParams{DecorationKind::kOffset, false},
|
||||
|
@ -382,6 +416,7 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{DecorationKind::kBuiltin, false},
|
||||
TestParams{DecorationKind::kGroup, false},
|
||||
TestParams{DecorationKind::kInterpolate, false},
|
||||
TestParams{DecorationKind::kInvariant, false},
|
||||
TestParams{DecorationKind::kLocation, false},
|
||||
TestParams{DecorationKind::kOverride, false},
|
||||
TestParams{DecorationKind::kOffset, false},
|
||||
|
@ -445,6 +480,7 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{DecorationKind::kBuiltin, true},
|
||||
TestParams{DecorationKind::kGroup, false},
|
||||
TestParams{DecorationKind::kInterpolate, true},
|
||||
TestParams{DecorationKind::kInvariant, true},
|
||||
TestParams{DecorationKind::kLocation, true},
|
||||
TestParams{DecorationKind::kOverride, false},
|
||||
TestParams{DecorationKind::kOffset, true},
|
||||
|
@ -507,6 +543,7 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{DecorationKind::kBuiltin, false},
|
||||
TestParams{DecorationKind::kGroup, false},
|
||||
TestParams{DecorationKind::kInterpolate, false},
|
||||
TestParams{DecorationKind::kInvariant, false},
|
||||
TestParams{DecorationKind::kLocation, false},
|
||||
TestParams{DecorationKind::kOverride, false},
|
||||
TestParams{DecorationKind::kOffset, false},
|
||||
|
@ -558,6 +595,7 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{DecorationKind::kBuiltin, false},
|
||||
TestParams{DecorationKind::kGroup, false},
|
||||
TestParams{DecorationKind::kInterpolate, false},
|
||||
TestParams{DecorationKind::kInvariant, false},
|
||||
TestParams{DecorationKind::kLocation, false},
|
||||
TestParams{DecorationKind::kOverride, true},
|
||||
TestParams{DecorationKind::kOffset, false},
|
||||
|
@ -607,6 +645,7 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{DecorationKind::kBuiltin, false},
|
||||
TestParams{DecorationKind::kGroup, false},
|
||||
TestParams{DecorationKind::kInterpolate, false},
|
||||
TestParams{DecorationKind::kInvariant, false},
|
||||
TestParams{DecorationKind::kLocation, false},
|
||||
TestParams{DecorationKind::kOverride, false},
|
||||
TestParams{DecorationKind::kOffset, false},
|
||||
|
|
|
@ -722,7 +722,7 @@ bool Resolver::ValidateGlobalVariable(const VariableInfo* info) {
|
|||
} else {
|
||||
bool is_shader_io_decoration =
|
||||
deco->IsAnyOf<ast::BuiltinDecoration, ast::InterpolateDecoration,
|
||||
ast::LocationDecoration>();
|
||||
ast::InvariantDecoration, ast::LocationDecoration>();
|
||||
bool has_io_storage_class =
|
||||
info->storage_class == ast::StorageClass::kInput ||
|
||||
info->storage_class == ast::StorageClass::kOutput;
|
||||
|
@ -1194,6 +1194,7 @@ bool Resolver::ValidateFunction(const ast::Function* func,
|
|||
return false;
|
||||
}
|
||||
} else if (!deco->IsAnyOf<ast::LocationDecoration, ast::BuiltinDecoration,
|
||||
ast::InvariantDecoration,
|
||||
ast::InternalDecoration>() &&
|
||||
(IsValidationEnabled(
|
||||
info->declaration->decorations(),
|
||||
|
@ -1242,6 +1243,7 @@ bool Resolver::ValidateEntryPoint(const ast::Function* func,
|
|||
// Scan decorations for pipeline IO attributes.
|
||||
// Check for overlap with attributes that have been seen previously.
|
||||
ast::Decoration* pipeline_io_attribute = nullptr;
|
||||
ast::InvariantDecoration* invariant_attribute = nullptr;
|
||||
for (auto* deco : decos) {
|
||||
if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
|
||||
if (pipeline_io_attribute) {
|
||||
|
@ -1286,6 +1288,8 @@ bool Resolver::ValidateEntryPoint(const ast::Function* func,
|
|||
return false;
|
||||
}
|
||||
locations.emplace(location->value());
|
||||
} else if (auto* invariant = deco->As<ast::InvariantDecoration>()) {
|
||||
invariant_attribute = invariant;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1312,10 +1316,19 @@ bool Resolver::ValidateEntryPoint(const ast::Function* func,
|
|||
return false;
|
||||
}
|
||||
|
||||
auto* builtin = pipeline_io_attribute->As<ast::BuiltinDecoration>();
|
||||
if (invariant_attribute &&
|
||||
!(builtin && builtin->value() == ast::Builtin::kPosition)) {
|
||||
AddError(
|
||||
"invariant attribute must only be applied to a position builtin",
|
||||
invariant_attribute->source());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that all user defined attributes are numeric scalars, vectors
|
||||
// of numeric scalars.
|
||||
// Testing for being a struct is handled by the if portion above.
|
||||
if (!pipeline_io_attribute->Is<ast::BuiltinDecoration>()) {
|
||||
if (!builtin) {
|
||||
if (!ty->is_numeric_scalar_or_vector()) {
|
||||
AddError(
|
||||
"User defined entry point IO types must be a numeric scalar, "
|
||||
|
@ -3558,6 +3571,7 @@ bool Resolver::ValidateStructure(const sem::Struct* str) {
|
|||
for (auto* deco : member->Declaration()->decorations()) {
|
||||
if (!(deco->Is<ast::BuiltinDecoration>() ||
|
||||
deco->Is<ast::InterpolateDecoration>() ||
|
||||
deco->Is<ast::InvariantDecoration>() ||
|
||||
deco->Is<ast::LocationDecoration>() ||
|
||||
deco->Is<ast::StructMemberOffsetDecoration>() ||
|
||||
deco->Is<ast::StructMemberSizeDecoration>() ||
|
||||
|
|
Loading…
Reference in New Issue