#include #include "../dxgi/dxgi_adapter.h" #include "../dxvk/dxvk_instance.h" #include "d3d11_device.h" #include "d3d11_enums.h" #include "d3d11_interop.h" namespace dxvk { Logger Logger::s_instance("d3d11.log"); } extern "C" { using namespace dxvk; DLLEXPORT HRESULT __stdcall D3D11CoreCreateDevice( IDXGIFactory* pFactory, IDXGIAdapter* pAdapter, UINT Flags, const D3D_FEATURE_LEVEL* pFeatureLevels, UINT FeatureLevels, ID3D11Device** ppDevice) { InitReturnPtr(ppDevice); Rc dxvkAdapter; Rc dxvkInstance; Com dxgiVkAdapter; // Try to find the corresponding Vulkan device for the DXGI adapter if (SUCCEEDED(pAdapter->QueryInterface(__uuidof(IDXGIDXVKAdapter), reinterpret_cast(&dxgiVkAdapter)))) { dxvkAdapter = dxgiVkAdapter->GetDXVKAdapter(); dxvkInstance = dxgiVkAdapter->GetDXVKInstance(); } else { Logger::warn("D3D11CoreCreateDevice: Adapter is not a DXVK adapter"); DXGI_ADAPTER_DESC desc; pAdapter->GetDesc(&desc); dxvkInstance = new DxvkInstance(); dxvkAdapter = dxvkInstance->findAdapterByLuid(&desc.AdapterLuid); if (dxvkAdapter == nullptr) dxvkAdapter = dxvkInstance->findAdapterByDeviceId(desc.VendorId, desc.DeviceId); if (dxvkAdapter == nullptr) dxvkAdapter = dxvkInstance->enumAdapters(0); if (dxvkAdapter == nullptr) return E_FAIL; } // Feature levels to probe if the // application does not specify any. std::array defaultFeatureLevels = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1, }; if (!pFeatureLevels || !FeatureLevels) { pFeatureLevels = defaultFeatureLevels.data(); FeatureLevels = defaultFeatureLevels.size(); } // Find the highest feature level supported by the device. // This works because the feature level array is ordered. D3D_FEATURE_LEVEL maxFeatureLevel = D3D11Device::GetMaxFeatureLevel(dxvkInstance, dxvkAdapter); D3D_FEATURE_LEVEL minFeatureLevel = D3D_FEATURE_LEVEL(); D3D_FEATURE_LEVEL devFeatureLevel = D3D_FEATURE_LEVEL(); Logger::info(str::format("D3D11CoreCreateDevice: Maximum supported feature level: ", maxFeatureLevel)); for (uint32_t flId = 0 ; flId < FeatureLevels; flId++) { minFeatureLevel = pFeatureLevels[flId]; if (minFeatureLevel <= maxFeatureLevel) { devFeatureLevel = minFeatureLevel; break; } } if (!devFeatureLevel) { Logger::err(str::format("D3D11CoreCreateDevice: Minimum required feature level ", minFeatureLevel, " not supported")); return E_INVALIDARG; } try { Logger::info(str::format("D3D11CoreCreateDevice: Using feature level ", devFeatureLevel)); Com device = new D3D11DXGIDevice( pAdapter, dxvkInstance, dxvkAdapter, devFeatureLevel, Flags); return device->QueryInterface( __uuidof(ID3D11Device), reinterpret_cast(ppDevice)); } catch (const DxvkError& e) { Logger::err("D3D11CoreCreateDevice: Failed to create D3D11 device"); return E_FAIL; } } static HRESULT D3D11InternalCreateDeviceAndSwapChain( 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) { InitReturnPtr(ppDevice); InitReturnPtr(ppSwapChain); InitReturnPtr(ppImmediateContext); if (pFeatureLevel) *pFeatureLevel = D3D_FEATURE_LEVEL(0); HRESULT hr; Com dxgiFactory = nullptr; Com dxgiAdapter = pAdapter; Com device = nullptr; if (ppSwapChain && !pSwapChainDesc) return E_INVALIDARG; if (!pAdapter) { // 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 hr = CreateDXGIFactory1(__uuidof(IDXGIFactory), reinterpret_cast(&dxgiFactory)); if (FAILED(hr)) { Logger::err("D3D11CreateDevice: Failed to create a DXGI factory"); return hr; } hr = dxgiFactory->EnumAdapters(0, &dxgiAdapter); if (FAILED(hr)) { Logger::err("D3D11CreateDevice: No default adapter available"); return hr; } } 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_INVALIDARG; } // 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) return E_INVALIDARG; } // Create the actual device hr = D3D11CoreCreateDevice( dxgiFactory.ptr(), dxgiAdapter.ptr(), Flags, pFeatureLevels, FeatureLevels, &device); if (FAILED(hr)) return hr; // Create the swap chain, if requested if (ppSwapChain) { DXGI_SWAP_CHAIN_DESC desc = *pSwapChainDesc; hr = dxgiFactory->CreateSwapChain(device.ptr(), &desc, ppSwapChain); if (FAILED(hr)) { Logger::err("D3D11CreateDevice: Failed to create swap chain"); return hr; } } // Write back whatever info the application requested if (pFeatureLevel) *pFeatureLevel = device->GetFeatureLevel(); if (ppDevice) *ppDevice = device.ref(); if (ppImmediateContext) 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 && !ppImmediateContext && !ppSwapChain) return S_FALSE; return S_OK; } 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) { return D3D11InternalCreateDeviceAndSwapChain( pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, nullptr, nullptr, ppDevice, pFeatureLevel, ppImmediateContext); } 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) { return D3D11InternalCreateDeviceAndSwapChain( pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, pSwapChainDesc, ppSwapChain, ppDevice, pFeatureLevel, ppImmediateContext); } DLLEXPORT HRESULT __stdcall D3D11On12CreateDevice( IUnknown* pDevice, UINT Flags, const D3D_FEATURE_LEVEL* pFeatureLevels, UINT FeatureLevels, IUnknown* const* ppCommandQueues, UINT NumQueues, UINT NodeMask, ID3D11Device** ppDevice, ID3D11DeviceContext** ppImmediateContext, D3D_FEATURE_LEVEL* pChosenFeatureLevel) { static bool s_errorShown = false; if (!std::exchange(s_errorShown, true)) Logger::err("D3D11On12CreateDevice: Not implemented"); return E_NOTIMPL; } }