transform: Add a debug flag to dump WGSL

Before and after each transform of a transform::Manager.

This change makes the transforms use the Castable system so we can get the transform name.

Change-Id: I2cf9335960f1aca56f1d32c5ba0d104db4cc46c1
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/54581
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
Ben Clayton 2021-07-15 20:24:38 +00:00 committed by Tint LUCI CQ
parent aa5686acc3
commit 4511a2ebb6
5 changed files with 73 additions and 5 deletions

View File

@ -773,6 +773,16 @@ int main(int argc, const char** argv) {
tint::SetInternalCompilerErrorReporter(&TintInternalCompilerErrorReporter); tint::SetInternalCompilerErrorReporter(&TintInternalCompilerErrorReporter);
#if TINT_BUILD_WGSL_WRITER
tint::Program::printer = [](const tint::Program* program) {
auto result = tint::writer::wgsl::Generate(program, {});
if (!result.error.empty()) {
return "error: " + result.error;
}
return result.wgsl;
};
#endif // TINT_BUILD_WGSL_WRITER
if (!ParseArgs(args, &options)) { if (!ParseArgs(args, &options)) {
std::cerr << "Failed to parse arguments." << std::endl; std::cerr << "Failed to parse arguments." << std::endl;
return 1; return 1;

View File

@ -21,6 +21,15 @@
#include "src/sem/expression.h" #include "src/sem/expression.h"
namespace tint { namespace tint {
namespace {
std::string DefaultPrinter(const Program*) {
return "<no program printer assigned>";
}
} // namespace
Program::Printer Program::printer = DefaultPrinter;
Program::Program() = default; Program::Program() = default;

View File

@ -186,6 +186,12 @@ class Program {
/// @returns a string representation of the node /// @returns a string representation of the node
std::string str(const ast::Node* node) const; std::string str(const ast::Node* node) const;
/// A function that can be used to print a program
using Printer = std::string (*)(const Program*);
/// The Program printer used for testing and debugging.
static Printer printer;
private: private:
Program(const Program&) = delete; Program(const Program&) = delete;

View File

@ -13,9 +13,9 @@
// limitations under the License. // limitations under the License.
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "src/program.h"
#include "src/reader/spirv/parser_impl_test_helper.h" #include "src/reader/spirv/parser_impl_test_helper.h"
#include "src/writer/hlsl/test_helper.h" #include "src/writer/wgsl/generator.h"
#include "src/writer/msl/test_helper.h"
namespace { namespace {
@ -48,6 +48,16 @@ struct Flags {
int main(int argc, char** argv) { int main(int argc, char** argv) {
testing::InitGoogleMock(&argc, argv); testing::InitGoogleMock(&argc, argv);
#if TINT_BUILD_WGSL_WRITER
tint::Program::printer = [](const tint::Program* program) {
auto result = tint::writer::wgsl::Generate(program, {});
if (!result.error.empty()) {
return "error: " + result.error;
}
return result.wgsl;
};
#endif // TINT_BUILD_WGSL_WRITER
Flags flags; Flags flags;
if (!flags.parse(argc, argv)) { if (!flags.parse(argc, argv)) {
return -1; return -1;

View File

@ -14,6 +14,16 @@
#include "src/transform/manager.h" #include "src/transform/manager.h"
/// If set to 1 then the transform::Manager will dump the WGSL of the program
/// before and after each transform. Helpful for debugging bad output.
#define PRINT_PROGRAM_FOR_EACH_TRANSFORM 0
#if PRINT_PROGRAM_FOR_EACH_TRANSFORM
#define IF_PRINT_PROGRAM(x) x
#else // PRINT_PROGRAM_FOR_EACH_TRANSFORM
#define IF_PRINT_PROGRAM(x)
#endif // PRINT_PROGRAM_FOR_EACH_TRANSFORM
TINT_INSTANTIATE_TYPEINFO(tint::transform::Manager); TINT_INSTANTIATE_TYPEINFO(tint::transform::Manager);
namespace tint { namespace tint {
@ -23,16 +33,39 @@ Manager::Manager() = default;
Manager::~Manager() = default; Manager::~Manager() = default;
Output Manager::Run(const Program* program, const DataMap& data) { Output Manager::Run(const Program* program, const DataMap& data) {
#if PRINT_PROGRAM_FOR_EACH_TRANSFORM
auto print_program = [&](const char* msg, const Transform* transform) {
auto wgsl = Program::printer(program);
std::cout << "---------------------------------------------------------"
<< std::endl;
std::cout << "-- " << msg << " " << transform->TypeInfo().name << ":"
<< std::endl;
std::cout << "---------------------------------------------------------"
<< std::endl;
std::cout << wgsl << std::endl;
std::cout << "---------------------------------------------------------"
<< std::endl
<< std::endl;
};
#endif
Output out; Output out;
if (!transforms_.empty()) { if (!transforms_.empty()) {
for (auto& transform : transforms_) { for (const auto& transform : transforms_) {
IF_PRINT_PROGRAM(print_program("Input to", transform.get()));
auto res = transform->Run(program, data); auto res = transform->Run(program, data);
out.program = std::move(res.program); out.program = std::move(res.program);
out.data.Add(std::move(res.data)); out.data.Add(std::move(res.data));
if (!out.program.IsValid()) { program = &out.program;
if (!program->IsValid()) {
IF_PRINT_PROGRAM(print_program("Invalid output of", transform.get()));
return out; return out;
} }
program = &out.program;
if (transform == transforms_.back()) {
IF_PRINT_PROGRAM(print_program("Output of", transform.get()));
}
} }
} else { } else {
out.program = program->Clone(); out.program = program->Clone();