spirv-reader: remove builtin-inputs special cases

Remove special case handling of pointers and values related
to builtins SampleId, VertexIndex, and InstanceIndex.
These map to private variables with store type matching the
type stated in the SPIR-V code. There is no need to generate
special case code for user-written functions accessing those variables.

Therefore:
- Remove SkipReason enums associated with those builtin inputs
- Remove newly unreachable code.

Bug: tint:508
Change-Id: I22ea86d49e14f171a92863d9f02145606ad37683
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/55321
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: James Price <jrprice@google.com>
Auto-Submit: David Neto <dneto@google.com>
This commit is contained in:
David Neto 2021-06-21 19:21:36 +00:00 committed by Tint LUCI CQ
parent 4d94eee072
commit 3d5453ce9c
3 changed files with 147 additions and 151 deletions

View File

@ -2309,20 +2309,6 @@ TypedExpression FunctionEmitter::MakeExpression(uint32_t id) {
Fail() << "unhandled use of a pointer to the PointSize builtin, with ID: " Fail() << "unhandled use of a pointer to the PointSize builtin, with ID: "
<< id; << id;
return {}; return {};
case SkipReason::kSampleIdBuiltinPointer:
Fail() << "unhandled use of a pointer to the SampleId builtin, with ID: "
<< id;
return {};
case SkipReason::kVertexIndexBuiltinPointer:
Fail()
<< "unhandled use of a pointer to the VertexIndex builtin, with ID: "
<< id;
return {};
case SkipReason::kInstanceIndexBuiltinPointer:
Fail() << "unhandled use of a pointer to the InstanceIndex builtin, with "
"ID: "
<< id;
return {};
case SkipReason::kSampleMaskInBuiltinPointer: case SkipReason::kSampleMaskInBuiltinPointer:
Fail() Fail()
<< "unhandled use of a pointer to the SampleMask builtin, with ID: " << "unhandled use of a pointer to the SampleMask builtin, with ID: "
@ -3423,22 +3409,6 @@ bool FunctionEmitter::EmitStatement(const spvtools::opt::Instruction& inst) {
GetDefInfo(inst.result_id())->skip = GetDefInfo(inst.result_id())->skip =
SkipReason::kPointSizeBuiltinValue; SkipReason::kPointSizeBuiltinValue;
return true; return true;
case SkipReason::kSampleIdBuiltinPointer:
case SkipReason::kVertexIndexBuiltinPointer:
case SkipReason::kInstanceIndexBuiltinPointer: {
auto name = NameForSpecialInputBuiltin(skip_reason);
if (name.empty()) {
return Fail() << "internal error: unhandled special input builtin "
"variable: "
<< inst.PrettyPrint();
}
ast::Expression* id_expr = create<ast::IdentifierExpression>(
Source{}, builder_.Symbols().Register(name));
auto* loaded_type = parser_impl_.ConvertType(inst.type_id());
auto expr = TypedExpression{loaded_type, id_expr};
return EmitConstDefinition(inst, expr);
}
case SkipReason::kSampleMaskInBuiltinPointer: { case SkipReason::kSampleMaskInBuiltinPointer: {
auto name = namer_.Name(sample_mask_in_id); auto name = namer_.Name(sample_mask_in_id);
ast::Expression* id_expr = create<ast::IdentifierExpression>( ast::Expression* id_expr = create<ast::IdentifierExpression>(
@ -3573,28 +3543,6 @@ bool FunctionEmitter::EmitStatement(const spvtools::opt::Instruction& inst) {
<< inst.PrettyPrint(); << inst.PrettyPrint();
} }
std::string FunctionEmitter::NameForSpecialInputBuiltin(
SkipReason skip_reason) {
SpvBuiltIn spv_builtin = SpvBuiltIn(0);
switch (skip_reason) {
case SkipReason::kSampleIdBuiltinPointer:
spv_builtin = SpvBuiltInSampleId;
break;
case SkipReason::kVertexIndexBuiltinPointer:
spv_builtin = SpvBuiltInVertexIndex;
break;
case SkipReason::kInstanceIndexBuiltinPointer:
spv_builtin = SpvBuiltInInstanceIndex;
break;
default:
// Invalid. Issue the error in the caller.
return "";
}
// The SPIR-V variable is i32, but WGSL requires u32.
auto var_id = parser_impl_.IdForSpecialBuiltIn(spv_builtin);
return namer_.Name(var_id);
}
TypedExpression FunctionEmitter::MakeOperand( TypedExpression FunctionEmitter::MakeOperand(
const spvtools::opt::Instruction& inst, const spvtools::opt::Instruction& inst,
uint32_t operand_index) { uint32_t operand_index) {
@ -4279,15 +4227,6 @@ bool FunctionEmitter::RegisterSpecialBuiltInVariables() {
case SpvBuiltInPointSize: case SpvBuiltInPointSize:
def->skip = SkipReason::kPointSizeBuiltinPointer; def->skip = SkipReason::kPointSizeBuiltinPointer;
break; break;
case SpvBuiltInSampleId:
def->skip = SkipReason::kSampleIdBuiltinPointer;
break;
case SpvBuiltInVertexIndex:
def->skip = SkipReason::kVertexIndexBuiltinPointer;
break;
case SpvBuiltInInstanceIndex:
def->skip = SkipReason::kInstanceIndexBuiltinPointer;
break;
case SpvBuiltInSampleMask: { case SpvBuiltInSampleMask: {
// Distinguish between input and output variable. // Distinguish between input and output variable.
const auto storage_class = const auto storage_class =
@ -4301,6 +4240,9 @@ bool FunctionEmitter::RegisterSpecialBuiltInVariables() {
} }
break; break;
} }
case SpvBuiltInSampleId:
case SpvBuiltInInstanceIndex:
case SpvBuiltInVertexIndex:
case SpvBuiltInLocalInvocationIndex: case SpvBuiltInLocalInvocationIndex:
case SpvBuiltInLocalInvocationId: case SpvBuiltInLocalInvocationId:
case SpvBuiltInGlobalInvocationId: case SpvBuiltInGlobalInvocationId:

View File

@ -214,19 +214,6 @@ enum class SkipReason {
/// supported by WebGPU. /// supported by WebGPU.
kPointSizeBuiltinValue, kPointSizeBuiltinValue,
/// `kSampleIdBuiltinPointer`: the value is a pointer to the SampleId builtin
/// variable. Don't generate its address.
kSampleIdBuiltinPointer,
/// `kVertexIndexBuiltinPointer`: the value is a pointer to the VertexIndex
/// builtin variable. Don't generate its address.
kVertexIndexBuiltinPointer,
/// `kInstanceIndexBuiltinPointer`: the value is a pointer to the
/// InstanceIndex
/// builtin variable. Don't generate its address.
kInstanceIndexBuiltinPointer,
/// `kSampleMaskInBuiltinPointer`: the value is a pointer to the SampleMaskIn /// `kSampleMaskInBuiltinPointer`: the value is a pointer to the SampleMaskIn
/// builtin input variable. Don't generate its address. /// builtin input variable. Don't generate its address.
kSampleMaskInBuiltinPointer, kSampleMaskInBuiltinPointer,
@ -339,15 +326,6 @@ inline std::ostream& operator<<(std::ostream& o, const DefInfo& di) {
case SkipReason::kPointSizeBuiltinValue: case SkipReason::kPointSizeBuiltinValue:
o << " skip:pointsize_value"; o << " skip:pointsize_value";
break; break;
case SkipReason::kSampleIdBuiltinPointer:
o << " skip:sampleid_pointer";
break;
case SkipReason::kVertexIndexBuiltinPointer:
o << " skip:vertexindex_pointer";
break;
case SkipReason::kInstanceIndexBuiltinPointer:
o << " skip:instanceindex_pointer";
break;
case SkipReason::kSampleMaskInBuiltinPointer: case SkipReason::kSampleMaskInBuiltinPointer:
o << " skip:samplemaskin_pointer"; o << " skip:samplemaskin_pointer";
break; break;
@ -795,13 +773,6 @@ class FunctionEmitter {
return SkipReason::kDontSkip; return SkipReason::kDontSkip;
} }
/// Returns the WGSL variable name for an input builtin variable whose
/// translation is managed via the SkipReason mechanism.
/// @param skip_reason the skip reason for the special variable
/// @returns the variable name for a special builtin variable
/// that is handled via the "skip" mechanism.
std::string NameForSpecialInputBuiltin(SkipReason skip_reason);
/// Returns the most deeply nested structured construct which encloses the /// Returns the most deeply nested structured construct which encloses the
/// WGSL scopes of names declared in both block positions. Each position must /// WGSL scopes of names declared in both block positions. Each position must
/// be a valid index into the function block order array. /// be a valid index into the function block order array.

View File

@ -2443,18 +2443,31 @@ TEST_F(SpvModuleScopeVarParserTest, SampleId_I32_Load_CopyObject) {
ASSERT_TRUE(p->BuildAndParseInternalModule()) << p->error() << assembly; ASSERT_TRUE(p->BuildAndParseInternalModule()) << p->error() << assembly;
EXPECT_TRUE(p->error().empty()); EXPECT_TRUE(p->error().empty());
const auto module_str = p->program().to_str(); const auto module_str = p->program().to_str();
const std::string expected =
// Correct declaration R"(Module{
EXPECT_THAT(module_str, HasSubstr(R"(
Variable{ Variable{
x_1 x_1
private private
undefined undefined
__i32 __i32
})")) <<module_str; }
Function main_1 -> __void
// Correct creation of value ()
EXPECT_THAT(module_str, HasSubstr(R"( {
VariableDeclStatement{
VariableConst{
x_11
none
undefined
__ptr_none__i32
{
UnaryOp[not set]{
address-of
Identifier[not set]{x_1}
}
}
}
}
VariableDeclStatement{ VariableDeclStatement{
VariableConst{ VariableConst{
x_2 x_2
@ -2462,14 +2475,15 @@ TEST_F(SpvModuleScopeVarParserTest, SampleId_I32_Load_CopyObject) {
undefined undefined
__i32 __i32
{ {
Identifier[not set]{x_1} UnaryOp[not set]{
indirection
Identifier[not set]{x_11}
}
} }
} }
})")) }
<< module_str; Return{}
}
// Correct parameter on entry point
EXPECT_THAT(module_str, HasSubstr(R"(
Function main -> __void Function main -> __void
StageDecoration{fragment} StageDecoration{fragment}
( (
@ -2489,8 +2503,15 @@ TEST_F(SpvModuleScopeVarParserTest, SampleId_I32_Load_CopyObject) {
Bitcast[not set]<__i32>{ Bitcast[not set]<__i32>{
Identifier[not set]{x_1_param} Identifier[not set]{x_1_param}
} }
})")) }
<< module_str; Call[not set]{
Identifier[not set]{main_1}
(
)
}
}
}
)";
} }
TEST_F(SpvModuleScopeVarParserTest, SampleId_I32_Load_AccessChain) { TEST_F(SpvModuleScopeVarParserTest, SampleId_I32_Load_AccessChain) {
@ -2668,6 +2689,20 @@ TEST_F(SpvModuleScopeVarParserTest, SampleId_U32_Load_CopyObject) {
Function main_1 -> __void Function main_1 -> __void
() ()
{ {
VariableDeclStatement{
VariableConst{
x_11
none
undefined
__ptr_none__u32
{
UnaryOp[not set]{
address-of
Identifier[not set]{x_1}
}
}
}
}
VariableDeclStatement{ VariableDeclStatement{
VariableConst{ VariableConst{
x_2 x_2
@ -2675,7 +2710,10 @@ TEST_F(SpvModuleScopeVarParserTest, SampleId_U32_Load_CopyObject) {
undefined undefined
__u32 __u32
{ {
Identifier[not set]{x_1} UnaryOp[not set]{
indirection
Identifier[not set]{x_11}
}
} }
} }
} }
@ -2944,18 +2982,16 @@ TEST_F(SpvModuleScopeVarParserTest, SampleMask_In_U32_CopyObject) {
ASSERT_TRUE(p->BuildAndParseInternalModule()) << p->error() << assembly; ASSERT_TRUE(p->BuildAndParseInternalModule()) << p->error() << assembly;
EXPECT_TRUE(p->error().empty()); EXPECT_TRUE(p->error().empty());
const auto module_str = p->program().to_str(); const auto module_str = p->program().to_str();
const std::string expected = R"(Module{
// Correct declaration
EXPECT_THAT(module_str, HasSubstr(R"(
Variable{ Variable{
x_1 x_1
private private
undefined undefined
__array__u32_1 __array__u32_1
})")) <<module_str; }
Function main_1 -> __void
// Correct creation of value ()
EXPECT_THAT(module_str, HasSubstr(R"( {
VariableDeclStatement{ VariableDeclStatement{
VariableConst{ VariableConst{
x_4 x_4
@ -2969,10 +3005,9 @@ TEST_F(SpvModuleScopeVarParserTest, SampleMask_In_U32_CopyObject) {
} }
} }
} }
})")); }
Return{}
// Correct parameter on entry point }
EXPECT_THAT(module_str, HasSubstr(R"(
Function main -> __void Function main -> __void
StageDecoration{fragment} StageDecoration{fragment}
( (
@ -2993,8 +3028,16 @@ TEST_F(SpvModuleScopeVarParserTest, SampleMask_In_U32_CopyObject) {
ScalarConstructor[not set]{0} ScalarConstructor[not set]{0}
} }
Identifier[not set]{x_1_param} Identifier[not set]{x_1_param}
})")) }
<< module_str; Call[not set]{
Identifier[not set]{main_1}
(
)
}
}
}
)";
EXPECT_EQ(module_str, expected) << module_str;
} }
TEST_F(SpvModuleScopeVarParserTest, SampleMask_In_U32_AccessChain) { TEST_F(SpvModuleScopeVarParserTest, SampleMask_In_U32_AccessChain) {
@ -3955,6 +3998,20 @@ TEST_F(SpvModuleScopeVarParserTest, VertexIndex_I32_Load_CopyObject) {
Function main_1 -> __void Function main_1 -> __void
() ()
{ {
VariableDeclStatement{
VariableConst{
x_11
none
undefined
__ptr_none__i32
{
UnaryOp[not set]{
address-of
Identifier[not set]{x_1}
}
}
}
}
VariableDeclStatement{ VariableDeclStatement{
VariableConst{ VariableConst{
x_2 x_2
@ -3962,7 +4019,10 @@ TEST_F(SpvModuleScopeVarParserTest, VertexIndex_I32_Load_CopyObject) {
undefined undefined
__i32 __i32
{ {
Identifier[not set]{x_1} UnaryOp[not set]{
indirection
Identifier[not set]{x_11}
}
} }
} }
} }
@ -4066,34 +4126,6 @@ TEST_F(SpvModuleScopeVarParserTest, VertexIndex_I32_Load_AccessChain) {
EXPECT_EQ(module_str, expected); EXPECT_EQ(module_str, expected);
} }
TEST_F(SpvModuleScopeVarParserTest, VertexIndex_I32_FunctParam) {
// TODO(dneto): Passing by pointer-to-input is not allowed.
// Remove this test.
const std::string assembly = VertexIndexPreamble("%int") + R"(
%helper_ty = OpTypeFunction %int %ptr_ty
%helper = OpFunction %int None %helper_ty
%param = OpFunctionParameter %ptr_ty
%helper_entry = OpLabel
%3 = OpLoad %int %param
OpReturnValue %3
OpFunctionEnd
%main = OpFunction %void None %voidfn
%entry = OpLabel
%result = OpFunctionCall %int %helper %1
OpReturn
OpFunctionEnd
)";
auto p = parser(test::Assemble(assembly));
// TODO(dneto): We can handle this if we make a shadow variable and mutate
// the parameter type.
ASSERT_FALSE(p->BuildAndParseInternalModule());
EXPECT_THAT(
p->error(),
HasSubstr(
"unhandled use of a pointer to the VertexIndex builtin, with ID: 1"));
}
TEST_F(SpvModuleScopeVarParserTest, VertexIndex_U32_Load_Direct) { TEST_F(SpvModuleScopeVarParserTest, VertexIndex_U32_Load_Direct) {
const std::string assembly = VertexIndexPreamble("%uint") + R"( const std::string assembly = VertexIndexPreamble("%uint") + R"(
%main = OpFunction %void None %voidfn %main = OpFunction %void None %voidfn
@ -4181,6 +4213,20 @@ TEST_F(SpvModuleScopeVarParserTest, VertexIndex_U32_Load_CopyObject) {
Function main_1 -> __void Function main_1 -> __void
() ()
{ {
VariableDeclStatement{
VariableConst{
x_11
none
undefined
__ptr_none__u32
{
UnaryOp[not set]{
address-of
Identifier[not set]{x_1}
}
}
}
}
VariableDeclStatement{ VariableDeclStatement{
VariableConst{ VariableConst{
x_2 x_2
@ -4188,7 +4234,10 @@ TEST_F(SpvModuleScopeVarParserTest, VertexIndex_U32_Load_CopyObject) {
undefined undefined
__u32 __u32
{ {
Identifier[not set]{x_1} UnaryOp[not set]{
indirection
Identifier[not set]{x_11}
}
} }
} }
} }
@ -4421,6 +4470,20 @@ TEST_F(SpvModuleScopeVarParserTest, InstanceIndex_I32_Load_CopyObject) {
Function main_1 -> __void Function main_1 -> __void
() ()
{ {
VariableDeclStatement{
VariableConst{
x_11
none
undefined
__ptr_none__i32
{
UnaryOp[not set]{
address-of
Identifier[not set]{x_1}
}
}
}
}
VariableDeclStatement{ VariableDeclStatement{
VariableConst{ VariableConst{
x_2 x_2
@ -4428,7 +4491,10 @@ TEST_F(SpvModuleScopeVarParserTest, InstanceIndex_I32_Load_CopyObject) {
undefined undefined
__i32 __i32
{ {
Identifier[not set]{x_1} UnaryOp[not set]{
indirection
Identifier[not set]{x_11}
}
} }
} }
} }
@ -4643,6 +4709,20 @@ TEST_F(SpvModuleScopeVarParserTest, InstanceIndex_U32_Load_CopyObject) {
Function main_1 -> __void Function main_1 -> __void
() ()
{ {
VariableDeclStatement{
VariableConst{
x_11
none
undefined
__ptr_none__u32
{
UnaryOp[not set]{
address-of
Identifier[not set]{x_1}
}
}
}
}
VariableDeclStatement{ VariableDeclStatement{
VariableConst{ VariableConst{
x_2 x_2
@ -4650,7 +4730,10 @@ TEST_F(SpvModuleScopeVarParserTest, InstanceIndex_U32_Load_CopyObject) {
undefined undefined
__u32 __u32
{ {
Identifier[not set]{x_1} UnaryOp[not set]{
indirection
Identifier[not set]{x_11}
}
} }
} }
} }