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;
|
std::vector<OverridableConstant> overridable_constants;
|
||||||
/// Does the entry point use the sample_mask builtin
|
/// Does the entry point use the sample_mask builtin
|
||||||
bool sample_mask_used = false;
|
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
|
/// @returns the size of the workgroup in {x,y,z} format
|
||||||
std::tuple<uint32_t, uint32_t, uint32_t> workgroup_size() {
|
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()),
|
program_->Symbols().NameFor(param->Declaration()->symbol()),
|
||||||
param->Type(), param->Declaration()->decorations(),
|
param->Type(), param->Declaration()->decorations(),
|
||||||
entry_point.input_variables);
|
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>()) {
|
if (!sem->ReturnType()->Is<sem::Void>()) {
|
||||||
AddEntryPointInOutVariables("<retval>", sem->ReturnType(),
|
AddEntryPointInOutVariables("<retval>", sem->ReturnType(),
|
||||||
func->return_type_decorations(),
|
func->return_type_decorations(),
|
||||||
entry_point.output_variables);
|
entry_point.output_variables);
|
||||||
}
|
|
||||||
|
|
||||||
entry_point.sample_mask_used = ContainsSampleMaskBuiltin(
|
entry_point.sample_mask_used =
|
||||||
sem->ReturnType(), func->return_type_decorations());
|
ContainsBuiltin(ast::Builtin::kSampleMask, sem->ReturnType(),
|
||||||
|
func->return_type_decorations());
|
||||||
|
}
|
||||||
|
|
||||||
for (auto* var : sem->ReferencedModuleVariables()) {
|
for (auto* var : sem->ReferencedModuleVariables()) {
|
||||||
auto* decl = var->Declaration();
|
auto* decl = var->Declaration();
|
||||||
|
@ -609,25 +620,26 @@ void Inspector::AddEntryPointInOutVariables(
|
||||||
variables.push_back(stage_variable);
|
variables.push_back(stage_variable);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Inspector::ContainsSampleMaskBuiltin(
|
bool Inspector::ContainsBuiltin(ast::Builtin builtin,
|
||||||
sem::Type* type,
|
sem::Type* type,
|
||||||
const ast::DecorationList& decorations) const {
|
const ast::DecorationList& decorations) const {
|
||||||
auto* unwrapped_type = type->UnwrapRef();
|
auto* unwrapped_type = type->UnwrapRef();
|
||||||
|
|
||||||
if (auto* struct_ty = unwrapped_type->As<sem::Struct>()) {
|
if (auto* struct_ty = unwrapped_type->As<sem::Struct>()) {
|
||||||
// Recurse into members.
|
// Recurse into members.
|
||||||
for (auto* member : struct_ty->Members()) {
|
for (auto* member : struct_ty->Members()) {
|
||||||
if (ContainsSampleMaskBuiltin(member->Type(),
|
if (ContainsBuiltin(builtin, member->Type(),
|
||||||
member->Declaration()->decorations())) {
|
member->Declaration()->decorations())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Base case: check for [[builtin(sample_mask)]]
|
// Base case: check for builtin
|
||||||
auto* builtin = ast::GetDecoration<ast::BuiltinDecoration>(decorations);
|
auto* builtin_declaration =
|
||||||
if (!builtin || builtin->value() != ast::Builtin::kSampleMask) {
|
ast::GetDecoration<ast::BuiltinDecoration>(decorations);
|
||||||
|
if (!builtin_declaration || builtin_declaration->value() != builtin) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -166,11 +166,12 @@ class Inspector {
|
||||||
const ast::DecorationList& decorations,
|
const ast::DecorationList& decorations,
|
||||||
std::vector<StageVariable>& variables) const;
|
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.
|
/// If `type` is a struct, recurse into members to check for the decoration.
|
||||||
/// Otherwise, check `decorations` for the decoration.
|
/// Otherwise, check `decorations` for the decoration.
|
||||||
bool ContainsSampleMaskBuiltin(sem::Type* type,
|
bool ContainsBuiltin(ast::Builtin builtin,
|
||||||
const ast::DecorationList& decorations) const;
|
sem::Type* type,
|
||||||
|
const ast::DecorationList& decorations) const;
|
||||||
|
|
||||||
/// Gathers all the texture resource bindings of the given type for the given
|
/// Gathers all the texture resource bindings of the given type for the given
|
||||||
/// entry point.
|
/// entry point.
|
||||||
|
|
|
@ -629,7 +629,7 @@ TEST_F(InspectorGetEntryPointTest, NonOverridableConstantSkipped) {
|
||||||
EXPECT_EQ(0u, result[0].overridable_constants.size());
|
EXPECT_EQ(0u, result[0].overridable_constants.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(InspectorGetEntryPointTest, SampleMaskNotReferenced) {
|
TEST_F(InspectorGetEntryPointTest, BuiltinNotReferenced) {
|
||||||
MakeEmptyBodyFunction("ep_func", {Stage(ast::PipelineStage::kFragment)});
|
MakeEmptyBodyFunction("ep_func", {Stage(ast::PipelineStage::kFragment)});
|
||||||
|
|
||||||
Inspector& inspector = Build();
|
Inspector& inspector = Build();
|
||||||
|
@ -638,6 +638,9 @@ TEST_F(InspectorGetEntryPointTest, SampleMaskNotReferenced) {
|
||||||
|
|
||||||
ASSERT_EQ(1u, result.size());
|
ASSERT_EQ(1u, result.size());
|
||||||
EXPECT_FALSE(result[0].sample_mask_used);
|
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) {
|
TEST_F(InspectorGetEntryPointTest, SampleMaskSimpleReferenced) {
|
||||||
|
@ -673,6 +676,102 @@ TEST_F(InspectorGetEntryPointTest, SampleMaskStructReferenced) {
|
||||||
EXPECT_TRUE(result[0].sample_mask_used);
|
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) {
|
TEST_F(InspectorGetEntryPointTest, ImplicitInterpolate) {
|
||||||
ast::StructMemberList members;
|
ast::StructMemberList members;
|
||||||
members.push_back(Member("struct_inner", ty.f32(), {Location(0)}));
|
members.push_back(Member("struct_inner", ty.f32(), {Location(0)}));
|
||||||
|
|
Loading…
Reference in New Issue