tint/writer/spirv: Add path for generating from IR
This adds a GeneratorImplIr class and an option to the SPIR-V writer to use it instead of the AST-based GeneratorImpl class. The Tint exe now has a --use-ir flag which will use this path. Bug: tint:1906 Change-Id: I34cc5c7468c8faf4a808669da8c44551ad01da8f Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/131341 Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: James Price <jrprice@google.com> Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
1164fe7475
commit
8f9ea96c20
|
@ -974,6 +974,17 @@ libtint_source_set("libtint_spv_writer_src") {
|
|||
":libtint_utils_src",
|
||||
":libtint_writer_src",
|
||||
]
|
||||
|
||||
if (tint_build_ir) {
|
||||
sources += [
|
||||
"writer/spirv/generator_impl_ir.cc",
|
||||
"writer/spirv/generator_impl_ir.h",
|
||||
]
|
||||
deps += [
|
||||
":libtint_ir_builder_src",
|
||||
":libtint_ir_src",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
libtint_source_set("libtint_wgsl_reader_src") {
|
||||
|
@ -1845,6 +1856,11 @@ if (tint_build_unittests) {
|
|||
":tint_unittests_ast_src",
|
||||
"${tint_spirv_tools_dir}/:spvtools",
|
||||
]
|
||||
|
||||
if (tint_build_ir) {
|
||||
sources += [ "writer/spirv/generator_impl_ir_test.cc" ]
|
||||
deps += [ ":libtint_ir_src" ]
|
||||
}
|
||||
}
|
||||
|
||||
tint_unittests_source_set("tint_unittests_wgsl_reader_src") {
|
||||
|
|
|
@ -650,6 +650,13 @@ if(${TINT_BUILD_SPV_WRITER})
|
|||
writer/spirv/operand.h
|
||||
writer/spirv/scalar_constant.h
|
||||
)
|
||||
|
||||
if(${TINT_BUILD_IR})
|
||||
list(APPEND TINT_LIB_SRCS
|
||||
writer/spirv/generator_impl_ir.cc
|
||||
writer/spirv/generator_impl_ir.h
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(${TINT_BUILD_WGSL_WRITER})
|
||||
|
@ -1217,6 +1224,12 @@ if(TINT_BUILD_TESTS)
|
|||
writer/spirv/spv_dump.h
|
||||
writer/spirv/test_helper.h
|
||||
)
|
||||
|
||||
if(${TINT_BUILD_IR})
|
||||
list(APPEND TINT_TEST_SRCS
|
||||
writer/spirv/generator_impl_ir_test.cc
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(${TINT_BUILD_WGSL_WRITER})
|
||||
|
|
|
@ -111,6 +111,7 @@ struct Options {
|
|||
#if TINT_BUILD_IR
|
||||
bool dump_ir = false;
|
||||
bool dump_ir_graph = false;
|
||||
bool use_ir = false;
|
||||
#endif // TINT_BUILD_IR
|
||||
|
||||
#if TINT_BUILD_SYNTAX_TREE_WRITER
|
||||
|
@ -388,6 +389,8 @@ bool ParseArgs(const std::vector<std::string>& args, Options* opts) {
|
|||
opts->dump_ir = true;
|
||||
} else if (arg == "--dump-ir-graph") {
|
||||
opts->dump_ir_graph = true;
|
||||
} else if (arg == "--use-ir") {
|
||||
opts->use_ir = true;
|
||||
#endif // TINT_BUILD_IR
|
||||
#if TINT_BUILD_SYNTAX_TREE_WRITER
|
||||
} else if (arg == "--dump-ast") {
|
||||
|
@ -548,6 +551,9 @@ bool GenerateSpirv(const tint::Program* program, const Options& options) {
|
|||
gen_options.disable_workgroup_init = options.disable_workgroup_init;
|
||||
gen_options.external_texture_options.bindings_map =
|
||||
tint::cmd::GenerateExternalTextureBindings(program);
|
||||
#if TINT_BUILD_IR
|
||||
gen_options.use_tint_ir = options.use_ir;
|
||||
#endif
|
||||
auto result = tint::writer::spirv::Generate(program, gen_options);
|
||||
if (!result.success) {
|
||||
tint::cmd::PrintWGSL(std::cerr, *program);
|
||||
|
@ -1023,7 +1029,8 @@ int main(int argc, const char** argv) {
|
|||
#if TINT_BUILD_IR
|
||||
usage +=
|
||||
" --dump-ir -- Writes the IR to stdout\n"
|
||||
" --dump-ir-graph -- Writes the IR graph to 'tint.dot' as a dot graph\n";
|
||||
" --dump-ir-graph -- Writes the IR graph to 'tint.dot' as a dot graph\n"
|
||||
" --use-ir -- Use the IR for writers and transforms when possible\n";
|
||||
#endif // TINT_BUILD_IR
|
||||
#if TINT_BUILD_SYNTAX_TREE_WRITER
|
||||
usage += " --dump-ast -- Writes the AST to stdout\n";
|
||||
|
|
|
@ -17,6 +17,10 @@
|
|||
#include <utility>
|
||||
|
||||
#include "src/tint/writer/spirv/generator_impl.h"
|
||||
#if TINT_BUILD_IR
|
||||
#include "src/tint/ir/converter.h" // nogncheck
|
||||
#include "src/tint/writer/spirv/generator_impl_ir.h" // nogncheck
|
||||
#endif // TINT_BUILD_IR
|
||||
|
||||
namespace tint::writer::spirv {
|
||||
|
||||
|
@ -31,23 +35,41 @@ Result Generate(const Program* program, const Options& options) {
|
|||
return result;
|
||||
}
|
||||
|
||||
// Sanitize the program.
|
||||
auto sanitized_result = Sanitize(program, options);
|
||||
if (!sanitized_result.program.IsValid()) {
|
||||
result.success = false;
|
||||
result.error = sanitized_result.program.Diagnostics().str();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Generate the SPIR-V code.
|
||||
bool zero_initialize_workgroup_memory =
|
||||
!options.disable_workgroup_init && options.use_zero_initialize_workgroup_memory_extension;
|
||||
|
||||
auto impl = std::make_unique<GeneratorImpl>(&sanitized_result.program,
|
||||
zero_initialize_workgroup_memory);
|
||||
result.success = impl->Generate();
|
||||
result.error = impl->Diagnostics().str();
|
||||
result.spirv = std::move(impl->Result());
|
||||
#if TINT_BUILD_IR
|
||||
if (options.use_tint_ir) {
|
||||
// Convert the AST program to an IR module.
|
||||
auto ir = ir::Converter::FromProgram(program);
|
||||
if (!ir) {
|
||||
result.error = "IR converter: " + ir.Failure();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Generate the SPIR-V code.
|
||||
auto impl = std::make_unique<GeneratorImplIr>(&ir.Get(), zero_initialize_workgroup_memory);
|
||||
result.success = impl->Generate();
|
||||
result.error = impl->Diagnostics().str();
|
||||
result.spirv = std::move(impl->Result());
|
||||
} else // NOLINT(readability/braces)
|
||||
#endif
|
||||
{
|
||||
// Sanitize the program.
|
||||
auto sanitized_result = Sanitize(program, options);
|
||||
if (!sanitized_result.program.IsValid()) {
|
||||
result.success = false;
|
||||
result.error = sanitized_result.program.Diagnostics().str();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Generate the SPIR-V code.
|
||||
auto impl = std::make_unique<GeneratorImpl>(&sanitized_result.program,
|
||||
zero_initialize_workgroup_memory);
|
||||
result.success = impl->Generate();
|
||||
result.error = impl->Diagnostics().str();
|
||||
result.spirv = std::move(impl->Result());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -60,6 +60,11 @@ struct Options {
|
|||
/// VK_KHR_zero_initialize_workgroup_memory is enabled.
|
||||
bool use_zero_initialize_workgroup_memory_extension = false;
|
||||
|
||||
#if TINT_BUILD_IR
|
||||
/// Set to `true` to generate SPIR-V via the Tint IR instead of from the AST.
|
||||
bool use_tint_ir = false;
|
||||
#endif
|
||||
|
||||
/// Reflect the fields of this class so that it can be used by tint::ForeachField()
|
||||
TINT_REFLECT(disable_robustness,
|
||||
emit_vertex_point_size,
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright 2023 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/tint/writer/spirv/generator_impl_ir.h"
|
||||
|
||||
#include "spirv/unified1/spirv.h"
|
||||
#include "src/tint/ir/module.h"
|
||||
#include "src/tint/writer/spirv/module.h"
|
||||
|
||||
namespace tint::writer::spirv {
|
||||
|
||||
GeneratorImplIr::GeneratorImplIr(const ir::Module* module, bool zero_init_workgroup_mem)
|
||||
: ir_(module), zero_init_workgroup_memory_(zero_init_workgroup_mem) {}
|
||||
|
||||
bool GeneratorImplIr::Generate() {
|
||||
// TODO(crbug.com/tint/1906): Check supported extensions.
|
||||
|
||||
module_.PushCapability(SpvCapabilityShader);
|
||||
module_.PushMemoryModel(spv::Op::OpMemoryModel, {U32Operand(SpvAddressingModelLogical),
|
||||
U32Operand(SpvMemoryModelGLSL450)});
|
||||
|
||||
// TODO(crbug.com/tint/1906): Emit extensions.
|
||||
|
||||
// TODO(crbug.com/tint/1906): Emit variables.
|
||||
(void)zero_init_workgroup_memory_;
|
||||
|
||||
// TODO(crbug.com/tint/1906): Emit functions.
|
||||
(void)ir_;
|
||||
|
||||
// Serialize the module into binary SPIR-V.
|
||||
writer_.WriteHeader(module_.IdBound());
|
||||
writer_.WriteModule(&module_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace tint::writer::spirv
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright 2023 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SRC_TINT_WRITER_SPIRV_GENERATOR_IMPL_IR_H_
|
||||
#define SRC_TINT_WRITER_SPIRV_GENERATOR_IMPL_IR_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "src/tint/diagnostic/diagnostic.h"
|
||||
#include "src/tint/writer/spirv/binary_writer.h"
|
||||
#include "src/tint/writer/spirv/module.h"
|
||||
|
||||
// Forward declarations
|
||||
namespace tint::ir {
|
||||
class Module;
|
||||
} // namespace tint::ir
|
||||
|
||||
namespace tint::writer::spirv {
|
||||
|
||||
/// Implementation class for SPIR-V generator
|
||||
class GeneratorImplIr {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param module the Tint IR module to generate
|
||||
/// @param zero_init_workgroup_memory `true` to initialize all the variables in the Workgroup
|
||||
/// storage class with OpConstantNull
|
||||
GeneratorImplIr(const ir::Module* module, bool zero_init_workgroup_memory);
|
||||
|
||||
/// @returns true on successful generation; false otherwise
|
||||
bool Generate();
|
||||
|
||||
/// @returns the module that this generator has produced
|
||||
spirv::Module& Module() { return module_; }
|
||||
|
||||
/// @returns the generated SPIR-V binary data
|
||||
const std::vector<uint32_t>& Result() const { return writer_.result(); }
|
||||
|
||||
/// @returns the list of diagnostics raised by the generator
|
||||
diag::List Diagnostics() const { return diagnostics_; }
|
||||
|
||||
private:
|
||||
const ir::Module* ir_;
|
||||
spirv::Module module_;
|
||||
BinaryWriter writer_;
|
||||
diag::List diagnostics_;
|
||||
|
||||
bool zero_init_workgroup_memory_ = false;
|
||||
};
|
||||
|
||||
} // namespace tint::writer::spirv
|
||||
|
||||
#endif // SRC_TINT_WRITER_SPIRV_GENERATOR_IMPL_IR_H_
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright 2023 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "src/tint/ir/module.h"
|
||||
#include "src/tint/writer/spirv/generator_impl_ir.h"
|
||||
#include "src/tint/writer/spirv/spv_dump.h"
|
||||
|
||||
namespace tint::writer::spirv {
|
||||
namespace {
|
||||
|
||||
using SpvGeneratorImplTest = testing::Test;
|
||||
|
||||
TEST_F(SpvGeneratorImplTest, ModuleHeader) {
|
||||
ir::Module module;
|
||||
GeneratorImplIr generator(&module, false);
|
||||
ASSERT_TRUE(generator.Generate()) << generator.Diagnostics().str();
|
||||
auto got = Disassemble(generator.Result());
|
||||
EXPECT_EQ(got, R"(OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
)");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::writer::spirv
|
|
@ -18,7 +18,6 @@
|
|||
#include "src/tint/writer/spirv/binary_writer.h"
|
||||
|
||||
namespace tint::writer::spirv {
|
||||
namespace {
|
||||
|
||||
std::string Disassemble(const std::vector<uint32_t>& data) {
|
||||
std::string spv_errors;
|
||||
|
@ -56,8 +55,6 @@ std::string Disassemble(const std::vector<uint32_t>& data) {
|
|||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string DumpBuilder(Builder& builder) {
|
||||
BinaryWriter writer;
|
||||
writer.WriteHeader(builder.Module().IdBound());
|
||||
|
|
|
@ -22,6 +22,11 @@
|
|||
|
||||
namespace tint::writer::spirv {
|
||||
|
||||
/// Disassembles SPIR-V binary data into its textual form.
|
||||
/// @param data the SPIR-V binary data
|
||||
/// @returns the disassembled SPIR-V string
|
||||
std::string Disassemble(const std::vector<uint32_t>& data);
|
||||
|
||||
/// Dumps the given builder to a SPIR-V disassembly string
|
||||
/// @param builder the builder to convert
|
||||
/// @returns the builder as a SPIR-V disassembly string
|
||||
|
|
Loading…
Reference in New Issue