Inspector: Add all fragment builtin inputs to EntryPoint
This patch adds all the fragment builtin inputs (position, front_face, sample_index) to EntryPoint for the validation on the total number of fragment inputs. According to Vulkan SPEC: "All variables in both the built-in interface block and the user-defined variable interface count against these limits". BUG=dawn:802 Change-Id: I8a8503c1a33646b50f010c6b6e38d74de9a40ff5 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/59421 Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Jiawei Shao <jiawei.shao@intel.com> Reviewed-by: Ryan Harrison <rharrison@chromium.org>
This commit is contained in:
parent
a5d73ce965
commit
b5025dbc82
|
@ -124,6 +124,13 @@ struct EntryPoint {
|
|||
std::vector<OverridableConstant> overridable_constants;
|
||||
/// Does the entry point use the sample_mask builtin
|
||||
bool sample_mask_used = false;
|
||||
/// Does the entry point use the position builtin as an input builtin
|
||||
/// variable.
|
||||
bool input_position_used = false;
|
||||
/// Does the entry point use the front_facing builtin
|
||||
bool front_facing_used = false;
|
||||
/// Does the entry point use the sample_index builtin
|
||||
bool sample_index_used = false;
|
||||
|
||||
/// @returns the size of the workgroup in {x,y,z} format
|
||||
std::tuple<uint32_t, uint32_t, uint32_t> workgroup_size() {
|
||||
|
|
|
@ -160,16 +160,27 @@ std::vector<EntryPoint> Inspector::GetEntryPoints() {
|
|||
program_->Symbols().NameFor(param->Declaration()->symbol()),
|
||||
param->Type(), param->Declaration()->decorations(),
|
||||
entry_point.input_variables);
|
||||
|
||||
entry_point.input_position_used |=
|
||||
ContainsBuiltin(ast::Builtin::kPosition, param->Type(),
|
||||
param->Declaration()->decorations());
|
||||
entry_point.front_facing_used |=
|
||||
ContainsBuiltin(ast::Builtin::kFrontFacing, param->Type(),
|
||||
param->Declaration()->decorations());
|
||||
entry_point.sample_index_used |=
|
||||
ContainsBuiltin(ast::Builtin::kSampleIndex, param->Type(),
|
||||
param->Declaration()->decorations());
|
||||
}
|
||||
|
||||
if (!sem->ReturnType()->Is<sem::Void>()) {
|
||||
AddEntryPointInOutVariables("<retval>", sem->ReturnType(),
|
||||
func->return_type_decorations(),
|
||||
entry_point.output_variables);
|
||||
}
|
||||
|
||||
entry_point.sample_mask_used = ContainsSampleMaskBuiltin(
|
||||
sem->ReturnType(), func->return_type_decorations());
|
||||
entry_point.sample_mask_used =
|
||||
ContainsBuiltin(ast::Builtin::kSampleMask, sem->ReturnType(),
|
||||
func->return_type_decorations());
|
||||
}
|
||||
|
||||
for (auto* var : sem->ReferencedModuleVariables()) {
|
||||
auto* decl = var->Declaration();
|
||||
|
@ -609,7 +620,7 @@ void Inspector::AddEntryPointInOutVariables(
|
|||
variables.push_back(stage_variable);
|
||||
}
|
||||
|
||||
bool Inspector::ContainsSampleMaskBuiltin(
|
||||
bool Inspector::ContainsBuiltin(ast::Builtin builtin,
|
||||
sem::Type* type,
|
||||
const ast::DecorationList& decorations) const {
|
||||
auto* unwrapped_type = type->UnwrapRef();
|
||||
|
@ -617,7 +628,7 @@ bool Inspector::ContainsSampleMaskBuiltin(
|
|||
if (auto* struct_ty = unwrapped_type->As<sem::Struct>()) {
|
||||
// Recurse into members.
|
||||
for (auto* member : struct_ty->Members()) {
|
||||
if (ContainsSampleMaskBuiltin(member->Type(),
|
||||
if (ContainsBuiltin(builtin, member->Type(),
|
||||
member->Declaration()->decorations())) {
|
||||
return true;
|
||||
}
|
||||
|
@ -625,9 +636,10 @@ bool Inspector::ContainsSampleMaskBuiltin(
|
|||
return false;
|
||||
}
|
||||
|
||||
// Base case: check for [[builtin(sample_mask)]]
|
||||
auto* builtin = ast::GetDecoration<ast::BuiltinDecoration>(decorations);
|
||||
if (!builtin || builtin->value() != ast::Builtin::kSampleMask) {
|
||||
// Base case: check for builtin
|
||||
auto* builtin_declaration =
|
||||
ast::GetDecoration<ast::BuiltinDecoration>(decorations);
|
||||
if (!builtin_declaration || builtin_declaration->value() != builtin) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -166,10 +166,11 @@ class Inspector {
|
|||
const ast::DecorationList& decorations,
|
||||
std::vector<StageVariable>& variables) const;
|
||||
|
||||
/// Recursively determine if the type contains [[builtin(sample_mask)]]
|
||||
/// Recursively determine if the type contains builtin.
|
||||
/// If `type` is a struct, recurse into members to check for the decoration.
|
||||
/// Otherwise, check `decorations` for the decoration.
|
||||
bool ContainsSampleMaskBuiltin(sem::Type* type,
|
||||
bool ContainsBuiltin(ast::Builtin builtin,
|
||||
sem::Type* type,
|
||||
const ast::DecorationList& decorations) const;
|
||||
|
||||
/// Gathers all the texture resource bindings of the given type for the given
|
||||
|
|
|
@ -629,7 +629,7 @@ TEST_F(InspectorGetEntryPointTest, NonOverridableConstantSkipped) {
|
|||
EXPECT_EQ(0u, result[0].overridable_constants.size());
|
||||
}
|
||||
|
||||
TEST_F(InspectorGetEntryPointTest, SampleMaskNotReferenced) {
|
||||
TEST_F(InspectorGetEntryPointTest, BuiltinNotReferenced) {
|
||||
MakeEmptyBodyFunction("ep_func", {Stage(ast::PipelineStage::kFragment)});
|
||||
|
||||
Inspector& inspector = Build();
|
||||
|
@ -638,6 +638,9 @@ TEST_F(InspectorGetEntryPointTest, SampleMaskNotReferenced) {
|
|||
|
||||
ASSERT_EQ(1u, result.size());
|
||||
EXPECT_FALSE(result[0].sample_mask_used);
|
||||
EXPECT_FALSE(result[0].input_position_used);
|
||||
EXPECT_FALSE(result[0].front_facing_used);
|
||||
EXPECT_FALSE(result[0].sample_index_used);
|
||||
}
|
||||
|
||||
TEST_F(InspectorGetEntryPointTest, SampleMaskSimpleReferenced) {
|
||||
|
@ -673,6 +676,102 @@ TEST_F(InspectorGetEntryPointTest, SampleMaskStructReferenced) {
|
|||
EXPECT_TRUE(result[0].sample_mask_used);
|
||||
}
|
||||
|
||||
TEST_F(InspectorGetEntryPointTest, InputPositionSimpleReferenced) {
|
||||
auto* in_var =
|
||||
Param("in_var", ty.vec4<f32>(), {Builtin(ast::Builtin::kPosition)});
|
||||
Func("ep_func", {in_var}, ty.void_(), {Return()},
|
||||
{Stage(ast::PipelineStage::kFragment)}, {});
|
||||
|
||||
Inspector& inspector = Build();
|
||||
|
||||
auto result = inspector.GetEntryPoints();
|
||||
|
||||
ASSERT_EQ(1u, result.size());
|
||||
EXPECT_TRUE(result[0].input_position_used);
|
||||
}
|
||||
|
||||
TEST_F(InspectorGetEntryPointTest, InputPositionStructReferenced) {
|
||||
ast::StructMemberList members;
|
||||
members.push_back(Member("inner_position", ty.vec4<f32>(),
|
||||
{Builtin(ast::Builtin::kPosition)}));
|
||||
Structure("in_struct", members, {});
|
||||
auto* in_var = Param("in_var", ty.type_name("in_struct"), {});
|
||||
|
||||
Func("ep_func", {in_var}, ty.void_(), {Return()},
|
||||
{Stage(ast::PipelineStage::kFragment)}, {});
|
||||
|
||||
Inspector& inspector = Build();
|
||||
|
||||
auto result = inspector.GetEntryPoints();
|
||||
|
||||
ASSERT_EQ(1u, result.size());
|
||||
EXPECT_TRUE(result[0].input_position_used);
|
||||
}
|
||||
|
||||
TEST_F(InspectorGetEntryPointTest, FrontFacingSimpleReferenced) {
|
||||
auto* in_var =
|
||||
Param("in_var", ty.bool_(), {Builtin(ast::Builtin::kFrontFacing)});
|
||||
Func("ep_func", {in_var}, ty.void_(), {Return()},
|
||||
{Stage(ast::PipelineStage::kFragment)}, {});
|
||||
|
||||
Inspector& inspector = Build();
|
||||
|
||||
auto result = inspector.GetEntryPoints();
|
||||
|
||||
ASSERT_EQ(1u, result.size());
|
||||
EXPECT_TRUE(result[0].front_facing_used);
|
||||
}
|
||||
|
||||
TEST_F(InspectorGetEntryPointTest, FrontFacingStructReferenced) {
|
||||
ast::StructMemberList members;
|
||||
members.push_back(Member("inner_position", ty.bool_(),
|
||||
{Builtin(ast::Builtin::kFrontFacing)}));
|
||||
Structure("in_struct", members, {});
|
||||
auto* in_var = Param("in_var", ty.type_name("in_struct"), {});
|
||||
|
||||
Func("ep_func", {in_var}, ty.void_(), {Return()},
|
||||
{Stage(ast::PipelineStage::kFragment)}, {});
|
||||
|
||||
Inspector& inspector = Build();
|
||||
|
||||
auto result = inspector.GetEntryPoints();
|
||||
|
||||
ASSERT_EQ(1u, result.size());
|
||||
EXPECT_TRUE(result[0].front_facing_used);
|
||||
}
|
||||
|
||||
TEST_F(InspectorGetEntryPointTest, SampleIndexSimpleReferenced) {
|
||||
auto* in_var =
|
||||
Param("in_var", ty.u32(), {Builtin(ast::Builtin::kSampleIndex)});
|
||||
Func("ep_func", {in_var}, ty.void_(), {Return()},
|
||||
{Stage(ast::PipelineStage::kFragment)}, {});
|
||||
|
||||
Inspector& inspector = Build();
|
||||
|
||||
auto result = inspector.GetEntryPoints();
|
||||
|
||||
ASSERT_EQ(1u, result.size());
|
||||
EXPECT_TRUE(result[0].sample_index_used);
|
||||
}
|
||||
|
||||
TEST_F(InspectorGetEntryPointTest, SampleIndexStructReferenced) {
|
||||
ast::StructMemberList members;
|
||||
members.push_back(Member("inner_position", ty.u32(),
|
||||
{Builtin(ast::Builtin::kSampleIndex)}));
|
||||
Structure("in_struct", members, {});
|
||||
auto* in_var = Param("in_var", ty.type_name("in_struct"), {});
|
||||
|
||||
Func("ep_func", {in_var}, ty.void_(), {Return()},
|
||||
{Stage(ast::PipelineStage::kFragment)}, {});
|
||||
|
||||
Inspector& inspector = Build();
|
||||
|
||||
auto result = inspector.GetEntryPoints();
|
||||
|
||||
ASSERT_EQ(1u, result.size());
|
||||
EXPECT_TRUE(result[0].sample_index_used);
|
||||
}
|
||||
|
||||
TEST_F(InspectorGetEntryPointTest, ImplicitInterpolate) {
|
||||
ast::StructMemberList members;
|
||||
members.push_back(Member("struct_inner", ty.f32(), {Location(0)}));
|
||||
|
|
Loading…
Reference in New Issue