[d3d11] Implement D3D11on12 device creation

This commit is contained in:
Philip Rebohle 2023-03-16 01:34:49 +01:00
parent da32453b42
commit 6432787ac3
7 changed files with 386 additions and 20 deletions

View File

@ -1832,6 +1832,11 @@ namespace dxvk {
DXGI_VK_FORMAT_MODE Mode) const {
return m_d3d11Formats.GetFormatFamily(Format, Mode);
}
bool D3D11Device::Is11on12Device() const {
return m_container->Is11on12Device();
}
void D3D11Device::FlushInitContext() {
@ -3057,18 +3062,22 @@ namespace dxvk {
D3D11DXGIDevice::D3D11DXGIDevice(
IDXGIAdapter* pAdapter,
const Rc<DxvkInstance>& pDxvkInstance,
const Rc<DxvkAdapter>& pDxvkAdapter,
ID3D12Device* pD3D12Device,
ID3D12CommandQueue* pD3D12Queue,
Rc<DxvkInstance> pDxvkInstance,
Rc<DxvkAdapter> pDxvkAdapter,
Rc<DxvkDevice> pDxvkDevice,
D3D_FEATURE_LEVEL FeatureLevel,
UINT FeatureFlags)
: m_dxgiAdapter (pAdapter),
m_dxvkInstance (pDxvkInstance),
m_dxvkAdapter (pDxvkAdapter),
m_dxvkDevice (CreateDevice(FeatureLevel)),
m_dxvkDevice (pDxvkDevice),
m_d3d11Device (this, FeatureLevel, FeatureFlags),
m_d3d11DeviceExt(this, &m_d3d11Device),
m_d3d11Interop (this, &m_d3d11Device),
m_d3d11Video (this, &m_d3d11Device),
m_d3d11on12 (this, &m_d3d11Device, pD3D12Device, pD3D12Queue),
m_metaDevice (this),
m_dxvkFactory (this, &m_d3d11Device) {
@ -3076,7 +3085,7 @@ namespace dxvk {
D3D11DXGIDevice::~D3D11DXGIDevice() {
}
@ -3140,6 +3149,13 @@ namespace dxvk {
return S_OK;
}
if (m_d3d11on12.Is11on12Device()) {
if (riid == __uuidof(ID3D11On12Device)) {
*ppvObject = ref(&m_d3d11on12);
return S_OK;
}
}
if (riid == __uuidof(ID3D10Multithread)) {
Com<ID3D11DeviceContext> context;
m_d3d11Device.GetImmediateContext(&context);
@ -3403,10 +3419,4 @@ namespace dxvk {
return m_dxvkDevice;
}
Rc<DxvkDevice> D3D11DXGIDevice::CreateDevice(D3D_FEATURE_LEVEL FeatureLevel) {
DxvkDeviceFeatures deviceFeatures = D3D11Device::GetDeviceFeatures(m_dxvkAdapter);
return m_dxvkAdapter->createDevice(m_dxvkInstance, deviceFeatures);
}
}

View File

@ -20,6 +20,7 @@
#include "d3d11_initializer.h"
#include "d3d11_interfaces.h"
#include "d3d11_interop.h"
#include "d3d11_on_12.h"
#include "d3d11_options.h"
#include "d3d11_shader.h"
#include "d3d11_state.h"
@ -421,6 +422,8 @@ namespace dxvk {
return m_d3d10Device;
}
bool Is11on12Device() const;
static D3D_FEATURE_LEVEL GetMaxFeatureLevel(
const Rc<DxvkInstance>& Instance,
const Rc<DxvkAdapter>& Adapter);
@ -430,7 +433,7 @@ namespace dxvk {
private:
IDXGIObject* m_container;
D3D11DXGIDevice* m_container;
D3D_FEATURE_LEVEL m_featureLevel;
UINT m_featureFlags;
@ -764,8 +767,11 @@ namespace dxvk {
D3D11DXGIDevice(
IDXGIAdapter* pAdapter,
const Rc<DxvkInstance>& pDxvkInstance,
const Rc<DxvkAdapter>& pDxvkAdapter,
ID3D12Device* pD3D12Device,
ID3D12CommandQueue* pD3D12Queue,
Rc<DxvkInstance> pDxvkInstance,
Rc<DxvkAdapter> pDxvkAdapter,
Rc<DxvkDevice> pDxvkDevice,
D3D_FEATURE_LEVEL FeatureLevel,
UINT FeatureFlags);
@ -834,6 +840,10 @@ namespace dxvk {
Rc<DxvkDevice> STDMETHODCALLTYPE GetDXVKDevice();
BOOL Is11on12Device() const {
return m_d3d11on12.Is11on12Device();
}
private:
Com<IDXGIAdapter> m_dxgiAdapter;
@ -846,14 +856,13 @@ namespace dxvk {
D3D11DeviceExt m_d3d11DeviceExt;
D3D11VkInterop m_d3d11Interop;
D3D11VideoDevice m_d3d11Video;
D3D11on12Device m_d3d11on12;
DXGIDXVKDevice m_metaDevice;
DXGIVkSwapChainFactory m_dxvkFactory;
uint32_t m_frameLatency = DefaultFrameLatency;
Rc<DxvkDevice> CreateDevice(D3D_FEATURE_LEVEL FeatureLevel);
};
}

View File

@ -89,8 +89,13 @@ extern "C" {
try {
Logger::info(str::format("D3D11CoreCreateDevice: Using feature level ", devFeatureLevel));
DxvkDeviceFeatures deviceFeatures = D3D11Device::GetDeviceFeatures(dxvkAdapter);
Rc<DxvkDevice> dxvkDevice = dxvkAdapter->createDevice(dxvkInstance, deviceFeatures);
Com<D3D11DXGIDevice> device = new D3D11DXGIDevice(
pAdapter, dxvkInstance, dxvkAdapter, devFeatureLevel, Flags);
pAdapter, nullptr, nullptr,
dxvkInstance, dxvkAdapter, dxvkDevice,
devFeatureLevel, Flags);
return device->QueryInterface(
__uuidof(ID3D11Device),
@ -258,12 +263,169 @@ extern "C" {
ID3D11Device** ppDevice,
ID3D11DeviceContext** ppImmediateContext,
D3D_FEATURE_LEVEL* pChosenFeatureLevel) {
static bool s_errorShown = false;
InitReturnPtr(ppDevice);
InitReturnPtr(ppImmediateContext);
if (!std::exchange(s_errorShown, true))
Logger::err("D3D11On12CreateDevice: Not implemented");
if (pChosenFeatureLevel)
*pChosenFeatureLevel = D3D_FEATURE_LEVEL(0);
return E_NOTIMPL;
if (!pDevice)
return E_INVALIDARG;
// Figure out D3D12 objects
Com<ID3D12Device> d3d12Device;
Com<ID3D12CommandQueue> d3d12Queue;
if (FAILED(pDevice->QueryInterface(__uuidof(ID3D12Device), reinterpret_cast<void**>(&d3d12Device)))) {
Logger::err("D3D11On12CreateDevice: Device is not a valid D3D12 device");
return E_INVALIDARG;
}
if (NodeMask & (NodeMask - 1)) {
Logger::err("D3D11On12CreateDevice: Invalid node mask");
return E_INVALIDARG;
}
if (!NumQueues || !ppCommandQueues || !ppCommandQueues[0]) {
Logger::err("D3D11On12CreateDevice: No command queue specified");
return E_INVALIDARG;
}
if (NumQueues > 1) {
// Not sure what to do with more than one graphics queue
Logger::warn("D3D11On12CreateDevice: Only one queue supported");
}
if (FAILED(ppCommandQueues[0]->QueryInterface(__uuidof(ID3D12CommandQueue), reinterpret_cast<void**>(&d3d12Queue)))) {
Logger::err("D3D11On12CreateDevice: Queue is not a valid D3D12 command queue");
return E_INVALIDARG;
}
// Determine feature level for the D3D11 device
std::array<D3D_FEATURE_LEVEL, 4> defaultFeatureLevels = {{
D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_12_0, D3D_FEATURE_LEVEL_12_1,
}};
D3D12_FEATURE_DATA_FEATURE_LEVELS featureLevel = { };
if (!FeatureLevels || !pFeatureLevels) {
featureLevel.NumFeatureLevels = defaultFeatureLevels.size();
featureLevel.pFeatureLevelsRequested = defaultFeatureLevels.data();
} else {
featureLevel.NumFeatureLevels = FeatureLevels;
featureLevel.pFeatureLevelsRequested = pFeatureLevels;
}
HRESULT hr = d3d12Device->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS, &featureLevel, sizeof(featureLevel));
if (FAILED(hr) || !featureLevel.MaxSupportedFeatureLevel) {
Logger::err(str::format("D3D11On12CreateDevice: Minimum required feature level not supported"));
return hr;
}
Logger::info(str::format("D3D11On12CreateDevice: Chosen feature level: ", featureLevel.MaxSupportedFeatureLevel));
Com<ID3D12DXVKInteropDevice> interopDevice;
if (FAILED(d3d12Device->QueryInterface(__uuidof(ID3D12DXVKInteropDevice), reinterpret_cast<void**>(&interopDevice)))) {
Logger::err("D3D11On12CreateDevice: Device not a vkd3d-proton device.");
return E_INVALIDARG;
}
Com<IDXGIAdapter> dxgiAdapter;
if (FAILED(interopDevice->GetDXGIAdapter(IID_PPV_ARGS(&dxgiAdapter)))) {
Logger::err("D3D11On12CreateDevice: Failed to query DXGI adapter.");
return E_INVALIDARG;
}
try {
// Initialize DXVK instance
DxvkInstanceImportInfo instanceInfo = { };
DxvkDeviceImportInfo deviceInfo = { };
VkPhysicalDevice vulkanAdapter = VK_NULL_HANDLE;
interopDevice->GetVulkanHandles(&instanceInfo.instance, &vulkanAdapter, &deviceInfo.device);
uint32_t instanceExtensionCount = 0;
interopDevice->GetInstanceExtensions(&instanceExtensionCount, nullptr);
std::vector<const char*> instanceExtensions(instanceExtensionCount);
interopDevice->GetInstanceExtensions(&instanceExtensionCount, instanceExtensions.data());
instanceInfo.extensionCount = instanceExtensions.size();
instanceInfo.extensionNames = instanceExtensions.data();
Rc<DxvkInstance> dxvkInstance = new DxvkInstance(instanceInfo);
// Find adapter by physical device handle
Rc<DxvkAdapter> dxvkAdapter;
for (uint32_t i = 0; i < dxvkInstance->adapterCount(); i++) {
Rc<DxvkAdapter> curr = dxvkInstance->enumAdapters(i);
if (curr->handle() == vulkanAdapter)
dxvkAdapter = std::move(curr);
}
if (dxvkAdapter == nullptr) {
Logger::err("D3D11On12CreateDevice: No matching adapter found");
return E_INVALIDARG;
}
interopDevice->GetVulkanQueueInfo(d3d12Queue.ptr(), &deviceInfo.queue, &deviceInfo.queueFamily);
interopDevice->GetDeviceFeatures(&deviceInfo.features);
uint32_t deviceExtensionCount = 0;
interopDevice->GetDeviceExtensions(&deviceExtensionCount, nullptr);
std::vector<const char*> deviceExtensions(deviceExtensionCount);
interopDevice->GetDeviceExtensions(&deviceExtensionCount, deviceExtensions.data());
deviceInfo.extensionCount = deviceExtensions.size();
deviceInfo.extensionNames = deviceExtensions.data();
deviceInfo.queueCallback = [
cDevice = interopDevice,
cQueue = d3d12Queue
] (bool doLock) {
HRESULT hr = doLock
? cDevice->LockCommandQueue(cQueue.ptr())
: cDevice->UnlockCommandQueue(cQueue.ptr());
if (FAILED(hr))
Logger::err(str::format("Failed to lock vkd3d-proton device queue: ", hr));
};
Rc<DxvkDevice> dxvkDevice = dxvkAdapter->importDevice(dxvkInstance, deviceInfo);
// Create and return the actual D3D11 device
Com<D3D11DXGIDevice> device = new D3D11DXGIDevice(
dxgiAdapter.ptr(), d3d12Device.ptr(), d3d12Queue.ptr(),
dxvkInstance, dxvkAdapter, dxvkDevice,
featureLevel.MaxSupportedFeatureLevel, Flags);
Com<ID3D11Device> d3d11Device;
device->QueryInterface(__uuidof(ID3D11Device), reinterpret_cast<void**>(&d3d11Device));
if (ppDevice)
*ppDevice = d3d11Device.ref();
if (ppImmediateContext)
d3d11Device->GetImmediateContext(ppImmediateContext);
if (pChosenFeatureLevel)
*pChosenFeatureLevel = d3d11Device->GetFeatureLevel();
if (!ppDevice && !ppImmediateContext)
return S_FALSE;
return S_OK;
} catch (const DxvkError& e) {
Logger::err("D3D11On12CreateDevice: Failed to create D3D11 device");
return E_FAIL;
}
}
}

66
src/d3d11/d3d11_on_12.cpp Normal file
View File

@ -0,0 +1,66 @@
#include "d3d11_device.h"
#include "d3d11_on_12.h"
namespace dxvk {
D3D11on12Device::D3D11on12Device(
D3D11DXGIDevice* pContainer,
D3D11Device* pDevice,
ID3D12Device* pD3D12Device,
ID3D12CommandQueue* pD3D12Queue)
: m_container (pContainer),
m_device (pDevice),
m_d3d12Device (pD3D12Device),
m_d3d12Queue (pD3D12Queue) {
}
D3D11on12Device::~D3D11on12Device() {
}
ULONG STDMETHODCALLTYPE D3D11on12Device::AddRef() {
return m_container->AddRef();
}
ULONG STDMETHODCALLTYPE D3D11on12Device::Release() {
return m_container->Release();
}
HRESULT STDMETHODCALLTYPE D3D11on12Device::QueryInterface(
REFIID riid,
void** ppvObject) {
return m_container->QueryInterface(riid, ppvObject);
}
HRESULT STDMETHODCALLTYPE D3D11on12Device::CreateWrappedResource(
IUnknown* pResource12,
const D3D11_RESOURCE_FLAGS* pResourceFlags,
D3D12_RESOURCE_STATES InputState,
D3D12_RESOURCE_STATES OutputState,
REFIID riid,
void** ppResource11) {
Logger::err("D3D11on12Device::CreateWrappedResource: Stub");
return E_NOTIMPL;
}
void STDMETHODCALLTYPE D3D11on12Device::ReleaseWrappedResources(
ID3D11Resource* const* ppResources,
UINT ResourceCount) {
Logger::err("D3D11on12Device::ReleaseWrappedResources: Stub");
}
void STDMETHODCALLTYPE D3D11on12Device::AcquireWrappedResources(
ID3D11Resource* const* ppResources,
UINT ResourceCount) {
Logger::err("D3D11on12Device::AcquireWrappedResources: Stub");
}
}

62
src/d3d11/d3d11_on_12.h Normal file
View File

@ -0,0 +1,62 @@
#pragma once
#include "d3d11_on_12_interfaces.h"
#include "../util/log/log.h"
namespace dxvk {
class D3D11Device;
class D3D11DXGIDevice;
class D3D11on12Device : public ID3D11On12Device {
public:
D3D11on12Device(
D3D11DXGIDevice* pContainer,
D3D11Device* pDevice,
ID3D12Device* pD3D12Device,
ID3D12CommandQueue* pD3D12Queue);
~D3D11on12Device();
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid,
void** ppvObject);
HRESULT STDMETHODCALLTYPE CreateWrappedResource(
IUnknown* pResource12,
const D3D11_RESOURCE_FLAGS* pResourceFlags,
D3D12_RESOURCE_STATES InputState,
D3D12_RESOURCE_STATES OutputState,
REFIID riid,
void** ppResource11);
void STDMETHODCALLTYPE ReleaseWrappedResources(
ID3D11Resource* const* ppResources,
UINT ResourceCount);
void STDMETHODCALLTYPE AcquireWrappedResources(
ID3D11Resource* const* ppResources,
UINT ResourceCount);
bool Is11on12Device() const {
return m_d3d12Device != nullptr;
}
private:
D3D11DXGIDevice* m_container;
D3D11Device* m_device;
Com<ID3D12Device> m_d3d12Device;
Com<ID3D12CommandQueue> m_d3d12Queue;
};
}

View File

@ -0,0 +1,56 @@
#pragma once
#include "../vulkan/vulkan_loader.h"
#include <d3d11on12.h>
MIDL_INTERFACE("39da4e09-bd1c-4198-9fae-86bbe3be41fd")
ID3D12DXVKInteropDevice : public IUnknown {
virtual HRESULT STDMETHODCALLTYPE GetDXGIAdapter(
REFIID iid,
void** ppvObject) = 0;
virtual HRESULT STDMETHODCALLTYPE GetInstanceExtensions(
UINT* pExtensionCount,
const char** ppExtensions) = 0;
virtual HRESULT STDMETHODCALLTYPE GetDeviceExtensions(
UINT* pExtensionCount,
const char** ppExtensions) = 0;
virtual HRESULT STDMETHODCALLTYPE GetDeviceFeatures(
const VkPhysicalDeviceFeatures2** ppFeatures) = 0;
virtual HRESULT STDMETHODCALLTYPE GetVulkanHandles(
VkInstance* pVkInstance,
VkPhysicalDevice* pVkPhysicalDevice,
VkDevice* pVkDevice) = 0;
virtual HRESULT STDMETHODCALLTYPE GetVulkanQueueInfo(
ID3D12CommandQueue* pCommandQueue,
VkQueue* pVkQueue,
UINT32* pVkQueueFamily) = 0;
virtual void STDMETHODCALLTYPE GetVulkanImageLayout(
ID3D12Resource* pResource,
D3D12_RESOURCE_STATES State,
VkImageLayout* pVkLayout) = 0;
virtual HRESULT STDMETHODCALLTYPE GetVulkanResourceInfo(
ID3D12Resource* pResource,
UINT64* pVkHandle,
UINT64* pBufferOffset) = 0;
virtual HRESULT STDMETHODCALLTYPE LockCommandQueue(
ID3D12CommandQueue* pCommandQueue) = 0;
virtual HRESULT STDMETHODCALLTYPE UnlockCommandQueue(
ID3D12CommandQueue* pCommandQueue) = 0;
};
#ifdef _MSC_VER
struct __declspec(uuid("39da4e09-bd1c-4198-9fae-86bbe3be41fd")) ID3D12DXVKInteropDevice;
#else
__CRT_UUID_DECL(ID3D12DXVKInteropDevice, 0x39da4e09, 0xbd1c, 0x4198, 0x9f,0xae, 0x86,0xbb,0xe3,0xbe,0x41,0xfd)
#endif

View File

@ -42,6 +42,7 @@ d3d11_src = [
'd3d11_input_layout.cpp',
'd3d11_interop.cpp',
'd3d11_main.cpp',
'd3d11_on_12.cpp',
'd3d11_options.cpp',
'd3d11_query.cpp',
'd3d11_rasterizer.cpp',