D3DCommon: Use once_flag for library loading

Avoids the mutex.
wip3-rebase
Stenzek 6 days ago
parent b7e20507b0
commit 2f4724dd1f
No known key found for this signature in database

@ -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<DynamicHeapArray<u8>> 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<FeatureLevelTableEntry, 11> s_feature_levels = {{
{D3D_FEATURE_LEVEL_1_0_CORE, 100, 40, "D3D_FEATURE_LEVEL_1_0_CORE"},
@ -138,19 +141,26 @@ Microsoft::WRL::ComPtr<IDXGIFactory5> 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<DynamicHeapArray<u8>> 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<DynamicHeapArray<u8>> D3DCommon::CompileShaderWithFXC(u32 shader_m
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,
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<IDxcUtils> utils;
@ -792,29 +831,6 @@ std::optional<DynamicHeapArray<u8>> D3DCommon::CompileShaderWithDXC(u32 shader_m
return DynamicHeapArray<u8>(static_cast<const u8*>(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<D3DCommon::DXGIFormatMapping, static_cast<int>(GPUTextureFormat::MaxCount)>
s_format_mapping = {{
// clang-format off

Loading…
Cancel
Save