Skip to content

Commit 26c4fed

Browse files
doitsujinHansKristian-Work
authored andcommitted
vkd3d: Implement DXVK interop interface.
This enables D3D11on12 support. Signed-off-by: Philip Rebohle <[email protected]>
1 parent 0ffc125 commit 26c4fed

File tree

4 files changed

+203
-1
lines changed

4 files changed

+203
-1
lines changed

libs/vkd3d/command.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -8252,7 +8252,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_SetPipelineState(d3d12_command_
82528252
}
82538253
}
82548254

8255-
static VkImageLayout vk_image_layout_from_d3d12_resource_state(
8255+
VkImageLayout vk_image_layout_from_d3d12_resource_state(
82568256
struct d3d12_command_list *list, const struct d3d12_resource *resource, D3D12_RESOURCE_STATES state)
82578257
{
82588258
/* Simultaneous access is always general, until we're forced to treat it differently in

libs/vkd3d/device.c

+11
Original file line numberDiff line numberDiff line change
@@ -2856,6 +2856,7 @@ void d3d12_device_return_query_pool(struct d3d12_device *device, const struct vk
28562856

28572857
/* ID3D12Device */
28582858
extern ULONG STDMETHODCALLTYPE d3d12_device_vkd3d_ext_AddRef(ID3D12DeviceExt *iface);
2859+
extern ULONG STDMETHODCALLTYPE d3d12_dxvk_interop_device_AddRef(ID3D12DXVKInteropDevice *iface);
28592860

28602861
HRESULT STDMETHODCALLTYPE d3d12_device_QueryInterface(d3d12_device_iface *iface,
28612862
REFIID riid, void **object)
@@ -2889,6 +2890,14 @@ HRESULT STDMETHODCALLTYPE d3d12_device_QueryInterface(d3d12_device_iface *iface,
28892890
return S_OK;
28902891
}
28912892

2893+
if (IsEqualGUID(riid, &IID_ID3D12DXVKInteropDevice))
2894+
{
2895+
struct d3d12_device *device = impl_from_ID3D12Device(iface);
2896+
d3d12_dxvk_interop_device_AddRef(&device->ID3D12DXVKInteropDevice_iface);
2897+
*object = &device->ID3D12DXVKInteropDevice_iface;
2898+
return S_OK;
2899+
}
2900+
28922901
WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
28932902

28942903
*object = NULL;
@@ -6908,6 +6917,7 @@ static void d3d12_device_replace_vtable(struct d3d12_device *device)
69086917
}
69096918

69106919
extern CONST_VTBL struct ID3D12DeviceExtVtbl d3d12_device_vkd3d_ext_vtbl;
6920+
extern CONST_VTBL struct ID3D12DXVKInteropDeviceVtbl d3d12_dxvk_interop_device_vtbl;
69116921

69126922
static HRESULT d3d12_device_init(struct d3d12_device *device,
69136923
struct vkd3d_instance *instance, const struct vkd3d_device_create_info *create_info)
@@ -6945,6 +6955,7 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
69456955
}
69466956

69476957
device->ID3D12DeviceExt_iface.lpVtbl = &d3d12_device_vkd3d_ext_vtbl;
6958+
device->ID3D12DXVKInteropDevice_iface.lpVtbl = &d3d12_dxvk_interop_device_vtbl;
69486959

69496960
if ((rc = rwlock_init(&device->vertex_input_lock)))
69506961
{

libs/vkd3d/device_vkd3d_ext.c

+185
Original file line numberDiff line numberDiff line change
@@ -232,3 +232,188 @@ CONST_VTBL struct ID3D12DeviceExtVtbl d3d12_device_vkd3d_ext_vtbl =
232232
d3d12_device_vkd3d_ext_CaptureUAVInfo
233233
};
234234

235+
236+
static inline struct d3d12_device *d3d12_device_from_ID3D12DXVKInteropDevice(ID3D12DXVKInteropDevice *iface)
237+
{
238+
return CONTAINING_RECORD(iface, struct d3d12_device, ID3D12DXVKInteropDevice_iface);
239+
}
240+
241+
ULONG STDMETHODCALLTYPE d3d12_dxvk_interop_device_AddRef(ID3D12DXVKInteropDevice *iface)
242+
{
243+
struct d3d12_device *device = d3d12_device_from_ID3D12DXVKInteropDevice(iface);
244+
return d3d12_device_add_ref(device);
245+
}
246+
247+
static ULONG STDMETHODCALLTYPE d3d12_dxvk_interop_device_Release(ID3D12DXVKInteropDevice *iface)
248+
{
249+
struct d3d12_device *device = d3d12_device_from_ID3D12DXVKInteropDevice(iface);
250+
return d3d12_device_release(device);
251+
}
252+
253+
extern HRESULT STDMETHODCALLTYPE d3d12_device_QueryInterface(d3d12_device_iface *iface,
254+
REFIID riid, void **object);
255+
256+
static HRESULT STDMETHODCALLTYPE d3d12_dxvk_interop_device_QueryInterface(ID3D12DXVKInteropDevice *iface,
257+
REFIID iid, void **out)
258+
{
259+
struct d3d12_device *device = d3d12_device_from_ID3D12DXVKInteropDevice(iface);
260+
TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
261+
return d3d12_device_QueryInterface(&device->ID3D12Device_iface, iid, out);
262+
}
263+
264+
static HRESULT STDMETHODCALLTYPE d3d12_dxvk_interop_device_GetDXGIAdapter(ID3D12DXVKInteropDevice *iface,
265+
REFIID iid, void **object)
266+
{
267+
struct d3d12_device *device = d3d12_device_from_ID3D12DXVKInteropDevice(iface);
268+
TRACE("iface %p, iid %s, object %p.\n", iface, debugstr_guid(iid), object);
269+
return IUnknown_QueryInterface(device->parent, iid, object);
270+
}
271+
272+
static HRESULT STDMETHODCALLTYPE d3d12_dxvk_interop_device_GetVulkanHandles(ID3D12DXVKInteropDevice *iface,
273+
VkInstance *vk_instance, VkPhysicalDevice *vk_physical_device, VkDevice *vk_device)
274+
{
275+
struct d3d12_device *device = d3d12_device_from_ID3D12DXVKInteropDevice(iface);
276+
TRACE("iface %p, vk_instance %p, vk_physical_device %p, vk_device %p \n", iface, vk_instance, vk_physical_device, vk_device);
277+
if (!vk_device || !vk_instance || !vk_physical_device)
278+
return E_INVALIDARG;
279+
280+
*vk_instance = device->vkd3d_instance->vk_instance;
281+
*vk_physical_device = device->vk_physical_device;
282+
*vk_device = device->vk_device;
283+
return S_OK;
284+
}
285+
286+
static HRESULT STDMETHODCALLTYPE d3d12_dxvk_interop_device_GetInstanceExtensions(ID3D12DXVKInteropDevice *iface, UINT *extension_count, const char **extensions)
287+
{
288+
struct d3d12_device *device = d3d12_device_from_ID3D12DXVKInteropDevice(iface);
289+
struct vkd3d_instance *instance = device->vkd3d_instance;
290+
291+
TRACE("iface %p, extension_count %u, extensions %p.\n", iface, extension_count, extensions);
292+
293+
if (extensions && (*extension_count < instance->vk_info.extension_count))
294+
return E_INVALIDARG;
295+
296+
*extension_count = instance->vk_info.extension_count;
297+
298+
if (!extensions)
299+
return S_OK;
300+
301+
memcpy(extensions, instance->vk_info.extension_names,
302+
sizeof(*extensions) * instance->vk_info.extension_count);
303+
return S_OK;
304+
}
305+
306+
static HRESULT STDMETHODCALLTYPE d3d12_dxvk_interop_device_GetDeviceExtensions(ID3D12DXVKInteropDevice *iface, UINT *extension_count, const char **extensions)
307+
{
308+
struct d3d12_device *device = d3d12_device_from_ID3D12DXVKInteropDevice(iface);
309+
310+
TRACE("iface %p, extension_count %u, extensions %p.\n", iface, extension_count, extensions);
311+
312+
if (extensions && (*extension_count < device->vk_info.extension_count))
313+
return E_INVALIDARG;
314+
315+
*extension_count = device->vk_info.extension_count;
316+
317+
if (!extensions)
318+
return S_OK;
319+
320+
memcpy(extensions, device->vk_info.extension_names,
321+
sizeof(*extensions) * device->vk_info.extension_count);
322+
return S_OK;
323+
}
324+
325+
static HRESULT STDMETHODCALLTYPE d3d12_dxvk_interop_device_GetDeviceFeatures(ID3D12DXVKInteropDevice *iface, const VkPhysicalDeviceFeatures2 **features)
326+
{
327+
struct d3d12_device *device = d3d12_device_from_ID3D12DXVKInteropDevice(iface);
328+
329+
TRACE("iface %p, features %p.\n", iface, features);
330+
331+
*features = &device->device_info.features2;
332+
return S_OK;
333+
}
334+
335+
static HRESULT STDMETHODCALLTYPE d3d12_dxvk_interop_device_GetVulkanQueueInfo(ID3D12DXVKInteropDevice *iface,
336+
ID3D12CommandQueue *queue, VkQueue *vk_queue, UINT32 *vk_queue_family)
337+
{
338+
TRACE("iface %p, queue %p, vk_queue %p, vk_queue_family %p.\n", iface, queue, vk_queue, vk_queue_family);
339+
340+
/* This only gets called during D3D11 device creation */
341+
*vk_queue = vkd3d_acquire_vk_queue(queue);
342+
vkd3d_release_vk_queue(queue);
343+
344+
*vk_queue_family = vkd3d_get_vk_queue_family_index(queue);
345+
return S_OK;
346+
}
347+
348+
static void STDMETHODCALLTYPE d3d12_dxvk_interop_device_GetVulkanImageLayout(ID3D12DXVKInteropDevice *iface,
349+
ID3D12Resource *resource, D3D12_RESOURCE_STATES state, VkImageLayout *vk_layout)
350+
{
351+
struct d3d12_resource *resource_impl = impl_from_ID3D12Resource(resource);
352+
353+
TRACE("iface %p, resource %p, state %#x.\n", iface, resource, state);
354+
355+
*vk_layout = vk_image_layout_from_d3d12_resource_state(NULL, resource_impl, state);
356+
}
357+
358+
static HRESULT STDMETHODCALLTYPE d3d12_dxvk_interop_device_GetVulkanResourceInfo(ID3D12DXVKInteropDevice *iface,
359+
ID3D12Resource *resource, UINT64 *vk_handle, UINT64 *buffer_offset)
360+
{
361+
struct d3d12_resource *resource_impl = impl_from_ID3D12Resource(resource);
362+
363+
TRACE("iface %p, resource %p, vk_handle %p.\n", iface, resource, vk_handle);
364+
365+
if (resource_impl->desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
366+
{
367+
*vk_handle = (UINT64)resource_impl->res.vk_buffer;
368+
*buffer_offset = (UINT64)resource_impl->mem.offset;
369+
}
370+
else
371+
{
372+
*vk_handle = (UINT64)resource_impl->res.vk_image;
373+
*buffer_offset = 0;
374+
}
375+
376+
return S_OK;
377+
}
378+
379+
static HRESULT STDMETHODCALLTYPE d3d12_dxvk_interop_device_LockCommandQueue(ID3D12DXVKInteropDevice *iface, ID3D12CommandQueue *queue)
380+
{
381+
struct d3d12_device *device = d3d12_device_from_ID3D12DXVKInteropDevice(iface);
382+
383+
TRACE("iface %p, queue %p.\n", iface, queue);
384+
385+
/* Flushing the transfer queue adds a wait to all other queues, and the
386+
* acquire operation will drain the queue, ensuring that any pending clear
387+
* or upload happens before D3D11 submissions on the GPU timeline. */
388+
vkd3d_memory_transfer_queue_flush(&device->memory_transfers);
389+
vkd3d_acquire_vk_queue(queue);
390+
return S_OK;
391+
}
392+
393+
static HRESULT STDMETHODCALLTYPE d3d12_dxvk_interop_device_UnlockCommandQueue(ID3D12DXVKInteropDevice *iface, ID3D12CommandQueue *queue)
394+
{
395+
TRACE("iface %p, queue %p.\n", iface, queue);
396+
397+
vkd3d_release_vk_queue(queue);
398+
return S_OK;
399+
}
400+
401+
CONST_VTBL struct ID3D12DXVKInteropDeviceVtbl d3d12_dxvk_interop_device_vtbl =
402+
{
403+
/* IUnknown methods */
404+
d3d12_dxvk_interop_device_QueryInterface,
405+
d3d12_dxvk_interop_device_AddRef,
406+
d3d12_dxvk_interop_device_Release,
407+
408+
/* ID3D12DXVKInteropDevice methods */
409+
d3d12_dxvk_interop_device_GetDXGIAdapter,
410+
d3d12_dxvk_interop_device_GetInstanceExtensions,
411+
d3d12_dxvk_interop_device_GetDeviceExtensions,
412+
d3d12_dxvk_interop_device_GetDeviceFeatures,
413+
d3d12_dxvk_interop_device_GetVulkanHandles,
414+
d3d12_dxvk_interop_device_GetVulkanQueueInfo,
415+
d3d12_dxvk_interop_device_GetVulkanImageLayout,
416+
d3d12_dxvk_interop_device_GetVulkanResourceInfo,
417+
d3d12_dxvk_interop_device_LockCommandQueue,
418+
d3d12_dxvk_interop_device_UnlockCommandQueue,
419+
};

libs/vkd3d/vkd3d_private.h

+6
Original file line numberDiff line numberDiff line change
@@ -985,6 +985,8 @@ VkImageSubresource vk_image_subresource_from_d3d12(
985985
const struct vkd3d_format *format, uint32_t subresource_idx,
986986
unsigned int miplevel_count, unsigned int layer_count,
987987
bool all_aspects);
988+
VkImageLayout vk_image_layout_from_d3d12_resource_state(
989+
struct d3d12_command_list *list, const struct d3d12_resource *resource, D3D12_RESOURCE_STATES state);
988990
UINT d3d12_plane_index_from_vk_aspect(VkImageAspectFlagBits aspect);
989991

990992
HRESULT d3d12_resource_create_committed(struct d3d12_device *device, const D3D12_RESOURCE_DESC1 *desc,
@@ -4016,6 +4018,9 @@ struct vkd3d_descriptor_qa_heap_buffer_data;
40164018
/* ID3D12DeviceExt */
40174019
typedef ID3D12DeviceExt d3d12_device_vkd3d_ext_iface;
40184020

4021+
/* ID3D12DXVKInteropDevice */
4022+
typedef ID3D12DXVKInteropDevice d3d12_dxvk_interop_device_iface;
4023+
40194024
struct d3d12_device_scratch_pool
40204025
{
40214026
struct vkd3d_scratch_buffer scratch_buffers[VKD3D_SCRATCH_BUFFER_COUNT];
@@ -4026,6 +4031,7 @@ struct d3d12_device
40264031
{
40274032
d3d12_device_iface ID3D12Device_iface;
40284033
d3d12_device_vkd3d_ext_iface ID3D12DeviceExt_iface;
4034+
d3d12_dxvk_interop_device_iface ID3D12DXVKInteropDevice_iface;
40294035
LONG refcount;
40304036

40314037
VkDevice vk_device;

0 commit comments

Comments
 (0)