transform/Spirv: Add EmitVertexPointSize logic
This is disabled by default and can be enabled via transform data. The separate EmitVertexPointSize transform will be removed once Dawn starts using the Spirv sanitizer to do this. Bug: tint:753 Change-Id: I676c4cef5bc53f2dbf2330645faa4a0f2bfe11bd Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/49980 Auto-Submit: James Price <jrprice@google.com> Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
6c1cf6569e
commit
8c6808fa13
|
@ -20,6 +20,7 @@
|
|||
namespace tint {
|
||||
namespace transform {
|
||||
|
||||
/// DEPRECATED: This should now be performed using the SPIR-V sanitizer.
|
||||
/// EmitVertexPointSize is a Transform that adds a PointSize builtin global
|
||||
/// output variable to the program which is assigned 1.0 as the new first
|
||||
/// statement for all vertex stage entry points.
|
||||
|
|
|
@ -26,13 +26,17 @@
|
|||
#include "src/sem/struct.h"
|
||||
#include "src/sem/variable.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::transform::Spirv::Config);
|
||||
|
||||
namespace tint {
|
||||
namespace transform {
|
||||
|
||||
Spirv::Spirv() = default;
|
||||
Spirv::~Spirv() = default;
|
||||
|
||||
Output Spirv::Run(const Program* in, const DataMap&) {
|
||||
Output Spirv::Run(const Program* in, const DataMap& data) {
|
||||
auto* cfg = data.Get<Config>();
|
||||
|
||||
ProgramBuilder out;
|
||||
CloneContext ctx(&out, in);
|
||||
HandleEntryPointIOTypes(ctx);
|
||||
|
@ -45,6 +49,9 @@ Output Spirv::Run(const Program* in, const DataMap&) {
|
|||
CloneContext ctx2(&out2, &tmp);
|
||||
HandleSampleMaskBuiltins(ctx2);
|
||||
AddEmptyEntryPoint(ctx2);
|
||||
if (cfg && cfg->emit_vertex_point_size) {
|
||||
EmitVertexPointSize(ctx2);
|
||||
}
|
||||
ctx2.Clone();
|
||||
|
||||
return Output{Program(std::move(out2))};
|
||||
|
@ -242,6 +249,29 @@ void Spirv::HandleSampleMaskBuiltins(CloneContext& ctx) const {
|
|||
}
|
||||
}
|
||||
|
||||
void Spirv::EmitVertexPointSize(CloneContext& ctx) const {
|
||||
// No-op if there are no vertex stages in the module.
|
||||
if (!ctx.src->AST().Functions().HasStage(ast::PipelineStage::kVertex)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a module-scope pointsize builtin output variable.
|
||||
Symbol pointsize = ctx.dst->Symbols().New("tint_pointsize");
|
||||
ctx.dst->Global(pointsize, ctx.dst->ty.f32(), ast::StorageClass::kOutput,
|
||||
nullptr, {ctx.dst->Builtin(ast::Builtin::kPointSize)});
|
||||
|
||||
// Assign 1.0 to the global at the start of all vertex shader entry points.
|
||||
ctx.ReplaceAll([&ctx, pointsize](ast::Function* func) -> ast::Function* {
|
||||
if (func->pipeline_stage() != ast::PipelineStage::kVertex) {
|
||||
return nullptr;
|
||||
}
|
||||
return CloneWithStatementsAtStart(&ctx, func,
|
||||
{
|
||||
ctx.dst->Assign(pointsize, 1.0f),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void Spirv::AddEmptyEntryPoint(CloneContext& ctx) const {
|
||||
for (auto* func : ctx.src->AST().Functions()) {
|
||||
if (func->IsEntryPoint()) {
|
||||
|
@ -347,5 +377,12 @@ void Spirv::HoistToOutputVariables(CloneContext& ctx,
|
|||
}
|
||||
}
|
||||
|
||||
Spirv::Config::Config(bool emit_vertex_point_size)
|
||||
: emit_vertex_point_size(emit_vertex_point_size) {}
|
||||
|
||||
Spirv::Config::Config(const Config&) = default;
|
||||
Spirv::Config::~Config() = default;
|
||||
Spirv::Config& Spirv::Config::operator=(const Config&) = default;
|
||||
|
||||
} // namespace transform
|
||||
} // namespace tint
|
||||
|
|
|
@ -31,6 +31,27 @@ namespace transform {
|
|||
/// undefined behavior.
|
||||
class Spirv : public Transform {
|
||||
public:
|
||||
/// Configuration options for the transform.
|
||||
struct Config : public Castable<Config, Data> {
|
||||
/// Constructor
|
||||
/// @param emit_vertex_point_size `true` to generate a PointSize builtin
|
||||
explicit Config(bool emit_vertex_point_size = false);
|
||||
|
||||
/// Copy constructor.
|
||||
Config(const Config&);
|
||||
|
||||
/// Destructor.
|
||||
~Config() override;
|
||||
|
||||
/// Assignment operator.
|
||||
/// @returns this Config
|
||||
Config& operator=(const Config&);
|
||||
|
||||
/// Set to `true` to generate a PointSize builtin and have it set to 1.0
|
||||
/// from all vertex shaders in the module.
|
||||
bool emit_vertex_point_size;
|
||||
};
|
||||
|
||||
/// Constructor
|
||||
Spirv();
|
||||
~Spirv() override;
|
||||
|
@ -47,6 +68,9 @@ class Spirv : public Transform {
|
|||
void HandleEntryPointIOTypes(CloneContext& ctx) const;
|
||||
/// Change type of sample mask builtin variables to single element arrays.
|
||||
void HandleSampleMaskBuiltins(CloneContext& ctx) const;
|
||||
/// Add a PointSize builtin output to the module and set it to 1.0 from all
|
||||
/// vertex stage entry points.
|
||||
void EmitVertexPointSize(CloneContext& ctx) const;
|
||||
/// Add an empty shader entry point if none exist in the module.
|
||||
void AddEmptyEntryPoint(CloneContext& ctx) const;
|
||||
|
||||
|
|
|
@ -566,6 +566,128 @@ fn main() {
|
|||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(SpirvTest, EmitVertexPointSize_Basic) {
|
||||
auto* src = R"(
|
||||
fn non_entry_point() {
|
||||
}
|
||||
|
||||
[[stage(vertex)]]
|
||||
fn main() -> [[builtin(position)]] vec4<f32> {
|
||||
non_entry_point();
|
||||
return vec4<f32>();
|
||||
}
|
||||
)";
|
||||
|
||||
auto* expect = R"(
|
||||
[[builtin(pointsize)]] var<out> tint_pointsize : f32;
|
||||
|
||||
fn non_entry_point() {
|
||||
}
|
||||
|
||||
[[builtin(position)]] var<out> tint_symbol_1 : vec4<f32>;
|
||||
|
||||
fn tint_symbol_2(tint_symbol : vec4<f32>) {
|
||||
tint_symbol_1 = tint_symbol;
|
||||
}
|
||||
|
||||
[[stage(vertex)]]
|
||||
fn main() {
|
||||
tint_pointsize = 1.0;
|
||||
non_entry_point();
|
||||
tint_symbol_2(vec4<f32>());
|
||||
return;
|
||||
}
|
||||
)";
|
||||
|
||||
DataMap data;
|
||||
data.Add<Spirv::Config>(true);
|
||||
auto got = Run<Spirv>(src, data);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(SpirvTest, EmitVertexPointSize_MultipleVertexShaders) {
|
||||
auto* src = R"(
|
||||
[[stage(vertex)]]
|
||||
fn main1() -> [[builtin(position)]] vec4<f32> {
|
||||
return vec4<f32>();
|
||||
}
|
||||
|
||||
[[stage(vertex)]]
|
||||
fn main2() -> [[builtin(position)]] vec4<f32> {
|
||||
return vec4<f32>();
|
||||
}
|
||||
|
||||
[[stage(vertex)]]
|
||||
fn main3() -> [[builtin(position)]] vec4<f32> {
|
||||
return vec4<f32>();
|
||||
}
|
||||
)";
|
||||
|
||||
auto* expect = R"(
|
||||
[[builtin(pointsize)]] var<out> tint_pointsize : f32;
|
||||
|
||||
[[builtin(position)]] var<out> tint_symbol_1 : vec4<f32>;
|
||||
|
||||
fn tint_symbol_2(tint_symbol : vec4<f32>) {
|
||||
tint_symbol_1 = tint_symbol;
|
||||
}
|
||||
|
||||
[[stage(vertex)]]
|
||||
fn main1() {
|
||||
tint_pointsize = 1.0;
|
||||
tint_symbol_2(vec4<f32>());
|
||||
return;
|
||||
}
|
||||
|
||||
[[builtin(position)]] var<out> tint_symbol_4 : vec4<f32>;
|
||||
|
||||
fn tint_symbol_5(tint_symbol_3 : vec4<f32>) {
|
||||
tint_symbol_4 = tint_symbol_3;
|
||||
}
|
||||
|
||||
[[stage(vertex)]]
|
||||
fn main2() {
|
||||
tint_pointsize = 1.0;
|
||||
tint_symbol_5(vec4<f32>());
|
||||
return;
|
||||
}
|
||||
|
||||
[[builtin(position)]] var<out> tint_symbol_7 : vec4<f32>;
|
||||
|
||||
fn tint_symbol_8(tint_symbol_6 : vec4<f32>) {
|
||||
tint_symbol_7 = tint_symbol_6;
|
||||
}
|
||||
|
||||
[[stage(vertex)]]
|
||||
fn main3() {
|
||||
tint_pointsize = 1.0;
|
||||
tint_symbol_8(vec4<f32>());
|
||||
return;
|
||||
}
|
||||
)";
|
||||
|
||||
DataMap data;
|
||||
data.Add<Spirv::Config>(true);
|
||||
auto got = Run<Spirv>(src, data);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
||||
TEST_F(SpirvTest, EmitVertexPointSize_NoVertexShaders) {
|
||||
auto* src = R"(
|
||||
[[stage(compute)]]
|
||||
fn main() {
|
||||
}
|
||||
)";
|
||||
|
||||
DataMap data;
|
||||
data.Add<Spirv::Config>(true);
|
||||
auto got = Run<Spirv>(src, data);
|
||||
|
||||
EXPECT_EQ(src, str(got));
|
||||
}
|
||||
|
||||
TEST_F(SpirvTest, AddEmptyEntryPoint) {
|
||||
auto* src = R"()";
|
||||
|
||||
|
@ -583,8 +705,13 @@ fn _tint_unused_entry_point() {
|
|||
// Test that different transforms within the sanitizer interact correctly.
|
||||
TEST_F(SpirvTest, MultipleTransforms) {
|
||||
auto* src = R"(
|
||||
[[stage(vertex)]]
|
||||
fn vert_main() -> [[builtin(position)]] vec4<f32> {
|
||||
return vec4<f32>();
|
||||
}
|
||||
|
||||
[[stage(fragment)]]
|
||||
fn main([[builtin(sample_index)]] sample_index : u32,
|
||||
fn frag_main([[builtin(sample_index)]] sample_index : u32,
|
||||
[[builtin(sample_mask)]] mask_in : u32)
|
||||
-> [[builtin(sample_mask)]] u32 {
|
||||
return mask_in;
|
||||
|
@ -592,24 +719,41 @@ fn main([[builtin(sample_index)]] sample_index : u32,
|
|||
)";
|
||||
|
||||
auto* expect = R"(
|
||||
[[builtin(sample_index)]] var<in> tint_symbol : u32;
|
||||
[[builtin(pointsize)]] var<out> tint_pointsize : f32;
|
||||
|
||||
[[builtin(sample_mask)]] var<in> tint_symbol_1 : array<u32, 1>;
|
||||
[[builtin(position)]] var<out> tint_symbol_1 : vec4<f32>;
|
||||
|
||||
[[builtin(sample_mask)]] var<out> tint_symbol_3 : array<u32, 1>;
|
||||
fn tint_symbol_2(tint_symbol : vec4<f32>) {
|
||||
tint_symbol_1 = tint_symbol;
|
||||
}
|
||||
|
||||
fn tint_symbol_4(tint_symbol_2 : u32) {
|
||||
tint_symbol_3[0] = tint_symbol_2;
|
||||
[[stage(vertex)]]
|
||||
fn vert_main() {
|
||||
tint_pointsize = 1.0;
|
||||
tint_symbol_2(vec4<f32>());
|
||||
return;
|
||||
}
|
||||
|
||||
[[builtin(sample_index)]] var<in> tint_symbol_3 : u32;
|
||||
|
||||
[[builtin(sample_mask)]] var<in> tint_symbol_4 : array<u32, 1>;
|
||||
|
||||
[[builtin(sample_mask)]] var<out> tint_symbol_6 : array<u32, 1>;
|
||||
|
||||
fn tint_symbol_7(tint_symbol_5 : u32) {
|
||||
tint_symbol_6[0] = tint_symbol_5;
|
||||
}
|
||||
|
||||
[[stage(fragment)]]
|
||||
fn main() {
|
||||
tint_symbol_4(tint_symbol_1[0]);
|
||||
fn frag_main() {
|
||||
tint_symbol_7(tint_symbol_4[0]);
|
||||
return;
|
||||
}
|
||||
)";
|
||||
|
||||
auto got = Run<Spirv>(src);
|
||||
DataMap data;
|
||||
data.Add<Spirv::Config>(true);
|
||||
auto got = Run<Spirv>(src, data);
|
||||
|
||||
EXPECT_EQ(expect, str(got));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue