D3DCommon: Load d3d11.dll dynamically

This commit is contained in:
Stenzek 2025-07-13 16:02:30 +10:00
parent 3928eaff54
commit 0195b2886e
No known key found for this signature in database
5 changed files with 55 additions and 14 deletions

View File

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

View File

@ -81,14 +81,11 @@ bool D3D11Device::CreateDeviceAndMainSwapChain(std::string_view adapter, Feature
ComPtr<ID3D11Device> temp_device;
ComPtr<ID3D11DeviceContext> temp_context;
HRESULT hr =
D3D11CreateDevice(dxgi_adapter.Get(), dxgi_adapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE, nullptr,
create_flags, requested_feature_levels.data(), static_cast<UINT>(requested_feature_levels.size()),
D3D11_SDK_VERSION, temp_device.GetAddressOf(), nullptr, temp_context.GetAddressOf());
if (FAILED(hr))
HRESULT hr;
if (!D3DCommon::CreateD3D11Device(dxgi_adapter.Get(), create_flags, requested_feature_levels.data(),
static_cast<UINT>(requested_feature_levels.size()), &temp_device, nullptr,
&temp_context, error))
{
Error::SetHResult(error, "Failed to create D3D device: ", hr);
return false;
}
else if (FAILED(hr = temp_device.As(&m_device)) || FAILED(hr = temp_context.As(&m_context)))

View File

@ -35,6 +35,8 @@ struct FeatureLevelTableEntry
struct Libs
{
std::mutex load_mutex;
DynamicLibrary d3d11_library;
PFN_D3D11_CREATE_DEVICE D3D11CreateDevice;
DynamicLibrary d3dcompiler_library;
pD3DCompile D3DCompile;
DynamicLibrary dxcompiler_library;
@ -111,12 +113,12 @@ D3D_FEATURE_LEVEL D3DCommon::GetDeviceMaxFeatureLevel(IDXGIAdapter1* adapter)
D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0};
D3D_FEATURE_LEVEL max_supported_level;
HRESULT hr = D3D11CreateDevice(adapter, adapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE, nullptr, 0,
requested_feature_levels.data(), static_cast<UINT>(requested_feature_levels.size()),
D3D11_SDK_VERSION, nullptr, &max_supported_level, nullptr);
if (FAILED(hr))
Error error;
if (!CreateD3D11Device(adapter, 0, requested_feature_levels.data(),
static_cast<UINT>(requested_feature_levels.size()), nullptr, &max_supported_level, nullptr,
&error))
{
WARNING_LOG("D3D11CreateDevice() for getting max feature level failed: 0x{:08X}", static_cast<unsigned>(hr));
WARNING_LOG("D3D11CreateDevice() for getting max feature level failed: {}", error.GetDescription());
max_supported_level = requested_feature_levels.back();
}
@ -145,6 +147,40 @@ bool D3DCommon::SupportsAllowTearing(IDXGIFactory5* factory)
return (SUCCEEDED(hr) && allow_tearing_supported == TRUE);
}
bool D3DCommon::CreateD3D11Device(IDXGIAdapter* adapter, UINT create_flags, const D3D_FEATURE_LEVEL* feature_levels,
UINT num_feature_levels, Microsoft::WRL::ComPtr<ID3D11Device>* device,
D3D_FEATURE_LEVEL* out_feature_level,
Microsoft::WRL::ComPtr<ID3D11DeviceContext>* immediate_context, Error* error)
{
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))
{
Error::SetStringView(error, "Failed to load D3D11CreateDevice from d3d11.dll");
s_libs.d3dcompiler_library.Close();
return false;
}
}
}
const HRESULT hr = s_libs.D3D11CreateDevice(
adapter, adapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE, nullptr, create_flags, feature_levels,
num_feature_levels, D3D11_SDK_VERSION, device ? device->ReleaseAndGetAddressOf() : nullptr, out_feature_level,
immediate_context ? immediate_context->ReleaseAndGetAddressOf() : nullptr);
if (SUCCEEDED(hr))
return true;
Error::SetHResult(error, "D3D11CreateDevice() failed: ", hr);
return true;
}
static std::string FixupDuplicateAdapterNames(const GPUDevice::AdapterInfoList& adapter_names, std::string adapter_name)
{
if (std::any_of(adapter_names.begin(), adapter_names.end(),

View File

@ -25,6 +25,8 @@ struct IDXGIFactory5;
struct IDXGIAdapter;
struct IDXGIAdapter1;
struct IDXGIOutput;
struct ID3D11Device;
struct ID3D11DeviceContext;
namespace D3DCommon {
@ -41,6 +43,12 @@ D3D_FEATURE_LEVEL GetDeviceMaxFeatureLevel(IDXGIAdapter1* adapter);
Microsoft::WRL::ComPtr<IDXGIFactory5> CreateFactory(bool debug, Error* error);
bool SupportsAllowTearing(IDXGIFactory5* factory);
// create a D3D device
bool CreateD3D11Device(IDXGIAdapter* adapter, UINT create_flags, const D3D_FEATURE_LEVEL* feature_levels,
UINT num_feature_levels, Microsoft::WRL::ComPtr<ID3D11Device>* device,
D3D_FEATURE_LEVEL* out_feature_level,
Microsoft::WRL::ComPtr<ID3D11DeviceContext>* immediate_context, Error* error);
// returns a list of all adapter names
GPUDevice::AdapterInfoList GetAdapterInfoList();

View File

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