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>
diff --git a/samples/main.cc b/samples/main.cc
index e44fbfa..dd7970f 100644
--- a/samples/main.cc
+++ b/samples/main.cc
@@ -773,6 +773,16 @@
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)) {
std::cerr << "Failed to parse arguments." << std::endl;
return 1;
diff --git a/src/program.cc b/src/program.cc
index 24d2a1f..5e72982 100644
--- a/src/program.cc
+++ b/src/program.cc
@@ -21,6 +21,15 @@
#include "src/sem/expression.h"
namespace tint {
+namespace {
+
+std::string DefaultPrinter(const Program*) {
+ return "<no program printer assigned>";
+}
+
+} // namespace
+
+Program::Printer Program::printer = DefaultPrinter;
Program::Program() = default;
diff --git a/src/program.h b/src/program.h
index 32534fa..d2ffe11 100644
--- a/src/program.h
+++ b/src/program.h
@@ -186,6 +186,12 @@
/// @returns a string representation of the node
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:
Program(const Program&) = delete;
diff --git a/src/test_main.cc b/src/test_main.cc
index c01a825..9b9823a 100644
--- a/src/test_main.cc
+++ b/src/test_main.cc
@@ -13,9 +13,9 @@
// limitations under the License.
#include "gmock/gmock.h"
+#include "src/program.h"
#include "src/reader/spirv/parser_impl_test_helper.h"
-#include "src/writer/hlsl/test_helper.h"
-#include "src/writer/msl/test_helper.h"
+#include "src/writer/wgsl/generator.h"
namespace {
@@ -48,6 +48,16 @@
int main(int argc, char** 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;
if (!flags.parse(argc, argv)) {
return -1;
diff --git a/src/transform/manager.cc b/src/transform/manager.cc
index 0c1a0f0..c974fbc 100644
--- a/src/transform/manager.cc
+++ b/src/transform/manager.cc
@@ -14,6 +14,16 @@
#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);
namespace tint {
@@ -23,16 +33,39 @@
Manager::~Manager() = default;
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;
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);
out.program = std::move(res.program);
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;
}
- program = &out.program;
+
+ if (transform == transforms_.back()) {
+ IF_PRINT_PROGRAM(print_program("Output of", transform.get()));
+ }
}
} else {
out.program = program->Clone();