tint_cmd: use DXC via shared library (dxcompiler) rather than executable (dxc)
Bug: tint:2234
Change-Id: I90386392f55970c19723365e707a8a43293e16ff
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/185902
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn
index f01ff5e..b1e1a64 100644
--- a/src/tint/BUILD.gn
+++ b/src/tint/BUILD.gn
@@ -252,6 +252,13 @@
libs = [ "ws2_32.lib" ]
}
+config("dxc-include-config") {
+ include_dirs = [ "${dawn_dxc_dir}/include" ]
+}
+source_set("dxc-include") {
+ public_configs = [ ":dxc-include-config" ]
+}
+
###############################################################################
# Fuzzers
###############################################################################
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt
index 235349c..6969216 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -501,6 +501,8 @@
target_link_libraries(${TARGET} PRIVATE
absl_strings
)
+ elseif(${DEPENDENCY} STREQUAL "dxc-include")
+ target_include_directories(${TARGET} PRIVATE "${DAWN_THIRD_PARTY_DIR}/dxc/include")
elseif(${DEPENDENCY} STREQUAL "jsoncpp")
target_link_libraries(${TARGET} PRIVATE jsoncpp_static)
elseif(${DEPENDENCY} STREQUAL "langsvr")
diff --git a/src/tint/cmd/tint/main.cc b/src/tint/cmd/tint/main.cc
index 24ef2fd..68a9d81 100644
--- a/src/tint/cmd/tint/main.cc
+++ b/src/tint/cmd/tint/main.cc
@@ -1009,8 +1009,9 @@
tint::hlsl::validate::Result dxc_res;
bool dxc_found = false;
if (options.validate || must_validate_dxc) {
- auto dxc = tint::Command::LookPath(
- options.dxc_path.empty() ? "dxc" : std::string(options.dxc_path));
+ auto dxc =
+ tint::Command::LookPath(options.dxc_path.empty() ? tint::hlsl::validate::kDxcDLLName
+ : std::string(options.dxc_path));
if (dxc.Found()) {
dxc_found = true;
@@ -1053,7 +1054,7 @@
fxc_res.output = "FXC DLL '" + options.fxc_path + "' not found. Cannot validate";
}
#else
- if (must_validate_dxc) {
+ if (must_validate_fxc) {
fxc_res.failed = true;
fxc_res.output = "FXC can only be used on Windows.";
}
diff --git a/src/tint/externals.json b/src/tint/externals.json
index dbdf96d..03048a5 100644
--- a/src/tint/externals.json
+++ b/src/tint/externals.json
@@ -6,7 +6,13 @@
"abseil": {
"IncludePatterns": [
"absl/**"
+ ]
+ },
+ "dxc-include": {
+ "IncludePatterns": [
+ "dxc/**"
],
+ "Condition": "tint_build_hlsl_writer"
},
"google-benchmark": {
"IncludePatterns": [
diff --git a/src/tint/lang/hlsl/validate/BUILD.bazel b/src/tint/lang/hlsl/validate/BUILD.bazel
index 512dfd0..e045855 100644
--- a/src/tint/lang/hlsl/validate/BUILD.bazel
+++ b/src/tint/lang/hlsl/validate/BUILD.bazel
@@ -56,7 +56,12 @@
"//src/tint/utils/rtti",
"//src/tint/utils/text",
"//src/tint/utils/traits",
- ],
+ ] + select({
+ ":tint_build_hlsl_writer": [
+
+ ],
+ "//conditions:default": [],
+ }),
copts = COPTS,
visibility = ["//visibility:public"],
)
diff --git a/src/tint/lang/hlsl/validate/BUILD.cmake b/src/tint/lang/hlsl/validate/BUILD.cmake
index a16018e..5aded7f 100644
--- a/src/tint/lang/hlsl/validate/BUILD.cmake
+++ b/src/tint/lang/hlsl/validate/BUILD.cmake
@@ -59,4 +59,10 @@
tint_utils_traits
)
+if(TINT_BUILD_HLSL_WRITER)
+ tint_target_add_external_dependencies(tint_lang_hlsl_validate lib
+ "dxc-include"
+ )
+endif(TINT_BUILD_HLSL_WRITER)
+
endif(TINT_BUILD_HLSL_WRITER)
\ No newline at end of file
diff --git a/src/tint/lang/hlsl/validate/BUILD.gn b/src/tint/lang/hlsl/validate/BUILD.gn
index 44d66c5..3143d42 100644
--- a/src/tint/lang/hlsl/validate/BUILD.gn
+++ b/src/tint/lang/hlsl/validate/BUILD.gn
@@ -56,5 +56,9 @@
"${tint_src_dir}/utils/text",
"${tint_src_dir}/utils/traits",
]
+
+ if (tint_build_hlsl_writer) {
+ deps += [ "${tint_src_dir}:dxc-include" ]
+ }
}
}
diff --git a/src/tint/lang/hlsl/validate/validate.cc b/src/tint/lang/hlsl/validate/validate.cc
index cfca843..027756f 100644
--- a/src/tint/lang/hlsl/validate/validate.cc
+++ b/src/tint/lang/hlsl/validate/validate.cc
@@ -31,17 +31,32 @@
#include "src/tint/utils/command/command.h"
#include "src/tint/utils/file/tmpfile.h"
+#include "src/tint/utils/macros/defer.h"
#include "src/tint/utils/text/string.h"
#ifdef _WIN32
#include <Windows.h>
+#include <atlbase.h>
#include <d3dcommon.h>
#include <d3dcompiler.h>
-
#include <wrl.h>
-using Microsoft::WRL::ComPtr;
+#else
+#include <dlfcn.h>
#endif // _WIN32
+// dxc headers
+TINT_BEGIN_DISABLE_ALL_WARNINGS();
+#ifdef __clang__
+// # Use UUID emulation with clang to avoid compiling with ms-extensions
+#define __EMULATE_UUID
+#endif
+#include "dxc/dxcapi.h"
+TINT_END_DISABLE_ALL_WARNINGS();
+
+// Disable warnings about old-style casts which result from using
+// the SUCCEEDED and FAILED macros that C-style cast to HRESULT.
+TINT_DISABLE_WARNING_OLD_STYLE_CAST
+
namespace tint::hlsl::validate {
Result ValidateUsingDXC(const std::string& dxc_path,
@@ -51,9 +66,8 @@
uint32_t hlsl_shader_model) {
Result result;
- auto dxc = tint::Command(dxc_path);
- if (!dxc.Found()) {
- result.output = "DXC not found at '" + std::string(dxc_path) + "'";
+ if (entry_points.empty()) {
+ result.output = "No entrypoint found";
result.failed = true;
return result;
}
@@ -70,64 +84,140 @@
result.failed = true;
return result;
}
- std::string shader_model_version =
- std::to_string(hlsl_shader_model / 10) + "_" + std::to_string(hlsl_shader_model % 10);
- tint::TmpFile file;
- file << source;
+#define CHECK_HR(hr, error_msg) \
+ do { \
+ if (FAILED(hr)) { \
+ result.output = error_msg; \
+ result.failed = true; \
+ return result; \
+ } \
+ } while (false)
+
+ HRESULT hr;
+
+ // Load the dll and get the DxcCreateInstance function
+ using PFN_DXC_CREATE_INSTANCE =
+ HRESULT(__stdcall*)(REFCLSID rclsid, REFIID riid, LPVOID * ppCompiler);
+ PFN_DXC_CREATE_INSTANCE dxc_create_instance = nullptr;
+#ifdef _WIN32
+ HMODULE dxcLib = LoadLibraryA(dxc_path.c_str());
+ if (dxcLib == nullptr) {
+ result.output = "Failed to load dxc: " + dxc_path;
+ result.failed = true;
+ return result;
+ }
+ // Avoid ASAN false positives when unloading DLL: https://github.com/google/sanitizers/issues/89
+#if !defined(TINT_ASAN_ENABLED)
+ TINT_DEFER({ FreeLibrary(dxcLib); });
+#endif
+
+ dxc_create_instance =
+ reinterpret_cast<PFN_DXC_CREATE_INSTANCE>(GetProcAddress(dxcLib, "DxcCreateInstance"));
+#else
+ void* dxcLib = dlopen(dxc_path.c_str(), RTLD_LAZY | RTLD_GLOBAL);
+ if (dxcLib == nullptr) {
+ result.output = "Failed to load dxc: " + dxc_path;
+ result.failed = true;
+ return result;
+ }
+ // Avoid ASAN false positives when unloading DLL: https://github.com/google/sanitizers/issues/89
+#if !defined(TINT_ASAN_ENABLED)
+ TINT_DEFER({ dlclose(dxcLib); });
+#endif
+
+ dxc_create_instance =
+ reinterpret_cast<PFN_DXC_CREATE_INSTANCE>(dlsym(dxcLib, "DxcCreateInstance"));
+#endif
+ if (dxc_create_instance == nullptr) {
+ result.output = "GetProcAccess failed";
+ result.failed = true;
+ return result;
+ }
+
+ CComPtr<IDxcCompiler3> dxc_compiler;
+ hr = dxc_create_instance(CLSID_DxcCompiler, IID_PPV_ARGS(&dxc_compiler));
+ CHECK_HR(hr, "DxcCreateInstance failed");
for (auto ep : entry_points) {
- const char* stage_prefix = "";
-
+ const wchar_t* stage_prefix = L"";
switch (ep.second) {
case ast::PipelineStage::kNone:
result.output = "Invalid PipelineStage";
result.failed = true;
return result;
case ast::PipelineStage::kVertex:
- stage_prefix = "vs";
+ stage_prefix = L"vs";
break;
case ast::PipelineStage::kFragment:
- stage_prefix = "ps";
+ stage_prefix = L"ps";
break;
case ast::PipelineStage::kCompute:
- stage_prefix = "cs";
+ stage_prefix = L"cs";
break;
}
// Match Dawn's compile flags
// See dawn\src\dawn_native\d3d12\RenderPipelineD3D12.cpp
// and dawn_native\d3d\ShaderUtils.cpp (GetDXCArguments)
- auto res =
- dxc("-T " + std::string(stage_prefix) + "_" + shader_model_version, // Profile
- "-HV 2018", // Use HLSL 2018
- "-E " + ep.first, // Entry point
- "/Zpr", // D3DCOMPILE_PACK_MATRIX_ROW_MAJOR
- "/Gis", // D3DCOMPILE_IEEE_STRICTNESS
- require_16bit_types ? "-enable-16bit-types" : "", // Enable 16-bit if required
- file.Path());
- if (!res.out.empty()) {
- if (!result.output.empty()) {
- result.output += "\n";
- }
- result.output += res.out;
- }
- if (!res.err.empty()) {
- if (!result.output.empty()) {
- result.output += "\n";
- }
- result.output += res.err;
- }
- result.failed = (res.error_code != 0);
+ std::wstring shader_model_version = std::to_wstring(hlsl_shader_model / 10) + L"_" +
+ std::to_wstring(hlsl_shader_model % 10);
+ std::wstring profile = std::wstring(stage_prefix) + L"_" + shader_model_version;
+ std::wstring entry_point = std::wstring(ep.first.begin(), ep.first.end());
+ std::vector<const wchar_t*> args{
+ L"-T", // Profile
+ profile.c_str(), //
+ L"-HV 2018", // Use HLSL 2018
+ L"-E", // Entry point
+ entry_point.c_str(), //
+ L"/Zpr", // D3DCOMPILE_PACK_MATRIX_ROW_MAJOR
+ L"/Gis", // D3DCOMPILE_IEEE_STRICTNESS
+ require_16bit_types ? L"-enable-16bit-types" : L"" // Enable 16-bit if required
+ };
- // Remove the temporary file name from the output to keep output deterministic
- result.output = tint::ReplaceAll(result.output, file.Path(), "shader.hlsl");
- }
+ DxcBuffer source_buffer;
+ source_buffer.Ptr = source.c_str();
+ source_buffer.Size = source.length();
+ source_buffer.Encoding = DXC_CP_UTF8;
+ CComPtr<IDxcResult> compile_result;
+ hr = dxc_compiler->Compile(&source_buffer, args.data(), static_cast<UINT32>(args.size()),
+ nullptr, IID_PPV_ARGS(&compile_result));
+ CHECK_HR(hr, "Compile call failed");
- if (entry_points.empty()) {
- result.output = "No entrypoint found";
- result.failed = true;
- return result;
+ HRESULT compile_status;
+ hr = compile_result->GetStatus(&compile_status);
+ CHECK_HR(hr, "GetStatus call failed");
+
+ if (FAILED(compile_status)) {
+ CComPtr<IDxcBlobEncoding> errors;
+ hr = compile_result->GetErrorBuffer(&errors);
+ CHECK_HR(hr, "GetErrorBuffer call failed");
+ result.output = static_cast<char*>(errors->GetBufferPointer());
+ result.failed = true;
+ return result;
+ }
+
+ // Compilation succeeded, get compiled shader blob and disassamble it
+ CComPtr<IDxcBlob> compiled_shader;
+ hr = compile_result->GetResult(&compiled_shader);
+ CHECK_HR(hr, "GetResult call failed");
+
+ DxcBuffer compiled_shader_buffer;
+ compiled_shader_buffer.Ptr = compiled_shader->GetBufferPointer();
+ compiled_shader_buffer.Size = compiled_shader->GetBufferSize();
+ compiled_shader_buffer.Encoding = DXC_CP_UTF8;
+ CComPtr<IDxcResult> dis_result;
+ hr = dxc_compiler->Disassemble(&compiled_shader_buffer, IID_PPV_ARGS(&dis_result));
+ CHECK_HR(hr, "Disassemble call failed");
+
+ CComPtr<IDxcBlobEncoding> disassembly;
+ if (dis_result && dis_result->HasOutput(DXC_OUT_DISASSEMBLY) &&
+ SUCCEEDED(
+ dis_result->GetOutput(DXC_OUT_DISASSEMBLY, IID_PPV_ARGS(&disassembly), nullptr))) {
+ result.output = static_cast<char*>(disassembly->GetBufferPointer());
+ } else {
+ result.output = "Failed to disassemble shader";
+ }
}
return result;
@@ -139,6 +229,12 @@
const EntryPointList& entry_points) {
Result result;
+ if (entry_points.empty()) {
+ result.output = "No entrypoint found";
+ result.failed = true;
+ return 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 UsingFXC
// are short-lived.
@@ -188,8 +284,8 @@
UINT compileFlags = D3DCOMPILE_OPTIMIZATION_LEVEL0 | D3DCOMPILE_PACK_MATRIX_ROW_MAJOR |
D3DCOMPILE_IEEE_STRICTNESS;
- ComPtr<ID3DBlob> compiledShader;
- ComPtr<ID3DBlob> errors;
+ CComPtr<ID3DBlob> compiledShader;
+ CComPtr<ID3DBlob> errors;
HRESULT res = d3dCompile(source.c_str(), // pSrcData
source.length(), // SrcDataSize
nullptr, // pSourceName
@@ -206,11 +302,11 @@
result.failed = true;
return result;
} else {
- ComPtr<ID3DBlob> disassembly;
+ CComPtr<ID3DBlob> disassembly;
res = d3dDisassemble(compiledShader->GetBufferPointer(),
compiledShader->GetBufferSize(), 0, "", &disassembly);
if (FAILED(res)) {
- result.output = "failed to disassemble shader";
+ result.output = "Failed to disassemble shader";
} else {
result.output = static_cast<char*>(disassembly->GetBufferPointer());
}
@@ -219,12 +315,6 @@
FreeLibrary(fxcLib);
- if (entry_points.empty()) {
- result.output = "No entrypoint found";
- result.failed = true;
- return result;
- }
-
return result;
}
#endif // _WIN32
diff --git a/src/tint/lang/hlsl/validate/validate.h b/src/tint/lang/hlsl/validate/validate.h
index 8efb4fb..67ce25e 100644
--- a/src/tint/lang/hlsl/validate/validate.h
+++ b/src/tint/lang/hlsl/validate/validate.h
@@ -46,6 +46,16 @@
/// Name of the FXC compiler DLL
static constexpr const char kFxcDLLName[] = "d3dcompiler_47.dll";
+#if TINT_BUILD_IS_WIN
+static constexpr const char* kDxcDLLName = "dxcompiler.dll";
+#elif TINT_BUILD_IS_LINUX
+static constexpr const char* kDxcDLLName = "libdxcompiler.so";
+#elif TINT_BUILD_IS_MAC
+static constexpr const char* kDxcDLLName = "libdxcompiler.dylib";
+#else
+static constexpr const char* kDxcDLLName = "Invalid";
+#endif
+
/// The return structure of Validate()
struct Result {
/// True if validation passed
diff --git a/src/tint/utils/macros/compiler.h b/src/tint/utils/macros/compiler.h
index a3de76f..ff60f3f0 100644
--- a/src/tint/utils/macros/compiler.h
+++ b/src/tint/utils/macros/compiler.h
@@ -54,6 +54,10 @@
#define TINT_DISABLE_WARNING_ZERO_AS_NULLPTR /* currently no-op */
#define TINT_DISABLE_WARNING_MISSING_DESTRUCTOR_OVERRIDE /* currently no-op */
+#define TINT_BEGIN_DISABLE_ALL_WARNINGS() __pragma(warning(push, 0)) TINT_REQUIRE_SEMICOLON
+
+#define TINT_END_DISABLE_ALL_WARNINGS() __pragma(warning(pop)) TINT_REQUIRE_SEMICOLON
+
// clang-format off
#define TINT_BEGIN_DISABLE_WARNING(name) \
__pragma(warning(push)) \
@@ -71,6 +75,10 @@
#define TINT_UNLIKELY(x) x /* currently no-op */
#define TINT_LIKELY(x) x /* currently no-op */
+#if defined(__SANITIZE_ADDRESS__)
+#define TINT_ASAN_ENABLED
+#endif
+
#elif defined(__clang__)
////////////////////////////////////////////////////////////////////////////////
// Clang
@@ -123,6 +131,15 @@
_Pragma("clang diagnostic pop") \
TINT_REQUIRE_SEMICOLON
+#define TINT_BEGIN_DISABLE_ALL_WARNINGS() \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Weverything\"") \
+ TINT_REQUIRE_SEMICOLON
+
+#define TINT_END_DISABLE_ALL_WARNINGS() \
+ _Pragma("clang diagnostic pop") \
+ TINT_REQUIRE_SEMICOLON
+
#define TINT_BEGIN_DISABLE_WARNING(name) \
_Pragma("clang diagnostic push") \
TINT_CONCAT(TINT_DISABLE_WARNING_, name) \
@@ -135,6 +152,11 @@
#define TINT_UNLIKELY(x) __builtin_expect(!!(x), false)
#define TINT_LIKELY(x) __builtin_expect(!!(x), true)
+
+#if __has_feature(address_sanitizer)
+#define TINT_ASAN_ENABLED
+#endif
+
#elif defined(__GNUC__)
////////////////////////////////////////////////////////////////////////////////
// GCC
@@ -163,6 +185,12 @@
_Pragma("GCC diagnostic push") TINT_DISABLE_WARNING_UNUSED_PARAMETER TINT_REQUIRE_SEMICOLON
#define TINT_END_DISABLE_PROTOBUF_WARNINGS() _Pragma("GCC diagnostic pop") TINT_REQUIRE_SEMICOLON
+#define TINT_BEGIN_DISABLE_ALL_WARNINGS() \
+ _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wall\"") \
+ _Pragma("GCC diagnostic ignored \"-Wextra\"") TINT_REQUIRE_SEMICOLON
+
+#define TINT_END_DISABLE_ALL_WARNINGS() _Pragma("GCC diagnostic pop") TINT_REQUIRE_SEMICOLON
+
// clang-format off
#define TINT_BEGIN_DISABLE_WARNING(name) \
_Pragma("GCC diagnostic push") \
@@ -175,10 +203,17 @@
#define TINT_UNLIKELY(x) __builtin_expect(!!(x), false)
#define TINT_LIKELY(x) __builtin_expect(!!(x), true)
+
+#if defined(__SANITIZE_ADDRESS__)
+#define TINT_ASAN_ENABLED
+#endif
+
#else
////////////////////////////////////////////////////////////////////////////////
// Other
////////////////////////////////////////////////////////////////////////////////
+#define TINT_BEGIN_DISABLE_ALL_WARNINGS() TINT_REQUIRE_SEMICOLON
+#define TINT_END_DISABLE_ALL_WARNINGS TINT_REQUIRE_SEMICOLON
#define TINT_BEGIN_DISABLE_WARNING(name) TINT_REQUIRE_SEMICOLON
#define TINT_END_DISABLE_WARNING(name) TINT_REQUIRE_SEMICOLON
#define TINT_BEGIN_DISABLE_PROTOBUF_WARNINGS() TINT_REQUIRE_SEMICOLON
diff --git a/tools/src/cmd/gen/build/BUILD.bazel.tmpl b/tools/src/cmd/gen/build/BUILD.bazel.tmpl
index b2537e5..46eafcb 100644
--- a/tools/src/cmd/gen/build/BUILD.bazel.tmpl
+++ b/tools/src/cmd/gen/build/BUILD.bazel.tmpl
@@ -141,6 +141,7 @@
*/ -}}
{{- define "ExternalDependencyTarget"}}
{{- if eq $.Name "abseil" -}}"@abseil_cpp//absl/strings",
+{{- else if eq $.Name "dxc-include" -}}{{/* unsupported */}}
{{- else if eq $.Name "glslang-res-limits" -}}{{/* unsupported */}}
{{- else if eq $.Name "glslang" -}}{{/* unsupported */}}
{{- else if eq $.Name "gmock" -}}"@gtest",
diff --git a/tools/src/cmd/gen/build/BUILD.gn.tmpl b/tools/src/cmd/gen/build/BUILD.gn.tmpl
index 1b299eb..fee28b7 100644
--- a/tools/src/cmd/gen/build/BUILD.gn.tmpl
+++ b/tools/src/cmd/gen/build/BUILD.gn.tmpl
@@ -165,6 +165,7 @@
*/ -}}
{{- define "ExternalDependencyTargets"}}
{{- if eq $.Name "abseil" -}}"${tint_src_dir}:abseil",
+{{- else if eq $.Name "dxc-include" -}}"${tint_src_dir}:dxc-include",
{{- else if eq $.Name "glslang-res-limits" -}}"${tint_glslang_dir}:glslang_default_resource_limits_sources",
{{- else if eq $.Name "glslang" -}}"${tint_glslang_dir}:glslang_lib_sources",
{{- else if eq $.Name "google-benchmark" -}}"${tint_src_dir}:google_benchmark",
diff --git a/tools/src/cmd/tests/main.go b/tools/src/cmd/tests/main.go
index 890f8c4..4994444 100644
--- a/tools/src/cmd/tests/main.go
+++ b/tools/src/cmd/tests/main.go
@@ -138,7 +138,7 @@
verbose, useIr, generateExpected, generateSkip := false, false, false, false
flag.StringVar(&formatList, "format", "all", "comma separated list of formats to emit. Possible values are: all, wgsl, spvasm, msl, hlsl, hlsl-dxc, hlsl-fxc, glsl")
flag.StringVar(&ignore, "ignore", "**.expected.*", "files to ignore in globs")
- flag.StringVar(&dxcPath, "dxc", "", "path to DXC executable for validating HLSL output")
+ flag.StringVar(&dxcPath, "dxcompiler", "", "path to DXC DLL for validating HLSL output")
flag.StringVar(&fxcPath, "fxc", "", "path to FXC DLL for validating HLSL output")
flag.StringVar(&tintPath, "tint", defaultTintPath(), "path to the tint executable")
flag.StringVar(&xcrunPath, "xcrun", "", "path to xcrun executable for validating MSL output")
@@ -240,6 +240,13 @@
defaultMSLExe = "metal.exe"
}
+ defaultDXCDll := "libdxcompiler.so"
+ if runtime.GOOS == "windows" {
+ defaultDXCDll = "dxcompiler.dll"
+ } else if runtime.GOOS == "darwin" {
+ defaultDXCDll = "libdxcompiler.dylib"
+ }
+
toolchainHash := sha256.New()
// If explicit verification compilers have been specified, check they exist.
@@ -249,7 +256,7 @@
lang string
path *string
}{
- {"dxc", "hlsl-dxc", &dxcPath},
+ {defaultDXCDll, "hlsl-dxc", &dxcPath},
{"d3dcompiler_47.dll", "hlsl-fxc", &fxcPath},
{defaultMSLExe, "msl", &xcrunPath},
} {