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/i32.h"
|
||||||
#include "src/ast/if_statement.h"
|
#include "src/ast/if_statement.h"
|
||||||
#include "src/ast/interpolate_decoration.h"
|
#include "src/ast/interpolate_decoration.h"
|
||||||
|
#include "src/ast/invariant_decoration.h"
|
||||||
#include "src/ast/loop_statement.h"
|
#include "src/ast/loop_statement.h"
|
||||||
#include "src/ast/matrix.h"
|
#include "src/ast/matrix.h"
|
||||||
#include "src/ast/member_accessor_expression.h"
|
#include "src/ast/member_accessor_expression.h"
|
||||||
|
@ -2042,6 +2043,19 @@ class ProgramBuilder {
|
||||||
return create<ast::InterpolateDecoration>(source_, type, sampling);
|
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
|
/// Creates an ast::LocationDecoration
|
||||||
/// @param source the source information
|
/// @param source the source information
|
||||||
/// @param location the location value
|
/// @param location the location value
|
||||||
|
|
|
@ -62,6 +62,7 @@ enum class DecorationKind {
|
||||||
kBuiltin,
|
kBuiltin,
|
||||||
kGroup,
|
kGroup,
|
||||||
kInterpolate,
|
kInterpolate,
|
||||||
|
kInvariant,
|
||||||
kLocation,
|
kLocation,
|
||||||
kOverride,
|
kOverride,
|
||||||
kOffset,
|
kOffset,
|
||||||
|
@ -107,6 +108,8 @@ static ast::DecorationList createDecorations(const Source& source,
|
||||||
return {builder.Interpolate(source, ast::InterpolationType::kLinear,
|
return {builder.Interpolate(source, ast::InterpolationType::kLinear,
|
||||||
ast::InterpolationSampling::kCenter),
|
ast::InterpolationSampling::kCenter),
|
||||||
builder.Location(0)};
|
builder.Location(0)};
|
||||||
|
case DecorationKind::kInvariant:
|
||||||
|
return {builder.Invariant(source)};
|
||||||
case DecorationKind::kLocation:
|
case DecorationKind::kLocation:
|
||||||
return {builder.Location(source, 1)};
|
return {builder.Location(source, 1)};
|
||||||
case DecorationKind::kOverride:
|
case DecorationKind::kOverride:
|
||||||
|
@ -157,6 +160,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
TestParams{DecorationKind::kBuiltin, false},
|
TestParams{DecorationKind::kBuiltin, false},
|
||||||
TestParams{DecorationKind::kGroup, false},
|
TestParams{DecorationKind::kGroup, false},
|
||||||
TestParams{DecorationKind::kInterpolate, false},
|
TestParams{DecorationKind::kInterpolate, false},
|
||||||
|
TestParams{DecorationKind::kInvariant, false},
|
||||||
TestParams{DecorationKind::kLocation, false},
|
TestParams{DecorationKind::kLocation, false},
|
||||||
TestParams{DecorationKind::kOverride, false},
|
TestParams{DecorationKind::kOverride, false},
|
||||||
TestParams{DecorationKind::kOffset, false},
|
TestParams{DecorationKind::kOffset, false},
|
||||||
|
@ -193,6 +197,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, false},
|
||||||
TestParams{DecorationKind::kLocation, true},
|
TestParams{DecorationKind::kLocation, true},
|
||||||
TestParams{DecorationKind::kOverride, false},
|
TestParams{DecorationKind::kOverride, false},
|
||||||
TestParams{DecorationKind::kOffset, false},
|
TestParams{DecorationKind::kOffset, false},
|
||||||
|
@ -257,6 +262,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
TestParams{DecorationKind::kBuiltin, false},
|
TestParams{DecorationKind::kBuiltin, false},
|
||||||
TestParams{DecorationKind::kGroup, false},
|
TestParams{DecorationKind::kGroup, false},
|
||||||
TestParams{DecorationKind::kInterpolate, false},
|
TestParams{DecorationKind::kInterpolate, false},
|
||||||
|
TestParams{DecorationKind::kInvariant, false},
|
||||||
TestParams{DecorationKind::kLocation, false},
|
TestParams{DecorationKind::kLocation, false},
|
||||||
TestParams{DecorationKind::kOverride, false},
|
TestParams{DecorationKind::kOverride, false},
|
||||||
TestParams{DecorationKind::kOffset, false},
|
TestParams{DecorationKind::kOffset, false},
|
||||||
|
@ -293,6 +299,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},
|
||||||
|
// 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, false},
|
TestParams{DecorationKind::kOffset, false},
|
||||||
|
@ -317,6 +324,32 @@ TEST_F(EntryPointReturnTypeDecorationTest, DuplicateDecoration) {
|
||||||
12:34 note: first decoration declared here)");
|
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;
|
using ArrayDecorationTest = TestWithParams;
|
||||||
TEST_P(ArrayDecorationTest, IsValid) {
|
TEST_P(ArrayDecorationTest, IsValid) {
|
||||||
auto& params = GetParam();
|
auto& params = GetParam();
|
||||||
|
@ -347,6 +380,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
TestParams{DecorationKind::kBuiltin, false},
|
TestParams{DecorationKind::kBuiltin, false},
|
||||||
TestParams{DecorationKind::kGroup, false},
|
TestParams{DecorationKind::kGroup, false},
|
||||||
TestParams{DecorationKind::kInterpolate, false},
|
TestParams{DecorationKind::kInterpolate, false},
|
||||||
|
TestParams{DecorationKind::kInvariant, false},
|
||||||
TestParams{DecorationKind::kLocation, false},
|
TestParams{DecorationKind::kLocation, false},
|
||||||
TestParams{DecorationKind::kOverride, false},
|
TestParams{DecorationKind::kOverride, false},
|
||||||
TestParams{DecorationKind::kOffset, false},
|
TestParams{DecorationKind::kOffset, false},
|
||||||
|
@ -382,6 +416,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
TestParams{DecorationKind::kBuiltin, false},
|
TestParams{DecorationKind::kBuiltin, false},
|
||||||
TestParams{DecorationKind::kGroup, false},
|
TestParams{DecorationKind::kGroup, false},
|
||||||
TestParams{DecorationKind::kInterpolate, false},
|
TestParams{DecorationKind::kInterpolate, false},
|
||||||
|
TestParams{DecorationKind::kInvariant, false},
|
||||||
TestParams{DecorationKind::kLocation, false},
|
TestParams{DecorationKind::kLocation, false},
|
||||||
TestParams{DecorationKind::kOverride, false},
|
TestParams{DecorationKind::kOverride, false},
|
||||||
TestParams{DecorationKind::kOffset, false},
|
TestParams{DecorationKind::kOffset, false},
|
||||||
|
@ -445,6 +480,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},
|
||||||
TestParams{DecorationKind::kLocation, true},
|
TestParams{DecorationKind::kLocation, true},
|
||||||
TestParams{DecorationKind::kOverride, false},
|
TestParams{DecorationKind::kOverride, false},
|
||||||
TestParams{DecorationKind::kOffset, true},
|
TestParams{DecorationKind::kOffset, true},
|
||||||
|
@ -507,6 +543,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
TestParams{DecorationKind::kBuiltin, false},
|
TestParams{DecorationKind::kBuiltin, false},
|
||||||
TestParams{DecorationKind::kGroup, false},
|
TestParams{DecorationKind::kGroup, false},
|
||||||
TestParams{DecorationKind::kInterpolate, false},
|
TestParams{DecorationKind::kInterpolate, false},
|
||||||
|
TestParams{DecorationKind::kInvariant, false},
|
||||||
TestParams{DecorationKind::kLocation, false},
|
TestParams{DecorationKind::kLocation, false},
|
||||||
TestParams{DecorationKind::kOverride, false},
|
TestParams{DecorationKind::kOverride, false},
|
||||||
TestParams{DecorationKind::kOffset, false},
|
TestParams{DecorationKind::kOffset, false},
|
||||||
|
@ -558,6 +595,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
TestParams{DecorationKind::kBuiltin, false},
|
TestParams{DecorationKind::kBuiltin, false},
|
||||||
TestParams{DecorationKind::kGroup, false},
|
TestParams{DecorationKind::kGroup, false},
|
||||||
TestParams{DecorationKind::kInterpolate, false},
|
TestParams{DecorationKind::kInterpolate, false},
|
||||||
|
TestParams{DecorationKind::kInvariant, false},
|
||||||
TestParams{DecorationKind::kLocation, false},
|
TestParams{DecorationKind::kLocation, false},
|
||||||
TestParams{DecorationKind::kOverride, true},
|
TestParams{DecorationKind::kOverride, true},
|
||||||
TestParams{DecorationKind::kOffset, false},
|
TestParams{DecorationKind::kOffset, false},
|
||||||
|
@ -607,6 +645,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
TestParams{DecorationKind::kBuiltin, false},
|
TestParams{DecorationKind::kBuiltin, false},
|
||||||
TestParams{DecorationKind::kGroup, false},
|
TestParams{DecorationKind::kGroup, false},
|
||||||
TestParams{DecorationKind::kInterpolate, false},
|
TestParams{DecorationKind::kInterpolate, false},
|
||||||
|
TestParams{DecorationKind::kInvariant, false},
|
||||||
TestParams{DecorationKind::kLocation, false},
|
TestParams{DecorationKind::kLocation, false},
|
||||||
TestParams{DecorationKind::kOverride, false},
|
TestParams{DecorationKind::kOverride, false},
|
||||||
TestParams{DecorationKind::kOffset, false},
|
TestParams{DecorationKind::kOffset, false},
|
||||||
|
|
|
@ -722,7 +722,7 @@ bool Resolver::ValidateGlobalVariable(const VariableInfo* info) {
|
||||||
} else {
|
} else {
|
||||||
bool is_shader_io_decoration =
|
bool is_shader_io_decoration =
|
||||||
deco->IsAnyOf<ast::BuiltinDecoration, ast::InterpolateDecoration,
|
deco->IsAnyOf<ast::BuiltinDecoration, ast::InterpolateDecoration,
|
||||||
ast::LocationDecoration>();
|
ast::InvariantDecoration, ast::LocationDecoration>();
|
||||||
bool has_io_storage_class =
|
bool has_io_storage_class =
|
||||||
info->storage_class == ast::StorageClass::kInput ||
|
info->storage_class == ast::StorageClass::kInput ||
|
||||||
info->storage_class == ast::StorageClass::kOutput;
|
info->storage_class == ast::StorageClass::kOutput;
|
||||||
|
@ -1194,6 +1194,7 @@ bool Resolver::ValidateFunction(const ast::Function* func,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (!deco->IsAnyOf<ast::LocationDecoration, ast::BuiltinDecoration,
|
} else if (!deco->IsAnyOf<ast::LocationDecoration, ast::BuiltinDecoration,
|
||||||
|
ast::InvariantDecoration,
|
||||||
ast::InternalDecoration>() &&
|
ast::InternalDecoration>() &&
|
||||||
(IsValidationEnabled(
|
(IsValidationEnabled(
|
||||||
info->declaration->decorations(),
|
info->declaration->decorations(),
|
||||||
|
@ -1242,6 +1243,7 @@ bool Resolver::ValidateEntryPoint(const ast::Function* func,
|
||||||
// Scan decorations for pipeline IO attributes.
|
// Scan decorations for pipeline IO attributes.
|
||||||
// Check for overlap with attributes that have been seen previously.
|
// Check for overlap with attributes that have been seen previously.
|
||||||
ast::Decoration* pipeline_io_attribute = nullptr;
|
ast::Decoration* pipeline_io_attribute = nullptr;
|
||||||
|
ast::InvariantDecoration* invariant_attribute = nullptr;
|
||||||
for (auto* deco : decos) {
|
for (auto* deco : decos) {
|
||||||
if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
|
if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
|
||||||
if (pipeline_io_attribute) {
|
if (pipeline_io_attribute) {
|
||||||
|
@ -1286,6 +1288,8 @@ bool Resolver::ValidateEntryPoint(const ast::Function* func,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
locations.emplace(location->value());
|
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;
|
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
|
// Check that all user defined attributes are numeric scalars, vectors
|
||||||
// of numeric scalars.
|
// of numeric scalars.
|
||||||
// Testing for being a struct is handled by the if portion above.
|
// 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()) {
|
if (!ty->is_numeric_scalar_or_vector()) {
|
||||||
AddError(
|
AddError(
|
||||||
"User defined entry point IO types must be a numeric scalar, "
|
"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()) {
|
for (auto* deco : member->Declaration()->decorations()) {
|
||||||
if (!(deco->Is<ast::BuiltinDecoration>() ||
|
if (!(deco->Is<ast::BuiltinDecoration>() ||
|
||||||
deco->Is<ast::InterpolateDecoration>() ||
|
deco->Is<ast::InterpolateDecoration>() ||
|
||||||
|
deco->Is<ast::InvariantDecoration>() ||
|
||||||
deco->Is<ast::LocationDecoration>() ||
|
deco->Is<ast::LocationDecoration>() ||
|
||||||
deco->Is<ast::StructMemberOffsetDecoration>() ||
|
deco->Is<ast::StructMemberOffsetDecoration>() ||
|
||||||
deco->Is<ast::StructMemberSizeDecoration>() ||
|
deco->Is<ast::StructMemberSizeDecoration>() ||
|
||||||
|
|
Loading…
Reference in New Issue