mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-10 22:17:51 +00:00
Split Program into Program and ProgramBuilder
Program is now immutable*, and remains part of the public Tint interface. ProgramBuilder is the mutable builder for Programs, and is not part of the public Tint interface. ast::Builder has been folded into ProgramBuilder. Immutable Programs can be cloned into a mutable ProgramBuilder with Program::CloneAsBuilder(). Mutable ProgramBuilders can be moved into immutable Programs. * - mostly immutable. It still has a move constructor and move assignment operator - required for practical usage - and the semantic information on AST nodes is still mutable. Bug: tint:390 Change-Id: Ia856c50b1880c2f95c91467a9eef5024cbc380c6 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/38240 Reviewed-by: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
@@ -23,7 +23,6 @@
|
||||
#include "src/ast/bitcast_expression.h"
|
||||
#include "src/ast/block_statement.h"
|
||||
#include "src/ast/break_statement.h"
|
||||
#include "src/ast/builder.h"
|
||||
#include "src/ast/call_expression.h"
|
||||
#include "src/ast/call_statement.h"
|
||||
#include "src/ast/case_statement.h"
|
||||
@@ -44,6 +43,7 @@
|
||||
#include "src/ast/variable.h"
|
||||
#include "src/ast/variable_decl_statement.h"
|
||||
#include "src/clone_context.h"
|
||||
#include "src/program_builder.h"
|
||||
#include "src/type/array_type.h"
|
||||
#include "src/type/matrix_type.h"
|
||||
#include "src/type/u32_type.h"
|
||||
@@ -56,13 +56,14 @@ BoundArrayAccessors::BoundArrayAccessors() = default;
|
||||
BoundArrayAccessors::~BoundArrayAccessors() = default;
|
||||
|
||||
Transform::Output BoundArrayAccessors::Run(const Program* in) {
|
||||
Output out;
|
||||
CloneContext(&out.program, in)
|
||||
ProgramBuilder out;
|
||||
diag::List diagnostics;
|
||||
CloneContext(&out, in)
|
||||
.ReplaceAll([&](CloneContext* ctx, ast::ArrayAccessorExpression* expr) {
|
||||
return Transform(expr, ctx, &out.diagnostics);
|
||||
return Transform(expr, ctx, &diagnostics);
|
||||
})
|
||||
.Clone();
|
||||
return out;
|
||||
return Output(Program(std::move(out)), std::move(diagnostics));
|
||||
}
|
||||
|
||||
ast::ArrayAccessorExpression* BoundArrayAccessors::Transform(
|
||||
@@ -75,8 +76,8 @@ ast::ArrayAccessorExpression* BoundArrayAccessors::Transform(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ast::Builder b(ctx->dst);
|
||||
using u32 = ast::Builder::u32;
|
||||
ProgramBuilder& b = *ctx->dst;
|
||||
using u32 = ProgramBuilder::u32;
|
||||
|
||||
uint32_t size = 0;
|
||||
bool is_vec = ret_type->Is<type::Vector>();
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "src/ast/scalar_constructor_expression.h"
|
||||
#include "src/ast/variable.h"
|
||||
#include "src/clone_context.h"
|
||||
#include "src/program.h"
|
||||
#include "src/program_builder.h"
|
||||
#include "src/type/f32_type.h"
|
||||
#include "src/type/type_manager.h"
|
||||
|
||||
@@ -39,41 +41,39 @@ EmitVertexPointSize::EmitVertexPointSize() = default;
|
||||
EmitVertexPointSize::~EmitVertexPointSize() = default;
|
||||
|
||||
Transform::Output EmitVertexPointSize::Run(const Program* in) {
|
||||
Output out;
|
||||
|
||||
if (!in->AST().Functions().HasStage(ast::PipelineStage::kVertex)) {
|
||||
// If the module doesn't have any vertex stages, then there's nothing to do.
|
||||
out.program = in->Clone();
|
||||
return out;
|
||||
return Output(Program(in->Clone()));
|
||||
}
|
||||
|
||||
auto* f32 = out.program.create<type::F32>();
|
||||
ProgramBuilder out;
|
||||
auto* f32 = out.create<type::F32>();
|
||||
|
||||
// Declare the pointsize builtin output variable.
|
||||
auto* pointsize_var = out.program.create<ast::Variable>(
|
||||
Source{}, // source
|
||||
out.program.Symbols().Register(kPointSizeVar), // symbol
|
||||
ast::StorageClass::kOutput, // storage_class
|
||||
f32, // type
|
||||
false, // is_const
|
||||
nullptr, // constructor
|
||||
auto* pointsize_var = out.create<ast::Variable>(
|
||||
Source{}, // source
|
||||
out.Symbols().Register(kPointSizeVar), // symbol
|
||||
ast::StorageClass::kOutput, // storage_class
|
||||
f32, // type
|
||||
false, // is_const
|
||||
nullptr, // constructor
|
||||
ast::VariableDecorationList{
|
||||
// decorations
|
||||
out.program.create<ast::BuiltinDecoration>(Source{},
|
||||
ast::Builtin::kPointSize),
|
||||
out.create<ast::BuiltinDecoration>(Source{},
|
||||
ast::Builtin::kPointSize),
|
||||
});
|
||||
out.program.AST().AddGlobalVariable(pointsize_var);
|
||||
out.AST().AddGlobalVariable(pointsize_var);
|
||||
|
||||
// Build the AST expression & statement for assigning pointsize one.
|
||||
auto* one = out.program.create<ast::ScalarConstructorExpression>(
|
||||
Source{}, out.program.create<ast::FloatLiteral>(Source{}, f32, 1.0f));
|
||||
auto* pointsize_ident = out.program.create<ast::IdentifierExpression>(
|
||||
Source{}, out.program.Symbols().Register(kPointSizeVar));
|
||||
auto* pointsize_assign = out.program.create<ast::AssignmentStatement>(
|
||||
Source{}, pointsize_ident, one);
|
||||
auto* one = out.create<ast::ScalarConstructorExpression>(
|
||||
Source{}, out.create<ast::FloatLiteral>(Source{}, f32, 1.0f));
|
||||
auto* pointsize_ident = out.create<ast::IdentifierExpression>(
|
||||
Source{}, out.Symbols().Register(kPointSizeVar));
|
||||
auto* pointsize_assign =
|
||||
out.create<ast::AssignmentStatement>(Source{}, pointsize_ident, one);
|
||||
|
||||
// Add the pointsize assignment statement to the front of all vertex stages.
|
||||
CloneContext(&out.program, in)
|
||||
CloneContext(&out, in)
|
||||
.ReplaceAll(
|
||||
[&](CloneContext* ctx, ast::Function* func) -> ast::Function* {
|
||||
if (func->pipeline_stage() != ast::PipelineStage::kVertex) {
|
||||
@@ -83,7 +83,7 @@ Transform::Output EmitVertexPointSize::Run(const Program* in) {
|
||||
})
|
||||
.Clone();
|
||||
|
||||
return out;
|
||||
return Output(Program(std::move(out)));
|
||||
}
|
||||
|
||||
} // namespace transform
|
||||
|
||||
@@ -47,6 +47,8 @@
|
||||
#include "src/ast/variable_decl_statement.h"
|
||||
#include "src/ast/variable_decoration.h"
|
||||
#include "src/clone_context.h"
|
||||
#include "src/program.h"
|
||||
#include "src/program_builder.h"
|
||||
#include "src/type/struct_type.h"
|
||||
#include "src/type/u32_type.h"
|
||||
#include "src/type_determiner.h"
|
||||
@@ -99,15 +101,20 @@ Transform::Output FirstIndexOffset::Run(const Program* in) {
|
||||
// Running TypeDeterminer as we require local_referenced_builtin_variables()
|
||||
// to be populated. TODO(bclayton) - it should not be necessary to re-run the
|
||||
// type determiner if semantic information is already generated. Remove.
|
||||
// TODO(https://crbug.com/tint/390): Remove this const_cast hack!
|
||||
TypeDeterminer td(const_cast<Program*>(in));
|
||||
if (!td.Determine()) {
|
||||
diag::Diagnostic err;
|
||||
err.severity = diag::Severity::Error;
|
||||
err.message = td.error();
|
||||
Output out;
|
||||
out.diagnostics.add(std::move(err));
|
||||
return out;
|
||||
Program program;
|
||||
{
|
||||
ProgramBuilder builder = in->CloneAsBuilder();
|
||||
TypeDeterminer td(&builder);
|
||||
if (!td.Determine()) {
|
||||
diag::Diagnostic err;
|
||||
err.severity = diag::Severity::Error;
|
||||
err.message = td.error();
|
||||
Output out;
|
||||
out.diagnostics.add(std::move(err));
|
||||
return out;
|
||||
}
|
||||
program = Program(std::move(builder));
|
||||
in = &program;
|
||||
}
|
||||
|
||||
Symbol vertex_index_sym;
|
||||
@@ -116,9 +123,9 @@ Transform::Output FirstIndexOffset::Run(const Program* in) {
|
||||
// Lazilly construct the UniformBuffer on first call to
|
||||
// maybe_create_buffer_var()
|
||||
ast::Variable* buffer_var = nullptr;
|
||||
auto maybe_create_buffer_var = [&](Program* program) {
|
||||
auto maybe_create_buffer_var = [&](ProgramBuilder* dst) {
|
||||
if (buffer_var == nullptr) {
|
||||
buffer_var = AddUniformBuffer(program);
|
||||
buffer_var = AddUniformBuffer(dst);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -126,8 +133,8 @@ Transform::Output FirstIndexOffset::Run(const Program* in) {
|
||||
// add a CreateFirstIndexOffset() statement to each function that uses one of
|
||||
// these builtins.
|
||||
|
||||
Output out;
|
||||
CloneContext(&out.program, in)
|
||||
ProgramBuilder out;
|
||||
CloneContext(&out, in)
|
||||
.ReplaceAll([&](CloneContext* ctx, ast::Variable* var) -> ast::Variable* {
|
||||
for (ast::VariableDecoration* dec : var->decorations()) {
|
||||
if (auto* blt_dec = dec->As<ast::BuiltinDecoration>()) {
|
||||
@@ -174,7 +181,7 @@ Transform::Output FirstIndexOffset::Run(const Program* in) {
|
||||
})
|
||||
.Clone();
|
||||
|
||||
return out;
|
||||
return Output(Program(std::move(out)));
|
||||
}
|
||||
|
||||
bool FirstIndexOffset::HasVertexIndex() {
|
||||
@@ -195,7 +202,7 @@ uint32_t FirstIndexOffset::GetFirstInstanceOffset() {
|
||||
return instance_index_offset_;
|
||||
}
|
||||
|
||||
ast::Variable* FirstIndexOffset::AddUniformBuffer(Program* dst) {
|
||||
ast::Variable* FirstIndexOffset::AddUniformBuffer(ProgramBuilder* dst) {
|
||||
auto* u32_type = dst->create<type::U32>();
|
||||
ast::StructMemberList members;
|
||||
uint32_t offset = 0;
|
||||
@@ -251,7 +258,7 @@ ast::VariableDeclStatement* FirstIndexOffset::CreateFirstIndexOffset(
|
||||
const std::string& original_name,
|
||||
const std::string& field_name,
|
||||
ast::Variable* buffer_var,
|
||||
Program* dst) {
|
||||
ProgramBuilder* dst) {
|
||||
auto* buffer =
|
||||
dst->create<ast::IdentifierExpression>(Source{}, buffer_var->symbol());
|
||||
|
||||
|
||||
@@ -89,19 +89,19 @@ class FirstIndexOffset : public Transform {
|
||||
uint32_t GetFirstInstanceOffset();
|
||||
|
||||
private:
|
||||
/// Adds uniform buffer with firstVertex/Instance to `program`
|
||||
/// Adds uniform buffer with firstVertex/Instance to the program builder
|
||||
/// @returns variable of new uniform buffer
|
||||
ast::Variable* AddUniformBuffer(Program* program);
|
||||
ast::Variable* AddUniformBuffer(ProgramBuilder* builder);
|
||||
/// Adds constant with modified original_name builtin to func
|
||||
/// @param original_name the name of the original builtin used in function
|
||||
/// @param field_name name of field in firstVertex/Instance buffer
|
||||
/// @param buffer_var variable of firstVertex/Instance buffer
|
||||
/// @param program the target program to contain the new ast nodes
|
||||
/// @param builder the target to contain the new ast nodes
|
||||
ast::VariableDeclStatement* CreateFirstIndexOffset(
|
||||
const std::string& original_name,
|
||||
const std::string& field_name,
|
||||
ast::Variable* buffer_var,
|
||||
Program* program);
|
||||
ProgramBuilder* builder);
|
||||
|
||||
uint32_t binding_;
|
||||
uint32_t group_;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "src/transform/manager.h"
|
||||
|
||||
#include "src/program_builder.h"
|
||||
#include "src/type_determiner.h"
|
||||
|
||||
namespace tint {
|
||||
@@ -35,16 +36,10 @@ Transform::Output Manager::Run(const Program* program) {
|
||||
program = &out.program;
|
||||
}
|
||||
} else {
|
||||
out.program = program->Clone();
|
||||
out.program = Program(program->Clone());
|
||||
}
|
||||
|
||||
TypeDeterminer td(&out.program);
|
||||
if (!td.Determine()) {
|
||||
diag::Diagnostic err;
|
||||
err.severity = diag::Severity::Error;
|
||||
err.message = td.error();
|
||||
out.diagnostics.add(std::move(err));
|
||||
}
|
||||
out.diagnostics.add(TypeDeterminer::Run(&out.program));
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/program.h"
|
||||
#include "src/program_builder.h"
|
||||
#include "src/reader/wgsl/parser.h"
|
||||
#include "src/transform/manager.h"
|
||||
#include "src/type_determiner.h"
|
||||
@@ -46,29 +48,33 @@ class TransformTest : public testing::Test {
|
||||
return "WGSL reader failed:\n" + parser.error();
|
||||
}
|
||||
|
||||
diag::Formatter::Style style;
|
||||
style.print_newline_at_end = false;
|
||||
|
||||
auto program = parser.program();
|
||||
TypeDeterminer td(&program);
|
||||
if (!td.Determine()) {
|
||||
return "Type determination failed:\n" + td.error();
|
||||
{
|
||||
auto diagnostics = TypeDeterminer::Run(&program);
|
||||
if (diagnostics.contains_errors()) {
|
||||
return "Type determination failed:\n" +
|
||||
diag::Formatter(style).format(diagnostics);
|
||||
}
|
||||
}
|
||||
|
||||
Manager manager;
|
||||
for (auto& transform : transforms) {
|
||||
manager.append(std::move(transform));
|
||||
}
|
||||
auto result = manager.Run(&program);
|
||||
{
|
||||
Manager manager;
|
||||
for (auto& transform : transforms) {
|
||||
manager.append(std::move(transform));
|
||||
}
|
||||
auto result = manager.Run(&program);
|
||||
|
||||
if (result.diagnostics.contains_errors()) {
|
||||
diag::Formatter::Style style;
|
||||
style.print_newline_at_end = false;
|
||||
return "manager().Run() errored:\n" +
|
||||
diag::Formatter(style).format(result.diagnostics);
|
||||
if (result.diagnostics.contains_errors()) {
|
||||
return "manager().Run() errored:\n" +
|
||||
diag::Formatter(style).format(result.diagnostics);
|
||||
}
|
||||
program = std::move(result.program);
|
||||
}
|
||||
|
||||
// Release the source program to ensure there's no uncloned data in result
|
||||
{ auto tmp = std::move(program); }
|
||||
|
||||
writer::wgsl::Generator generator(&result.program);
|
||||
writer::wgsl::Generator generator(&program);
|
||||
if (!generator.Generate()) {
|
||||
return "WGSL writer failed:\n" + generator.error();
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "src/ast/block_statement.h"
|
||||
#include "src/ast/function.h"
|
||||
#include "src/clone_context.h"
|
||||
#include "src/program_builder.h"
|
||||
|
||||
namespace tint {
|
||||
namespace transform {
|
||||
@@ -28,12 +29,6 @@ Transform::Output::Output(Program&& p) : program(std::move(p)) {}
|
||||
Transform::Output::Output(Program&& p, diag::List&& d)
|
||||
: program(std::move(p)), diagnostics(std::move(d)) {}
|
||||
|
||||
Transform::Output::~Output() = default;
|
||||
|
||||
Transform::Output::Output(Output&&) = default;
|
||||
|
||||
Transform::Output& Transform::Output::operator=(Output&& rhs) = default;
|
||||
|
||||
Transform::Transform() = default;
|
||||
|
||||
Transform::~Transform() = default;
|
||||
|
||||
@@ -47,18 +47,6 @@ class Transform {
|
||||
/// @param diags the list of diagnostics to move into this Output
|
||||
Output(Program&& program, diag::List&& diags);
|
||||
|
||||
/// Move constructor
|
||||
/// @param output the output to move into this Output
|
||||
Output(Output&& output);
|
||||
|
||||
/// Destructor
|
||||
~Output();
|
||||
|
||||
/// Move assignment operator
|
||||
/// @param rhs the Output to move into this Output
|
||||
/// @returns this Output
|
||||
Output& operator=(Output&& rhs);
|
||||
|
||||
/// The transformed program. May be empty on error.
|
||||
Program program;
|
||||
/// Diagnostics raised while running the Transform.
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#include "src/ast/variable.h"
|
||||
#include "src/ast/variable_decl_statement.h"
|
||||
#include "src/clone_context.h"
|
||||
#include "src/program.h"
|
||||
#include "src/program_builder.h"
|
||||
#include "src/type/array_type.h"
|
||||
#include "src/type/f32_type.h"
|
||||
#include "src/type/i32_type.h"
|
||||
@@ -101,9 +103,9 @@ Transform::Output VertexPulling::Run(const Program* in) {
|
||||
|
||||
// TODO(idanr): Make sure we covered all error cases, to guarantee the
|
||||
// following stages will pass
|
||||
Output out;
|
||||
ProgramBuilder out;
|
||||
|
||||
CloneContext ctx(&out.program, in);
|
||||
CloneContext ctx(&out, in);
|
||||
State state{ctx, cfg};
|
||||
state.FindOrInsertVertexIndexIfUsed();
|
||||
state.FindOrInsertInstanceIndexIfUsed();
|
||||
@@ -122,7 +124,7 @@ Transform::Output VertexPulling::Run(const Program* in) {
|
||||
});
|
||||
ctx.Clone();
|
||||
|
||||
return out;
|
||||
return Output(Program(std::move(out)));
|
||||
}
|
||||
|
||||
VertexPulling::Config::Config() = default;
|
||||
|
||||
Reference in New Issue
Block a user