Rename builtin(sample_mask_{in,out}) to builtin(sample_mask)

Removes the need to pass the storage class to the SPIR-V reader
builtin mapping function.

Added a deprecation warning for sample_mask_{in,out}.

Bug: tint:715
Change-Id: I948ff2de2d5de7bd05e1c6ff45bd721c856900e3
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/47743
Commit-Queue: James Price <jrprice@google.com>
Auto-Submit: James Price <jrprice@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
James Price 2021-04-14 16:44:38 +00:00 committed by Commit Bot service account
parent 88d7edcf7a
commit edd4d3cc3b
19 changed files with 144 additions and 86 deletions

View File

@ -63,6 +63,10 @@ std::ostream& operator<<(std::ostream& out, Builtin builtin) {
out << "sample_index"; out << "sample_index";
break; break;
} }
case Builtin::kSampleMask: {
out << "sample_mask";
break;
}
case Builtin::kSampleMaskIn: { case Builtin::kSampleMaskIn: {
out << "sample_mask_in"; out << "sample_mask_in";
break; break;

View File

@ -33,8 +33,9 @@ enum class Builtin {
kLocalInvocationIndex, kLocalInvocationIndex,
kGlobalInvocationId, kGlobalInvocationId,
kSampleIndex, kSampleIndex,
kSampleMaskIn, kSampleMask,
kSampleMaskOut, kSampleMaskIn, // TODO(crbug.com/tint/715): Remove this
kSampleMaskOut, // TODO(crbug.com/tint/715): Remove this
// Below are not currently WGSL builtins, but are included in this enum as // Below are not currently WGSL builtins, but are included in this enum as
// they are used by certain backends. // they are used by certain backends.

View File

@ -1041,7 +1041,7 @@ TEST_F(InspectorGetEntryPointTest, BuiltInsNotStageVariables) {
auto* in_var1 = Param("in_var1", ty.u32(), {Location(0u)}); auto* in_var1 = Param("in_var1", ty.u32(), {Location(0u)});
Func("foo", {in_var0, in_var1}, ty.u32(), {Return(Expr("in_var1"))}, Func("foo", {in_var0, in_var1}, ty.u32(), {Return(Expr("in_var1"))},
{Stage(ast::PipelineStage::kFragment)}, {Stage(ast::PipelineStage::kFragment)},
{Builtin(ast::Builtin::kSampleMaskOut)}); {Builtin(ast::Builtin::kSampleMask)});
Inspector& inspector = Build(); Inspector& inspector = Build();
auto result = inspector.GetEntryPoints(); auto result = inspector.GetEntryPoints();

View File

@ -66,7 +66,7 @@ ast::StorageClass EnumConverter::ToStorageClass(const SpvStorageClass sc) {
return ast::StorageClass::kNone; return ast::StorageClass::kNone;
} }
ast::Builtin EnumConverter::ToBuiltin(SpvBuiltIn b, ast::StorageClass sc) { ast::Builtin EnumConverter::ToBuiltin(SpvBuiltIn b) {
switch (b) { switch (b) {
case SpvBuiltInPosition: case SpvBuiltInPosition:
return ast::Builtin::kPosition; return ast::Builtin::kPosition;
@ -89,8 +89,7 @@ ast::Builtin EnumConverter::ToBuiltin(SpvBuiltIn b, ast::StorageClass sc) {
case SpvBuiltInSampleId: case SpvBuiltInSampleId:
return ast::Builtin::kSampleIndex; return ast::Builtin::kSampleIndex;
case SpvBuiltInSampleMask: case SpvBuiltInSampleMask:
return sc == ast::StorageClass::kInput ? ast::Builtin::kSampleMaskIn return ast::Builtin::kSampleMask;
: ast::Builtin::kSampleMaskOut;
default: default:
break; break;
} }

View File

@ -50,9 +50,8 @@ class EnumConverter {
/// Converts a SPIR-V Builtin value a Tint Builtin. /// Converts a SPIR-V Builtin value a Tint Builtin.
/// On failure, logs an error and returns kNone /// On failure, logs an error and returns kNone
/// @param b the SPIR-V builtin /// @param b the SPIR-V builtin
/// @param sc the Tint storage class
/// @returns a Tint AST builtin /// @returns a Tint AST builtin
ast::Builtin ToBuiltin(SpvBuiltIn b, ast::StorageClass sc); ast::Builtin ToBuiltin(SpvBuiltIn b);
/// Converts a possibly arrayed SPIR-V Dim to a Tint texture dimension. /// Converts a possibly arrayed SPIR-V Dim to a Tint texture dimension.
/// On failure, logs an error and returns kNone /// On failure, logs an error and returns kNone

View File

@ -162,12 +162,11 @@ INSTANTIATE_TEST_SUITE_P(EnumConverterBad,
struct BuiltinCase { struct BuiltinCase {
SpvBuiltIn builtin; SpvBuiltIn builtin;
ast::StorageClass sc;
bool expect_success; bool expect_success;
ast::Builtin expected; ast::Builtin expected;
}; };
inline std::ostream& operator<<(std::ostream& out, BuiltinCase bc) { inline std::ostream& operator<<(std::ostream& out, BuiltinCase bc) {
out << "BuiltinCase{ SpvBuiltIn:" << int(bc.builtin) << " sc:" << int(bc.sc) out << "BuiltinCase{ SpvBuiltIn:" << int(bc.builtin)
<< " expect_success?:" << int(bc.expect_success) << " expect_success?:" << int(bc.expect_success)
<< " expected:" << int(bc.expected) << "}"; << " expected:" << int(bc.expected) << "}";
return out; return out;
@ -192,7 +191,7 @@ class SpvBuiltinTest : public testing::TestWithParam<BuiltinCase> {
TEST_P(SpvBuiltinTest, Samples) { TEST_P(SpvBuiltinTest, Samples) {
const auto params = GetParam(); const auto params = GetParam();
const auto result = converter_.ToBuiltin(params.builtin, params.sc); const auto result = converter_.ToBuiltin(params.builtin);
EXPECT_EQ(success_, params.expect_success); EXPECT_EQ(success_, params.expect_success);
if (params.expect_success) { if (params.expect_success) {
EXPECT_EQ(result, params.expected); EXPECT_EQ(result, params.expected);
@ -207,46 +206,35 @@ INSTANTIATE_TEST_SUITE_P(
EnumConverterGood_Input, EnumConverterGood_Input,
SpvBuiltinTest, SpvBuiltinTest,
testing::Values( testing::Values(
BuiltinCase{SpvBuiltInPosition, ast::StorageClass::kInput, true, BuiltinCase{SpvBuiltInPosition, true, ast::Builtin::kPosition},
ast::Builtin::kPosition}, BuiltinCase{SpvBuiltInInstanceIndex, true,
BuiltinCase{SpvBuiltInInstanceIndex, ast::StorageClass::kInput, true,
ast::Builtin::kInstanceIndex}, ast::Builtin::kInstanceIndex},
BuiltinCase{SpvBuiltInFrontFacing, ast::StorageClass::kInput, true, BuiltinCase{SpvBuiltInFrontFacing, true, ast::Builtin::kFrontFacing},
ast::Builtin::kFrontFacing}, BuiltinCase{SpvBuiltInFragCoord, true, ast::Builtin::kPosition},
BuiltinCase{SpvBuiltInFragCoord, ast::StorageClass::kInput, true, BuiltinCase{SpvBuiltInLocalInvocationId, true,
ast::Builtin::kPosition}, ast::Builtin::kLocalInvocationId},
BuiltinCase{SpvBuiltInLocalInvocationId, ast::StorageClass::kInput, BuiltinCase{SpvBuiltInLocalInvocationIndex, true,
true, ast::Builtin::kLocalInvocationId}, ast::Builtin::kLocalInvocationIndex},
BuiltinCase{SpvBuiltInLocalInvocationIndex, ast::StorageClass::kInput, BuiltinCase{SpvBuiltInGlobalInvocationId, true,
true, ast::Builtin::kLocalInvocationIndex}, ast::Builtin::kGlobalInvocationId},
BuiltinCase{SpvBuiltInGlobalInvocationId, ast::StorageClass::kInput, BuiltinCase{SpvBuiltInSampleId, true, ast::Builtin::kSampleIndex},
true, ast::Builtin::kGlobalInvocationId}, BuiltinCase{SpvBuiltInSampleMask, true, ast::Builtin::kSampleMask}));
BuiltinCase{SpvBuiltInSampleId, ast::StorageClass::kInput, true,
ast::Builtin::kSampleIndex},
BuiltinCase{SpvBuiltInSampleMask, ast::StorageClass::kInput, true,
ast::Builtin::kSampleMaskIn}));
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
EnumConverterGood_Output, EnumConverterGood_Output,
SpvBuiltinTest, SpvBuiltinTest,
testing::Values(BuiltinCase{SpvBuiltInPosition, ast::StorageClass::kOutput, testing::Values(
true, ast::Builtin::kPosition}, BuiltinCase{SpvBuiltInPosition, true, ast::Builtin::kPosition},
BuiltinCase{SpvBuiltInFragDepth, ast::StorageClass::kOutput, BuiltinCase{SpvBuiltInFragDepth, true, ast::Builtin::kFragDepth},
true, ast::Builtin::kFragDepth}, BuiltinCase{SpvBuiltInSampleMask, true, ast::Builtin::kSampleMask}));
BuiltinCase{SpvBuiltInSampleMask,
ast::StorageClass::kOutput, true,
ast::Builtin::kSampleMaskOut}));
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
EnumConverterBad, EnumConverterBad,
SpvBuiltinTest, SpvBuiltinTest,
testing::Values( testing::Values(
BuiltinCase{static_cast<SpvBuiltIn>(9999), ast::StorageClass::kInput, BuiltinCase{static_cast<SpvBuiltIn>(9999), false, ast::Builtin::kNone},
false, ast::Builtin::kNone}, BuiltinCase{static_cast<SpvBuiltIn>(9999), false, ast::Builtin::kNone},
BuiltinCase{static_cast<SpvBuiltIn>(9999), ast::StorageClass::kOutput, BuiltinCase{SpvBuiltInNumWorkgroups, false, ast::Builtin::kNone}));
false, ast::Builtin::kNone},
BuiltinCase{SpvBuiltInNumWorkgroups, ast::StorageClass::kInput, false,
ast::Builtin::kNone}));
// Dim // Dim

View File

@ -1304,7 +1304,7 @@ ast::Variable* ParserImpl::MakeVariable(uint32_t id,
default: default:
break; break;
} }
auto ast_builtin = enum_converter_.ToBuiltin(spv_builtin, sc); auto ast_builtin = enum_converter_.ToBuiltin(spv_builtin);
if (ast_builtin == ast::Builtin::kNone) { if (ast_builtin == ast::Builtin::kNone) {
return nullptr; return nullptr;
} }

View File

@ -2473,7 +2473,7 @@ TEST_F(SpvModuleScopeVarParserTest, SampleMask_In_U32_Direct) {
EXPECT_THAT(module_str, HasSubstr(R"( EXPECT_THAT(module_str, HasSubstr(R"(
Variable{ Variable{
Decorations{ Decorations{
BuiltinDecoration{sample_mask_in} BuiltinDecoration{sample_mask}
} }
x_1 x_1
in in
@ -2515,7 +2515,7 @@ TEST_F(SpvModuleScopeVarParserTest, SampleMask_In_U32_CopyObject) {
EXPECT_THAT(module_str, HasSubstr(R"( EXPECT_THAT(module_str, HasSubstr(R"(
Variable{ Variable{
Decorations{ Decorations{
BuiltinDecoration{sample_mask_in} BuiltinDecoration{sample_mask}
} }
x_1 x_1
in in
@ -2557,7 +2557,7 @@ TEST_F(SpvModuleScopeVarParserTest, SampleMask_In_U32_AccessChain) {
EXPECT_THAT(module_str, HasSubstr(R"( EXPECT_THAT(module_str, HasSubstr(R"(
Variable{ Variable{
Decorations{ Decorations{
BuiltinDecoration{sample_mask_in} BuiltinDecoration{sample_mask}
} }
x_1 x_1
in in
@ -2598,7 +2598,7 @@ TEST_F(SpvModuleScopeVarParserTest, SampleMask_In_I32_Direct) {
EXPECT_THAT(module_str, HasSubstr(R"( EXPECT_THAT(module_str, HasSubstr(R"(
Variable{ Variable{
Decorations{ Decorations{
BuiltinDecoration{sample_mask_in} BuiltinDecoration{sample_mask}
} }
x_1 x_1
in in
@ -2643,7 +2643,7 @@ TEST_F(SpvModuleScopeVarParserTest, SampleMask_In_I32_CopyObject) {
EXPECT_THAT(module_str, HasSubstr(R"( EXPECT_THAT(module_str, HasSubstr(R"(
Variable{ Variable{
Decorations{ Decorations{
BuiltinDecoration{sample_mask_in} BuiltinDecoration{sample_mask}
} }
x_1 x_1
in in
@ -2688,7 +2688,7 @@ TEST_F(SpvModuleScopeVarParserTest, SampleMask_In_I32_AccessChain) {
EXPECT_THAT(module_str, HasSubstr(R"( EXPECT_THAT(module_str, HasSubstr(R"(
Variable{ Variable{
Decorations{ Decorations{
BuiltinDecoration{sample_mask_in} BuiltinDecoration{sample_mask}
} }
x_1 x_1
in in
@ -2751,7 +2751,7 @@ TEST_F(SpvModuleScopeVarParserTest, SampleMask_Out_U32_Direct) {
EXPECT_THAT(module_str, HasSubstr(R"( EXPECT_THAT(module_str, HasSubstr(R"(
Variable{ Variable{
Decorations{ Decorations{
BuiltinDecoration{sample_mask_out} BuiltinDecoration{sample_mask}
} }
x_1 x_1
out out
@ -2787,7 +2787,7 @@ TEST_F(SpvModuleScopeVarParserTest, SampleMask_Out_U32_CopyObject) {
EXPECT_THAT(module_str, HasSubstr(R"( EXPECT_THAT(module_str, HasSubstr(R"(
Variable{ Variable{
Decorations{ Decorations{
BuiltinDecoration{sample_mask_out} BuiltinDecoration{sample_mask}
} }
x_1 x_1
out out
@ -2823,7 +2823,7 @@ TEST_F(SpvModuleScopeVarParserTest, SampleMask_Out_U32_AccessChain) {
EXPECT_THAT(module_str, HasSubstr(R"( EXPECT_THAT(module_str, HasSubstr(R"(
Variable{ Variable{
Decorations{ Decorations{
BuiltinDecoration{sample_mask_out} BuiltinDecoration{sample_mask}
} }
x_1 x_1
out out
@ -2858,7 +2858,7 @@ TEST_F(SpvModuleScopeVarParserTest, SampleMask_Out_I32_Direct) {
EXPECT_THAT(module_str, HasSubstr(R"( EXPECT_THAT(module_str, HasSubstr(R"(
Variable{ Variable{
Decorations{ Decorations{
BuiltinDecoration{sample_mask_out} BuiltinDecoration{sample_mask}
} }
x_1 x_1
out out
@ -2900,7 +2900,7 @@ TEST_F(SpvModuleScopeVarParserTest, SampleMask_Out_I32_CopyObject) {
EXPECT_THAT(module_str, HasSubstr(R"( EXPECT_THAT(module_str, HasSubstr(R"(
Variable{ Variable{
Decorations{ Decorations{
BuiltinDecoration{sample_mask_out} BuiltinDecoration{sample_mask}
} }
x_1 x_1
out out
@ -2942,7 +2942,7 @@ TEST_F(SpvModuleScopeVarParserTest, SampleMask_Out_I32_AccessChain) {
EXPECT_THAT(module_str, HasSubstr(R"( EXPECT_THAT(module_str, HasSubstr(R"(
Variable{ Variable{
Decorations{ Decorations{
BuiltinDecoration{sample_mask_out} BuiltinDecoration{sample_mask}
} }
x_1 x_1
out out

View File

@ -88,6 +88,9 @@ ast::Builtin ident_to_builtin(const std::string& str) {
if (str == "sample_index") { if (str == "sample_index") {
return ast::Builtin::kSampleIndex; return ast::Builtin::kSampleIndex;
} }
if (str == "sample_mask") {
return ast::Builtin::kSampleMask;
}
if (str == "sample_mask_in") { if (str == "sample_mask_in") {
return ast::Builtin::kSampleMaskIn; return ast::Builtin::kSampleMaskIn;
} }
@ -1382,6 +1385,12 @@ Expect<ast::Builtin> ParserImpl::expect_builtin() {
if (builtin == ast::Builtin::kFragCoord) { if (builtin == ast::Builtin::kFragCoord) {
deprecated(ident.source, "use 'position' instead of 'frag_coord'"); deprecated(ident.source, "use 'position' instead of 'frag_coord'");
} }
if (builtin == ast::Builtin::kSampleMaskIn) {
deprecated(ident.source, "use 'sample_mask' instead of 'sample_mask_in'");
}
if (builtin == ast::Builtin::kSampleMaskOut) {
deprecated(ident.source, "use 'sample_mask' instead of 'sample_mask_out'");
}
return {builtin, ident.source}; return {builtin, ident.source};
} }

View File

@ -122,6 +122,7 @@ INSTANTIATE_TEST_SUITE_P(
ast::Builtin::kLocalInvocationIndex}, ast::Builtin::kLocalInvocationIndex},
BuiltinData{"global_invocation_id", ast::Builtin::kGlobalInvocationId}, BuiltinData{"global_invocation_id", ast::Builtin::kGlobalInvocationId},
BuiltinData{"sample_index", ast::Builtin::kSampleIndex}, BuiltinData{"sample_index", ast::Builtin::kSampleIndex},
BuiltinData{"sample_mask", ast::Builtin::kSampleMask},
BuiltinData{"sample_mask_in", ast::Builtin::kSampleMaskIn}, BuiltinData{"sample_mask_in", ast::Builtin::kSampleMaskIn},
BuiltinData{"sample_mask_out", ast::Builtin::kSampleMaskOut})); BuiltinData{"sample_mask_out", ast::Builtin::kSampleMaskOut}));
@ -327,6 +328,50 @@ builtin(frag_coord)
)"); )");
} }
TEST_F(ParserImplTest, Decoration_SampleMaskIn_Deprecated) {
auto p = parser("builtin(sample_mask_in)");
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::kSampleMaskIn);
EXPECT_EQ(
p->builder().Diagnostics().str(),
R"(test.wgsl:1:9 warning: use of deprecated language feature: use 'sample_mask' instead of 'sample_mask_in'
builtin(sample_mask_in)
^^^^^^^^^^^^^^
)");
}
TEST_F(ParserImplTest, Decoration_SampleMaskOut_Deprecated) {
auto p = parser("builtin(sample_mask_out)");
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::kSampleMaskOut);
EXPECT_EQ(
p->builder().Diagnostics().str(),
R"(test.wgsl:1:9 warning: use of deprecated language feature: use 'sample_mask' instead of 'sample_mask_out'
builtin(sample_mask_out)
^^^^^^^^^^^^^^^
)");
}
} // namespace } // namespace
} // namespace wgsl } // namespace wgsl
} // namespace reader } // namespace reader

View File

@ -197,7 +197,7 @@ TEST_F(CanonicalizeEntryPointIOTest, Return_Struct) {
auto* src = R"( auto* src = R"(
struct FragOutput { struct FragOutput {
[[builtin(frag_depth)]] depth : f32; [[builtin(frag_depth)]] depth : f32;
[[builtin(sample_mask_out)]] mask : u32; [[builtin(sample_mask)]] mask : u32;
[[location(0)]] color : vec4<f32>; [[location(0)]] color : vec4<f32>;
}; };
@ -221,7 +221,7 @@ struct FragOutput {
struct tint_symbol { struct tint_symbol {
[[builtin(frag_depth)]] [[builtin(frag_depth)]]
depth : f32; depth : f32;
[[builtin(sample_mask_out)]] [[builtin(sample_mask)]]
mask : u32; mask : u32;
[[location(0)]] [[location(0)]]
color : vec4<f32>; color : vec4<f32>;

View File

@ -59,11 +59,11 @@ void Spirv::HandleEntryPointIOTypes(CloneContext& ctx) const {
// ``` // ```
// struct FragmentInput { // struct FragmentInput {
// [[builtin(sample_index)]] sample_index : u32; // [[builtin(sample_index)]] sample_index : u32;
// [[builtin(sample_mask_in)]] sample_mask_in : u32; // [[builtin(sample_mask)]] sample_mask : u32;
// }; // };
// struct FragmentOutput { // struct FragmentOutput {
// [[builtin(frag_depth)]] depth: f32; // [[builtin(frag_depth)]] depth: f32;
// [[builtin(sample_mask_out)]] mask_out : u32; // [[builtin(sample_mask)]] mask_out : u32;
// }; // };
// //
// [[stage(fragment)]] // [[stage(fragment)]]
@ -72,7 +72,7 @@ void Spirv::HandleEntryPointIOTypes(CloneContext& ctx) const {
// samples : FragmentInput // samples : FragmentInput
// ) -> FragmentOutput { // ) -> FragmentOutput {
// var output : FragmentOutput = FragmentOutput(1.0, // var output : FragmentOutput = FragmentOutput(1.0,
// samples.sample_mask_in); // samples.sample_mask);
// return output; // return output;
// } // }
// ``` // ```
@ -81,7 +81,7 @@ void Spirv::HandleEntryPointIOTypes(CloneContext& ctx) const {
// ``` // ```
// struct FragmentInput { // struct FragmentInput {
// sample_index : u32; // sample_index : u32;
// sample_mask_in : u32; // sample_mask : u32;
// }; // };
// struct FragmentOutput { // struct FragmentOutput {
// depth: f32; // depth: f32;
@ -90,9 +90,9 @@ void Spirv::HandleEntryPointIOTypes(CloneContext& ctx) const {
// //
// [[builtin(position)]] 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)]] var<in> sample_mask : u32,
// [[builtin(frag_depth)]] var<out> depth: f32; // [[builtin(frag_depth)]] var<out> depth: f32;
// [[builtin(sample_mask_out)]] var<out> mask_out : u32; // [[builtin(sample_mask)]] var<out> mask_out : u32;
// //
// fn frag_main_ret(retval : FragmentOutput) { // fn frag_main_ret(retval : FragmentOutput) {
// depth = reval.depth; // depth = reval.depth;
@ -101,9 +101,9 @@ void Spirv::HandleEntryPointIOTypes(CloneContext& ctx) const {
// //
// [[stage(fragment)]] // [[stage(fragment)]]
// fn frag_main() { // fn frag_main() {
// let samples : FragmentInput(sample_index, sample_mask_in); // let samples : FragmentInput(sample_index, sample_mask);
// var output : FragmentOutput = FragmentOutput(1.0, // var output : FragmentOutput = FragmentOutput(1.0,
// samples.sample_mask_in); // samples.sample_mask);
// frag_main_ret(output); // frag_main_ret(output);
// return; // return;
// } // }
@ -189,19 +189,19 @@ void Spirv::HandleEntryPointIOTypes(CloneContext& ctx) const {
} }
void Spirv::HandleSampleMaskBuiltins(CloneContext& ctx) const { void Spirv::HandleSampleMaskBuiltins(CloneContext& ctx) const {
// Find global variables decorated with [[builtin(sample_mask_{in,out})]] and // Find global variables decorated with [[builtin(sample_mask)]] and
// change their type from `u32` to `array<u32, 1>`, as required by Vulkan. // change their type from `u32` to `array<u32, 1>`, as required by Vulkan.
// //
// Before: // Before:
// ``` // ```
// [[builtin(sample_mask_out)]] var<out> mask_out : u32; // [[builtin(sample_mask)]] var<out> mask_out : u32;
// fn main() { // fn main() {
// mask_out = 1u; // mask_out = 1u;
// } // }
// ``` // ```
// After: // After:
// ``` // ```
// [[builtin(sample_mask_out)]] var<out> mask_out : array<u32, 1>; // [[builtin(sample_mask)]] var<out> mask_out : array<u32, 1>;
// fn main() { // fn main() {
// mask_out[0] = 1u; // mask_out[0] = 1u;
// } // }
@ -210,7 +210,8 @@ void Spirv::HandleSampleMaskBuiltins(CloneContext& ctx) const {
for (auto* var : ctx.src->AST().GlobalVariables()) { for (auto* var : ctx.src->AST().GlobalVariables()) {
for (auto* deco : var->decorations()) { for (auto* deco : var->decorations()) {
if (auto* builtin = deco->As<ast::BuiltinDecoration>()) { if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
if (builtin->value() != ast::Builtin::kSampleMaskIn && if (builtin->value() != ast::Builtin::kSampleMask &&
builtin->value() != ast::Builtin::kSampleMaskIn &&
builtin->value() != ast::Builtin::kSampleMaskOut) { builtin->value() != ast::Builtin::kSampleMaskOut) {
continue; continue;
} }

View File

@ -487,9 +487,9 @@ TEST_F(SpirvTest, HandleSampleMaskBuiltins_Basic) {
auto* src = R"( auto* src = R"(
[[builtin(sample_index)]] var<in> sample_index : u32; [[builtin(sample_index)]] var<in> sample_index : u32;
[[builtin(sample_mask_in)]] var<in> mask_in : u32; [[builtin(sample_mask)]] var<in> mask_in : u32;
[[builtin(sample_mask_out)]] var<out> mask_out : u32; [[builtin(sample_mask)]] var<out> mask_out : u32;
[[stage(fragment)]] [[stage(fragment)]]
fn main() { fn main() {
@ -500,9 +500,9 @@ fn main() {
auto* expect = R"( auto* expect = R"(
[[builtin(sample_index)]] var<in> sample_index : u32; [[builtin(sample_index)]] var<in> sample_index : u32;
[[builtin(sample_mask_in)]] var<in> mask_in : array<u32, 1>; [[builtin(sample_mask)]] var<in> mask_in : array<u32, 1>;
[[builtin(sample_mask_out)]] var<out> mask_out : array<u32, 1>; [[builtin(sample_mask)]] var<out> mask_out : array<u32, 1>;
[[stage(fragment)]] [[stage(fragment)]]
fn main() { fn main() {
@ -517,9 +517,9 @@ fn main() {
TEST_F(SpirvTest, HandleSampleMaskBuiltins_FunctionArg) { TEST_F(SpirvTest, HandleSampleMaskBuiltins_FunctionArg) {
auto* src = R"( auto* src = R"(
[[builtin(sample_mask_in)]] var<in> mask_in : u32; [[builtin(sample_mask)]] var<in> mask_in : u32;
[[builtin(sample_mask_out)]] var<out> mask_out : u32; [[builtin(sample_mask)]] var<out> mask_out : u32;
fn filter(mask: u32) -> u32 { fn filter(mask: u32) -> u32 {
return (mask & 3u); return (mask & 3u);
@ -536,9 +536,9 @@ fn main() {
)"; )";
auto* expect = R"( auto* expect = R"(
[[builtin(sample_mask_in)]] var<in> mask_in : array<u32, 1>; [[builtin(sample_mask)]] var<in> mask_in : array<u32, 1>;
[[builtin(sample_mask_out)]] var<out> mask_out : array<u32, 1>; [[builtin(sample_mask)]] var<out> mask_out : array<u32, 1>;
fn filter(mask : u32) -> u32 { fn filter(mask : u32) -> u32 {
return (mask & 3u); return (mask & 3u);
@ -578,8 +578,8 @@ TEST_F(SpirvTest, MultipleTransforms) {
auto* src = R"( auto* src = R"(
[[stage(fragment)]] [[stage(fragment)]]
fn main([[builtin(sample_index)]] sample_index : u32, fn main([[builtin(sample_index)]] sample_index : u32,
[[builtin(sample_mask_in)]] mask_in : u32) [[builtin(sample_mask)]] mask_in : u32)
-> [[builtin(sample_mask_out)]] u32 { -> [[builtin(sample_mask)]] u32 {
return mask_in; return mask_in;
} }
)"; )";
@ -587,9 +587,9 @@ fn main([[builtin(sample_index)]] sample_index : u32,
auto* expect = R"( auto* expect = R"(
[[builtin(sample_index)]] var<in> tint_symbol : u32; [[builtin(sample_index)]] var<in> tint_symbol : u32;
[[builtin(sample_mask_in)]] var<in> tint_symbol_1 : array<u32, 1>; [[builtin(sample_mask)]] var<in> tint_symbol_1 : array<u32, 1>;
[[builtin(sample_mask_out)]] var<out> tint_symbol_3 : array<u32, 1>; [[builtin(sample_mask)]] var<out> tint_symbol_3 : array<u32, 1>;
fn tint_symbol_4(tint_symbol_2 : u32) { fn tint_symbol_4(tint_symbol_2 : u32) {
tint_symbol_3[0] = tint_symbol_2; tint_symbol_3[0] = tint_symbol_2;

View File

@ -1954,6 +1954,8 @@ std::string GeneratorImpl::builtin_to_attribute(ast::Builtin builtin) const {
return "SV_DispatchThreadID"; return "SV_DispatchThreadID";
case ast::Builtin::kSampleIndex: case ast::Builtin::kSampleIndex:
return "SV_SampleIndex"; return "SV_SampleIndex";
case ast::Builtin::kSampleMask:
return "SV_Coverage";
case ast::Builtin::kSampleMaskIn: case ast::Builtin::kSampleMaskIn:
return "SV_Coverage"; return "SV_Coverage";
case ast::Builtin::kSampleMaskOut: case ast::Builtin::kSampleMaskOut:

View File

@ -83,6 +83,7 @@ INSTANTIATE_TEST_SUITE_P(
HlslBuiltinData{ast::Builtin::kGlobalInvocationId, HlslBuiltinData{ast::Builtin::kGlobalInvocationId,
"SV_DispatchThreadID"}, "SV_DispatchThreadID"},
HlslBuiltinData{ast::Builtin::kSampleIndex, "SV_SampleIndex"}, HlslBuiltinData{ast::Builtin::kSampleIndex, "SV_SampleIndex"},
HlslBuiltinData{ast::Builtin::kSampleMask, "SV_Coverage"},
HlslBuiltinData{ast::Builtin::kSampleMaskIn, "SV_Coverage"}, HlslBuiltinData{ast::Builtin::kSampleMaskIn, "SV_Coverage"},
HlslBuiltinData{ast::Builtin::kSampleMaskOut, "SV_Coverage"})); HlslBuiltinData{ast::Builtin::kSampleMaskOut, "SV_Coverage"}));

View File

@ -1354,6 +1354,8 @@ std::string GeneratorImpl::builtin_to_attribute(ast::Builtin builtin) const {
return "thread_position_in_grid"; return "thread_position_in_grid";
case ast::Builtin::kSampleIndex: case ast::Builtin::kSampleIndex:
return "sample_id"; return "sample_id";
case ast::Builtin::kSampleMask:
return "sample_mask";
case ast::Builtin::kSampleMaskIn: case ast::Builtin::kSampleMaskIn:
return "sample_mask"; return "sample_mask";
case ast::Builtin::kSampleMaskOut: case ast::Builtin::kSampleMaskOut:

View File

@ -74,6 +74,7 @@ INSTANTIATE_TEST_SUITE_P(
MslBuiltinData{ast::Builtin::kGlobalInvocationId, MslBuiltinData{ast::Builtin::kGlobalInvocationId,
"thread_position_in_grid"}, "thread_position_in_grid"},
MslBuiltinData{ast::Builtin::kSampleIndex, "sample_id"}, MslBuiltinData{ast::Builtin::kSampleIndex, "sample_id"},
MslBuiltinData{ast::Builtin::kSampleMask, "sample_mask"},
MslBuiltinData{ast::Builtin::kSampleMaskIn, "sample_mask"}, MslBuiltinData{ast::Builtin::kSampleMaskIn, "sample_mask"},
MslBuiltinData{ast::Builtin::kSampleMaskOut, MslBuiltinData{ast::Builtin::kSampleMaskOut,
"sample_mask"})); "sample_mask"}));

View File

@ -3308,6 +3308,8 @@ SpvBuiltIn Builder::ConvertBuiltin(ast::Builtin builtin,
case ast::Builtin::kSampleIndex: case ast::Builtin::kSampleIndex:
push_capability(SpvCapabilitySampleRateShading); push_capability(SpvCapabilitySampleRateShading);
return SpvBuiltInSampleId; return SpvBuiltInSampleId;
case ast::Builtin::kSampleMask:
return SpvBuiltInSampleMask;
case ast::Builtin::kSampleMaskIn: case ast::Builtin::kSampleMaskIn:
return SpvBuiltInSampleMask; return SpvBuiltInSampleMask;
case ast::Builtin::kSampleMaskOut: case ast::Builtin::kSampleMaskOut:

View File

@ -370,6 +370,10 @@ INSTANTIATE_TEST_SUITE_P(
ast::StorageClass::kInput, SpvBuiltInGlobalInvocationId}, ast::StorageClass::kInput, SpvBuiltInGlobalInvocationId},
BuiltinData{ast::Builtin::kSampleIndex, ast::StorageClass::kInput, BuiltinData{ast::Builtin::kSampleIndex, ast::StorageClass::kInput,
SpvBuiltInSampleId}, SpvBuiltInSampleId},
BuiltinData{ast::Builtin::kSampleMask, ast::StorageClass::kInput,
SpvBuiltInSampleMask},
BuiltinData{ast::Builtin::kSampleMask, ast::StorageClass::kOutput,
SpvBuiltInSampleMask},
BuiltinData{ast::Builtin::kSampleMaskIn, ast::StorageClass::kInput, BuiltinData{ast::Builtin::kSampleMaskIn, ast::StorageClass::kInput,
SpvBuiltInSampleMask}, SpvBuiltInSampleMask},
BuiltinData{ast::Builtin::kSampleMaskOut, ast::StorageClass::kOutput, BuiltinData{ast::Builtin::kSampleMaskOut, ast::StorageClass::kOutput,
@ -622,16 +626,16 @@ TEST_F(BuilderTest, SampleIndex) {
TEST_F(BuilderTest, SampleMask) { TEST_F(BuilderTest, SampleMask) {
// Input: // Input:
// [[builtin(sample_mask_in)]] var<in> mask_in : u32; // [[builtin(sample_mask)]] var<in> mask_in : u32;
// [[builtin(sample_mask_out)]] var<out> mask_out : u32; // [[builtin(sample_mask)]] var<out> mask_out : u32;
// [[stage(fragment)]] // [[stage(fragment)]]
// fn main() { // fn main() {
// mask_out = mask_in; // mask_out = mask_in;
// } // }
// After sanitization: // After sanitization:
// [[builtin(sample_mask_in)]] var<in> mask_in : array<u32, 1>; // [[builtin(sample_mask)]] var<in> mask_in : array<u32, 1>;
// [[builtin(sample_mask_out)]] var<out> mask_out : array<u32, 1>; // [[builtin(sample_mask)]] var<out> mask_out : array<u32, 1>;
// [[stage(fragment)]] // [[stage(fragment)]]
// fn main() { // fn main() {
// mask_out[0] = mask_in[0]; // mask_out[0] = mask_in[0];
@ -639,11 +643,11 @@ TEST_F(BuilderTest, SampleMask) {
Global("mask_in", ty.u32(), ast::StorageClass::kInput, nullptr, Global("mask_in", ty.u32(), ast::StorageClass::kInput, nullptr,
ast::DecorationList{ ast::DecorationList{
create<ast::BuiltinDecoration>(ast::Builtin::kSampleMaskIn), create<ast::BuiltinDecoration>(ast::Builtin::kSampleMask),
}); });
Global("mask_out", ty.u32(), ast::StorageClass::kOutput, nullptr, Global("mask_out", ty.u32(), ast::StorageClass::kOutput, nullptr,
ast::DecorationList{ ast::DecorationList{
create<ast::BuiltinDecoration>(ast::Builtin::kSampleMaskOut), create<ast::BuiltinDecoration>(ast::Builtin::kSampleMask),
}); });
Func("main", ast::VariableList{}, ty.void_(), Func("main", ast::VariableList{}, ty.void_(),
ast::StatementList{ ast::StatementList{