diff --git a/include/meson.build b/include/meson.build index 83a09173..ba100152 100644 --- a/include/meson.build +++ b/include/meson.build @@ -10,6 +10,8 @@ vkd3d_idl = [ 'vkd3d_dxgiformat.idl', 'vkd3d_dxgitype.idl', 'vkd3d_swapchain_factory.idl', + 'vkd3d_command_list_vkd3d_ext.idl', + 'vkd3d_device_vkd3d_ext.idl' ] vkd3d_header_files = idl_generator.process(vkd3d_idl) diff --git a/include/vkd3d_command_list_vkd3d_ext.idl b/include/vkd3d_command_list_vkd3d_ext.idl new file mode 100644 index 00000000..9bf3423d --- /dev/null +++ b/include/vkd3d_command_list_vkd3d_ext.idl @@ -0,0 +1,32 @@ +/* + * * Copyright 2021 NVIDIA Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +import "vkd3d_d3d12.idl"; +import "vkd3d_vk_includes.h"; + +[ + uuid(77a86b09-2bea-4801-b89a-37648e104af1), + object, + local, + pointer_default(unique) +] +interface ID3D12GraphicsCommandListExt : IUnknown +{ + HRESULT GetVulkanHandle(VkCommandBuffer *pVkCommandBuffer); + HRESULT LaunchCubinShader(D3D12_CUBIN_DATA_HANDLE *handle, UINT32 block_x, UINT32 block_y, UINT32 block_z, const void *params, UINT32 param_size); +} + diff --git a/include/vkd3d_device_vkd3d_ext.idl b/include/vkd3d_device_vkd3d_ext.idl new file mode 100644 index 00000000..53588b66 --- /dev/null +++ b/include/vkd3d_device_vkd3d_ext.idl @@ -0,0 +1,37 @@ +/* + * * Copyright 2021 NVIDIA Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +import "vkd3d_d3d12.idl"; +import "vkd3d_vk_includes.h"; + +[ + uuid(11ea7a1a-0f6a-49bf-b612-3e30f8e201dd), + object, + local, + pointer_default(unique) +] +interface ID3D12DeviceExt : IUnknown +{ + HRESULT GetVulkanHandles(VkInstance *vk_instance, VkPhysicalDevice *vk_physical_device, VkDevice *vk_device); + BOOL GetExtensionSupport(D3D12_VK_EXTENSION extension); + HRESULT CreateCubinComputeShaderWithName(const void *cubin_data, UINT32 cubin_size, UINT32 block_x, UINT32 block_y, UINT32 block_z, const char *shader_name, D3D12_CUBIN_DATA_HANDLE **handle); + HRESULT DestroyCubinComputeShader(D3D12_CUBIN_DATA_HANDLE *handle); + HRESULT GetCudaTextureObject(D3D12_CPU_DESCRIPTOR_HANDLE srv_handle, D3D12_CPU_DESCRIPTOR_HANDLE sampler_handle, UINT32 *cuda_texture_handle); + HRESULT GetCudaSurfaceObject(D3D12_CPU_DESCRIPTOR_HANDLE uav_handle, UINT32 *cuda_surface_handle); + HRESULT CaptureUAVInfo(D3D12_UAV_INFO *uav_info); +} + diff --git a/include/vkd3d_vk_includes.h b/include/vkd3d_vk_includes.h new file mode 100644 index 00000000..e16169a0 --- /dev/null +++ b/include/vkd3d_vk_includes.h @@ -0,0 +1,58 @@ +/* + * * Copyright 2021 NVIDIA Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#ifndef __VKD3D_VK_INCLUDES_H +#define __VKD3D_VK_INCLUDES_H + +#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) + typedef struct VkCuFunctionNVX_T *VkCuFunctionNVX; + typedef struct VkCuModuleNVX_T *VkCuModuleNVX; +#else + typedef UINT64 VkCuFunctionNVX; + typedef UINT64 VkCuModuleNVX; +#endif + +typedef struct VkPhysicalDevice_T *VkPhysicalDevice; +typedef struct VkCommandBuffer_T *VkCommandBuffer; +typedef struct VkInstance_T *VkInstance; +typedef struct VkDevice_T *VkDevice; + +typedef enum D3D12_VK_EXTENSION +{ + D3D12_VK_NVX_BINARY_IMPORT = 0x1, + D3D12_VK_NVX_IMAGE_VIEW_HANDLE = 0x2 +} D3D12_VK_EXTENSION; + +typedef struct D3D12_CUBIN_DATA_HANDLE +{ + VkCuFunctionNVX vkCuFunction; + VkCuModuleNVX vkCuModule; + UINT32 blockX; + UINT32 blockY; + UINT32 blockZ; +} D3D12_CUBIN_DATA_HANDLE; + +typedef struct D3D12_UAV_INFO +{ + UINT32 version; + UINT32 surfaceHandle; + UINT64 gpuVAStart; + UINT64 gpuVASize; +} D3D12_UAV_INFO; + +#endif // __VKD3D_VK_INCLUDES_H + diff --git a/include/vkd3d_win32.h b/include/vkd3d_win32.h index 27fc9e62..d9d0128d 100644 --- a/include/vkd3d_win32.h +++ b/include/vkd3d_win32.h @@ -68,6 +68,8 @@ #define __vkd3d_dxgi1_4_h__ #include +#include +#include #include #include diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index 6902f550..810167b5 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -4002,7 +4002,9 @@ static void d3d12_command_list_track_query_heap(struct d3d12_command_list *list, } } -static HRESULT STDMETHODCALLTYPE d3d12_command_list_QueryInterface(d3d12_command_list_iface *iface, +extern ULONG STDMETHODCALLTYPE d3d12_command_list_vkd3d_ext_AddRef(ID3D12GraphicsCommandListExt *iface); + +HRESULT STDMETHODCALLTYPE d3d12_command_list_QueryInterface(d3d12_command_list_iface *iface, REFIID iid, void **object) { TRACE("iface %p, iid %s, object %p.\n", iface, debugstr_guid(iid), object); @@ -4023,13 +4025,21 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_list_QueryInterface(d3d12_command return S_OK; } + if (IsEqualGUID(iid, &IID_ID3D12GraphicsCommandListExt)) + { + struct d3d12_command_list *command_list = impl_from_ID3D12GraphicsCommandList(iface); + d3d12_command_list_vkd3d_ext_AddRef(&command_list->ID3D12GraphicsCommandListExt_iface); + *object = &command_list->ID3D12GraphicsCommandListExt_iface; + return S_OK; + } + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); *object = NULL; return E_NOINTERFACE; } -static ULONG STDMETHODCALLTYPE d3d12_command_list_AddRef(d3d12_command_list_iface *iface) +ULONG STDMETHODCALLTYPE d3d12_command_list_AddRef(d3d12_command_list_iface *iface) { struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList(iface); ULONG refcount = InterlockedIncrement(&list->refcount); @@ -4039,7 +4049,7 @@ static ULONG STDMETHODCALLTYPE d3d12_command_list_AddRef(d3d12_command_list_ifac return refcount; } -static ULONG STDMETHODCALLTYPE d3d12_command_list_Release(d3d12_command_list_iface *iface) +ULONG STDMETHODCALLTYPE d3d12_command_list_Release(d3d12_command_list_iface *iface) { struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList(iface); ULONG refcount = InterlockedDecrement(&list->refcount); @@ -9756,6 +9766,8 @@ static struct d3d12_command_list *unsafe_impl_from_ID3D12CommandList(ID3D12Comma return CONTAINING_RECORD(iface, struct d3d12_command_list, ID3D12GraphicsCommandList_iface); } +extern CONST_VTBL struct ID3D12GraphicsCommandListExtVtbl d3d12_command_list_vkd3d_ext_vtbl; + static HRESULT d3d12_command_list_init(struct d3d12_command_list *list, struct d3d12_device *device, D3D12_COMMAND_LIST_TYPE type) { @@ -9776,6 +9788,8 @@ static HRESULT d3d12_command_list_init(struct d3d12_command_list *list, struct d list->type = type; + list->ID3D12GraphicsCommandListExt_iface.lpVtbl = &d3d12_command_list_vkd3d_ext_vtbl; + if (FAILED(hr = vkd3d_private_store_init(&list->private_store))) return hr; diff --git a/libs/vkd3d/command_list_vkd3d_ext.c b/libs/vkd3d/command_list_vkd3d_ext.c new file mode 100644 index 00000000..c5135b56 --- /dev/null +++ b/libs/vkd3d/command_list_vkd3d_ext.c @@ -0,0 +1,116 @@ +/* + * * Copyright 2021 NVIDIA Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API + +#include "vkd3d_private.h" + +static inline struct d3d12_command_list *d3d12_command_list_from_ID3D12GraphicsCommandListExt(ID3D12GraphicsCommandListExt *iface) +{ + return CONTAINING_RECORD(iface, struct d3d12_command_list, ID3D12GraphicsCommandListExt_iface); +} + +extern ULONG STDMETHODCALLTYPE d3d12_command_list_AddRef(d3d12_command_list_iface *iface); + +ULONG STDMETHODCALLTYPE d3d12_command_list_vkd3d_ext_AddRef(ID3D12GraphicsCommandListExt *iface) +{ + struct d3d12_command_list *command_list = d3d12_command_list_from_ID3D12GraphicsCommandListExt(iface); + return d3d12_command_list_AddRef(&command_list->ID3D12GraphicsCommandList_iface); +} + +extern ULONG STDMETHODCALLTYPE d3d12_command_list_Release(d3d12_command_list_iface *iface); + +static ULONG STDMETHODCALLTYPE d3d12_command_list_vkd3d_ext_Release(ID3D12GraphicsCommandListExt *iface) +{ + struct d3d12_command_list *command_list = d3d12_command_list_from_ID3D12GraphicsCommandListExt(iface); + return d3d12_command_list_Release(&command_list->ID3D12GraphicsCommandList_iface); +} + +extern HRESULT STDMETHODCALLTYPE d3d12_command_list_QueryInterface(d3d12_command_list_iface *iface, + REFIID iid, void **object); + +static HRESULT STDMETHODCALLTYPE d3d12_command_list_vkd3d_ext_QueryInterface(ID3D12GraphicsCommandListExt *iface, + REFIID iid, void **out) +{ + struct d3d12_command_list *command_list = d3d12_command_list_from_ID3D12GraphicsCommandListExt(iface); + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + return d3d12_command_list_QueryInterface(&command_list->ID3D12GraphicsCommandList_iface, iid, out); +} + +static HRESULT STDMETHODCALLTYPE d3d12_command_list_vkd3d_ext_GetVulkanHandle(ID3D12GraphicsCommandListExt *iface, + VkCommandBuffer *pVkCommandBuffer) +{ + struct d3d12_command_list *command_list = d3d12_command_list_from_ID3D12GraphicsCommandListExt(iface); + TRACE("iface %p, pVkCommandBuffer %p.\n", iface, pVkCommandBuffer); + if (!pVkCommandBuffer) + return E_INVALIDARG; + + *pVkCommandBuffer = command_list->vk_command_buffer; + return S_OK; +} + +#define CU_LAUNCH_PARAM_BUFFER_POINTER (const void*)0x01 +#define CU_LAUNCH_PARAM_BUFFER_SIZE (const void*)0x02 +#define CU_LAUNCH_PARAM_END (const void*)0x00 + +static HRESULT STDMETHODCALLTYPE d3d12_command_list_vkd3d_ext_LaunchCubinShader(ID3D12GraphicsCommandListExt *iface, D3D12_CUBIN_DATA_HANDLE *handle, UINT32 block_x, UINT32 block_y, UINT32 block_z, const void *params, UINT32 param_size) +{ + VkCuLaunchInfoNVX launchInfo = { VK_STRUCTURE_TYPE_CU_LAUNCH_INFO_NVX }; + const struct vkd3d_vk_device_procs *vk_procs; + + const void *config[] = { + CU_LAUNCH_PARAM_BUFFER_POINTER, params, + CU_LAUNCH_PARAM_BUFFER_SIZE, ¶m_size, + CU_LAUNCH_PARAM_END + }; + + struct d3d12_command_list *command_list = d3d12_command_list_from_ID3D12GraphicsCommandListExt(iface); + TRACE("iface %p, handle %p, block_x %u, block_y %u, block_z %u, params %p, param_size %u \n", iface, handle, block_x, block_y, block_z, params, param_size); + if (!handle || !block_x || !block_y || !block_z || !params || !param_size) + return E_INVALIDARG; + + launchInfo.function = handle->vkCuFunction; + launchInfo.gridDimX = block_x; + launchInfo.gridDimY = block_y; + launchInfo.gridDimZ = block_z; + launchInfo.blockDimX = handle->blockX; + launchInfo.blockDimY = handle->blockY; + launchInfo.blockDimZ = handle->blockZ; + launchInfo.sharedMemBytes = 0; + launchInfo.paramCount = 0; + launchInfo.pParams = NULL; + launchInfo.extraCount = 1; + launchInfo.pExtras = config; + + vk_procs = &command_list->device->vk_procs; + VK_CALL(vkCmdCuLaunchKernelNVX(command_list->vk_command_buffer, &launchInfo)); + return S_OK; +} + +CONST_VTBL struct ID3D12GraphicsCommandListExtVtbl d3d12_command_list_vkd3d_ext_vtbl = +{ + /* IUnknown methods */ + d3d12_command_list_vkd3d_ext_QueryInterface, + d3d12_command_list_vkd3d_ext_AddRef, + d3d12_command_list_vkd3d_ext_Release, + + /* ID3D12GraphicsCommandListExt methods */ + d3d12_command_list_vkd3d_ext_GetVulkanHandle, + d3d12_command_list_vkd3d_ext_LaunchCubinShader +}; + diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 0adbca76..05c9ec2e 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -2416,7 +2416,9 @@ static inline struct d3d12_device *impl_from_ID3D12Device(d3d12_device_iface *if return CONTAINING_RECORD(iface, struct d3d12_device, ID3D12Device_iface); } -static HRESULT STDMETHODCALLTYPE d3d12_device_QueryInterface(d3d12_device_iface *iface, +extern ULONG STDMETHODCALLTYPE d3d12_device_vkd3d_ext_AddRef(ID3D12DeviceExt *iface); + +HRESULT STDMETHODCALLTYPE d3d12_device_QueryInterface(d3d12_device_iface *iface, REFIID riid, void **object) { TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); @@ -2436,6 +2438,14 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_QueryInterface(d3d12_device_iface return S_OK; } + if (IsEqualGUID(riid, &IID_ID3D12DeviceExt)) + { + struct d3d12_device *device = impl_from_ID3D12Device(iface); + d3d12_device_vkd3d_ext_AddRef(&device->ID3D12DeviceExt_iface); + *object = &device->ID3D12DeviceExt_iface; + return S_OK; + } + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); *object = NULL; @@ -3447,18 +3457,46 @@ static void STDMETHODCALLTYPE d3d12_device_CreateShaderResourceView(d3d12_device device, unsafe_impl_from_ID3D12Resource(resource), desc); } +__thread struct D3D12_UAV_INFO *d3d12_uav_info = NULL; + static void STDMETHODCALLTYPE d3d12_device_CreateUnorderedAccessView(d3d12_device_iface *iface, ID3D12Resource *resource, ID3D12Resource *counter_resource, const D3D12_UNORDERED_ACCESS_VIEW_DESC *desc, D3D12_CPU_DESCRIPTOR_HANDLE descriptor) { + VkImageViewAddressPropertiesNVX out_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX }; + VkImageViewHandleInfoNVX imageViewHandleInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX }; + const struct vkd3d_vk_device_procs *vk_procs; + VkResult vr; + struct d3d12_resource *d3d12_resource_ = unsafe_impl_from_ID3D12Resource(resource); struct d3d12_device *device = impl_from_ID3D12Device(iface); - + struct d3d12_desc *d3d12_desc_cpu = d3d12_desc_from_cpu_handle(descriptor); TRACE("iface %p, resource %p, counter_resource %p, desc %p, descriptor %#lx.\n", iface, resource, counter_resource, desc, descriptor.ptr); - d3d12_desc_create_uav(d3d12_desc_from_cpu_handle(descriptor), - device, unsafe_impl_from_ID3D12Resource(resource), + d3d12_desc_create_uav(d3d12_desc_cpu, + device, d3d12_resource_, unsafe_impl_from_ID3D12Resource(counter_resource), desc); + + /* d3d12_uav_info stores the pointer to data from previous call to d3d12_device_vkd3d_ext_CaptureUAVInfo(). Below code will update the data. */ + if (d3d12_uav_info) + { + imageViewHandleInfo.imageView = d3d12_desc_cpu->info.view->vk_image_view; + imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + + vk_procs = &device->vk_procs; + d3d12_uav_info->surfaceHandle = VK_CALL(vkGetImageViewHandleNVX(device->vk_device, &imageViewHandleInfo)); + + if ((vr = VK_CALL(vkGetImageViewAddressNVX(device->vk_device, imageViewHandleInfo.imageView, &out_info))) < 0) + { + ERR("Failed to get imageview address, vr %d.\n", vr); + return; + } + + d3d12_uav_info->gpuVAStart = out_info.deviceAddress; + d3d12_uav_info->gpuVASize = out_info.size; + /* Set this to null so that subsequent calls to this API wont update the previous pointer. */ + d3d12_uav_info = NULL; + } } static void STDMETHODCALLTYPE d3d12_device_CreateRenderTargetView(d3d12_device_iface *iface, @@ -5076,6 +5114,8 @@ struct d3d12_device *unsafe_impl_from_ID3D12Device(d3d12_device_iface *iface) return impl_from_ID3D12Device(iface); } +extern CONST_VTBL struct ID3D12DeviceExtVtbl d3d12_device_vkd3d_ext_vtbl; + static HRESULT d3d12_device_init(struct d3d12_device *device, struct vkd3d_instance *instance, const struct vkd3d_device_create_info *create_info) { @@ -5109,6 +5149,8 @@ static HRESULT d3d12_device_init(struct d3d12_device *device, hr = hresult_from_errno(rc); goto out_free_instance; } + + device->ID3D12DeviceExt_iface.lpVtbl = &d3d12_device_vkd3d_ext_vtbl; if (FAILED(hr = vkd3d_create_vk_device(device, create_info))) goto out_free_mutex; diff --git a/libs/vkd3d/device_vkd3d_ext.c b/libs/vkd3d/device_vkd3d_ext.c new file mode 100644 index 00000000..401c9c1f --- /dev/null +++ b/libs/vkd3d/device_vkd3d_ext.c @@ -0,0 +1,232 @@ +/* + * * Copyright 2021 NVIDIA Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API + +#include "vkd3d_private.h" + +static inline struct d3d12_device *d3d12_device_from_ID3D12DeviceExt(ID3D12DeviceExt *iface) +{ + return CONTAINING_RECORD(iface, struct d3d12_device, ID3D12DeviceExt_iface); +} + +ULONG STDMETHODCALLTYPE d3d12_device_vkd3d_ext_AddRef(ID3D12DeviceExt *iface) +{ + struct d3d12_device *device = d3d12_device_from_ID3D12DeviceExt(iface); + return d3d12_device_add_ref(device); +} + +static ULONG STDMETHODCALLTYPE d3d12_device_vkd3d_ext_Release(ID3D12DeviceExt *iface) +{ + struct d3d12_device *device = d3d12_device_from_ID3D12DeviceExt(iface); + return d3d12_device_release(device); +} + +extern HRESULT STDMETHODCALLTYPE d3d12_device_QueryInterface(d3d12_device_iface *iface, + REFIID riid, void **object); + +static HRESULT STDMETHODCALLTYPE d3d12_device_vkd3d_ext_QueryInterface(ID3D12DeviceExt *iface, + REFIID iid, void **out) +{ + struct d3d12_device *device = d3d12_device_from_ID3D12DeviceExt(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_device_vkd3d_ext_GetVulkanHandles(ID3D12DeviceExt *iface, VkInstance *vk_instance, VkPhysicalDevice *vk_physical_device, VkDevice *vk_device) +{ + struct d3d12_device *device = d3d12_device_from_ID3D12DeviceExt(iface); + TRACE("iface %p, vk_instance %p, vk_physical_device %u, 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 BOOL STDMETHODCALLTYPE d3d12_device_vkd3d_ext_GetExtensionSupport(ID3D12DeviceExt *iface, D3D12_VK_EXTENSION extension) +{ + const struct d3d12_device *device = d3d12_device_from_ID3D12DeviceExt(iface); + bool ret_val = false; + + TRACE("iface %p, extension %u \n", iface, extension); + switch (extension) + { + case D3D12_VK_NVX_BINARY_IMPORT: + ret_val = device->vk_info.NVX_binary_import; + break; + case D3D12_VK_NVX_IMAGE_VIEW_HANDLE: + ret_val = device->vk_info.NVX_image_view_handle; + break; + default: + WARN("Invalid extension %x\n", extension); + } + + return ret_val; +} + +static HRESULT STDMETHODCALLTYPE d3d12_device_vkd3d_ext_CreateCubinComputeShaderWithName(ID3D12DeviceExt *iface, const void *cubin_data, + UINT32 cubin_size, UINT32 block_x, UINT32 block_y, UINT32 block_z, const char *shader_name, D3D12_CUBIN_DATA_HANDLE **out_handle) +{ + VkCuFunctionCreateInfoNVX functionCreateInfo = { VK_STRUCTURE_TYPE_CU_FUNCTION_CREATE_INFO_NVX }; + VkCuModuleCreateInfoNVX moduleCreateInfo = { VK_STRUCTURE_TYPE_CU_MODULE_CREATE_INFO_NVX }; + const struct vkd3d_vk_device_procs *vk_procs; + D3D12_CUBIN_DATA_HANDLE *handle; + struct d3d12_device *device; + VkDevice vk_device; + VkResult vr; + + TRACE("iface %p, cubin_data %p, cubin_size %u, shader_name %s \n", iface, cubin_data, cubin_size, shader_name); + if (!cubin_data || !cubin_size || !shader_name) + return E_INVALIDARG; + + device = d3d12_device_from_ID3D12DeviceExt(iface); + vk_device = device->vk_device; + handle = vkd3d_calloc(1, sizeof(D3D12_CUBIN_DATA_HANDLE)); + handle->blockX = block_x; + handle->blockY = block_y; + handle->blockZ = block_z; + + moduleCreateInfo.pData = cubin_data; + moduleCreateInfo.dataSize = cubin_size; + vk_procs = &device->vk_procs; + if ((vr = VK_CALL(vkCreateCuModuleNVX(vk_device, &moduleCreateInfo, NULL, &handle->vkCuModule))) < 0) + { + ERR("Failed to create cubin shader, vr %d.\n", vr); + vkd3d_free(handle); + return hresult_from_vk_result(vr); + } + + functionCreateInfo.module = handle->vkCuModule; + functionCreateInfo.pName = shader_name; + + if ((vr = VK_CALL(vkCreateCuFunctionNVX(vk_device, &functionCreateInfo, NULL, &handle->vkCuFunction))) < 0) + { + ERR("Failed to create cubin function module, vr %d.\n", vr); + VK_CALL(vkDestroyCuModuleNVX(vk_device, handle->vkCuModule, NULL)); + vkd3d_free(handle); + return hresult_from_vk_result(vr); + } + + *out_handle = handle; + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE d3d12_device_vkd3d_ext_DestroyCubinComputeShader(ID3D12DeviceExt *iface, D3D12_CUBIN_DATA_HANDLE *handle) +{ + const struct vkd3d_vk_device_procs *vk_procs; + struct d3d12_device *device; + VkDevice vk_device; + + TRACE("iface %p, handle %p \n", iface, handle); + if (!iface || !handle) + return E_INVALIDARG; + + device = d3d12_device_from_ID3D12DeviceExt(iface); + vk_device = device->vk_device; + vk_procs = &device->vk_procs; + + VK_CALL(vkDestroyCuFunctionNVX(vk_device, handle->vkCuFunction, NULL)); + VK_CALL(vkDestroyCuModuleNVX(vk_device, handle->vkCuModule, NULL)); + vkd3d_free(handle); + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE d3d12_device_vkd3d_ext_GetCudaTextureObject(ID3D12DeviceExt *iface, D3D12_CPU_DESCRIPTOR_HANDLE srv_handle, + D3D12_CPU_DESCRIPTOR_HANDLE sampler_handle, UINT32 *cuda_texture_handle) +{ + VkImageViewHandleInfoNVX imageViewHandleInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX }; + const struct vkd3d_vk_device_procs *vk_procs; + struct d3d12_desc *sampler_desc; + struct d3d12_device *device; + struct d3d12_desc *srv_desc; + + TRACE("iface %p, srv_handle %#x, sampler_handle %#x, cuda_texture_handle %p.\n", iface, srv_handle, sampler_handle, cuda_texture_handle); + if (!cuda_texture_handle) + return E_INVALIDARG; + + device = d3d12_device_from_ID3D12DeviceExt(iface); + srv_desc = d3d12_desc_from_cpu_handle(srv_handle); + sampler_desc = d3d12_desc_from_cpu_handle(sampler_handle); + + imageViewHandleInfo.imageView = srv_desc->info.view->vk_image_view; + imageViewHandleInfo.sampler = sampler_desc->info.view->vk_sampler; + imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + + vk_procs = &device->vk_procs; + *cuda_texture_handle = VK_CALL(vkGetImageViewHandleNVX(device->vk_device, &imageViewHandleInfo)); + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE d3d12_device_vkd3d_ext_GetCudaSurfaceObject(ID3D12DeviceExt *iface, D3D12_CPU_DESCRIPTOR_HANDLE uav_handle, + UINT32 *cuda_surface_handle) +{ + VkImageViewHandleInfoNVX imageViewHandleInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX }; + const struct vkd3d_vk_device_procs *vk_procs; + struct d3d12_device *device; + struct d3d12_desc *uav_desc; + + TRACE("iface %p, uav_handle %#x, cuda_surface_handle %p.\n", iface, uav_handle, cuda_surface_handle); + if (!cuda_surface_handle) + return E_INVALIDARG; + + device = d3d12_device_from_ID3D12DeviceExt(iface); + uav_desc = d3d12_desc_from_cpu_handle(uav_handle); + + imageViewHandleInfo.imageView = uav_desc->info.view->vk_image_view; + imageViewHandleInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + + vk_procs = &device->vk_procs; + *cuda_surface_handle = VK_CALL(vkGetImageViewHandleNVX(device->vk_device, &imageViewHandleInfo)); + return S_OK; +} + +extern __thread struct D3D12_UAV_INFO *d3d12_uav_info; + +static HRESULT STDMETHODCALLTYPE d3d12_device_vkd3d_ext_CaptureUAVInfo(ID3D12DeviceExt *iface, D3D12_UAV_INFO *uav_info) +{ + if (!uav_info) + return E_INVALIDARG; + + TRACE("iface %p, uav_info %p.\n", iface, uav_info); + + /* CaptureUAVInfo() supposed to capture the information from the next CreateUnorderedAccess() on the same thread. + We use d3d12_uav_info pointer to update the information in CreateUnorderedAccess() */ + d3d12_uav_info = uav_info; + return S_OK; +} + +CONST_VTBL struct ID3D12DeviceExtVtbl d3d12_device_vkd3d_ext_vtbl = +{ + /* IUnknown methods */ + d3d12_device_vkd3d_ext_QueryInterface, + d3d12_device_vkd3d_ext_AddRef, + d3d12_device_vkd3d_ext_Release, + + /* ID3D12DeviceExt methods */ + d3d12_device_vkd3d_ext_GetVulkanHandles, + d3d12_device_vkd3d_ext_GetExtensionSupport, + d3d12_device_vkd3d_ext_CreateCubinComputeShaderWithName, + d3d12_device_vkd3d_ext_DestroyCubinComputeShader, + d3d12_device_vkd3d_ext_GetCudaTextureObject, + d3d12_device_vkd3d_ext_GetCudaSurfaceObject, + d3d12_device_vkd3d_ext_CaptureUAVInfo +}; + diff --git a/libs/vkd3d/meson.build b/libs/vkd3d/meson.build index 23009679..3a32bace 100644 --- a/libs/vkd3d/meson.build +++ b/libs/vkd3d/meson.build @@ -32,7 +32,9 @@ vkd3d_src = [ 'bundle.c', 'cache.c', 'command.c', + 'command_list_vkd3d_ext.c', 'device.c', + 'device_vkd3d_ext.c', 'heap.c', 'memory.c', 'meta.c', diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 147f1e1e..1ffd6edc 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -36,6 +36,8 @@ #include "vkd3d_threads.h" #include "vkd3d_platform.h" #include "vkd3d_swapchain_factory.h" +#include "vkd3d_command_list_vkd3d_ext.h" +#include "vkd3d_device_vkd3d_ext.h" #include "vkd3d_string.h" #include #include @@ -1746,6 +1748,9 @@ struct vkd3d_query_range uint32_t flags; }; +/* ID3D12CommandListExt */ +typedef ID3D12GraphicsCommandListExt d3d12_command_list_vkd3d_ext_iface; + struct d3d12_state_object; struct d3d12_resource_tracking @@ -1757,6 +1762,7 @@ struct d3d12_resource_tracking struct d3d12_command_list { d3d12_command_list_iface ID3D12GraphicsCommandList_iface; + d3d12_command_list_vkd3d_ext_iface ID3D12GraphicsCommandListExt_iface; LONG refcount; D3D12_COMMAND_LIST_TYPE type; @@ -2609,9 +2615,13 @@ typedef ID3D12Device6 d3d12_device_iface; struct vkd3d_descriptor_qa_global_info; struct vkd3d_descriptor_qa_heap_buffer_data; +/* ID3D12DeviceExt */ +typedef ID3D12DeviceExt d3d12_device_vkd3d_ext_iface; + struct d3d12_device { d3d12_device_iface ID3D12Device_iface; + d3d12_device_vkd3d_ext_iface ID3D12DeviceExt_iface; LONG refcount; VkDevice vk_device; diff --git a/libs/vkd3d/vulkan_procs.h b/libs/vkd3d/vulkan_procs.h index acaa1d0e..e434c3d9 100644 --- a/libs/vkd3d/vulkan_procs.h +++ b/libs/vkd3d/vulkan_procs.h @@ -277,6 +277,17 @@ VK_DEVICE_EXT_PFN(vkQueuePresentKHR) /* VK_AMD_buffer_marker */ VK_DEVICE_EXT_PFN(vkCmdWriteBufferMarkerAMD) +/* VK_NVX_binary_import */ +VK_DEVICE_EXT_PFN(vkCreateCuModuleNVX); +VK_DEVICE_EXT_PFN(vkCreateCuFunctionNVX); +VK_DEVICE_EXT_PFN(vkDestroyCuModuleNVX); +VK_DEVICE_EXT_PFN(vkDestroyCuFunctionNVX); +VK_DEVICE_EXT_PFN(vkCmdCuLaunchKernelNVX); + +/* VK_NVX_image_view_handle */ +VK_DEVICE_EXT_PFN(vkGetImageViewHandleNVX); +VK_DEVICE_EXT_PFN(vkGetImageViewAddressNVX); + #undef VK_INSTANCE_PFN #undef VK_INSTANCE_EXT_PFN #undef VK_DEVICE_PFN