validation: Reject nested shader IO structures

We previously rejected nested structures for entry point IO only if
there was an attribute on the member in the outer struct. This change
rejects all nested structures instead.

Change-Id: I0d30c8521141154a63915e6c6d8fa31bc23f310e
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/66520
Auto-Submit: James Price <jrprice@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: James Price <jrprice@google.com>
This commit is contained in:
James Price 2021-10-15 14:55:39 +00:00 committed by Tint LUCI CQ
parent 5029e70b6e
commit b3e6c0d62c
2 changed files with 21 additions and 14 deletions

View File

@ -522,24 +522,22 @@ TEST_F(LocationDecorationTests, BadType_Input_Struct_NestedStruct) {
// [[location(0)]] b : f32; // [[location(0)]] b : f32;
// }; // };
// struct Input { // struct Input {
// [[location(0)]] a : Inner; // a : Inner;
// }; // };
// [[stage(fragment)]] // [[stage(fragment)]]
// fn main(param : Input) {} // fn main(param : Input) {}
auto* inner = Structure( auto* inner = Structure(
"Inner", {Member(Source{{13, 43}}, "a", ty.f32(), {Location(0)})}); "Inner", {Member(Source{{13, 43}}, "a", ty.f32(), {Location(0)})});
auto* input = Structure("Input", {Member(Source{{14, 52}}, "a", ty.Of(inner), auto* input =
{Location(Source{{12, 34}}, 0)})}); Structure("Input", {Member(Source{{14, 52}}, "a", ty.Of(inner))});
auto* param = Param("param", ty.Of(input)); auto* param = Param("param", ty.Of(input));
Func(Source{{12, 34}}, "main", {param}, ty.void_(), {}, Func(Source{{12, 34}}, "main", {param}, ty.void_(), {},
{Stage(ast::PipelineStage::kFragment)}); {Stage(ast::PipelineStage::kFragment)});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"14:52 error: cannot apply 'location' attribute to declaration of " "14:52 error: nested structures cannot be used for entry point IO\n"
"type 'Inner'\n" "12:34 note: while analysing entry point 'main'");
"12:34 note: 'location' attribute must only be applied to "
"declarations of numeric scalar or numeric vector type");
} }
TEST_F(LocationDecorationTests, BadType_Input_Struct_RuntimeArray) { TEST_F(LocationDecorationTests, BadType_Input_Struct_RuntimeArray) {
@ -666,19 +664,22 @@ TEST_F(LocationDecorationTests, ReturnType_Struct_NestedStruct) {
// [[location(0)]] b : f32; // [[location(0)]] b : f32;
// }; // };
// struct Output { // struct Output {
// [[location(0)]] a : Inner; // a : Inner;
// }; // };
// [[stage(fragment)]]
// fn main() -> Output { return Output(); }
auto* inner = Structure( auto* inner = Structure(
"Inner", {Member(Source{{13, 43}}, "a", ty.f32(), {Location(0)})}); "Inner", {Member(Source{{13, 43}}, "a", ty.f32(), {Location(0)})});
Structure("Output", {Member(Source{{14, 52}}, "a", ty.Of(inner), auto* output =
{Location(Source{{12, 34}}, 0)})}); Structure("Output", {Member(Source{{14, 52}}, "a", ty.Of(inner))});
Func(Source{{12, 34}}, "main", {}, ty.Of(output),
{Return(Construct(ty.Of(output)))},
{Stage(ast::PipelineStage::kFragment)});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"14:52 error: cannot apply 'location' attribute to declaration of " "14:52 error: nested structures cannot be used for entry point IO\n"
"type 'Inner'\n" "12:34 note: while analysing entry point 'main'");
"12:34 note: 'location' attribute must only be applied to "
"declarations of numeric scalar or numeric vector type");
} }
TEST_F(LocationDecorationTests, ReturnType_Struct_RuntimeArray) { TEST_F(LocationDecorationTests, ReturnType_Struct_RuntimeArray) {

View File

@ -1594,6 +1594,12 @@ bool Resolver::ValidateEntryPoint(const ast::Function* func,
if (IsValidationEnabled( if (IsValidationEnabled(
decos, ast::DisabledValidation::kEntryPointParameter)) { decos, ast::DisabledValidation::kEntryPointParameter)) {
if (is_struct_member && ty->Is<sem::Struct>()) {
AddError("nested structures cannot be used for entry point IO",
source);
return false;
}
if (!ty->Is<sem::Struct>() && !pipeline_io_attribute) { if (!ty->Is<sem::Struct>() && !pipeline_io_attribute) {
std::string err = "missing entry point IO attribute"; std::string err = "missing entry point IO attribute";
if (!is_struct_member) { if (!is_struct_member) {