Add tint_unittest flags for enabling DXC validation
HLSL validation will be disabled by default, and is now opt-in with --validate-hlsl and/or with a --dxc-path Change-Id: Ia98d7b1fbba50168bbe85c7982b73598100016d7 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/42024 Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
4c4ceeea9d
commit
53d057c572
|
@ -15,6 +15,8 @@
|
||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "src/debug.h"
|
#include "src/debug.h"
|
||||||
|
#include "src/utils/command.h"
|
||||||
|
#include "src/writer/hlsl/test_helper.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -22,12 +24,75 @@ void TintInternalCompilerErrorReporter(const tint::diag::List& diagnostics) {
|
||||||
FAIL() << diagnostics.str();
|
FAIL() << diagnostics.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Flags {
|
||||||
|
bool validate_hlsl = false;
|
||||||
|
std::string dxc_path;
|
||||||
|
|
||||||
|
bool parse(int argc, char** argv) {
|
||||||
|
bool errored = false;
|
||||||
|
for (int i = 1; i < argc && !errored; i++) {
|
||||||
|
auto match = [&](std::string name) { return name == argv[i]; };
|
||||||
|
|
||||||
|
auto parse_value = [&](std::string name, std::string& value) {
|
||||||
|
if (!match(name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (i + 1 >= argc) {
|
||||||
|
std::cout << "Expected value for flag " << name << "" << std::endl;
|
||||||
|
errored = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
value = argv[i];
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (match("--validate-hlsl") || parse_value("--dxc-path", dxc_path)) {
|
||||||
|
validate_hlsl = true;
|
||||||
|
} else {
|
||||||
|
std::cout << "Unknown flag '" << argv[i] << "'" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// Entry point for tint unit tests
|
// Entry point for tint unit tests
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
testing::InitGoogleMock(&argc, argv);
|
testing::InitGoogleMock(&argc, argv);
|
||||||
|
|
||||||
|
Flags flags;
|
||||||
|
if (!flags.parse(argc, argv)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if TINT_BUILD_HLSL_WRITER
|
||||||
|
// This must be kept alive for the duration of RUN_ALL_TESTS() as the c_str()
|
||||||
|
// is passed into tint::writer::hlsl::EnableHLSLValidation(), which does not
|
||||||
|
// make a copy. This is to work around Chromium's strict rules on globals
|
||||||
|
// having no constructors / destructors.
|
||||||
|
std::string dxc_path;
|
||||||
|
if (flags.validate_hlsl) {
|
||||||
|
auto dxc = flags.dxc_path.empty() ? tint::utils::Command::LookPath("dxc")
|
||||||
|
: tint::utils::Command(flags.dxc_path);
|
||||||
|
|
||||||
|
if (!dxc.Found()) {
|
||||||
|
std::cout << "DXC executable not found" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "HLSL validation with DXC enabled" << std::endl;
|
||||||
|
|
||||||
|
dxc_path = dxc.Path();
|
||||||
|
tint::writer::hlsl::EnableHLSLValidation(dxc_path.c_str());
|
||||||
|
} else {
|
||||||
|
std::cout << "HLSL validation with DXC is not enabled" << std::endl;
|
||||||
|
}
|
||||||
|
#endif // TINT_BUILD_HLSL_WRITER
|
||||||
|
|
||||||
tint::SetInternalCompilerErrorReporter(&TintInternalCompilerErrorReporter);
|
tint::SetInternalCompilerErrorReporter(&TintInternalCompilerErrorReporter);
|
||||||
|
|
||||||
auto res = RUN_ALL_TESTS();
|
auto res = RUN_ALL_TESTS();
|
||||||
|
|
|
@ -52,6 +52,9 @@ class Command {
|
||||||
/// constructor
|
/// constructor
|
||||||
bool Found() const;
|
bool Found() const;
|
||||||
|
|
||||||
|
/// @returns the path of the command
|
||||||
|
const std::string& Path() const { return path_; }
|
||||||
|
|
||||||
/// Invokes the command with the given argument strings, blocking until the
|
/// Invokes the command with the given argument strings, blocking until the
|
||||||
/// process has returned.
|
/// process has returned.
|
||||||
/// @param args the string arguments to pass to the process
|
/// @param args the string arguments to pass to the process
|
||||||
|
|
|
@ -21,12 +21,28 @@ namespace tint {
|
||||||
namespace writer {
|
namespace writer {
|
||||||
namespace hlsl {
|
namespace hlsl {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const char* dxc_path = nullptr;
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void EnableHLSLValidation(const char* dxc) {
|
||||||
|
dxc_path = dxc;
|
||||||
|
}
|
||||||
|
|
||||||
CompileResult Compile(Program* program, GeneratorImpl* generator) {
|
CompileResult Compile(Program* program, GeneratorImpl* generator) {
|
||||||
CompileResult result;
|
CompileResult result;
|
||||||
|
|
||||||
auto dxc = utils::Command::LookPath("dxc");
|
if (!dxc_path) {
|
||||||
|
result.status = CompileResult::Status::kVerificationNotEnabled;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dxc = utils::Command(dxc_path);
|
||||||
if (!dxc.Found()) {
|
if (!dxc.Found()) {
|
||||||
result.status = CompileResult::Status::kDXCNotFound;
|
result.output = "DXC not found at '" + std::string(dxc_path) + "'";
|
||||||
|
result.status = CompileResult::Status::kFailed;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,10 +31,15 @@ namespace tint {
|
||||||
namespace writer {
|
namespace writer {
|
||||||
namespace hlsl {
|
namespace hlsl {
|
||||||
|
|
||||||
|
/// EnableHLSLValidation enables verification of HLSL shaders by running DXC and
|
||||||
|
/// checking no errors are reported.
|
||||||
|
/// @param dxc_path the path to the DXC executable
|
||||||
|
void EnableHLSLValidation(const char* dxc_path);
|
||||||
|
|
||||||
/// The return structure of Compile()
|
/// The return structure of Compile()
|
||||||
struct CompileResult {
|
struct CompileResult {
|
||||||
/// Status is an enumerator of status codes from Compile()
|
/// Status is an enumerator of status codes from Compile()
|
||||||
enum class Status { kSuccess, kFailed, kDXCNotFound };
|
enum class Status { kSuccess, kFailed, kVerificationNotEnabled };
|
||||||
/// The resulting status of the compile
|
/// The resulting status of the compile
|
||||||
Status status;
|
Status status;
|
||||||
/// Output of DXC.
|
/// Output of DXC.
|
||||||
|
|
Loading…
Reference in New Issue