sample: add a --fxc option to validate HLSL with FXC
Change-Id: I39d684a71d9f985a1f30b871f08f51bdf50f17a1 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/56064 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
parent
1b1d963d7b
commit
3cbbeaf1db
|
@ -65,6 +65,7 @@ struct Options {
|
||||||
|
|
||||||
std::vector<std::string> transforms;
|
std::vector<std::string> transforms;
|
||||||
|
|
||||||
|
bool use_fxc = false;
|
||||||
std::string dxc_path;
|
std::string dxc_path;
|
||||||
std::string xcrun_path;
|
std::string xcrun_path;
|
||||||
};
|
};
|
||||||
|
@ -95,8 +96,9 @@ const char kUsage[] = R"(Usage: tint [options] <input-file>
|
||||||
Affects AST dumping, and text-based output languages.
|
Affects AST dumping, and text-based output languages.
|
||||||
--dump-inspector-bindings -- Dump reflection data about bindins to stdout.
|
--dump-inspector-bindings -- Dump reflection data about bindins to stdout.
|
||||||
-h -- This help text
|
-h -- This help text
|
||||||
--validate -- Validates generated SPIR-V with spirv-val.
|
--validate -- Validates the generated shader
|
||||||
Has no effect on non-SPIRV outputs.
|
--fxc -- Ask to validate HLSL output using FXC instead of DXC.
|
||||||
|
When specified, automatically enables --validate
|
||||||
--dxc -- Path to DXC executable, used to validate HLSL output.
|
--dxc -- Path to DXC executable, used to validate HLSL output.
|
||||||
When specified, automatically enables --validate
|
When specified, automatically enables --validate
|
||||||
--xcrun -- Path to xcrun executable, used to validate MSL output.
|
--xcrun -- Path to xcrun executable, used to validate MSL output.
|
||||||
|
@ -404,6 +406,9 @@ bool ParseArgs(const std::vector<std::string>& args, Options* opts) {
|
||||||
opts->dump_inspector_bindings = true;
|
opts->dump_inspector_bindings = true;
|
||||||
} else if (arg == "--validate") {
|
} else if (arg == "--validate") {
|
||||||
opts->validate = true;
|
opts->validate = true;
|
||||||
|
} else if (arg == "--fxc") {
|
||||||
|
opts->validate = true;
|
||||||
|
opts->use_fxc = true;
|
||||||
} else if (arg == "--dxc") {
|
} else if (arg == "--dxc") {
|
||||||
++i;
|
++i;
|
||||||
if (i >= args.size()) {
|
if (i >= args.size()) {
|
||||||
|
@ -872,20 +877,31 @@ int main(int argc, const char** argv) {
|
||||||
#endif
|
#endif
|
||||||
#if TINT_BUILD_HLSL_WRITER
|
#if TINT_BUILD_HLSL_WRITER
|
||||||
case Format::kHlsl: {
|
case Format::kHlsl: {
|
||||||
auto dxc = tint::utils::Command::LookPath(
|
auto* w = static_cast<tint::writer::Text*>(writer.get());
|
||||||
options.dxc_path.empty() ? "dxc" : options.dxc_path);
|
auto hlsl = w->result();
|
||||||
if (dxc.Found()) {
|
|
||||||
auto* w = static_cast<tint::writer::Text*>(writer.get());
|
tint::val::Result res;
|
||||||
auto hlsl = w->result();
|
if (options.use_fxc) {
|
||||||
auto res = tint::val::Hlsl(dxc.Path(), hlsl, program.get());
|
#ifdef _WIN32
|
||||||
if (res.failed) {
|
res = tint::val::HlslUsingFXC(hlsl, program.get());
|
||||||
validation_failed = true;
|
#else
|
||||||
validation_msgs << res.source << std::endl;
|
res.failed = true;
|
||||||
validation_msgs << res.output;
|
res.output = "FXC can only be used on Windows. Sorry :X";
|
||||||
}
|
#endif // _WIN32
|
||||||
} else {
|
} else {
|
||||||
|
auto dxc = tint::utils::Command::LookPath(
|
||||||
|
options.dxc_path.empty() ? "dxc" : options.dxc_path);
|
||||||
|
if (dxc.Found()) {
|
||||||
|
res = tint::val::HlslUsingDXC(dxc.Path(), hlsl, program.get());
|
||||||
|
} else {
|
||||||
|
res.failed = true;
|
||||||
|
res.output = "DXC executable not found. Cannot validate";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (res.failed) {
|
||||||
validation_failed = true;
|
validation_failed = true;
|
||||||
validation_msgs << "DXC executable not found. Cannot validate";
|
validation_msgs << res.source << std::endl;
|
||||||
|
validation_msgs << res.output;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,21 @@
|
||||||
#include "src/utils/io/command.h"
|
#include "src/utils/io/command.h"
|
||||||
#include "src/utils/io/tmpfile.h"
|
#include "src/utils/io/tmpfile.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <d3dcommon.h>
|
||||||
|
#include <d3dcompiler.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <wrl.h>
|
||||||
|
using Microsoft::WRL::ComPtr;
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
namespace val {
|
namespace val {
|
||||||
|
|
||||||
Result Hlsl(const std::string& dxc_path,
|
Result HlslUsingDXC(const std::string& dxc_path,
|
||||||
const std::string& source,
|
const std::string& source,
|
||||||
Program* program) {
|
Program* program) {
|
||||||
Result result;
|
Result result;
|
||||||
|
|
||||||
auto dxc = utils::Command(dxc_path);
|
auto dxc = utils::Command(dxc_path);
|
||||||
|
@ -89,5 +98,77 @@ Result Hlsl(const std::string& dxc_path,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
Result HlslUsingFXC(const std::string& source, Program* program) {
|
||||||
|
Result result;
|
||||||
|
|
||||||
|
// This library leaks if an error happens in this function, but it is ok
|
||||||
|
// because it is loaded at most once, and the executables using HlslUsingFXC
|
||||||
|
// are short-lived.
|
||||||
|
HMODULE fxcLib = LoadLibraryA("d3dcompiler_47.dll");
|
||||||
|
if (fxcLib == nullptr) {
|
||||||
|
result.output = "Couldn't load FXC";
|
||||||
|
result.failed = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
pD3DCompile d3dCompile =
|
||||||
|
reinterpret_cast<pD3DCompile>(GetProcAddress(fxcLib, "D3DCompile"));
|
||||||
|
if (d3dCompile == nullptr) {
|
||||||
|
result.output = "Couldn't load D3DCompile from FXC";
|
||||||
|
result.failed = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.source = source;
|
||||||
|
|
||||||
|
bool found_an_entrypoint = false;
|
||||||
|
for (auto* func : program->AST().Functions()) {
|
||||||
|
if (func->IsEntryPoint()) {
|
||||||
|
found_an_entrypoint = true;
|
||||||
|
|
||||||
|
const char* profile = "";
|
||||||
|
switch (func->pipeline_stage()) {
|
||||||
|
case ast::PipelineStage::kNone:
|
||||||
|
result.output = "Invalid PipelineStage";
|
||||||
|
result.failed = true;
|
||||||
|
return result;
|
||||||
|
case ast::PipelineStage::kVertex:
|
||||||
|
profile = "vs_5_1";
|
||||||
|
break;
|
||||||
|
case ast::PipelineStage::kFragment:
|
||||||
|
profile = "ps_5_1";
|
||||||
|
break;
|
||||||
|
case ast::PipelineStage::kCompute:
|
||||||
|
profile = "cs_5_1";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto name = program->Symbols().NameFor(func->symbol());
|
||||||
|
|
||||||
|
ComPtr<ID3DBlob> compiledShader;
|
||||||
|
ComPtr<ID3DBlob> errors;
|
||||||
|
if (FAILED(d3dCompile(source.c_str(), source.length(), nullptr, nullptr,
|
||||||
|
nullptr, name.c_str(), profile, 0, 0,
|
||||||
|
&compiledShader, &errors))) {
|
||||||
|
result.output = static_cast<char*>(errors->GetBufferPointer());
|
||||||
|
result.failed = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeLibrary(fxcLib);
|
||||||
|
|
||||||
|
if (!found_an_entrypoint) {
|
||||||
|
result.output = "No entrypoint found";
|
||||||
|
result.failed = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
} // namespace val
|
} // namespace val
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -41,9 +41,18 @@ struct Result {
|
||||||
/// @param source the generated HLSL source
|
/// @param source the generated HLSL source
|
||||||
/// @param program the HLSL program
|
/// @param program the HLSL program
|
||||||
/// @return the result of the compile
|
/// @return the result of the compile
|
||||||
Result Hlsl(const std::string& dxc_path,
|
Result HlslUsingDXC(const std::string& dxc_path,
|
||||||
const std::string& source,
|
const std::string& source,
|
||||||
Program* program);
|
Program* program);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
/// Hlsl attempts to compile the shader with FXC, verifying that the shader
|
||||||
|
/// compiles successfully.
|
||||||
|
/// @param source the generated HLSL source
|
||||||
|
/// @param program the HLSL program
|
||||||
|
/// @return the result of the compile
|
||||||
|
Result HlslUsingFXC(const std::string& source, Program* program);
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
/// Msl attempts to compile the shader with the Metal Shader Compiler,
|
/// Msl attempts to compile the shader with the Metal Shader Compiler,
|
||||||
/// verifying that the shader compiles successfully.
|
/// verifying that the shader compiles successfully.
|
||||||
|
|
Loading…
Reference in New Issue