msl: Add generator option to emit [[point_size]]
This option is passed through to the CanonicalizeEntryPointIO transform, which adds it to the set of builtin shader outputs for all vertex shaders in the module. Bug: tint:1000 Change-Id: Ibba4adde2c468b11ebfd7012fcb42ee48aad04e4 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/60522 Auto-Submit: James Price <jrprice@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: James Price <jrprice@google.com> Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
15e89fa7b7
commit
11e172ab64
|
@ -289,6 +289,13 @@ struct CanonicalizeEntryPointIO::State {
|
||||||
ctx.dst->Expr(cfg.fixed_sample_mask));
|
ctx.dst->Expr(cfg.fixed_sample_mask));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add a point size builtin to the wrapper function output.
|
||||||
|
void AddVertexPointSize() {
|
||||||
|
// Create a new output value and assign it a literal 1.0 value.
|
||||||
|
AddOutput("vertex_point_size", ctx.dst->ty.f32(),
|
||||||
|
{ctx.dst->Builtin(ast::Builtin::kPointSize)}, ctx.dst->Expr(1.f));
|
||||||
|
}
|
||||||
|
|
||||||
/// Create the wrapper function's struct parameter and type objects.
|
/// Create the wrapper function's struct parameter and type objects.
|
||||||
void CreateInputStruct() {
|
void CreateInputStruct() {
|
||||||
// Sort the struct members to satisfy HLSL interfacing matching rules.
|
// Sort the struct members to satisfy HLSL interfacing matching rules.
|
||||||
|
@ -376,14 +383,20 @@ struct CanonicalizeEntryPointIO::State {
|
||||||
/// Process the entry point function.
|
/// Process the entry point function.
|
||||||
void Process() {
|
void Process() {
|
||||||
bool needs_fixed_sample_mask = false;
|
bool needs_fixed_sample_mask = false;
|
||||||
|
bool needs_vertex_point_size = false;
|
||||||
if (func_ast->pipeline_stage() == ast::PipelineStage::kFragment &&
|
if (func_ast->pipeline_stage() == ast::PipelineStage::kFragment &&
|
||||||
cfg.fixed_sample_mask != 0xFFFFFFFF) {
|
cfg.fixed_sample_mask != 0xFFFFFFFF) {
|
||||||
needs_fixed_sample_mask = true;
|
needs_fixed_sample_mask = true;
|
||||||
}
|
}
|
||||||
|
if (func_ast->pipeline_stage() == ast::PipelineStage::kVertex &&
|
||||||
|
cfg.emit_vertex_point_size) {
|
||||||
|
needs_vertex_point_size = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Exit early if there is no shader IO to handle.
|
// Exit early if there is no shader IO to handle.
|
||||||
if (func_sem->Parameters().size() == 0 &&
|
if (func_sem->Parameters().size() == 0 &&
|
||||||
func_sem->ReturnType()->Is<sem::Void>() && !needs_fixed_sample_mask) {
|
func_sem->ReturnType()->Is<sem::Void>() && !needs_fixed_sample_mask &&
|
||||||
|
!needs_vertex_point_size) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,6 +443,11 @@ struct CanonicalizeEntryPointIO::State {
|
||||||
AddFixedSampleMask();
|
AddFixedSampleMask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add the pointsize builtin, if necessary.
|
||||||
|
if (needs_vertex_point_size) {
|
||||||
|
AddVertexPointSize();
|
||||||
|
}
|
||||||
|
|
||||||
// Produce the entry point outputs, if necessary.
|
// Produce the entry point outputs, if necessary.
|
||||||
if (!wrapper_output_values.empty()) {
|
if (!wrapper_output_values.empty()) {
|
||||||
auto* output_struct = CreateOutputStruct();
|
auto* output_struct = CreateOutputStruct();
|
||||||
|
@ -488,8 +506,11 @@ void CanonicalizeEntryPointIO::Run(CloneContext& ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
CanonicalizeEntryPointIO::Config::Config(BuiltinStyle builtins,
|
CanonicalizeEntryPointIO::Config::Config(BuiltinStyle builtins,
|
||||||
uint32_t sample_mask)
|
uint32_t sample_mask,
|
||||||
: builtin_style(builtins), fixed_sample_mask(sample_mask) {}
|
bool emit_point_size)
|
||||||
|
: builtin_style(builtins),
|
||||||
|
fixed_sample_mask(sample_mask),
|
||||||
|
emit_vertex_point_size(emit_point_size) {}
|
||||||
|
|
||||||
CanonicalizeEntryPointIO::Config::Config(const Config&) = default;
|
CanonicalizeEntryPointIO::Config::Config(const Config&) = default;
|
||||||
CanonicalizeEntryPointIO::Config::~Config() = default;
|
CanonicalizeEntryPointIO::Config::~Config() = default;
|
||||||
|
|
|
@ -96,7 +96,10 @@ class CanonicalizeEntryPointIO
|
||||||
/// Constructor
|
/// Constructor
|
||||||
/// @param builtins the approach to use for emitting builtins.
|
/// @param builtins the approach to use for emitting builtins.
|
||||||
/// @param sample_mask an optional sample mask to combine with shader masks
|
/// @param sample_mask an optional sample mask to combine with shader masks
|
||||||
explicit Config(BuiltinStyle builtins, uint32_t sample_mask = 0xFFFFFFFF);
|
/// @param emit_vertex_point_size `true` to generate a pointsize builtin
|
||||||
|
explicit Config(BuiltinStyle builtins,
|
||||||
|
uint32_t sample_mask = 0xFFFFFFFF,
|
||||||
|
bool emit_vertex_point_size = false);
|
||||||
|
|
||||||
/// Copy constructor
|
/// Copy constructor
|
||||||
Config(const Config&);
|
Config(const Config&);
|
||||||
|
@ -109,6 +112,10 @@ class CanonicalizeEntryPointIO
|
||||||
|
|
||||||
/// A fixed sample mask to combine into masks produced by fragment shaders.
|
/// A fixed sample mask to combine into masks produced by fragment shaders.
|
||||||
uint32_t const fixed_sample_mask;
|
uint32_t const fixed_sample_mask;
|
||||||
|
|
||||||
|
/// Set to `true` to generate a pointsize builtin and have it set to 1.0
|
||||||
|
/// from all vertex shaders in the module.
|
||||||
|
bool const emit_vertex_point_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
|
|
|
@ -1424,6 +1424,141 @@ fn frag_main() -> tint_symbol {
|
||||||
EXPECT_EQ(expect, str(got));
|
EXPECT_EQ(expect, str(got));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(CanonicalizeEntryPointIOTest, EmitVertexPointSize_ReturnNonStruct) {
|
||||||
|
auto* src = R"(
|
||||||
|
[[stage(vertex)]]
|
||||||
|
fn vert_main() -> [[builtin(position)]] vec4<f32> {
|
||||||
|
return vec4<f32>();
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
auto* expect = R"(
|
||||||
|
struct tint_symbol {
|
||||||
|
[[builtin(position)]]
|
||||||
|
value : vec4<f32>;
|
||||||
|
[[builtin(pointsize)]]
|
||||||
|
vertex_point_size : f32;
|
||||||
|
};
|
||||||
|
|
||||||
|
fn vert_main_inner() -> vec4<f32> {
|
||||||
|
return vec4<f32>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[stage(vertex)]]
|
||||||
|
fn vert_main() -> tint_symbol {
|
||||||
|
let inner_result = vert_main_inner();
|
||||||
|
var wrapper_result : tint_symbol;
|
||||||
|
wrapper_result.value = inner_result;
|
||||||
|
wrapper_result.vertex_point_size = 1.0;
|
||||||
|
return wrapper_result;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
DataMap data;
|
||||||
|
data.Add<CanonicalizeEntryPointIO::Config>(
|
||||||
|
CanonicalizeEntryPointIO::BuiltinStyle::kParameter, 0xFFFFFFFF, true);
|
||||||
|
auto got = Run<CanonicalizeEntryPointIO>(src, data);
|
||||||
|
|
||||||
|
EXPECT_EQ(expect, str(got));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CanonicalizeEntryPointIOTest, EmitVertexPointSize_ReturnStruct) {
|
||||||
|
auto* src = R"(
|
||||||
|
struct VertOut {
|
||||||
|
[[builtin(position)]] pos : vec4<f32>;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[stage(vertex)]]
|
||||||
|
fn vert_main() -> VertOut {
|
||||||
|
return VertOut();
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
auto* expect = R"(
|
||||||
|
struct VertOut {
|
||||||
|
pos : vec4<f32>;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tint_symbol {
|
||||||
|
[[builtin(position)]]
|
||||||
|
pos : vec4<f32>;
|
||||||
|
[[builtin(pointsize)]]
|
||||||
|
vertex_point_size : f32;
|
||||||
|
};
|
||||||
|
|
||||||
|
fn vert_main_inner() -> VertOut {
|
||||||
|
return VertOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[stage(vertex)]]
|
||||||
|
fn vert_main() -> tint_symbol {
|
||||||
|
let inner_result = vert_main_inner();
|
||||||
|
var wrapper_result : tint_symbol;
|
||||||
|
wrapper_result.pos = inner_result.pos;
|
||||||
|
wrapper_result.vertex_point_size = 1.0;
|
||||||
|
return wrapper_result;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
DataMap data;
|
||||||
|
data.Add<CanonicalizeEntryPointIO::Config>(
|
||||||
|
CanonicalizeEntryPointIO::BuiltinStyle::kParameter, 0xFFFFFFFF, true);
|
||||||
|
auto got = Run<CanonicalizeEntryPointIO>(src, data);
|
||||||
|
|
||||||
|
EXPECT_EQ(expect, str(got));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CanonicalizeEntryPointIOTest, EmitVertexPointSize_AvoidNameClash) {
|
||||||
|
auto* src = R"(
|
||||||
|
struct VertOut {
|
||||||
|
[[location(0)]] vertex_point_size : vec4<f32>;
|
||||||
|
[[builtin(position)]] vertex_point_size_1 : vec4<f32>;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[stage(vertex)]]
|
||||||
|
fn vert_main() -> VertOut {
|
||||||
|
return VertOut();
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
auto* expect = R"(
|
||||||
|
struct VertOut {
|
||||||
|
vertex_point_size : vec4<f32>;
|
||||||
|
vertex_point_size_1 : vec4<f32>;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tint_symbol {
|
||||||
|
[[location(0)]]
|
||||||
|
vertex_point_size : vec4<f32>;
|
||||||
|
[[builtin(position)]]
|
||||||
|
vertex_point_size_1 : vec4<f32>;
|
||||||
|
[[builtin(pointsize)]]
|
||||||
|
vertex_point_size_2 : f32;
|
||||||
|
};
|
||||||
|
|
||||||
|
fn vert_main_inner() -> VertOut {
|
||||||
|
return VertOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[stage(vertex)]]
|
||||||
|
fn vert_main() -> tint_symbol {
|
||||||
|
let inner_result = vert_main_inner();
|
||||||
|
var wrapper_result : tint_symbol;
|
||||||
|
wrapper_result.vertex_point_size = inner_result.vertex_point_size;
|
||||||
|
wrapper_result.vertex_point_size_1 = inner_result.vertex_point_size_1;
|
||||||
|
wrapper_result.vertex_point_size_2 = 1.0;
|
||||||
|
return wrapper_result;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
DataMap data;
|
||||||
|
data.Add<CanonicalizeEntryPointIO::Config>(
|
||||||
|
CanonicalizeEntryPointIO::BuiltinStyle::kParameter, 0xFFFFFFFF, true);
|
||||||
|
auto got = Run<CanonicalizeEntryPointIO>(src, data);
|
||||||
|
|
||||||
|
EXPECT_EQ(expect, str(got));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace transform
|
} // namespace transform
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -55,14 +55,17 @@ Output Msl::Run(const Program* in, const DataMap& inputs) {
|
||||||
// Build the configs for the internal transforms.
|
// Build the configs for the internal transforms.
|
||||||
uint32_t buffer_size_ubo_index = kDefaultBufferSizeUniformIndex;
|
uint32_t buffer_size_ubo_index = kDefaultBufferSizeUniformIndex;
|
||||||
uint32_t fixed_sample_mask = 0xFFFFFFFF;
|
uint32_t fixed_sample_mask = 0xFFFFFFFF;
|
||||||
|
bool emit_point_size = false;
|
||||||
if (cfg) {
|
if (cfg) {
|
||||||
buffer_size_ubo_index = cfg->buffer_size_ubo_index;
|
buffer_size_ubo_index = cfg->buffer_size_ubo_index;
|
||||||
fixed_sample_mask = cfg->fixed_sample_mask;
|
fixed_sample_mask = cfg->fixed_sample_mask;
|
||||||
|
emit_point_size = cfg->emit_vertex_point_size;
|
||||||
}
|
}
|
||||||
auto array_length_from_uniform_cfg = ArrayLengthFromUniform::Config(
|
auto array_length_from_uniform_cfg = ArrayLengthFromUniform::Config(
|
||||||
sem::BindingPoint{0, buffer_size_ubo_index});
|
sem::BindingPoint{0, buffer_size_ubo_index});
|
||||||
auto entry_point_io_cfg = CanonicalizeEntryPointIO::Config(
|
auto entry_point_io_cfg = CanonicalizeEntryPointIO::Config(
|
||||||
CanonicalizeEntryPointIO::BuiltinStyle::kParameter, fixed_sample_mask);
|
CanonicalizeEntryPointIO::BuiltinStyle::kParameter, fixed_sample_mask,
|
||||||
|
emit_point_size);
|
||||||
|
|
||||||
// Use the SSBO binding numbers as the indices for the buffer size lookups.
|
// Use the SSBO binding numbers as the indices for the buffer size lookups.
|
||||||
for (auto* var : in->AST().GlobalVariables()) {
|
for (auto* var : in->AST().GlobalVariables()) {
|
||||||
|
@ -310,9 +313,11 @@ void Msl::HandleModuleScopeVariables(CloneContext& ctx) const {
|
||||||
|
|
||||||
Msl::Config::Config(uint32_t buffer_size_ubo_idx,
|
Msl::Config::Config(uint32_t buffer_size_ubo_idx,
|
||||||
uint32_t sample_mask,
|
uint32_t sample_mask,
|
||||||
|
bool emit_point_size,
|
||||||
bool disable_wi)
|
bool disable_wi)
|
||||||
: buffer_size_ubo_index(buffer_size_ubo_idx),
|
: buffer_size_ubo_index(buffer_size_ubo_idx),
|
||||||
fixed_sample_mask(sample_mask),
|
fixed_sample_mask(sample_mask),
|
||||||
|
emit_vertex_point_size(emit_point_size),
|
||||||
disable_workgroup_init(disable_wi) {}
|
disable_workgroup_init(disable_wi) {}
|
||||||
Msl::Config::Config(const Config&) = default;
|
Msl::Config::Config(const Config&) = default;
|
||||||
Msl::Config::~Config() = default;
|
Msl::Config::~Config() = default;
|
||||||
|
|
|
@ -33,10 +33,12 @@ class Msl : public Castable<Msl, Transform> {
|
||||||
/// Constructor
|
/// Constructor
|
||||||
/// @param buffer_size_ubo_idx the index to use for the buffer size UBO
|
/// @param buffer_size_ubo_idx the index to use for the buffer size UBO
|
||||||
/// @param sample_mask the fixed sample mask to use for fragment shaders
|
/// @param sample_mask the fixed sample mask to use for fragment shaders
|
||||||
|
/// @param emit_point_size `true` to emit a vertex point size builtin
|
||||||
/// @param disable_workgroup_init `true` to disable workgroup memory zero
|
/// @param disable_workgroup_init `true` to disable workgroup memory zero
|
||||||
/// initialization
|
/// initialization
|
||||||
Config(uint32_t buffer_size_ubo_idx,
|
Config(uint32_t buffer_size_ubo_idx,
|
||||||
uint32_t sample_mask = 0xFFFFFFFF,
|
uint32_t sample_mask = 0xFFFFFFFF,
|
||||||
|
bool emit_point_size = false,
|
||||||
bool disable_workgroup_init = false);
|
bool disable_workgroup_init = false);
|
||||||
|
|
||||||
/// Copy constructor
|
/// Copy constructor
|
||||||
|
@ -51,6 +53,10 @@ class Msl : public Castable<Msl, Transform> {
|
||||||
/// The fixed sample mask to combine with fragment shader outputs.
|
/// The fixed sample mask to combine with fragment shader outputs.
|
||||||
uint32_t fixed_sample_mask = 0xFFFFFFFF;
|
uint32_t fixed_sample_mask = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
/// Set to `true` to generate a [[point_size]] attribute which is set to 1.0
|
||||||
|
/// for all vertex shaders in the module.
|
||||||
|
bool emit_vertex_point_size = false;
|
||||||
|
|
||||||
/// Set to `true` to disable workgroup memory zero initialization
|
/// Set to `true` to disable workgroup memory zero initialization
|
||||||
bool disable_workgroup_init = false;
|
bool disable_workgroup_init = false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,9 +31,9 @@ Result Generate(const Program* program, const Options& options) {
|
||||||
// Run the MSL sanitizer.
|
// Run the MSL sanitizer.
|
||||||
transform::Msl sanitizer;
|
transform::Msl sanitizer;
|
||||||
transform::DataMap transform_input;
|
transform::DataMap transform_input;
|
||||||
transform_input.Add<transform::Msl::Config>(options.buffer_size_ubo_index,
|
transform_input.Add<transform::Msl::Config>(
|
||||||
options.fixed_sample_mask,
|
options.buffer_size_ubo_index, options.fixed_sample_mask,
|
||||||
options.disable_workgroup_init);
|
options.emit_vertex_point_size, options.disable_workgroup_init);
|
||||||
auto output = sanitizer.Run(program, transform_input);
|
auto output = sanitizer.Run(program, transform_input);
|
||||||
if (!output.program.IsValid()) {
|
if (!output.program.IsValid()) {
|
||||||
result.success = false;
|
result.success = false;
|
||||||
|
|
|
@ -40,6 +40,10 @@ struct Options {
|
||||||
/// Defaults to 0xFFFFFFFF.
|
/// Defaults to 0xFFFFFFFF.
|
||||||
uint32_t fixed_sample_mask = 0xFFFFFFFF;
|
uint32_t fixed_sample_mask = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
/// Set to `true` to generate a [[point_size]] attribute which is set to 1.0
|
||||||
|
/// for all vertex shaders in the module.
|
||||||
|
bool emit_vertex_point_size = false;
|
||||||
|
|
||||||
/// Set to `true` to disable workgroup memory zero initialization
|
/// Set to `true` to disable workgroup memory zero initialization
|
||||||
bool disable_workgroup_init = false;
|
bool disable_workgroup_init = false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1531,6 +1531,8 @@ std::string GeneratorImpl::builtin_to_attribute(ast::Builtin builtin) const {
|
||||||
return "sample_id";
|
return "sample_id";
|
||||||
case ast::Builtin::kSampleMask:
|
case ast::Builtin::kSampleMask:
|
||||||
return "sample_mask";
|
return "sample_mask";
|
||||||
|
case ast::Builtin::kPointSize:
|
||||||
|
return "point_size";
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,8 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
MslBuiltinData{ast::Builtin::kWorkgroupId,
|
MslBuiltinData{ast::Builtin::kWorkgroupId,
|
||||||
"threadgroup_position_in_grid"},
|
"threadgroup_position_in_grid"},
|
||||||
MslBuiltinData{ast::Builtin::kSampleIndex, "sample_id"},
|
MslBuiltinData{ast::Builtin::kSampleIndex, "sample_id"},
|
||||||
MslBuiltinData{ast::Builtin::kSampleMask, "sample_mask"}));
|
MslBuiltinData{ast::Builtin::kSampleMask, "sample_mask"},
|
||||||
|
MslBuiltinData{ast::Builtin::kPointSize, "point_size"}));
|
||||||
|
|
||||||
TEST_F(MslGeneratorImplTest, HasInvariantAttribute_True) {
|
TEST_F(MslGeneratorImplTest, HasInvariantAttribute_True) {
|
||||||
auto* out = Structure(
|
auto* out = Structure(
|
||||||
|
|
Loading…
Reference in New Issue