From c58738a49eda862133e66d0c6108d8e5a4f41ece Mon Sep 17 00:00:00 2001 From: Sarah Date: Wed, 9 Jun 2021 16:01:29 +0000 Subject: [PATCH] [validation] v-15001: front_facing builtin must be boolean To declare a front_facing builtin variable - declare as a parameter of the entry point function or it can be - declared as members of structures that are entry point function parameters The type of the function-parameter/structure-member must be boolean. Bug: tint:357 Change-Id: I09c380ae5784d29e776e483d966a0f7d8cd2286c Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/53821 Reviewed-by: Sarah Mashayekhi Reviewed-by: Antonio Maiorano Kokoro: Kokoro Commit-Queue: Sarah Mashayekhi --- src/resolver/builtins_validation_test.cc | 67 ++++++++++++++++++++++++ src/resolver/resolver.cc | 25 +++++++++ 2 files changed, 92 insertions(+) diff --git a/src/resolver/builtins_validation_test.cc b/src/resolver/builtins_validation_test.cc index d526f1ef98..de9603e90a 100644 --- a/src/resolver/builtins_validation_test.cc +++ b/src/resolver/builtins_validation_test.cc @@ -20,6 +20,73 @@ namespace { class ResolverBuiltinsValidationTest : public resolver::TestHelper, public testing::Test {}; +TEST_F(ResolverBuiltinsValidationTest, FrontFacingParamIsBool_Pass) { + // [[stage(fragment)]] + // fn fs_main( + // [[builtin(front_facing)]] is_front: bool + // ) -> [[location(0)]] f32 { return 1.0; } + auto* is_front = + Param("is_front", ty.bool_(), + ast::DecorationList{Builtin(ast::Builtin::kFrontFacing)}); + Func("fs_main", ast::VariableList{is_front}, ty.f32(), {Return(1.0f)}, + ast::DecorationList{Stage(ast::PipelineStage::kFragment)}, + {Location(0)}); + EXPECT_TRUE(r()->Resolve()) << r()->error(); +} + +TEST_F(ResolverBuiltinsValidationTest, FrontFacingMemberIsBool_Pass) { + // struct MyInputs { + // [[builtin(front_facing)]] pos: bool; + // }; + // [[stage(fragment)]] + // fn fragShader(is_front: MyInputs) -> [[location(0)]] f32 { return 1.0; } + + auto* s = Structure( + "MyInputs", + {Member("pos", ty.bool_(), + ast::DecorationList{Builtin(ast::Builtin::kFrontFacing)})}); + Func("fragShader", {Param("is_front", ty.Of(s))}, ty.f32(), {Return(1.0f)}, + {Stage(ast::PipelineStage::kFragment)}, {Location(0)}); + EXPECT_TRUE(r()->Resolve()) << r()->error(); +} + +TEST_F(ResolverBuiltinsValidationTest, FrontFacingParamIsNotBool_Fail) { + // [[stage(fragment)]] + // fn fs_main( + // [[builtin(front_facing)]] is_front: i32; + // ) -> [[location(0)]] f32 { return 1.0; } + + auto* is_front = Param("is_front", ty.i32(), + ast::DecorationList{Builtin( + Source{{12, 34}}, ast::Builtin::kFrontFacing)}); + Func("fs_main", ast::VariableList{is_front}, ty.f32(), {Return(1.0f)}, + ast::DecorationList{Stage(ast::PipelineStage::kFragment)}, + {Location(0)}); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error v-15001: front_facing builtin must be boolean"); +} + +TEST_F(ResolverBuiltinsValidationTest, FrontFacingMemberIsNotBool_Fail) { + // struct MyInputs { + // [[builtin(front_facing)]] pos: f32; + // }; + // [[stage(fragment)]] + // fn fragShader(is_front: MyInputs) -> [[location(0)]] f32 { return 1.0; } + + auto* s = Structure( + "MyInputs", {Member("pos", ty.f32(), + ast::DecorationList{Builtin( + Source{{12, 34}}, ast::Builtin::kFrontFacing)})}); + Func("fragShader", {Param("is_front", ty.Of(s))}, ty.f32(), {Return(1.0f)}, + {Stage(ast::PipelineStage::kFragment)}, {Location(0)}); + + EXPECT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "12:34 error v-15001: front_facing builtin must be boolean"); +} + TEST_F(ResolverBuiltinsValidationTest, Length_Float_Scalar) { auto* builtin = Call("length", 1.0f); WrapInFunction(builtin); diff --git a/src/resolver/resolver.cc b/src/resolver/resolver.cc index df95064ac9..fa34926d9a 100644 --- a/src/resolver/resolver.cc +++ b/src/resolver/resolver.cc @@ -808,6 +808,21 @@ bool Resolver::ValidateVariable(const VariableInfo* info) { } bool Resolver::ValidateParameter(const VariableInfo* info) { + auto* var = info->declaration; + for (auto* deco : var->decorations()) { + if (auto* builtin = deco->As()) { + if (builtin->value() == ast::Builtin::kFrontFacing) { + auto* storage_type = info->type->UnwrapRef(); + if (!(storage_type->Is())) { + diagnostics_.add_error("v-15001", + "front_facing builtin must be boolean", + deco->source()); + return false; + } + } + } + } + return ValidateVariable(info); } @@ -2876,6 +2891,16 @@ bool Resolver::ValidateStructure(const sem::Struct* str) { deco->source()); return false; } + if (auto* builtin = deco->As()) { + if (builtin->value() == ast::Builtin::kFrontFacing) { + if (!(member->Type()->Is())) { + diagnostics_.add_error("v-15001", + "front_facing builtin must be boolean", + deco->source()); + return false; + } + } + } } }