mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-12 16:15:55 +00:00
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 tint {
|
||||||
namespace transform {
|
namespace transform {
|
||||||
|
|
||||||
|
/// DEPRECATED: This should now be performed using the SPIR-V sanitizer.
|
||||||
/// EmitVertexPointSize is a Transform that adds a PointSize builtin global
|
/// EmitVertexPointSize is a Transform that adds a PointSize builtin global
|
||||||
/// output variable to the program which is assigned 1.0 as the new first
|
/// output variable to the program which is assigned 1.0 as the new first
|
||||||
/// statement for all vertex stage entry points.
|
/// statement for all vertex stage entry points.
|
||||||
|
@ -26,13 +26,17 @@
|
|||||||
#include "src/sem/struct.h"
|
#include "src/sem/struct.h"
|
||||||
#include "src/sem/variable.h"
|
#include "src/sem/variable.h"
|
||||||
|
|
||||||
|
TINT_INSTANTIATE_TYPEINFO(tint::transform::Spirv::Config);
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
namespace transform {
|
namespace transform {
|
||||||
|
|
||||||
Spirv::Spirv() = default;
|
Spirv::Spirv() = default;
|
||||||
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;
|
ProgramBuilder out;
|
||||||
CloneContext ctx(&out, in);
|
CloneContext ctx(&out, in);
|
||||||
HandleEntryPointIOTypes(ctx);
|
HandleEntryPointIOTypes(ctx);
|
||||||
@ -45,6 +49,9 @@ Output Spirv::Run(const Program* in, const DataMap&) {
|
|||||||
CloneContext ctx2(&out2, &tmp);
|
CloneContext ctx2(&out2, &tmp);
|
||||||
HandleSampleMaskBuiltins(ctx2);
|
HandleSampleMaskBuiltins(ctx2);
|
||||||
AddEmptyEntryPoint(ctx2);
|
AddEmptyEntryPoint(ctx2);
|
||||||
|
if (cfg && cfg->emit_vertex_point_size) {
|
||||||
|
EmitVertexPointSize(ctx2);
|
||||||
|
}
|
||||||
ctx2.Clone();
|
ctx2.Clone();
|
||||||
|
|
||||||
return Output{Program(std::move(out2))};
|
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 {
|
void Spirv::AddEmptyEntryPoint(CloneContext& ctx) const {
|
||||||
for (auto* func : ctx.src->AST().Functions()) {
|
for (auto* func : ctx.src->AST().Functions()) {
|
||||||
if (func->IsEntryPoint()) {
|
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 transform
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
@ -31,6 +31,27 @@ namespace transform {
|
|||||||
/// undefined behavior.
|
/// undefined behavior.
|
||||||
class Spirv : public Transform {
|
class Spirv : public Transform {
|
||||||
public:
|
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
|
/// Constructor
|
||||||
Spirv();
|
Spirv();
|
||||||
~Spirv() override;
|
~Spirv() override;
|
||||||
@ -47,6 +68,9 @@ class Spirv : public Transform {
|
|||||||
void HandleEntryPointIOTypes(CloneContext& ctx) const;
|
void HandleEntryPointIOTypes(CloneContext& ctx) const;
|
||||||
/// Change type of sample mask builtin variables to single element arrays.
|
/// Change type of sample mask builtin variables to single element arrays.
|
||||||
void HandleSampleMaskBuiltins(CloneContext& ctx) const;
|
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.
|
/// Add an empty shader entry point if none exist in the module.
|
||||||
void AddEmptyEntryPoint(CloneContext& ctx) const;
|
void AddEmptyEntryPoint(CloneContext& ctx) const;
|
||||||
|
|
||||||
|
@ -566,6 +566,128 @@ fn main() {
|
|||||||
EXPECT_EQ(expect, str(got));
|
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) {
|
TEST_F(SpirvTest, AddEmptyEntryPoint) {
|
||||||
auto* src = R"()";
|
auto* src = R"()";
|
||||||
|
|
||||||
@ -583,8 +705,13 @@ fn _tint_unused_entry_point() {
|
|||||||
// Test that different transforms within the sanitizer interact correctly.
|
// Test that different transforms within the sanitizer interact correctly.
|
||||||
TEST_F(SpirvTest, MultipleTransforms) {
|
TEST_F(SpirvTest, MultipleTransforms) {
|
||||||
auto* src = R"(
|
auto* src = R"(
|
||||||
|
[[stage(vertex)]]
|
||||||
|
fn vert_main() -> [[builtin(position)]] vec4<f32> {
|
||||||
|
return vec4<f32>();
|
||||||
|
}
|
||||||
|
|
||||||
[[stage(fragment)]]
|
[[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)]] mask_in : u32)
|
||||||
-> [[builtin(sample_mask)]] u32 {
|
-> [[builtin(sample_mask)]] u32 {
|
||||||
return mask_in;
|
return mask_in;
|
||||||
@ -592,24 +719,41 @@ fn main([[builtin(sample_index)]] sample_index : u32,
|
|||||||
)";
|
)";
|
||||||
|
|
||||||
auto* expect = R"(
|
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) {
|
[[stage(vertex)]]
|
||||||
tint_symbol_3[0] = tint_symbol_2;
|
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)]]
|
[[stage(fragment)]]
|
||||||
fn main() {
|
fn frag_main() {
|
||||||
tint_symbol_4(tint_symbol_1[0]);
|
tint_symbol_7(tint_symbol_4[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
auto got = Run<Spirv>(src);
|
DataMap data;
|
||||||
|
data.Add<Spirv::Config>(true);
|
||||||
|
auto got = Run<Spirv>(src, data);
|
||||||
|
|
||||||
EXPECT_EQ(expect, str(got));
|
EXPECT_EQ(expect, str(got));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user