diff --git a/src/d3d11/d3d11.def b/src/d3d11/d3d11.def index 5565f198..d541650a 100644 --- a/src/d3d11/d3d11.def +++ b/src/d3d11/d3d11.def @@ -1,4 +1,5 @@ LIBRARY D3D11.DLL EXPORTS + D3D11CoreCreateDevice D3D11CreateDevice D3D11CreateDeviceAndSwapChain diff --git a/src/d3d11/d3d11_main.cpp b/src/d3d11/d3d11_main.cpp index ab2dcb80..59ebf95c 100644 --- a/src/d3d11/d3d11_main.cpp +++ b/src/d3d11/d3d11_main.cpp @@ -15,54 +15,20 @@ namespace dxvk { extern "C" { using namespace dxvk; - DLLEXPORT HRESULT __stdcall D3D11CreateDevice( - IDXGIAdapter *pAdapter, - D3D_DRIVER_TYPE DriverType, - HMODULE Software, + DLLEXPORT HRESULT __stdcall D3D11CoreCreateDevice( + IDXGIFactory* pFactory, + IDXGIAdapter* pAdapter, UINT Flags, - const D3D_FEATURE_LEVEL *pFeatureLevels, + const D3D_FEATURE_LEVEL* pFeatureLevels, UINT FeatureLevels, - UINT SDKVersion, - ID3D11Device **ppDevice, - D3D_FEATURE_LEVEL *pFeatureLevel, - ID3D11DeviceContext **ppImmediateContext) { - Com dxgiAdapter = pAdapter; + ID3D11Device** ppDevice) { Com dxvkAdapter = nullptr; - if (dxgiAdapter == nullptr) { - // We'll treat everything as hardware, even if the - // Vulkan device is actually a software device. - if (DriverType != D3D_DRIVER_TYPE_HARDWARE) - Logger::warn("D3D11CreateDevice: Unsupported driver type"); - - // We'll use the first adapter returned by a DXGI factory - Com factory = nullptr; - - if (FAILED(CreateDXGIFactory(__uuidof(IDXGIFactory), reinterpret_cast(&factory)))) { - Logger::err("D3D11CreateDevice: Failed to create a DXGI factory"); - return E_FAIL; - } - - if (FAILED(factory->EnumAdapters(0, &dxgiAdapter))) { - Logger::err("D3D11CreateDevice: No default adapter available"); - return E_FAIL; - } - - } else { - // In theory we could ignore these, but the Microsoft docs explicitly - // state that we need to return E_INVALIDARG in case the arguments are - // invalid. Both the driver type and software parameter can only be - // set if the adapter itself is unspecified. - // See: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476082(v=vs.85).aspx - if (DriverType != D3D_DRIVER_TYPE_UNKNOWN || Software != nullptr) - return E_INVALIDARG; - } - // The adapter must obviously be a DXVK-compatible adapter so // that we can create a DXVK-compatible DXGI device from it. - if (FAILED(dxgiAdapter->QueryInterface(__uuidof(IDXGIVkAdapter), + if (FAILED(pAdapter->QueryInterface(__uuidof(IDXGIVkAdapter), reinterpret_cast(&dxvkAdapter)))) { - Logger::err("D3D11CreateDevice: Adapter is not a DXVK adapter"); + Logger::err("D3D11CoreCreateDevice: Adapter is not a DXVK adapter"); return E_INVALIDARG; } @@ -85,14 +51,14 @@ extern "C" { UINT flId; for (flId = 0 ; flId < FeatureLevels; flId++) { - Logger::info(str::format("D3D11CreateDevice: Probing ", pFeatureLevels[flId])); + Logger::info(str::format("D3D11CoreCreateDevice: Probing ", pFeatureLevels[flId])); if (D3D11Device::CheckFeatureLevelSupport(adapter, pFeatureLevels[flId])) break; } if (flId == FeatureLevels) { - Logger::err("D3D11CreateDevice: Requested feature level not supported"); + Logger::err("D3D11CoreCreateDevice: Requested feature level not supported"); return E_INVALIDARG; } @@ -100,63 +66,124 @@ extern "C" { const D3D_FEATURE_LEVEL fl = pFeatureLevels[flId]; try { - Logger::info(str::format("D3D11CreateDevice: Using feature level ", fl)); - - // Write back the actual feature level - // if the application requested it. - if (pFeatureLevel != nullptr) - *pFeatureLevel = fl; - - // If we cannot write back either the device or - // the context, don't create the device at all - if (ppDevice == nullptr && ppImmediateContext == nullptr) - return S_FALSE; - + Logger::info(str::format("D3D11CoreCreateDevice: Using feature level ", fl)); Com container = new D3D11DeviceContainer(); const VkPhysicalDeviceFeatures deviceFeatures = D3D11Device::GetDeviceFeatures(adapter, fl); if (FAILED(dxvkAdapter->CreateDevice(container.ptr(), &deviceFeatures, &container->m_dxgiDevice))) { - Logger::err("D3D11CreateDevice: Failed to create DXGI device"); + Logger::err("D3D11CoreCreateDevice: Failed to create DXGI device"); return E_FAIL; } container->m_d3d11Device = new D3D11Device( container.ptr(), container->m_dxgiDevice, fl, Flags); - container->m_d3d11Presenter = new D3D11Presenter( container.ptr(), container->m_d3d11Device); - container->m_d3d11VkInterop = new D3D11VkInterop( container.ptr(), container->m_d3d11Device); - if (ppDevice != nullptr) - *ppDevice = ref(container->m_d3d11Device); - - if (ppImmediateContext != nullptr) - container->m_d3d11Device->GetImmediateContext(ppImmediateContext); + *ppDevice = ref(container->m_d3d11Device); return S_OK; } catch (const DxvkError& e) { - Logger::err("D3D11CreateDevice: Failed to create D3D11 device"); + Logger::err("D3D11CoreCreateDevice: Failed to create D3D11 device"); return E_FAIL; } } + DLLEXPORT HRESULT __stdcall D3D11CreateDevice( + IDXGIAdapter* pAdapter, + D3D_DRIVER_TYPE DriverType, + HMODULE Software, + UINT Flags, + const D3D_FEATURE_LEVEL* pFeatureLevels, + UINT FeatureLevels, + UINT SDKVersion, + ID3D11Device** ppDevice, + D3D_FEATURE_LEVEL* pFeatureLevel, + ID3D11DeviceContext** ppImmediateContext) { + Com dxgiFactory = nullptr; + Com dxgiAdapter = pAdapter; + + if (dxgiAdapter == nullptr) { + // We'll treat everything as hardware, even if the + // Vulkan device is actually a software device. + if (DriverType != D3D_DRIVER_TYPE_HARDWARE) + Logger::warn("D3D11CreateDevice: Unsupported driver type"); + + // We'll use the first adapter returned by a DXGI factory + if (FAILED(CreateDXGIFactory(__uuidof(IDXGIFactory), reinterpret_cast(&dxgiFactory)))) { + Logger::err("D3D11CreateDevice: Failed to create a DXGI factory"); + return E_FAIL; + } + + if (FAILED(dxgiFactory->EnumAdapters(0, &dxgiAdapter))) { + Logger::err("D3D11CreateDevice: No default adapter available"); + return E_FAIL; + } + + } else { + // We should be able to query the DXGI factory from the adapter + if (FAILED(dxgiAdapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast(&dxgiFactory)))) { + Logger::err("D3D11CreateDevice: Failed to query DXGI factory from DXGI adapter"); + return E_FAIL; + } + + // In theory we could ignore these, but the Microsoft docs explicitly + // state that we need to return E_INVALIDARG in case the arguments are + // invalid. Both the driver type and software parameter can only be + // set if the adapter itself is unspecified. + // See: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476082(v=vs.85).aspx + if (DriverType != D3D_DRIVER_TYPE_UNKNOWN || Software != nullptr) + return E_INVALIDARG; + } + + // Create the actual device + Com device; + + HRESULT hr = D3D11CoreCreateDevice( + dxgiFactory.ptr(), dxgiAdapter.ptr(), + Flags, pFeatureLevels, FeatureLevels, + &device); + + if (FAILED(hr)) + return hr; + + // Write back whatever info the application requested + if (pFeatureLevel != nullptr) + *pFeatureLevel = device->GetFeatureLevel(); + + if (ppDevice != nullptr) + *ppDevice = device.ref(); + + if (ppImmediateContext != nullptr) + device->GetImmediateContext(ppImmediateContext); + + // If we were unable to write back the device and the + // swap chain, the application has no way of working + // with the device so we should report S_FALSE here. + if (ppDevice == nullptr && ppImmediateContext == nullptr) + return S_FALSE; + + return S_OK; + } + + DLLEXPORT HRESULT __stdcall D3D11CreateDeviceAndSwapChain( - IDXGIAdapter *pAdapter, - D3D_DRIVER_TYPE DriverType, - HMODULE Software, - UINT Flags, - const D3D_FEATURE_LEVEL *pFeatureLevels, - UINT FeatureLevels, - UINT SDKVersion, - const DXGI_SWAP_CHAIN_DESC *pSwapChainDesc, - IDXGISwapChain **ppSwapChain, - ID3D11Device **ppDevice, - D3D_FEATURE_LEVEL *pFeatureLevel, - ID3D11DeviceContext **ppImmediateContext) { + IDXGIAdapter* pAdapter, + D3D_DRIVER_TYPE DriverType, + HMODULE Software, + UINT Flags, + const D3D_FEATURE_LEVEL* pFeatureLevels, + UINT FeatureLevels, + UINT SDKVersion, + const DXGI_SWAP_CHAIN_DESC* pSwapChainDesc, + IDXGISwapChain** ppSwapChain, + ID3D11Device** ppDevice, + D3D_FEATURE_LEVEL* pFeatureLevel, + ID3D11DeviceContext** ppImmediateContext) { Com d3d11Device; Com d3d11Context;