Skip to content

Commit

Permalink
vkd3d: Implement DXVK interop interface.
Browse files Browse the repository at this point in the history
This enables D3D11on12 support.

Signed-off-by: Philip Rebohle <philip.rebohle@tu-dortmund.de>
  • Loading branch information
doitsujin authored and HansKristian-Work committed Mar 20, 2023
1 parent 0ffc125 commit 26c4fed
Show file tree
Hide file tree
Showing 4 changed files with 203 additions and 1 deletion.
2 changes: 1 addition & 1 deletion libs/vkd3d/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -8252,7 +8252,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_SetPipelineState(d3d12_command_
}
}

static VkImageLayout vk_image_layout_from_d3d12_resource_state(
VkImageLayout vk_image_layout_from_d3d12_resource_state(
struct d3d12_command_list *list, const struct d3d12_resource *resource, D3D12_RESOURCE_STATES state)
{
/* Simultaneous access is always general, until we're forced to treat it differently in
Expand Down
11 changes: 11 additions & 0 deletions libs/vkd3d/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -2856,6 +2856,7 @@ void d3d12_device_return_query_pool(struct d3d12_device *device, const struct vk

/* ID3D12Device */
extern ULONG STDMETHODCALLTYPE d3d12_device_vkd3d_ext_AddRef(ID3D12DeviceExt *iface);
extern ULONG STDMETHODCALLTYPE d3d12_dxvk_interop_device_AddRef(ID3D12DXVKInteropDevice *iface);

HRESULT STDMETHODCALLTYPE d3d12_device_QueryInterface(d3d12_device_iface *iface,
REFIID riid, void **object)
Expand Down Expand Up @@ -2889,6 +2890,14 @@ HRESULT STDMETHODCALLTYPE d3d12_device_QueryInterface(d3d12_device_iface *iface,
return S_OK;
}

if (IsEqualGUID(riid, &IID_ID3D12DXVKInteropDevice))
{
struct d3d12_device *device = impl_from_ID3D12Device(iface);
d3d12_dxvk_interop_device_AddRef(&device->ID3D12DXVKInteropDevice_iface);
*object = &device->ID3D12DXVKInteropDevice_iface;
return S_OK;
}

WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));

*object = NULL;
Expand Down Expand Up @@ -6908,6 +6917,7 @@ static void d3d12_device_replace_vtable(struct d3d12_device *device)
}

extern CONST_VTBL struct ID3D12DeviceExtVtbl d3d12_device_vkd3d_ext_vtbl;
extern CONST_VTBL struct ID3D12DXVKInteropDeviceVtbl d3d12_dxvk_interop_device_vtbl;

static HRESULT d3d12_device_init(struct d3d12_device *device,
struct vkd3d_instance *instance, const struct vkd3d_device_create_info *create_info)
Expand Down Expand Up @@ -6945,6 +6955,7 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
}

device->ID3D12DeviceExt_iface.lpVtbl = &d3d12_device_vkd3d_ext_vtbl;
device->ID3D12DXVKInteropDevice_iface.lpVtbl = &d3d12_dxvk_interop_device_vtbl;

if ((rc = rwlock_init(&device->vertex_input_lock)))
{
Expand Down
185 changes: 185 additions & 0 deletions libs/vkd3d/device_vkd3d_ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,3 +232,188 @@ CONST_VTBL struct ID3D12DeviceExtVtbl d3d12_device_vkd3d_ext_vtbl =
d3d12_device_vkd3d_ext_CaptureUAVInfo
};


static inline struct d3d12_device *d3d12_device_from_ID3D12DXVKInteropDevice(ID3D12DXVKInteropDevice *iface)
{
return CONTAINING_RECORD(iface, struct d3d12_device, ID3D12DXVKInteropDevice_iface);
}

ULONG STDMETHODCALLTYPE d3d12_dxvk_interop_device_AddRef(ID3D12DXVKInteropDevice *iface)
{
struct d3d12_device *device = d3d12_device_from_ID3D12DXVKInteropDevice(iface);
return d3d12_device_add_ref(device);
}

static ULONG STDMETHODCALLTYPE d3d12_dxvk_interop_device_Release(ID3D12DXVKInteropDevice *iface)
{
struct d3d12_device *device = d3d12_device_from_ID3D12DXVKInteropDevice(iface);
return d3d12_device_release(device);
}

extern HRESULT STDMETHODCALLTYPE d3d12_device_QueryInterface(d3d12_device_iface *iface,
REFIID riid, void **object);

static HRESULT STDMETHODCALLTYPE d3d12_dxvk_interop_device_QueryInterface(ID3D12DXVKInteropDevice *iface,
REFIID iid, void **out)
{
struct d3d12_device *device = d3d12_device_from_ID3D12DXVKInteropDevice(iface);
TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
return d3d12_device_QueryInterface(&device->ID3D12Device_iface, iid, out);
}

static HRESULT STDMETHODCALLTYPE d3d12_dxvk_interop_device_GetDXGIAdapter(ID3D12DXVKInteropDevice *iface,
REFIID iid, void **object)
{
struct d3d12_device *device = d3d12_device_from_ID3D12DXVKInteropDevice(iface);
TRACE("iface %p, iid %s, object %p.\n", iface, debugstr_guid(iid), object);
return IUnknown_QueryInterface(device->parent, iid, object);
}

static HRESULT STDMETHODCALLTYPE d3d12_dxvk_interop_device_GetVulkanHandles(ID3D12DXVKInteropDevice *iface,
VkInstance *vk_instance, VkPhysicalDevice *vk_physical_device, VkDevice *vk_device)
{
struct d3d12_device *device = d3d12_device_from_ID3D12DXVKInteropDevice(iface);
TRACE("iface %p, vk_instance %p, vk_physical_device %p, vk_device %p \n", iface, vk_instance, vk_physical_device, vk_device);
if (!vk_device || !vk_instance || !vk_physical_device)
return E_INVALIDARG;

*vk_instance = device->vkd3d_instance->vk_instance;
*vk_physical_device = device->vk_physical_device;
*vk_device = device->vk_device;
return S_OK;
}

static HRESULT STDMETHODCALLTYPE d3d12_dxvk_interop_device_GetInstanceExtensions(ID3D12DXVKInteropDevice *iface, UINT *extension_count, const char **extensions)
{
struct d3d12_device *device = d3d12_device_from_ID3D12DXVKInteropDevice(iface);
struct vkd3d_instance *instance = device->vkd3d_instance;

TRACE("iface %p, extension_count %u, extensions %p.\n", iface, extension_count, extensions);

if (extensions && (*extension_count < instance->vk_info.extension_count))
return E_INVALIDARG;

*extension_count = instance->vk_info.extension_count;

if (!extensions)
return S_OK;

memcpy(extensions, instance->vk_info.extension_names,
sizeof(*extensions) * instance->vk_info.extension_count);
return S_OK;
}

static HRESULT STDMETHODCALLTYPE d3d12_dxvk_interop_device_GetDeviceExtensions(ID3D12DXVKInteropDevice *iface, UINT *extension_count, const char **extensions)
{
struct d3d12_device *device = d3d12_device_from_ID3D12DXVKInteropDevice(iface);

TRACE("iface %p, extension_count %u, extensions %p.\n", iface, extension_count, extensions);

if (extensions && (*extension_count < device->vk_info.extension_count))
return E_INVALIDARG;

*extension_count = device->vk_info.extension_count;

if (!extensions)
return S_OK;

memcpy(extensions, device->vk_info.extension_names,
sizeof(*extensions) * device->vk_info.extension_count);
return S_OK;
}

static HRESULT STDMETHODCALLTYPE d3d12_dxvk_interop_device_GetDeviceFeatures(ID3D12DXVKInteropDevice *iface, const VkPhysicalDeviceFeatures2 **features)
{
struct d3d12_device *device = d3d12_device_from_ID3D12DXVKInteropDevice(iface);

TRACE("iface %p, features %p.\n", iface, features);

*features = &device->device_info.features2;
return S_OK;
}

static HRESULT STDMETHODCALLTYPE d3d12_dxvk_interop_device_GetVulkanQueueInfo(ID3D12DXVKInteropDevice *iface,
ID3D12CommandQueue *queue, VkQueue *vk_queue, UINT32 *vk_queue_family)
{
TRACE("iface %p, queue %p, vk_queue %p, vk_queue_family %p.\n", iface, queue, vk_queue, vk_queue_family);

/* This only gets called during D3D11 device creation */
*vk_queue = vkd3d_acquire_vk_queue(queue);
vkd3d_release_vk_queue(queue);

*vk_queue_family = vkd3d_get_vk_queue_family_index(queue);
return S_OK;
}

static void STDMETHODCALLTYPE d3d12_dxvk_interop_device_GetVulkanImageLayout(ID3D12DXVKInteropDevice *iface,
ID3D12Resource *resource, D3D12_RESOURCE_STATES state, VkImageLayout *vk_layout)
{
struct d3d12_resource *resource_impl = impl_from_ID3D12Resource(resource);

TRACE("iface %p, resource %p, state %#x.\n", iface, resource, state);

*vk_layout = vk_image_layout_from_d3d12_resource_state(NULL, resource_impl, state);
}

static HRESULT STDMETHODCALLTYPE d3d12_dxvk_interop_device_GetVulkanResourceInfo(ID3D12DXVKInteropDevice *iface,
ID3D12Resource *resource, UINT64 *vk_handle, UINT64 *buffer_offset)
{
struct d3d12_resource *resource_impl = impl_from_ID3D12Resource(resource);

TRACE("iface %p, resource %p, vk_handle %p.\n", iface, resource, vk_handle);

if (resource_impl->desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
{
*vk_handle = (UINT64)resource_impl->res.vk_buffer;
*buffer_offset = (UINT64)resource_impl->mem.offset;
}
else
{
*vk_handle = (UINT64)resource_impl->res.vk_image;
*buffer_offset = 0;
}

return S_OK;
}

static HRESULT STDMETHODCALLTYPE d3d12_dxvk_interop_device_LockCommandQueue(ID3D12DXVKInteropDevice *iface, ID3D12CommandQueue *queue)
{
struct d3d12_device *device = d3d12_device_from_ID3D12DXVKInteropDevice(iface);

TRACE("iface %p, queue %p.\n", iface, queue);

/* Flushing the transfer queue adds a wait to all other queues, and the
* acquire operation will drain the queue, ensuring that any pending clear
* or upload happens before D3D11 submissions on the GPU timeline. */
vkd3d_memory_transfer_queue_flush(&device->memory_transfers);
vkd3d_acquire_vk_queue(queue);
return S_OK;
}

static HRESULT STDMETHODCALLTYPE d3d12_dxvk_interop_device_UnlockCommandQueue(ID3D12DXVKInteropDevice *iface, ID3D12CommandQueue *queue)
{
TRACE("iface %p, queue %p.\n", iface, queue);

vkd3d_release_vk_queue(queue);
return S_OK;
}

CONST_VTBL struct ID3D12DXVKInteropDeviceVtbl d3d12_dxvk_interop_device_vtbl =
{
/* IUnknown methods */
d3d12_dxvk_interop_device_QueryInterface,
d3d12_dxvk_interop_device_AddRef,
d3d12_dxvk_interop_device_Release,

/* ID3D12DXVKInteropDevice methods */
d3d12_dxvk_interop_device_GetDXGIAdapter,
d3d12_dxvk_interop_device_GetInstanceExtensions,
d3d12_dxvk_interop_device_GetDeviceExtensions,
d3d12_dxvk_interop_device_GetDeviceFeatures,
d3d12_dxvk_interop_device_GetVulkanHandles,
d3d12_dxvk_interop_device_GetVulkanQueueInfo,
d3d12_dxvk_interop_device_GetVulkanImageLayout,
d3d12_dxvk_interop_device_GetVulkanResourceInfo,
d3d12_dxvk_interop_device_LockCommandQueue,
d3d12_dxvk_interop_device_UnlockCommandQueue,
};
6 changes: 6 additions & 0 deletions libs/vkd3d/vkd3d_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -985,6 +985,8 @@ VkImageSubresource vk_image_subresource_from_d3d12(
const struct vkd3d_format *format, uint32_t subresource_idx,
unsigned int miplevel_count, unsigned int layer_count,
bool all_aspects);
VkImageLayout vk_image_layout_from_d3d12_resource_state(
struct d3d12_command_list *list, const struct d3d12_resource *resource, D3D12_RESOURCE_STATES state);
UINT d3d12_plane_index_from_vk_aspect(VkImageAspectFlagBits aspect);

HRESULT d3d12_resource_create_committed(struct d3d12_device *device, const D3D12_RESOURCE_DESC1 *desc,
Expand Down Expand Up @@ -4016,6 +4018,9 @@ struct vkd3d_descriptor_qa_heap_buffer_data;
/* ID3D12DeviceExt */
typedef ID3D12DeviceExt d3d12_device_vkd3d_ext_iface;

/* ID3D12DXVKInteropDevice */
typedef ID3D12DXVKInteropDevice d3d12_dxvk_interop_device_iface;

struct d3d12_device_scratch_pool
{
struct vkd3d_scratch_buffer scratch_buffers[VKD3D_SCRATCH_BUFFER_COUNT];
Expand All @@ -4026,6 +4031,7 @@ struct d3d12_device
{
d3d12_device_iface ID3D12Device_iface;
d3d12_device_vkd3d_ext_iface ID3D12DeviceExt_iface;
d3d12_dxvk_interop_device_iface ID3D12DXVKInteropDevice_iface;
LONG refcount;

VkDevice vk_device;
Expand Down

0 comments on commit 26c4fed

Please sign in to comment.