D3DCommon: Load D3DCompiler dynamically

This commit is contained in:
Stenzek 2025-07-13 15:51:15 +10:00
parent 5e2e39f642
commit 3928eaff54
No known key found for this signature in database
4 changed files with 60 additions and 13 deletions

View File

@ -241,7 +241,7 @@ if(WIN32)
xinput_source.h xinput_source.h
) )
target_link_libraries(util PRIVATE d3d12ma) target_link_libraries(util PRIVATE d3d12ma)
target_link_libraries(util PRIVATE d3d11.lib d3d12.lib d3dcompiler.lib dxgi.lib winmm.lib Dwmapi.lib winhttp.lib) target_link_libraries(util PRIVATE d3d11.lib d3d12.lib dxgi.lib winmm.lib Dwmapi.lib winhttp.lib)
if(CMAKE_BUILD_TYPE MATCHES "Debug|Devel") if(CMAKE_BUILD_TYPE MATCHES "Debug|Devel")
target_link_libraries(util PRIVATE WinPixEventRuntime::WinPixEventRuntime) target_link_libraries(util PRIVATE WinPixEventRuntime::WinPixEventRuntime)

View File

@ -18,6 +18,7 @@
#include <d3dcompiler.h> #include <d3dcompiler.h>
#include <dxcapi.h> #include <dxcapi.h>
#include <dxgi1_5.h> #include <dxgi1_5.h>
#include <mutex>
LOG_CHANNEL(GPUDevice); LOG_CHANNEL(GPUDevice);
@ -30,6 +31,16 @@ struct FeatureLevelTableEntry
u16 shader_model_number; u16 shader_model_number;
const char* feature_level_str; const char* feature_level_str;
}; };
struct Libs
{
std::mutex load_mutex;
DynamicLibrary d3dcompiler_library;
pD3DCompile D3DCompile;
DynamicLibrary dxcompiler_library;
DxcCreateInstanceProc DxcCreateInstance;
};
} // namespace } // namespace
static std::optional<DynamicHeapArray<u8>> CompileShaderWithFXC(u32 shader_model, bool debug_device, static std::optional<DynamicHeapArray<u8>> CompileShaderWithFXC(u32 shader_model, bool debug_device,
@ -38,11 +49,9 @@ static std::optional<DynamicHeapArray<u8>> CompileShaderWithFXC(u32 shader_model
static std::optional<DynamicHeapArray<u8>> CompileShaderWithDXC(u32 shader_model, bool debug_device, static std::optional<DynamicHeapArray<u8>> CompileShaderWithDXC(u32 shader_model, bool debug_device,
GPUShaderStage stage, std::string_view source, GPUShaderStage stage, std::string_view source,
const char* entry_point, Error* error); const char* entry_point, Error* error);
static bool LoadD3DCompilerLibrary(Error* error);
static bool LoadDXCompilerLibrary(Error* error); static bool LoadDXCompilerLibrary(Error* error);
static DynamicLibrary s_dxcompiler_library;
static DxcCreateInstanceProc s_DxcCreateInstance;
static constexpr std::array<FeatureLevelTableEntry, 11> s_feature_levels = {{ static constexpr std::array<FeatureLevelTableEntry, 11> s_feature_levels = {{
{D3D_FEATURE_LEVEL_1_0_CORE, 100, 40, "D3D_FEATURE_LEVEL_1_0_CORE"}, {D3D_FEATURE_LEVEL_1_0_CORE, 100, 40, "D3D_FEATURE_LEVEL_1_0_CORE"},
{D3D_FEATURE_LEVEL_9_1, 910, 40, "D3D_FEATURE_LEVEL_9_1"}, {D3D_FEATURE_LEVEL_9_1, 910, 40, "D3D_FEATURE_LEVEL_9_1"},
@ -56,6 +65,8 @@ static constexpr std::array<FeatureLevelTableEntry, 11> s_feature_levels = {{
{D3D_FEATURE_LEVEL_12_1, 1210, 60, "D3D_FEATURE_LEVEL_12_1"}, {D3D_FEATURE_LEVEL_12_1, 1210, 60, "D3D_FEATURE_LEVEL_12_1"},
{D3D_FEATURE_LEVEL_12_2, 1220, 60, "D3D_FEATURE_LEVEL_12_2"}, {D3D_FEATURE_LEVEL_12_2, 1220, 60, "D3D_FEATURE_LEVEL_12_2"},
}}; }};
static Libs s_libs;
} // namespace D3DCommon } // namespace D3DCommon
const char* D3DCommon::GetFeatureLevelString(u32 render_api_version) const char* D3DCommon::GetFeatureLevelString(u32 render_api_version)
@ -437,6 +448,9 @@ std::optional<DynamicHeapArray<u8>> D3DCommon::CompileShaderWithFXC(u32 shader_m
GPUShaderStage stage, std::string_view source, GPUShaderStage stage, std::string_view source,
const char* entry_point, Error* error) const char* entry_point, Error* error)
{ {
if (!LoadD3DCompilerLibrary(error))
return {};
const char* target; const char* target;
switch (shader_model) switch (shader_model)
{ {
@ -476,8 +490,8 @@ std::optional<DynamicHeapArray<u8>> D3DCommon::CompileShaderWithFXC(u32 shader_m
Microsoft::WRL::ComPtr<ID3DBlob> blob; Microsoft::WRL::ComPtr<ID3DBlob> blob;
Microsoft::WRL::ComPtr<ID3DBlob> error_blob; Microsoft::WRL::ComPtr<ID3DBlob> error_blob;
const HRESULT hr = const HRESULT hr =
D3DCompile(source.data(), source.size(), "0", nullptr, nullptr, entry_point, target, s_libs.D3DCompile(source.data(), source.size(), "0", nullptr, nullptr, entry_point, target,
debug_device ? flags_debug : flags_non_debug, 0, blob.GetAddressOf(), error_blob.GetAddressOf()); debug_device ? flags_debug : flags_non_debug, 0, blob.GetAddressOf(), error_blob.GetAddressOf());
std::string_view error_string; std::string_view error_string;
if (error_blob) if (error_blob)
@ -502,6 +516,29 @@ std::optional<DynamicHeapArray<u8>> D3DCommon::CompileShaderWithFXC(u32 shader_m
return DynamicHeapArray<u8>(static_cast<const u8*>(blob->GetBufferPointer()), blob->GetBufferSize()); return DynamicHeapArray<u8>(static_cast<const u8*>(blob->GetBufferPointer()), blob->GetBufferSize());
} }
bool D3DCommon::LoadD3DCompilerLibrary(Error* error)
{
if (s_libs.d3dcompiler_library.IsOpen())
return true;
// double check, another thread may have opened it
const std::unique_lock lock(s_libs.load_mutex);
if (s_libs.d3dcompiler_library.IsOpen())
return true;
if (!s_libs.d3dcompiler_library.Open(D3DCOMPILER_DLL_A, error))
return false;
if (!s_libs.d3dcompiler_library.GetSymbol("D3DCompile", &s_libs.D3DCompile))
{
Error::SetStringView(error, "Failed to load D3DCompile from d3dcompiler.dll");
s_libs.d3dcompiler_library.Close();
return false;
}
return true;
}
std::optional<DynamicHeapArray<u8>> D3DCommon::CompileShaderWithDXC(u32 shader_model, bool debug_device, std::optional<DynamicHeapArray<u8>> D3DCommon::CompileShaderWithDXC(u32 shader_model, bool debug_device,
GPUShaderStage stage, std::string_view source, GPUShaderStage stage, std::string_view source,
const char* entry_point, Error* error) const char* entry_point, Error* error)
@ -511,7 +548,7 @@ std::optional<DynamicHeapArray<u8>> D3DCommon::CompileShaderWithDXC(u32 shader_m
HRESULT hr; HRESULT hr;
Microsoft::WRL::ComPtr<IDxcUtils> utils; Microsoft::WRL::ComPtr<IDxcUtils> utils;
if (FAILED(hr = s_DxcCreateInstance(CLSID_DxcUtils, IID_PPV_ARGS(utils.GetAddressOf())))) [[unlikely]] if (FAILED(hr = s_libs.DxcCreateInstance(CLSID_DxcUtils, IID_PPV_ARGS(utils.GetAddressOf())))) [[unlikely]]
{ {
Error::SetHResult(error, "DxcCreateInstance(CLSID_DxcUtils) failed: ", hr); Error::SetHResult(error, "DxcCreateInstance(CLSID_DxcUtils) failed: ", hr);
return {}; return {};
@ -526,7 +563,7 @@ std::optional<DynamicHeapArray<u8>> D3DCommon::CompileShaderWithDXC(u32 shader_m
} }
Microsoft::WRL::ComPtr<IDxcCompiler> compiler; Microsoft::WRL::ComPtr<IDxcCompiler> compiler;
if (FAILED(hr = s_DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(compiler.GetAddressOf())))) [[unlikely]] if (FAILED(hr = s_libs.DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(compiler.GetAddressOf())))) [[unlikely]]
{ {
Error::SetHResult(error, "DxcCreateInstance(CLSID_DxcCompiler) failed: ", hr); Error::SetHResult(error, "DxcCreateInstance(CLSID_DxcCompiler) failed: ", hr);
return {}; return {};
@ -601,13 +638,21 @@ std::optional<DynamicHeapArray<u8>> D3DCommon::CompileShaderWithDXC(u32 shader_m
bool D3DCommon::LoadDXCompilerLibrary(Error* error) bool D3DCommon::LoadDXCompilerLibrary(Error* error)
{ {
if (s_dxcompiler_library.IsOpen()) if (s_libs.dxcompiler_library.IsOpen())
return true; return true;
if (!s_dxcompiler_library.Open("dxcompiler.dll", error) || // double check, another thread may have opened it
!s_dxcompiler_library.GetSymbol("DxcCreateInstance", &s_DxcCreateInstance)) const std::unique_lock lock(s_libs.load_mutex);
if (s_libs.dxcompiler_library.IsOpen())
return true;
if (!s_libs.dxcompiler_library.Open("dxcompiler.dll", error))
return false;
if (!s_libs.dxcompiler_library.GetSymbol("DxcCreateInstance", &s_libs.DxcCreateInstance))
{ {
s_dxcompiler_library.Close(); Error::SetStringView(error, "Failed to load DxcCreateInstance from dxcompiler.dll");
s_libs.dxcompiler_library.Close();
return false; return false;
} }

View File

@ -27,6 +27,7 @@ struct IDXGIAdapter1;
struct IDXGIOutput; struct IDXGIOutput;
namespace D3DCommon { namespace D3DCommon {
// returns string representation of feature level // returns string representation of feature level
const char* GetFeatureLevelString(u32 render_api_version); const char* GetFeatureLevelString(u32 render_api_version);
u32 GetRenderAPIVersionForFeatureLevel(D3D_FEATURE_LEVEL feature_level); u32 GetRenderAPIVersionForFeatureLevel(D3D_FEATURE_LEVEL feature_level);
@ -76,4 +77,5 @@ struct DXGIFormatMapping
}; };
const DXGIFormatMapping& GetFormatMapping(GPUTexture::Format format); const DXGIFormatMapping& GetFormatMapping(GPUTexture::Format format);
GPUTexture::Format GetFormatForDXGIFormat(DXGI_FORMAT format); GPUTexture::Format GetFormatForDXGIFormat(DXGI_FORMAT format);
} // namespace D3DCommon } // namespace D3DCommon

View File

@ -13,7 +13,7 @@
<ItemDefinitionGroup> <ItemDefinitionGroup>
<Link> <Link>
<AdditionalDependencies>%(AdditionalDependencies);d3d11.lib;d3d12.lib;d3dcompiler.lib;dxgi.lib;Dwmapi.lib;winhttp.lib</AdditionalDependencies> <AdditionalDependencies>%(AdditionalDependencies);d3d11.lib;d3d12.lib;dxgi.lib;Dwmapi.lib;winhttp.lib</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>