hlsl ast fuzzer: validate hlsl with dxc
Bug: tint:2234
Change-Id: I571b227db8b4c1d35e66aa2b44d6d02656a1c83b
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/186560
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/cmd/fuzz/wgsl/fuzz.h b/src/tint/cmd/fuzz/wgsl/fuzz.h
index 4533e5a..d128695 100644
--- a/src/tint/cmd/fuzz/wgsl/fuzz.h
+++ b/src/tint/cmd/fuzz/wgsl/fuzz.h
@@ -48,6 +48,9 @@
bool run_concurrently = false;
/// If true, print the fuzzer name to stdout before running.
bool verbose = false;
+ /// If not empty, load DXC from this path when fuzzing HLSL generation, and fail the fuzzer if
+ /// not found, or if DXC fails to compile.
+ std::string dxc;
};
/// ProgramFuzzer describes a fuzzer function that takes a WGSL program as input
diff --git a/src/tint/cmd/fuzz/wgsl/main_fuzz.cc b/src/tint/cmd/fuzz/wgsl/main_fuzz.cc
index 2608906..06489f1 100644
--- a/src/tint/cmd/fuzz/wgsl/main_fuzz.cc
+++ b/src/tint/cmd/fuzz/wgsl/main_fuzz.cc
@@ -26,6 +26,8 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <iostream>
+#include <string>
+#include <unordered_map>
#include "src/tint/cmd/fuzz/wgsl/fuzz.h"
#include "src/tint/utils/cli/cli.h"
@@ -76,6 +78,7 @@
opts.Add<tint::cli::BoolOption>("concurrent", "runs the fuzzers concurrently");
auto& opt_verbose =
opts.Add<tint::cli::BoolOption>("verbose", "prints the name of each fuzzer before running");
+ auto& opt_dxc = opts.Add<tint::cli::StringOption>("dxc", "path to DXC DLL");
tint::cli::ParseOptions parse_opts;
parse_opts.ignore_unknown = true;
@@ -93,5 +96,6 @@
options.filter = opt_filter.value.value_or("");
options.run_concurrently = opt_concurrent.value.value_or(false);
options.verbose = opt_verbose.value.value_or(false);
+ options.dxc = opt_dxc.value.value_or("");
return 0;
}
diff --git a/src/tint/lang/hlsl/writer/BUILD.cmake b/src/tint/lang/hlsl/writer/BUILD.cmake
index a40f368..67af1a7 100644
--- a/src/tint/lang/hlsl/writer/BUILD.cmake
+++ b/src/tint/lang/hlsl/writer/BUILD.cmake
@@ -159,6 +159,7 @@
tint_lang_wgsl_program
tint_lang_wgsl_sem
tint_utils_bytes
+ tint_utils_command
tint_utils_containers
tint_utils_diagnostic
tint_utils_ice
@@ -176,6 +177,7 @@
if(TINT_BUILD_HLSL_WRITER)
tint_target_add_dependencies(tint_lang_hlsl_writer_fuzz fuzz
+ tint_lang_hlsl_validate
tint_lang_hlsl_writer
)
endif(TINT_BUILD_HLSL_WRITER)
diff --git a/src/tint/lang/hlsl/writer/BUILD.gn b/src/tint/lang/hlsl/writer/BUILD.gn
index 4c8f704..2111f1c 100644
--- a/src/tint/lang/hlsl/writer/BUILD.gn
+++ b/src/tint/lang/hlsl/writer/BUILD.gn
@@ -140,6 +140,7 @@
"${tint_src_dir}/lang/wgsl/program",
"${tint_src_dir}/lang/wgsl/sem",
"${tint_src_dir}/utils/bytes",
+ "${tint_src_dir}/utils/command",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
"${tint_src_dir}/utils/ice",
@@ -156,7 +157,10 @@
]
if (tint_build_hlsl_writer) {
- deps += [ "${tint_src_dir}/lang/hlsl/writer" ]
+ deps += [
+ "${tint_src_dir}/lang/hlsl/validate",
+ "${tint_src_dir}/lang/hlsl/writer",
+ ]
}
if (tint_build_wgsl_reader) {
diff --git a/src/tint/lang/hlsl/writer/writer_ast_fuzz.cc b/src/tint/lang/hlsl/writer/writer_ast_fuzz.cc
index a2865f9..12497e6 100644
--- a/src/tint/lang/hlsl/writer/writer_ast_fuzz.cc
+++ b/src/tint/lang/hlsl/writer/writer_ast_fuzz.cc
@@ -27,19 +27,58 @@
// GEN_BUILD:CONDITION(tint_build_wgsl_reader)
+#include <string>
+#include <unordered_map>
+
#include "src/tint/cmd/fuzz/wgsl/fuzz.h"
+#include "src/tint/lang/hlsl/validate/validate.h"
#include "src/tint/lang/hlsl/writer/writer.h"
#include "src/tint/lang/wgsl/ast/module.h"
+#include "src/tint/utils/command/command.h"
namespace tint::hlsl::writer {
namespace {
-void ASTFuzzer(const tint::Program& program, Options options) {
+void ASTFuzzer(const tint::Program& program,
+ const fuzz::wgsl::Options& fuzz_options,
+ Options options) {
if (program.AST().HasOverrides()) {
return;
}
- [[maybe_unused]] auto res = tint::hlsl::writer::Generate(program, options);
+ auto res = tint::hlsl::writer::Generate(program, options);
+ if (res == Success) {
+ const char* dxc_path = validate::kDxcDLLName;
+ bool must_validate = false;
+ if (!fuzz_options.dxc.empty()) {
+ must_validate = true;
+ dxc_path = fuzz_options.dxc.c_str();
+ }
+
+ auto dxc = tint::Command::LookPath(dxc_path);
+ if (dxc.Found()) {
+ uint32_t hlsl_shader_model = 60;
+ bool require_16bit_types = false;
+ auto enable_list = program.AST().Enables();
+ for (auto* enable : enable_list) {
+ if (enable->HasExtension(tint::wgsl::Extension::kF16)) {
+ hlsl_shader_model = 62;
+ require_16bit_types = true;
+ break;
+ }
+ }
+
+ auto validate_res = validate::ValidateUsingDXC(dxc.Path(), res->hlsl, res->entry_points,
+ require_16bit_types, hlsl_shader_model);
+
+ if (must_validate && validate_res.failed) {
+ TINT_ICE() << "DXC was expected to succeed, but failed: " << validate_res.output;
+ }
+
+ } else if (must_validate) {
+ TINT_ICE() << "DXC path was explicitly specified, but was not found: " << dxc_path;
+ }
+ }
}
} // namespace