Rename builtin(frag_coord) to builtin(position)

Use the variable storage class to determine the correct builtin to use
in the SPIR-V generator.

Added a deprecation warning for frag_coord.

Bug: tint:714
Change-Id: I5ad4956f9345e2f39f4af16e84668dec345ac82e
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/47742
Auto-Submit: James Price <jrprice@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
James Price 2021-04-14 16:37:18 +00:00 committed by Commit Bot service account
parent d13982ff2e
commit 88d7edcf7a
19 changed files with 176 additions and 110 deletions

View File

@ -27,7 +27,7 @@ enum class Builtin {
kVertexIndex, kVertexIndex,
kInstanceIndex, kInstanceIndex,
kFrontFacing, kFrontFacing,
kFragCoord, kFragCoord, // TODO(crbug.com/tint/714): Remove this
kFragDepth, kFragDepth,
kLocalInvocationId, kLocalInvocationId,
kLocalInvocationIndex, kLocalInvocationIndex,

View File

@ -77,7 +77,7 @@ ast::Builtin EnumConverter::ToBuiltin(SpvBuiltIn b, ast::StorageClass sc) {
case SpvBuiltInFrontFacing: case SpvBuiltInFrontFacing:
return ast::Builtin::kFrontFacing; return ast::Builtin::kFrontFacing;
case SpvBuiltInFragCoord: case SpvBuiltInFragCoord:
return ast::Builtin::kFragCoord; return ast::Builtin::kPosition;
case SpvBuiltInFragDepth: case SpvBuiltInFragDepth:
return ast::Builtin::kFragDepth; return ast::Builtin::kFragDepth;
case SpvBuiltInLocalInvocationId: case SpvBuiltInLocalInvocationId:

View File

@ -214,7 +214,7 @@ INSTANTIATE_TEST_SUITE_P(
BuiltinCase{SpvBuiltInFrontFacing, ast::StorageClass::kInput, true, BuiltinCase{SpvBuiltInFrontFacing, ast::StorageClass::kInput, true,
ast::Builtin::kFrontFacing}, ast::Builtin::kFrontFacing},
BuiltinCase{SpvBuiltInFragCoord, ast::StorageClass::kInput, true, BuiltinCase{SpvBuiltInFragCoord, ast::StorageClass::kInput, true,
ast::Builtin::kFragCoord}, ast::Builtin::kPosition},
BuiltinCase{SpvBuiltInLocalInvocationId, ast::StorageClass::kInput, BuiltinCase{SpvBuiltInLocalInvocationId, ast::StorageClass::kInput,
true, ast::Builtin::kLocalInvocationId}, true, ast::Builtin::kLocalInvocationId},
BuiltinCase{SpvBuiltInLocalInvocationIndex, ast::StorageClass::kInput, BuiltinCase{SpvBuiltInLocalInvocationIndex, ast::StorageClass::kInput,

View File

@ -1379,6 +1379,10 @@ Expect<ast::Builtin> ParserImpl::expect_builtin() {
if (builtin == ast::Builtin::kNone) if (builtin == ast::Builtin::kNone)
return add_error(ident.source, "invalid value for builtin decoration"); return add_error(ident.source, "invalid value for builtin decoration");
if (builtin == ast::Builtin::kFragCoord) {
deprecated(ident.source, "use 'position' instead of 'frag_coord'");
}
return {builtin, ident.source}; return {builtin, ident.source};
} }

View File

@ -97,7 +97,7 @@ TEST_F(ParserImplTest, ParamList_HangingComma) {
TEST_F(ParserImplTest, ParamList_Decorations) { TEST_F(ParserImplTest, ParamList_Decorations) {
auto p = parser( auto p = parser(
"[[builtin(frag_coord)]] coord : vec4<f32>, " "[[builtin(position)]] coord : vec4<f32>, "
"[[location(1)]] loc1 : f32"); "[[location(1)]] loc1 : f32");
auto* f32 = p->builder().create<type::F32>(); auto* f32 = p->builder().create<type::F32>();
@ -115,12 +115,12 @@ TEST_F(ParserImplTest, ParamList_Decorations) {
ASSERT_EQ(decos0.size(), 1u); ASSERT_EQ(decos0.size(), 1u);
EXPECT_TRUE(decos0[0]->Is<ast::BuiltinDecoration>()); EXPECT_TRUE(decos0[0]->Is<ast::BuiltinDecoration>());
EXPECT_EQ(decos0[0]->As<ast::BuiltinDecoration>()->value(), EXPECT_EQ(decos0[0]->As<ast::BuiltinDecoration>()->value(),
ast::Builtin::kFragCoord); ast::Builtin::kPosition);
ASSERT_EQ(e.value[0]->source().range.begin.line, 1u); ASSERT_EQ(e.value[0]->source().range.begin.line, 1u);
ASSERT_EQ(e.value[0]->source().range.begin.column, 25u); ASSERT_EQ(e.value[0]->source().range.begin.column, 23u);
ASSERT_EQ(e.value[0]->source().range.end.line, 1u); ASSERT_EQ(e.value[0]->source().range.end.line, 1u);
ASSERT_EQ(e.value[0]->source().range.end.column, 30u); ASSERT_EQ(e.value[0]->source().range.end.column, 28u);
EXPECT_EQ(e.value[1]->symbol(), p->builder().Symbols().Get("loc1")); EXPECT_EQ(e.value[1]->symbol(), p->builder().Symbols().Get("loc1"));
EXPECT_EQ(e.value[1]->declared_type(), f32); EXPECT_EQ(e.value[1]->declared_type(), f32);
@ -131,9 +131,9 @@ TEST_F(ParserImplTest, ParamList_Decorations) {
EXPECT_EQ(decos1[0]->As<ast::LocationDecoration>()->value(), 1u); EXPECT_EQ(decos1[0]->As<ast::LocationDecoration>()->value(), 1u);
ASSERT_EQ(e.value[1]->source().range.begin.line, 1u); ASSERT_EQ(e.value[1]->source().range.begin.line, 1u);
ASSERT_EQ(e.value[1]->source().range.begin.column, 60u); ASSERT_EQ(e.value[1]->source().range.begin.column, 58u);
ASSERT_EQ(e.value[1]->source().range.end.line, 1u); ASSERT_EQ(e.value[1]->source().range.end.line, 1u);
ASSERT_EQ(e.value[1]->source().range.end.column, 64u); ASSERT_EQ(e.value[1]->source().range.end.column, 62u);
} }
} // namespace } // namespace

View File

@ -305,6 +305,28 @@ TEST_F(ParserImplTest, Decoration_Group_MissingInvalid) {
"1:7: expected signed integer literal for group decoration"); "1:7: expected signed integer literal for group decoration");
} }
TEST_F(ParserImplTest, Decoration_FragCoord_Deprecated) {
auto p = parser("builtin(frag_coord)");
auto deco = p->decoration();
EXPECT_TRUE(deco.matched);
EXPECT_FALSE(deco.errored);
ASSERT_NE(deco.value, nullptr);
auto* var_deco = deco.value->As<ast::Decoration>();
ASSERT_NE(var_deco, nullptr);
ASSERT_FALSE(p->has_error());
ASSERT_TRUE(var_deco->Is<ast::BuiltinDecoration>());
auto* builtin = var_deco->As<ast::BuiltinDecoration>();
EXPECT_EQ(builtin->value(), ast::Builtin::kFragCoord);
EXPECT_EQ(
p->builder().Diagnostics().str(),
R"(test.wgsl:1:9 warning: use of deprecated language feature: use 'position' instead of 'frag_coord'
builtin(frag_coord)
^^^^^^^^^^
)");
}
} // namespace } // namespace
} // namespace wgsl } // namespace wgsl
} // namespace reader } // namespace reader

View File

@ -34,7 +34,7 @@ namespace transform {
/// }; /// };
/// ///
/// [[stage(fragment)]] /// [[stage(fragment)]]
/// fn frag_main([[builtin(frag_coord)]] coord : vec4<f32>, /// fn frag_main([[builtin(position)]] coord : vec4<f32>,
/// locations : Locations) -> [[location(0)]] f32 { /// locations : Locations) -> [[location(0)]] f32 {
/// var col : f32 = (coord.x * locations.loc1); /// var col : f32 = (coord.x * locations.loc1);
/// return col; /// return col;
@ -49,7 +49,7 @@ namespace transform {
/// }; /// };
/// ///
/// struct frag_main_in { /// struct frag_main_in {
/// [[builtin(frag_coord)]] coord : vec4<f32>; /// [[builtin(position)]] coord : vec4<f32>;
/// [[location(1)]] loc1 : f32; /// [[location(1)]] loc1 : f32;
/// [[location(2)]] loc2 : vec4<u32> /// [[location(2)]] loc2 : vec4<u32>
/// }; /// };

View File

@ -25,7 +25,7 @@ using CanonicalizeEntryPointIOTest = TransformTest;
TEST_F(CanonicalizeEntryPointIOTest, Parameters) { TEST_F(CanonicalizeEntryPointIOTest, Parameters) {
auto* src = R"( auto* src = R"(
[[stage(fragment)]] [[stage(fragment)]]
fn frag_main([[builtin(frag_coord)]] coord : vec4<f32>, fn frag_main([[builtin(position)]] coord : vec4<f32>,
[[location(1)]] loc1 : f32, [[location(1)]] loc1 : f32,
[[location(2)]] loc2 : vec4<u32>) { [[location(2)]] loc2 : vec4<u32>) {
var col : f32 = (coord.x * loc1); var col : f32 = (coord.x * loc1);
@ -34,7 +34,7 @@ fn frag_main([[builtin(frag_coord)]] coord : vec4<f32>,
auto* expect = R"( auto* expect = R"(
struct tint_symbol_1 { struct tint_symbol_1 {
[[builtin(frag_coord)]] [[builtin(position)]]
coord : vec4<f32>; coord : vec4<f32>;
[[location(1)]] [[location(1)]]
loc1 : f32; loc1 : f32;
@ -89,7 +89,7 @@ fn frag_main(tint_symbol : tint_symbol_1) {
TEST_F(CanonicalizeEntryPointIOTest, Parameters_EmptyBody) { TEST_F(CanonicalizeEntryPointIOTest, Parameters_EmptyBody) {
auto* src = R"( auto* src = R"(
[[stage(fragment)]] [[stage(fragment)]]
fn frag_main([[builtin(frag_coord)]] coord : vec4<f32>, fn frag_main([[builtin(position)]] coord : vec4<f32>,
[[location(1)]] loc1 : f32, [[location(1)]] loc1 : f32,
[[location(2)]] loc2 : vec4<u32>) { [[location(2)]] loc2 : vec4<u32>) {
} }
@ -97,7 +97,7 @@ fn frag_main([[builtin(frag_coord)]] coord : vec4<f32>,
auto* expect = R"( auto* expect = R"(
struct tint_symbol_1 { struct tint_symbol_1 {
[[builtin(frag_coord)]] [[builtin(position)]]
coord : vec4<f32>; coord : vec4<f32>;
[[location(1)]] [[location(1)]]
loc1 : f32; loc1 : f32;
@ -118,7 +118,7 @@ fn frag_main(tint_symbol : tint_symbol_1) {
TEST_F(CanonicalizeEntryPointIOTest, StructParameters) { TEST_F(CanonicalizeEntryPointIOTest, StructParameters) {
auto* src = R"( auto* src = R"(
struct FragBuiltins { struct FragBuiltins {
[[builtin(frag_coord)]] coord : vec4<f32>; [[builtin(position)]] coord : vec4<f32>;
}; };
struct FragLocations { struct FragLocations {
[[location(1)]] loc1 : f32; [[location(1)]] loc1 : f32;
@ -144,7 +144,7 @@ struct FragLocations {
}; };
struct tint_symbol_1 { struct tint_symbol_1 {
[[builtin(frag_coord)]] [[builtin(position)]]
coord : vec4<f32>; coord : vec4<f32>;
[[location(1)]] [[location(1)]]
loc1 : f32; loc1 : f32;
@ -451,7 +451,7 @@ TEST_F(CanonicalizeEntryPointIOTest, Struct_LayoutDecorations) {
[[block]] [[block]]
struct FragmentInput { struct FragmentInput {
[[size(16), location(1)]] value : f32; [[size(16), location(1)]] value : f32;
[[builtin(frag_coord)]] [[align(32)]] coord : vec4<f32>; [[builtin(position)]] [[align(32)]] coord : vec4<f32>;
}; };
struct FragmentOutput { struct FragmentOutput {
@ -481,7 +481,7 @@ struct FragmentOutput {
struct tint_symbol_1 { struct tint_symbol_1 {
[[location(1)]] [[location(1)]]
value : f32; value : f32;
[[builtin(frag_coord)]] [[builtin(position)]]
coord : vec4<f32>; coord : vec4<f32>;
}; };

View File

@ -68,7 +68,7 @@ void Spirv::HandleEntryPointIOTypes(CloneContext& ctx) const {
// //
// [[stage(fragment)]] // [[stage(fragment)]]
// fn frag_main( // fn frag_main(
// [[builtin(frag_coord)]] coord : vec4<f32>, // [[builtin(position)]] coord : vec4<f32>,
// samples : FragmentInput // samples : FragmentInput
// ) -> FragmentOutput { // ) -> FragmentOutput {
// var output : FragmentOutput = FragmentOutput(1.0, // var output : FragmentOutput = FragmentOutput(1.0,
@ -88,7 +88,7 @@ void Spirv::HandleEntryPointIOTypes(CloneContext& ctx) const {
// mask_out : u32; // mask_out : u32;
// }; // };
// //
// [[builtin(frag_coord)]] var<in> coord : vec4<f32>, // [[builtin(position)]] var<in> coord : vec4<f32>,
// [[builtin(sample_index)]] var<in> sample_index : u32, // [[builtin(sample_index)]] var<in> sample_index : u32,
// [[builtin(sample_mask_in)]] var<in> sample_mask_in : u32, // [[builtin(sample_mask_in)]] var<in> sample_mask_in : u32,
// [[builtin(frag_depth)]] var<out> depth: f32; // [[builtin(frag_depth)]] var<out> depth: f32;

View File

@ -25,7 +25,7 @@ using SpirvTest = TransformTest;
TEST_F(SpirvTest, HandleEntryPointIOTypes_Parameters) { TEST_F(SpirvTest, HandleEntryPointIOTypes_Parameters) {
auto* src = R"( auto* src = R"(
[[stage(fragment)]] [[stage(fragment)]]
fn frag_main([[builtin(frag_coord)]] coord : vec4<f32>, fn frag_main([[builtin(position)]] coord : vec4<f32>,
[[location(1)]] loc1 : f32) { [[location(1)]] loc1 : f32) {
var col : f32 = (coord.x * loc1); var col : f32 = (coord.x * loc1);
} }
@ -38,7 +38,7 @@ fn compute_main([[builtin(local_invocation_id)]] local_id : vec3<u32>,
)"; )";
auto* expect = R"( auto* expect = R"(
[[builtin(frag_coord)]] var<in> tint_symbol : vec4<f32>; [[builtin(position)]] var<in> tint_symbol : vec4<f32>;
[[location(1)]] var<in> tint_symbol_1 : f32; [[location(1)]] var<in> tint_symbol_1 : f32;
@ -192,7 +192,7 @@ fn frag_main() {
TEST_F(SpirvTest, HandleEntryPointIOTypes_StructParameters) { TEST_F(SpirvTest, HandleEntryPointIOTypes_StructParameters) {
auto* src = R"( auto* src = R"(
struct FragmentInput { struct FragmentInput {
[[builtin(frag_coord)]] coord : vec4<f32>; [[builtin(position)]] coord : vec4<f32>;
[[location(1)]] value : f32; [[location(1)]] value : f32;
}; };
@ -208,7 +208,7 @@ struct FragmentInput {
value : f32; value : f32;
}; };
[[builtin(frag_coord)]] var<in> tint_symbol : vec4<f32>; [[builtin(position)]] var<in> tint_symbol : vec4<f32>;
[[location(1)]] var<in> tint_symbol_1 : f32; [[location(1)]] var<in> tint_symbol_1 : f32;
@ -392,7 +392,7 @@ TEST_F(SpirvTest, HandleEntryPointIOTypes_StructLayoutDecorations) {
[[block]] [[block]]
struct FragmentInput { struct FragmentInput {
[[size(16), location(1)]] value : f32; [[size(16), location(1)]] value : f32;
[[builtin(frag_coord)]] [[align(32)]] coord : vec4<f32>; [[builtin(position)]] [[align(32)]] coord : vec4<f32>;
}; };
struct FragmentOutput { struct FragmentOutput {
@ -421,7 +421,7 @@ struct FragmentOutput {
[[location(1)]] var<in> tint_symbol : f32; [[location(1)]] var<in> tint_symbol : f32;
[[builtin(frag_coord)]] var<in> tint_symbol_1 : vec4<f32>; [[builtin(position)]] var<in> tint_symbol_1 : vec4<f32>;
[[location(1)]] var<out> tint_symbol_4 : f32; [[location(1)]] var<out> tint_symbol_4 : f32;

View File

@ -268,7 +268,7 @@ TEST_F(HlslGeneratorImplTest_EntryPoint,
TEST_F(HlslGeneratorImplTest_EntryPoint, TEST_F(HlslGeneratorImplTest_EntryPoint,
Emit_Function_EntryPointData_Builtins) { Emit_Function_EntryPointData_Builtins) {
// [[builtin frag_coord]] var<in> coord : vec4<f32>; // [[builtin position]] var<in> coord : vec4<f32>;
// [[builtin frag_depth]] var<out> depth : f32; // [[builtin frag_depth]] var<out> depth : f32;
// //
// struct main_in { // struct main_in {
@ -281,7 +281,7 @@ TEST_F(HlslGeneratorImplTest_EntryPoint,
Global("coord", ty.vec4<f32>(), ast::StorageClass::kInput, nullptr, Global("coord", ty.vec4<f32>(), ast::StorageClass::kInput, nullptr,
ast::DecorationList{ ast::DecorationList{
create<ast::BuiltinDecoration>(ast::Builtin::kFragCoord), create<ast::BuiltinDecoration>(ast::Builtin::kPosition),
}); });
Global("depth", ty.f32(), ast::StorageClass::kOutput, nullptr, Global("depth", ty.f32(), ast::StorageClass::kOutput, nullptr,

View File

@ -144,7 +144,7 @@ TEST_F(HlslGeneratorImplTest_Function,
// } // }
auto* coord_in = auto* coord_in =
Param("coord", ty.vec4<f32>(), Param("coord", ty.vec4<f32>(),
{create<ast::BuiltinDecoration>(ast::Builtin::kFragCoord)}); {create<ast::BuiltinDecoration>(ast::Builtin::kPosition)});
Func("frag_main", ast::VariableList{coord_in}, ty.f32(), Func("frag_main", ast::VariableList{coord_in}, ty.f32(),
{create<ast::ReturnStatement>(MemberAccessor("coord", "x"))}, {create<ast::ReturnStatement>(MemberAccessor("coord", "x"))},
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)}, {create<ast::StageDecoration>(ast::PipelineStage::kFragment)},
@ -675,7 +675,7 @@ TEST_F(
Emit_Decoration_Called_By_EntryPoints_WithBuiltinGlobals_And_Params) { // NOLINT Emit_Decoration_Called_By_EntryPoints_WithBuiltinGlobals_And_Params) { // NOLINT
Global("coord", ty.vec4<f32>(), ast::StorageClass::kInput, nullptr, Global("coord", ty.vec4<f32>(), ast::StorageClass::kInput, nullptr,
ast::DecorationList{ ast::DecorationList{
create<ast::BuiltinDecoration>(ast::Builtin::kFragCoord), create<ast::BuiltinDecoration>(ast::Builtin::kPosition),
}); });
Global("depth", ty.f32(), ast::StorageClass::kOutput, nullptr, Global("depth", ty.f32(), ast::StorageClass::kOutput, nullptr,

View File

@ -234,7 +234,7 @@ TEST_F(MslGeneratorImplTest, Emit_Function_EntryPointData_Builtins) {
// Output builtins go in the output struct, input builtins will be passed // Output builtins go in the output struct, input builtins will be passed
// as input parameters to the entry point function. // as input parameters to the entry point function.
// [[builtin frag_coord]] var<in> coord : vec4<f32>; // [[builtin position]] var<in> coord : vec4<f32>;
// [[builtin frag_depth]] var<out> depth : f32; // [[builtin frag_depth]] var<out> depth : f32;
// //
// struct main_out { // struct main_out {
@ -243,7 +243,7 @@ TEST_F(MslGeneratorImplTest, Emit_Function_EntryPointData_Builtins) {
Global("coord", ty.vec4<f32>(), ast::StorageClass::kInput, nullptr, Global("coord", ty.vec4<f32>(), ast::StorageClass::kInput, nullptr,
ast::DecorationList{ ast::DecorationList{
create<ast::BuiltinDecoration>(ast::Builtin::kFragCoord)}); create<ast::BuiltinDecoration>(ast::Builtin::kPosition)});
Global("depth", ty.f32(), ast::StorageClass::kOutput, nullptr, Global("depth", ty.f32(), ast::StorageClass::kOutput, nullptr,
ast::DecorationList{ ast::DecorationList{

View File

@ -129,7 +129,7 @@ TEST_F(MslGeneratorImplTest, Emit_Decoration_EntryPoint_WithInOut_Builtins) {
// } // }
auto* coord_in = auto* coord_in =
Param("coord", ty.vec4<f32>(), Param("coord", ty.vec4<f32>(),
{create<ast::BuiltinDecoration>(ast::Builtin::kFragCoord)}); {create<ast::BuiltinDecoration>(ast::Builtin::kPosition)});
Func("frag_main", ast::VariableList{coord_in}, ty.f32(), Func("frag_main", ast::VariableList{coord_in}, ty.f32(),
{create<ast::ReturnStatement>(MemberAccessor("coord", "x"))}, {create<ast::ReturnStatement>(MemberAccessor("coord", "x"))},
{create<ast::StageDecoration>(ast::PipelineStage::kFragment)}, {create<ast::StageDecoration>(ast::PipelineStage::kFragment)},
@ -496,7 +496,7 @@ TEST_F(
Emit_Decoration_Called_By_EntryPoints_WithBuiltinGlobals_And_Params) { // NOLINT Emit_Decoration_Called_By_EntryPoints_WithBuiltinGlobals_And_Params) { // NOLINT
Global("coord", ty.vec4<f32>(), ast::StorageClass::kInput, nullptr, Global("coord", ty.vec4<f32>(), ast::StorageClass::kInput, nullptr,
ast::DecorationList{ ast::DecorationList{
create<ast::BuiltinDecoration>(ast::Builtin::kFragCoord)}); create<ast::BuiltinDecoration>(ast::Builtin::kPosition)});
Global("depth", ty.f32(), ast::StorageClass::kOutput, nullptr, Global("depth", ty.f32(), ast::StorageClass::kOutput, nullptr,
ast::DecorationList{ ast::DecorationList{

View File

@ -788,7 +788,8 @@ bool Builder::GenerateGlobalVariable(ast::Variable* var) {
if (auto* builtin = deco->As<ast::BuiltinDecoration>()) { if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
push_annot(spv::Op::OpDecorate, push_annot(spv::Op::OpDecorate,
{Operand::Int(var_id), Operand::Int(SpvDecorationBuiltIn), {Operand::Int(var_id), Operand::Int(SpvDecorationBuiltIn),
Operand::Int(ConvertBuiltin(builtin->value()))}); Operand::Int(ConvertBuiltin(builtin->value(),
var->declared_storage_class()))});
} else if (auto* location = deco->As<ast::LocationDecoration>()) { } else if (auto* location = deco->As<ast::LocationDecoration>()) {
push_annot(spv::Op::OpDecorate, push_annot(spv::Op::OpDecorate,
{Operand::Int(var_id), Operand::Int(SpvDecorationLocation), {Operand::Int(var_id), Operand::Int(SpvDecorationLocation),
@ -3274,10 +3275,18 @@ SpvStorageClass Builder::ConvertStorageClass(ast::StorageClass klass) const {
return SpvStorageClassMax; return SpvStorageClassMax;
} }
SpvBuiltIn Builder::ConvertBuiltin(ast::Builtin builtin) { SpvBuiltIn Builder::ConvertBuiltin(ast::Builtin builtin,
ast::StorageClass storage) {
switch (builtin) { switch (builtin) {
case ast::Builtin::kPosition: case ast::Builtin::kPosition:
if (storage == ast::StorageClass::kInput) {
return SpvBuiltInFragCoord;
} else if (storage == ast::StorageClass::kOutput) {
return SpvBuiltInPosition; return SpvBuiltInPosition;
} else {
TINT_ICE(builder_.Diagnostics()) << "invalid storage class for builtin";
break;
}
case ast::Builtin::kVertexIndex: case ast::Builtin::kVertexIndex:
return SpvBuiltInVertexIndex; return SpvBuiltInVertexIndex;
case ast::Builtin::kInstanceIndex: case ast::Builtin::kInstanceIndex:

View File

@ -204,8 +204,9 @@ class Builder {
SpvStorageClass ConvertStorageClass(ast::StorageClass klass) const; SpvStorageClass ConvertStorageClass(ast::StorageClass klass) const;
/// Converts a builtin to a SPIR-V builtin and pushes a capability if needed. /// Converts a builtin to a SPIR-V builtin and pushes a capability if needed.
/// @param builtin the builtin to convert /// @param builtin the builtin to convert
/// @param storage the storage class that this builtin is being used with
/// @returns the SPIR-V builtin or SpvBuiltInMax on error. /// @returns the SPIR-V builtin or SpvBuiltInMax on error.
SpvBuiltIn ConvertBuiltin(ast::Builtin builtin); SpvBuiltIn ConvertBuiltin(ast::Builtin builtin, ast::StorageClass storage);
/// Generates a label for the given id. Emits an error and returns false if /// Generates a label for the given id. Emits an error and returns false if
/// we're currently outside a function. /// we're currently outside a function.

View File

@ -38,15 +38,14 @@ using BuilderTest = TestHelper;
TEST_F(BuilderTest, EntryPoint_Parameters) { TEST_F(BuilderTest, EntryPoint_Parameters) {
// [[stage(fragment)]] // [[stage(fragment)]]
// fn frag_main([[builtin(frag_coord)]] coord : vec4<f32>, // fn frag_main([[builtin(position)]] coord : vec4<f32>,
// [[location(1)]] loc1 : f32) { // [[location(1)]] loc1 : f32) {
// var col : f32 = (coord.x * loc1); // var col : f32 = (coord.x * loc1);
// } // }
auto* f32 = ty.f32(); auto* f32 = ty.f32();
auto* vec4 = ty.vec4<float>(); auto* vec4 = ty.vec4<float>();
auto* coord = auto* coord = Param(
Param("coord", vec4, "coord", vec4, {create<ast::BuiltinDecoration>(ast::Builtin::kPosition)});
{create<ast::BuiltinDecoration>(ast::Builtin::kFragCoord)});
auto* loc1 = Param("loc1", f32, {create<ast::LocationDecoration>(1u)}); auto* loc1 = Param("loc1", f32, {create<ast::LocationDecoration>(1u)});
auto* mul = Mul(Expr(MemberAccessor("coord", "x")), Expr("loc1")); auto* mul = Mul(Expr(MemberAccessor("coord", "x")), Expr("loc1"));
auto* col = Var("col", f32, ast::StorageClass::kFunction, mul, {}); auto* col = Var("col", f32, ast::StorageClass::kFunction, mul, {});
@ -180,11 +179,12 @@ OpFunctionEnd
TEST_F(BuilderTest, EntryPoint_SharedStruct) { TEST_F(BuilderTest, EntryPoint_SharedStruct) {
// struct Interface { // struct Interface {
// [[location(1)]] value : f32; // [[location(1)]] value : f32;
// [[builtin(position)]] pos : vec4<f32>;
// }; // };
// //
// [[stage(vertex)]] // [[stage(vertex)]]
// fn vert_main() -> Interface { // fn vert_main() -> Interface {
// return Interface(42.0); // return Interface(42.0, vec4<f32>());
// } // }
// //
// [[stage(fragment)]] // [[stage(fragment)]]
@ -194,10 +194,13 @@ TEST_F(BuilderTest, EntryPoint_SharedStruct) {
auto* interface = Structure( auto* interface = Structure(
"Interface", "Interface",
{Member("value", ty.f32(), {
ast::DecorationList{create<ast::LocationDecoration>(1u)})}); Member("value", ty.f32(), ast::DecorationList{Location(1u)}),
Member("pos", ty.vec4<f32>(),
ast::DecorationList{Builtin(ast::Builtin::kPosition)}),
});
auto* vert_retval = Construct(interface, 42.f); auto* vert_retval = Construct(interface, 42.f, Construct(ty.vec4<f32>()));
Func("vert_main", ast::VariableList{}, interface, Func("vert_main", ast::VariableList{}, interface,
{create<ast::ReturnStatement>(vert_retval)}, {create<ast::ReturnStatement>(vert_retval)},
{create<ast::StageDecoration>(ast::PipelineStage::kVertex)}); {create<ast::StageDecoration>(ast::PipelineStage::kVertex)});
@ -214,63 +217,78 @@ TEST_F(BuilderTest, EntryPoint_SharedStruct) {
EXPECT_EQ(DumpBuilder(b), R"(OpCapability Shader EXPECT_EQ(DumpBuilder(b), R"(OpCapability Shader
OpMemoryModel Logical GLSL450 OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %16 "vert_main" %1 OpEntryPoint Vertex %23 "vert_main" %1 %5
OpEntryPoint Fragment %25 "frag_main" %5 %7 OpEntryPoint Fragment %32 "frag_main" %9 %11 %13
OpExecutionMode %25 OriginUpperLeft OpExecutionMode %32 OriginUpperLeft
OpExecutionMode %25 DepthReplacing OpExecutionMode %32 DepthReplacing
OpName %1 "tint_symbol_1" OpName %1 "tint_symbol_1"
OpName %5 "tint_symbol_3" OpName %5 "tint_symbol_2"
OpName %7 "tint_symbol_6" OpName %9 "tint_symbol_4"
OpName %10 "Interface" OpName %11 "tint_symbol_5"
OpMemberName %10 0 "value" OpName %13 "tint_symbol_8"
OpName %11 "tint_symbol_2" OpName %16 "Interface"
OpName %12 "tint_symbol" OpMemberName %16 0 "value"
OpName %16 "vert_main" OpMemberName %16 1 "pos"
OpName %22 "tint_symbol_7" OpName %17 "tint_symbol_3"
OpName %23 "tint_symbol_5" OpName %18 "tint_symbol"
OpName %25 "frag_main" OpName %23 "vert_main"
OpName %29 "tint_symbol_9"
OpName %30 "tint_symbol_7"
OpName %32 "frag_main"
OpDecorate %1 Location 1 OpDecorate %1 Location 1
OpDecorate %5 Location 1 OpDecorate %5 BuiltIn Position
OpDecorate %7 BuiltIn FragDepth OpDecorate %9 Location 1
OpMemberDecorate %10 0 Offset 0 OpDecorate %11 BuiltIn FragCoord
OpDecorate %13 BuiltIn FragDepth
OpMemberDecorate %16 0 Offset 0
OpMemberDecorate %16 1 Offset 16
%3 = OpTypeFloat 32 %3 = OpTypeFloat 32
%2 = OpTypePointer Output %3 %2 = OpTypePointer Output %3
%4 = OpConstantNull %3 %4 = OpConstantNull %3
%1 = OpVariable %2 Output %4 %1 = OpVariable %2 Output %4
%6 = OpTypePointer Input %3 %7 = OpTypeVector %3 4
%5 = OpVariable %6 Input %6 = OpTypePointer Output %7
%7 = OpVariable %2 Output %4 %8 = OpConstantNull %7
%9 = OpTypeVoid %5 = OpVariable %6 Output %8
%10 = OpTypeStruct %3 %10 = OpTypePointer Input %3
%8 = OpTypeFunction %9 %10 %9 = OpVariable %10 Input
%15 = OpTypeFunction %9 %12 = OpTypePointer Input %7
%19 = OpConstant %3 42 %11 = OpVariable %12 Input
%20 = OpConstantComposite %10 %19 %13 = OpVariable %2 Output %4
%21 = OpTypeFunction %9 %3 %15 = OpTypeVoid
%11 = OpFunction %9 None %8 %16 = OpTypeStruct %3 %7
%12 = OpFunctionParameter %10 %14 = OpTypeFunction %15 %16
%13 = OpLabel %22 = OpTypeFunction %15
%14 = OpCompositeExtract %3 %12 0 %26 = OpConstant %3 42
OpStore %1 %14 %27 = OpConstantComposite %16 %26 %8
%28 = OpTypeFunction %15 %3
%17 = OpFunction %15 None %14
%18 = OpFunctionParameter %16
%19 = OpLabel
%20 = OpCompositeExtract %3 %18 0
OpStore %1 %20
%21 = OpCompositeExtract %7 %18 1
OpStore %5 %21
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd
%16 = OpFunction %9 None %15 %23 = OpFunction %15 None %22
%17 = OpLabel
%18 = OpFunctionCall %9 %11 %20
OpReturn
OpFunctionEnd
%22 = OpFunction %9 None %21
%23 = OpFunctionParameter %3
%24 = OpLabel %24 = OpLabel
OpStore %7 %23 %25 = OpFunctionCall %15 %17 %27
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd
%25 = OpFunction %9 None %15 %29 = OpFunction %15 None %28
%26 = OpLabel %30 = OpFunctionParameter %3
%27 = OpLoad %3 %5 %31 = OpLabel
%28 = OpCompositeConstruct %10 %27 OpStore %13 %30
%30 = OpCompositeExtract %3 %28 0 OpReturn
%29 = OpFunctionCall %9 %22 %30 OpFunctionEnd
%32 = OpFunction %15 None %22
%33 = OpLabel
%34 = OpLoad %3 %9
%35 = OpLoad %7 %11
%36 = OpCompositeConstruct %16 %34 %35
%38 = OpCompositeExtract %3 %36 0
%37 = OpFunctionCall %15 %29 %38
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd
)"); )");

View File

@ -324,6 +324,7 @@ TEST_F(BuilderTest, GlobalVar_ConstantId_Scalar_U32_NoConstructor) {
struct BuiltinData { struct BuiltinData {
ast::Builtin builtin; ast::Builtin builtin;
ast::StorageClass storage;
SpvBuiltIn result; SpvBuiltIn result;
}; };
inline std::ostream& operator<<(std::ostream& out, BuiltinData data) { inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
@ -336,31 +337,43 @@ TEST_P(BuiltinDataTest, Convert) {
spirv::Builder& b = Build(); spirv::Builder& b = Build();
EXPECT_EQ(b.ConvertBuiltin(params.builtin), params.result); EXPECT_EQ(b.ConvertBuiltin(params.builtin, params.storage), params.result);
} }
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
BuilderTest_Type, BuilderTest_Type,
BuiltinDataTest, BuiltinDataTest,
testing::Values( testing::Values(
BuiltinData{ast::Builtin::kNone, SpvBuiltInMax}, BuiltinData{ast::Builtin::kNone, ast::StorageClass::kNone,
BuiltinData{ast::Builtin::kPosition, SpvBuiltInPosition}, SpvBuiltInMax},
BuiltinData{ast::Builtin::kPosition, ast::StorageClass::kInput,
SpvBuiltInFragCoord},
BuiltinData{ast::Builtin::kPosition, ast::StorageClass::kOutput,
SpvBuiltInPosition},
BuiltinData{ BuiltinData{
ast::Builtin::kVertexIndex, ast::Builtin::kVertexIndex,
ast::StorageClass::kInput,
SpvBuiltInVertexIndex, SpvBuiltInVertexIndex,
}, },
BuiltinData{ast::Builtin::kInstanceIndex, SpvBuiltInInstanceIndex}, BuiltinData{ast::Builtin::kInstanceIndex, ast::StorageClass::kInput,
BuiltinData{ast::Builtin::kFrontFacing, SpvBuiltInFrontFacing}, SpvBuiltInInstanceIndex},
BuiltinData{ast::Builtin::kFragCoord, SpvBuiltInFragCoord}, BuiltinData{ast::Builtin::kFrontFacing, ast::StorageClass::kInput,
BuiltinData{ast::Builtin::kFragDepth, SpvBuiltInFragDepth}, SpvBuiltInFrontFacing},
BuiltinData{ast::Builtin::kLocalInvocationId, BuiltinData{ast::Builtin::kFragCoord, ast::StorageClass::kInput,
SpvBuiltInFragCoord},
BuiltinData{ast::Builtin::kFragDepth, ast::StorageClass::kOutput,
SpvBuiltInFragDepth},
BuiltinData{ast::Builtin::kLocalInvocationId, ast::StorageClass::kInput,
SpvBuiltInLocalInvocationId}, SpvBuiltInLocalInvocationId},
BuiltinData{ast::Builtin::kLocalInvocationIndex, BuiltinData{ast::Builtin::kLocalInvocationIndex,
SpvBuiltInLocalInvocationIndex}, ast::StorageClass::kInput, SpvBuiltInLocalInvocationIndex},
BuiltinData{ast::Builtin::kGlobalInvocationId, BuiltinData{ast::Builtin::kGlobalInvocationId,
SpvBuiltInGlobalInvocationId}, ast::StorageClass::kInput, SpvBuiltInGlobalInvocationId},
BuiltinData{ast::Builtin::kSampleIndex, SpvBuiltInSampleId}, BuiltinData{ast::Builtin::kSampleIndex, ast::StorageClass::kInput,
BuiltinData{ast::Builtin::kSampleMaskIn, SpvBuiltInSampleMask}, SpvBuiltInSampleId},
BuiltinData{ast::Builtin::kSampleMaskOut, SpvBuiltInSampleMask})); BuiltinData{ast::Builtin::kSampleMaskIn, ast::StorageClass::kInput,
SpvBuiltInSampleMask},
BuiltinData{ast::Builtin::kSampleMaskOut, ast::StorageClass::kOutput,
SpvBuiltInSampleMask}));
TEST_F(BuilderTest, GlobalVar_DeclReadOnly) { TEST_F(BuilderTest, GlobalVar_DeclReadOnly) {
// struct A { // struct A {

View File

@ -143,9 +143,8 @@ TEST_F(WgslGeneratorImplTest, Emit_Function_WithDecoration_Multiple) {
TEST_F(WgslGeneratorImplTest, Emit_Function_EntryPoint_Parameters) { TEST_F(WgslGeneratorImplTest, Emit_Function_EntryPoint_Parameters) {
auto* vec4 = ty.vec4<f32>(); auto* vec4 = ty.vec4<f32>();
auto* coord = auto* coord = Param(
Param("coord", vec4, "coord", vec4, {create<ast::BuiltinDecoration>(ast::Builtin::kPosition)});
{create<ast::BuiltinDecoration>(ast::Builtin::kFragCoord)});
auto* loc1 = Param("loc1", ty.f32(), {create<ast::LocationDecoration>(1u)}); auto* loc1 = Param("loc1", ty.f32(), {create<ast::LocationDecoration>(1u)});
auto* func = auto* func =
Func("frag_main", ast::VariableList{coord, loc1}, ty.void_(), Func("frag_main", ast::VariableList{coord, loc1}, ty.void_(),
@ -160,7 +159,7 @@ TEST_F(WgslGeneratorImplTest, Emit_Function_EntryPoint_Parameters) {
ASSERT_TRUE(gen.EmitFunction(func)); ASSERT_TRUE(gen.EmitFunction(func));
EXPECT_EQ(gen.result(), R"( [[stage(fragment)]] EXPECT_EQ(gen.result(), R"( [[stage(fragment)]]
fn frag_main([[builtin(frag_coord)]] coord : vec4<f32>, [[location(1)]] loc1 : f32) { fn frag_main([[builtin(position)]] coord : vec4<f32>, [[location(1)]] loc1 : f32) {
} }
)"); )");
} }