From 2f4724dd1f95ba2eb36626d243f88eefb2a02d45 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Thu, 17 Sep 2026 17:17:21 +1000 Subject: [PATCH] D3DCommon: Use once_flag for library loading Avoids the mutex. --- src/util/d3d_common.cpp | 188 ++++++++++++++++++++++------------------ 1 file changed, 102 insertions(+), 86 deletions(-) diff --git a/src/util/d3d_common.cpp b/src/util/d3d_common.cpp index fb2870b66..18596c858 100644 --- a/src/util/d3d_common.cpp +++ b/src/util/d3d_common.cpp @@ -36,7 +36,6 @@ struct FeatureLevelTableEntry struct Libs { - std::mutex load_mutex; DynamicLibrary dxgi_library; decltype(&CreateDXGIFactory2) CreateDXGIFactory2; DynamicLibrary d3d11_library; @@ -49,6 +48,12 @@ struct Libs pD3DCompile D3DCompile; DynamicLibrary dxcompiler_library; DxcCreateInstanceProc DxcCreateInstance; + + std::once_flag dxgi_library_once_flag; + std::once_flag d3d11_library_once_flag; + std::once_flag d3d12_library_once_flag; + std::once_flag d3dcompiler_library_once_flag; + std::once_flag dxcompiler_library_once_flag; }; } // namespace @@ -60,8 +65,6 @@ static std::optional> CompileShaderWithDXC(u32 shader_model GPUShaderStage stage, std::string_view source, const char* entry_point, Error* error); static bool LoadD3D12Library(Error* error); -static bool LoadD3DCompilerLibrary(Error* error); -static bool LoadDXCompilerLibrary(Error* error); static constexpr std::array s_feature_levels = {{ {D3D_FEATURE_LEVEL_1_0_CORE, 100, 40, "D3D_FEATURE_LEVEL_1_0_CORE"}, @@ -138,19 +141,26 @@ Microsoft::WRL::ComPtr D3DCommon::CreateFactory(bool debug, Error { if (!s_libs.dxgi_library.IsOpen()) { - // another thread may have opened it - const std::unique_lock lock(s_libs.load_mutex); - if (!s_libs.dxgi_library.IsOpen()) - { - if (!s_libs.dxgi_library.Open("dxgi.dll", error)) - return {}; + std::call_once(s_libs.dxgi_library_once_flag, []() { + DynamicLibrary lib; + if (Error error; !lib.Open("dxgi.dll", &error)) + { + ERROR_LOG("Failed to load dxgi.dll: {}", error.GetDescription()); + return; + } - if (!s_libs.dxgi_library.GetSymbol("CreateDXGIFactory2", &s_libs.CreateDXGIFactory2)) + if (!lib.GetSymbol("CreateDXGIFactory2", &s_libs.CreateDXGIFactory2)) { - Error::SetStringView(error, "Failed to load CreateDXGIFactory2 from dxgi.dll"); - s_libs.dxgi_library.Close(); - return {}; + ERROR_LOG("Failed to load CreateDXGIFactory2 from dxgi.dll"); + return; } + + s_libs.dxgi_library = std::move(lib); + }); + if (!s_libs.dxgi_library.IsOpen()) + { + Error::SetStringView(error, "Failed to load dxgi.dll or CreateDXGIFactory2"); + return nullptr; } } @@ -181,19 +191,25 @@ bool D3DCommon::CreateD3D11Device(IDXGIAdapter* adapter, UINT create_flags, cons { if (!s_libs.d3d11_library.IsOpen()) { - // another thread may have opened it - const std::unique_lock lock(s_libs.load_mutex); - if (!s_libs.d3d11_library.IsOpen()) - { - if (!s_libs.d3d11_library.Open("d3d11.dll", error)) - return false; - - if (!s_libs.d3d11_library.GetSymbol("D3D11CreateDevice", &s_libs.D3D11CreateDevice)) + std::call_once(s_libs.d3d11_library_once_flag, []() { + DynamicLibrary lib; + if (Error error; !lib.Open("d3d11.dll", &error)) { - Error::SetStringView(error, "Failed to load D3D11CreateDevice from d3d11.dll"); - s_libs.d3d11_library.Close(); - return false; + ERROR_LOG("Failed to load d3d11.dll: {}", error.GetDescription()); + return; } + if (!lib.GetSymbol("D3D11CreateDevice", &s_libs.D3D11CreateDevice)) + { + ERROR_LOG("Failed to load D3D11CreateDevice from d3d11.dll"); + return; + } + + s_libs.d3d11_library = std::move(lib); + }); + if (!s_libs.d3d11_library.IsOpen()) + { + Error::SetStringView(error, "Failed to load d3d11.dll or D3D11CreateDevice"); + return false; } } @@ -213,20 +229,26 @@ bool D3DCommon::LoadD3D12Library(Error* error) if (s_libs.d3d12_library.IsOpen()) return true; - // double check, another thread may have opened it - const std::unique_lock lock(s_libs.load_mutex); - if (s_libs.d3d12_library.IsOpen()) - return true; - - if (!s_libs.d3d12_library.Open("d3d12.dll", error)) - return false; + std::call_once(s_libs.d3d12_library_once_flag, []() { + DynamicLibrary lib; + if (Error error; !lib.Open("d3d12.dll", &error)) + { + ERROR_LOG("Failed to load d3d12.dll: {}", error.GetDescription()); + return; + } + if (!lib.GetSymbol("D3D12CreateDevice", &s_libs.D3D12CreateDevice) || + !lib.GetSymbol("D3D12GetDebugInterface", &s_libs.D3D12GetDebugInterface) || + !lib.GetSymbol("D3D12SerializeRootSignature", &s_libs.D3D12SerializeRootSignature)) + { + ERROR_LOG("Failed to load one or more required functions from d3d12.dll"); + return; + } + s_libs.d3d12_library = std::move(lib); + }); - if (!s_libs.d3d12_library.GetSymbol("D3D12CreateDevice", &s_libs.D3D12CreateDevice) || - !s_libs.d3d12_library.GetSymbol("D3D12GetDebugInterface", &s_libs.D3D12GetDebugInterface) || - !s_libs.d3d12_library.GetSymbol("D3D12SerializeRootSignature", &s_libs.D3D12SerializeRootSignature)) + if (!s_libs.d3d12_library.IsOpen()) { - Error::SetStringView(error, "Failed to load one or more required functions from d3d12.dll"); - s_libs.d3d12_library.Close(); + Error::SetStringView(error, "Failed to load d3d12.dll or required functions"); return false; } @@ -604,8 +626,28 @@ std::optional> D3DCommon::CompileShaderWithFXC(u32 shader_m GPUShaderStage stage, std::string_view source, const char* entry_point, Error* error) { - if (!LoadD3DCompilerLibrary(error)) - return {}; + if (!s_libs.d3dcompiler_library.IsOpen()) + { + std::call_once(s_libs.d3dcompiler_library_once_flag, []() { + DynamicLibrary lib; + if (Error error; !lib.Open(D3DCOMPILER_DLL_A, &error)) + { + ERROR_LOG("Failed to load d3dcompiler.dll: {}", error.GetDescription()); + return; + } + if (!lib.GetSymbol("D3DCompile", &s_libs.D3DCompile)) + { + ERROR_LOG("Failed to load D3DCompile from d3dcompiler.dll"); + return; + } + s_libs.d3dcompiler_library = std::move(lib); + }); + if (!s_libs.d3dcompiler_library.IsOpen()) + { + Error::SetStringView(error, "Failed to load d3dcompiler.dll or D3DCompile"); + return {}; + } + } const char* target; switch (shader_model) @@ -672,35 +714,32 @@ std::optional> D3DCommon::CompileShaderWithFXC(u32 shader_m return DynamicHeapArray(static_cast(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> D3DCommon::CompileShaderWithDXC(u32 shader_model, bool debug_device, GPUShaderStage stage, std::string_view source, const char* entry_point, Error* error) { - if (!LoadDXCompilerLibrary(error)) - return {}; + if (!s_libs.dxcompiler_library.IsOpen()) + { + std::call_once(s_libs.dxcompiler_library_once_flag, []() { + DynamicLibrary lib; + if (Error error; !lib.Open("dxcompiler.dll", &error)) + { + ERROR_LOG("Failed to load dxcompiler.dll: {}", error.GetDescription()); + return; + } + if (!lib.GetSymbol("DxcCreateInstance", &s_libs.DxcCreateInstance)) + { + ERROR_LOG("Failed to load DxcCreateInstance from dxcompiler.dll"); + return; + } + s_libs.dxcompiler_library = std::move(lib); + }); + if (!s_libs.dxcompiler_library.IsOpen()) + { + Error::SetStringView(error, "Failed to load dxcompiler.dll or DxcCreateInstance"); + return {}; + } + } HRESULT hr; Microsoft::WRL::ComPtr utils; @@ -792,29 +831,6 @@ std::optional> D3DCommon::CompileShaderWithDXC(u32 shader_m return DynamicHeapArray(static_cast(object_blob->GetBufferPointer()), object_blob->GetBufferSize()); } -bool D3DCommon::LoadDXCompilerLibrary(Error* error) -{ - if (s_libs.dxcompiler_library.IsOpen()) - return true; - - // double check, another thread may have opened it - 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)) - { - Error::SetStringView(error, "Failed to load DxcCreateInstance from dxcompiler.dll"); - s_libs.dxcompiler_library.Close(); - return false; - } - - return true; -} - static constexpr std::array(GPUTextureFormat::MaxCount)> s_format_mapping = {{ // clang-format off