dxvk/src/d3d11/d3d11_main.cpp

269 lines
9.1 KiB
C++

#include <array>
#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> dxvkAdapter;
Rc<DxvkInstance> dxvkInstance;
Com<IDXGIDXVKAdapter> dxgiVkAdapter;
// Try to find the corresponding Vulkan device for the DXGI adapter
if (SUCCEEDED(pAdapter->QueryInterface(__uuidof(IDXGIDXVKAdapter), reinterpret_cast<void**>(&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<D3D_FEATURE_LEVEL, 6> 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<D3D11DXGIDevice> device = new D3D11DXGIDevice(
pAdapter, dxvkInstance, dxvkAdapter, devFeatureLevel, Flags);
return device->QueryInterface(
__uuidof(ID3D11Device),
reinterpret_cast<void**>(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<IDXGIFactory> dxgiFactory = nullptr;
Com<IDXGIAdapter> dxgiAdapter = pAdapter;
Com<ID3D11Device> 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<void**>(&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<void**>(&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;
}
}