From a6a22cd00ab8dfa77ae3faf6a09fbe9b91c5326f Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 19 Apr 2018 15:42:48 +0200 Subject: [PATCH 1/6] [dxvk] Export DxvkDeviceQueue from DxvkDevice Access to the Vulkan queues provided by the DXVK device is required for external Vulkan libraries to work. --- src/dxvk/dxvk_device.cpp | 17 +++++++++----- src/dxvk/dxvk_device.h | 49 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/src/dxvk/dxvk_device.cpp b/src/dxvk/dxvk_device.cpp index d6fb1d43..47ccce24 100644 --- a/src/dxvk/dxvk_device.cpp +++ b/src/dxvk/dxvk_device.cpp @@ -18,12 +18,16 @@ namespace dxvk { m_metaClearObjects(new DxvkMetaClearObjects (vkd)), m_unboundResources(this), m_submissionQueue (this) { + m_graphicsQueue.queueFamily = m_adapter->graphicsQueueFamily(); + m_presentQueue.queueFamily = m_adapter->presentQueueFamily(); + m_vkd->vkGetDeviceQueue(m_vkd->device(), - m_adapter->graphicsQueueFamily(), 0, - &m_graphicsQueue); + m_graphicsQueue.queueFamily, 0, + &m_graphicsQueue.queueHandle); + m_vkd->vkGetDeviceQueue(m_vkd->device(), - m_adapter->presentQueueFamily(), 0, - &m_presentQueue); + m_presentQueue.queueFamily, 0, + &m_presentQueue.queueHandle); } @@ -202,7 +206,7 @@ namespace dxvk { std::lock_guard statLock(m_statLock); m_statCounters.addCtr(DxvkStatCounter::QueuePresentCount, 1); - return m_vkd->vkQueuePresentKHR(m_presentQueue, &presentInfo); + return m_vkd->vkQueuePresentKHR(m_presentQueue.queueHandle, &presentInfo); } } @@ -234,7 +238,8 @@ namespace dxvk { m_statCounters.addCtr(DxvkStatCounter::QueueSubmitCount, 1); status = commandList->submit( - m_graphicsQueue, waitSemaphore, wakeSemaphore); + m_graphicsQueue.queueHandle, + waitSemaphore, wakeSemaphore); } if (status == VK_SUCCESS) { diff --git a/src/dxvk/dxvk_device.h b/src/dxvk/dxvk_device.h index c7f44a46..d4075574 100644 --- a/src/dxvk/dxvk_device.h +++ b/src/dxvk/dxvk_device.h @@ -27,6 +27,17 @@ namespace dxvk { class DxvkInstance; + /** + * \brief Device queue + * + * Stores a Vulkan queue and the + * queue family that it belongs to. + */ + struct DxvkDeviceQueue { + uint32_t queueFamily = 0; + VkQueue queueHandle = VK_NULL_HANDLE; + }; + /** * \brief DXVK device * @@ -66,6 +77,17 @@ namespace dxvk { return m_vkd->device(); } + /** + * \brief Graphics queue properties + * + * Handle and queue family index of + * the queue used for rendering. + * \returns Graphics queue info + */ + DxvkDeviceQueue graphicsQueue() const { + return m_graphicsQueue; + } + /** * \brief The adapter * @@ -291,6 +313,27 @@ namespace dxvk { const Rc& waitSync, const Rc& wakeSync); + /** + * \brief Locks submission queue + * + * Since Vulkan queues are only meant to be accessed + * from one thread at a time, external libraries need + * to lock the queue before submitting command buffers. + */ + void lockSubmission() { + m_submissionLock.lock(); + } + + /** + * \brief Unlocks submission queue + * + * Releases the Vulkan queues again so that DXVK + * itself can use them for submissions again. + */ + void unlockSubmission() { + m_submissionLock.unlock(); + } + /** * \brief Waits until the device becomes idle * @@ -318,9 +361,9 @@ namespace dxvk { sync::Spinlock m_statLock; DxvkStatCounters m_statCounters; - std::mutex m_submissionLock; - VkQueue m_graphicsQueue = VK_NULL_HANDLE; - VkQueue m_presentQueue = VK_NULL_HANDLE; + std::mutex m_submissionLock; + DxvkDeviceQueue m_graphicsQueue; + DxvkDeviceQueue m_presentQueue; DxvkRecycler m_recycledCommandLists; DxvkRecycler m_recycledStagingBuffers; From 478a87f6d2f5c0b34092c032e1908022b8504238 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 19 Apr 2018 15:46:57 +0200 Subject: [PATCH 2/6] [dxgi] Added IDXGIVkInteropDevice interface --- src/dxgi/dxgi_interfaces.h | 64 ++++++++++++++++++++++++++++++++++++++ src/util/com/com_guid.cpp | 9 +++--- 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/src/dxgi/dxgi_interfaces.h b/src/dxgi/dxgi_interfaces.h index 27463224..babdc289 100644 --- a/src/dxgi/dxgi_interfaces.h +++ b/src/dxgi/dxgi_interfaces.h @@ -133,14 +133,78 @@ IDXGIVkPresenter : public IUnknown { void** ppDevice) = 0; }; + +/** + * \brief DXGI device interface for Vulkan interop + * + * Provides access to the device and instance handles + * as well as the queue that is used for rendering. + */ +MIDL_INTERFACE("e2ef5fa5-dc21-4af7-90c4-f67ef6a09323") +IDXGIVkInteropDevice : public IUnknown { + static const GUID guid; + + /** + * \brief Queries Vulkan handles used by DXVK + * + * \param [out] pInstance The Vulkan instance + * \param [out] pPhysDev The physical device + * \param [out] pDevide The device handle + */ + virtual void STDMETHODCALLTYPE GetVulkanHandles( + VkInstance* pInstance, + VkPhysicalDevice* pPhysDev, + VkDevice* pDevice) = 0; + + /** + * \brief Queries the rendering queue used by DXVK + * + * \param [out] pQueue The Vulkan queue handle + * \param [out] pQueueFamilyIndex Queue family index + */ + virtual void STDMETHODCALLTYPE GetSubmissionQueue( + VkQueue* pQueue, + uint32_t* pQueueFamilyIndex) = 0; + + /** + * \brief Flushes outstanding D3D rendering commands + * + * Must be called before submitting Vulkan commands + * to the rendering queue if those commands use the + * backing resource of a D3D11 object. + */ + virtual void STDMETHODCALLTYPE FlushRenderingCommands() = 0; + + /** + * \brief Locks submission queue + * + * Should be called immediately before submitting + * Vulkan commands to the rendering queue in order + * to prevent DXVK from using the queue. + */ + virtual void STDMETHODCALLTYPE LockSubmissionQueue() = 0; + + /** + * \brief Releases submission queue + * + * Should be called immediately after submitting + * Vulkan commands to the rendering queue in order + * to allow DXVK to submit new commands. + */ + virtual void STDMETHODCALLTYPE ReleaseSubmissionQueue() = 0; +}; + + #ifdef _MSC_VER struct __declspec(uuid("907bf281-ea3c-43b4-a8e4-9f231107b4ff")) IDXGIVkAdapter; struct __declspec(uuid("7a622cf6-627a-46b2-b52f-360ef3da831c")) IDXGIVkDevice; struct __declspec(uuid("5679becd-8547-4d93-96a1-e61a1ce7ef37")) IDXGIVkBackBuffer; struct __declspec(uuid("79352328-16f2-4f81-9746-9c2e2ccd43cf")) IDXGIVkPresenter; +struct __declspec(uuid("e2ef5fa5-dc21-4af7-90c4-f67ef6a09323")) IDXGIVkInteropDevice; #else DXVK_DEFINE_GUID(IDXGIVkAdapter); DXVK_DEFINE_GUID(IDXGIVkDevice); DXVK_DEFINE_GUID(IDXGIVkBackBuffer); DXVK_DEFINE_GUID(IDXGIVkPresenter); +DXVK_DEFINE_GUID(IDXGIVkInteropDevice); #endif \ No newline at end of file diff --git a/src/util/com/com_guid.cpp b/src/util/com/com_guid.cpp index 969a1e2a..9fc48f14 100644 --- a/src/util/com/com_guid.cpp +++ b/src/util/com/com_guid.cpp @@ -4,10 +4,11 @@ #include "../../dxgi/dxgi_interfaces.h" -const GUID IDXGIVkAdapter::guid = {0x907bf281,0xea3c,0x43b4,{0xa8,0xe4,0x9f,0x23,0x11,0x07,0xb4,0xff}}; -const GUID IDXGIVkDevice::guid = {0x7a622cf6,0x627a,0x46b2,{0xb5,0x2f,0x36,0x0e,0xf3,0xda,0x83,0x1c}}; -const GUID IDXGIVkBackBuffer::guid = {0x5679becd,0x8547,0x4d93,{0x96,0xa1,0xe6,0x1a,0x1c,0xe7,0xef,0x37}}; -const GUID IDXGIVkPresenter::guid = {0x79352328,0x16f2,0x4f81,{0x97,0x46,0x9c,0x2e,0x2c,0xcd,0x43,0xcf}}; +const GUID IDXGIVkAdapter::guid = {0x907bf281,0xea3c,0x43b4,{0xa8,0xe4,0x9f,0x23,0x11,0x07,0xb4,0xff}}; +const GUID IDXGIVkDevice::guid = {0x7a622cf6,0x627a,0x46b2,{0xb5,0x2f,0x36,0x0e,0xf3,0xda,0x83,0x1c}}; +const GUID IDXGIVkBackBuffer::guid = {0x5679becd,0x8547,0x4d93,{0x96,0xa1,0xe6,0x1a,0x1c,0xe7,0xef,0x37}}; +const GUID IDXGIVkPresenter::guid = {0x79352328,0x16f2,0x4f81,{0x97,0x46,0x9c,0x2e,0x2c,0xcd,0x43,0xcf}}; +const GUID IDXGIVkInteropDevice::guid = {0xe2ef5fa5,0xdc21,0x4af7,{0x90,0xc4,0xf6,0x7e,0xf6,0xa0,0x93,0x23}}; std::ostream& operator << (std::ostream& os, REFIID guid) { os << std::hex << std::setfill('0') From c2854e1fb9db4f48b9069e8362518fd42a137199 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 19 Apr 2018 20:13:53 +0200 Subject: [PATCH 3/6] [dxgi] Added IDXGIVkInteropSurface interface --- src/dxgi/dxgi_interfaces.h | 67 ++++++++++++++++++++++++++++++++++++++ src/util/com/com_guid.cpp | 11 ++++--- 2 files changed, 73 insertions(+), 5 deletions(-) diff --git a/src/dxgi/dxgi_interfaces.h b/src/dxgi/dxgi_interfaces.h index babdc289..5fc268dc 100644 --- a/src/dxgi/dxgi_interfaces.h +++ b/src/dxgi/dxgi_interfaces.h @@ -134,6 +134,49 @@ IDXGIVkPresenter : public IUnknown { }; +/** + * \brief DXGI surface interface for Vulkan interop + * + * Provides access to the backing resource of a + * DXGI surface, which is typically a D3D texture. + */ +MIDL_INTERFACE("5546cf8c-77e7-4341-b05d-8d4d5000e77d") +IDXGIVkInteropSurface : public IUnknown { + static const GUID guid; + + /** + * \brief Retrieves Vulkan image info + * + * Retrieves both the image handle as well as the image's + * properties. Any of the given pointers may be \c nullptr. + * + * If \c pInfo is not \c nullptr, the following rules apply: + * - \c pInfo->sType \e must be \c VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO + * - \c pInfo->pNext \e must be \c nullptr or point ti a supported + * extension-specific structure (currently none) + * - \c pInfo->queueFamilyIndexCount must be the length of the + * \c pInfo->pQueueFamilyIndices array, in \c uint32_t units. + * - \c pInfo->pQueueFamilyIndices must point to a pre-allocated + * array of \c uint32_t of size \c pInfo->pQueueFamilyIndices. + * + * After the call, the structure pointed to by \c pInfo can + * be used to create an image with identical properties. + * + * If \c pLayout is not \c nullptr, it will receive the + * layout that the image will be in after flushing any + * outstanding commands on the device. + * \param [out] pHandle The image handle + * \param [out] pLayout Image layout + * \param [out] pInfo Image properties + * \returns \c S_OK on success, or \c E_INVALIDARG + */ + virtual HRESULT STDMETHODCALLTYPE GetVulkanImageInfo( + VkImage* pHandle, + VkImageLayout* pLayout, + VkImageCreateInfo* pInfo) = 0; +}; + + /** * \brief DXGI device interface for Vulkan interop * @@ -166,6 +209,24 @@ IDXGIVkInteropDevice : public IUnknown { VkQueue* pQueue, uint32_t* pQueueFamilyIndex) = 0; + /** + * \brief Transitions a surface to a given layout + * + * Executes an explicit image layout transition on the + * D3D device. Note that the image subresources \e must + * be transitioned back to its original layout before + * using it again from D3D11. + * \param [in] pSurface The image to transform + * \param [in] pSubresources Subresources to transform + * \param [in] OldLayout Current image layout + * \param [in] NewLayout Desired image layout + */ + virtual HRESULT STDMETHODCALLTYPE TransitionSurfaceLayout( + IDXGIVkInteropSurface* pSurface, + const VkImageSubresourceRange* pSubresources, + VkImageLayout OldLayout, + VkImageLayout NewLayout) = 0; + /** * \brief Flushes outstanding D3D rendering commands * @@ -181,6 +242,10 @@ IDXGIVkInteropDevice : public IUnknown { * Should be called immediately before submitting * Vulkan commands to the rendering queue in order * to prevent DXVK from using the queue. + * + * While the submission queue is locked, no D3D11 + * methods must be called from the locking thread, + * or otherwise a deadlock might occur. */ virtual void STDMETHODCALLTYPE LockSubmissionQueue() = 0; @@ -201,10 +266,12 @@ struct __declspec(uuid("7a622cf6-627a-46b2-b52f-360ef3da831c")) IDXGIVkDevice; struct __declspec(uuid("5679becd-8547-4d93-96a1-e61a1ce7ef37")) IDXGIVkBackBuffer; struct __declspec(uuid("79352328-16f2-4f81-9746-9c2e2ccd43cf")) IDXGIVkPresenter; struct __declspec(uuid("e2ef5fa5-dc21-4af7-90c4-f67ef6a09323")) IDXGIVkInteropDevice; +struct __declspec(uuid("5546cf8c-77e7-4341-b05d-8d4d5000e77d")) IDXGIVkInteropSurface; #else DXVK_DEFINE_GUID(IDXGIVkAdapter); DXVK_DEFINE_GUID(IDXGIVkDevice); DXVK_DEFINE_GUID(IDXGIVkBackBuffer); DXVK_DEFINE_GUID(IDXGIVkPresenter); DXVK_DEFINE_GUID(IDXGIVkInteropDevice); +DXVK_DEFINE_GUID(IDXGIVkInteropSurface); #endif \ No newline at end of file diff --git a/src/util/com/com_guid.cpp b/src/util/com/com_guid.cpp index 9fc48f14..1e8c0d4f 100644 --- a/src/util/com/com_guid.cpp +++ b/src/util/com/com_guid.cpp @@ -4,11 +4,12 @@ #include "../../dxgi/dxgi_interfaces.h" -const GUID IDXGIVkAdapter::guid = {0x907bf281,0xea3c,0x43b4,{0xa8,0xe4,0x9f,0x23,0x11,0x07,0xb4,0xff}}; -const GUID IDXGIVkDevice::guid = {0x7a622cf6,0x627a,0x46b2,{0xb5,0x2f,0x36,0x0e,0xf3,0xda,0x83,0x1c}}; -const GUID IDXGIVkBackBuffer::guid = {0x5679becd,0x8547,0x4d93,{0x96,0xa1,0xe6,0x1a,0x1c,0xe7,0xef,0x37}}; -const GUID IDXGIVkPresenter::guid = {0x79352328,0x16f2,0x4f81,{0x97,0x46,0x9c,0x2e,0x2c,0xcd,0x43,0xcf}}; -const GUID IDXGIVkInteropDevice::guid = {0xe2ef5fa5,0xdc21,0x4af7,{0x90,0xc4,0xf6,0x7e,0xf6,0xa0,0x93,0x23}}; +const GUID IDXGIVkAdapter::guid = {0x907bf281,0xea3c,0x43b4,{0xa8,0xe4,0x9f,0x23,0x11,0x07,0xb4,0xff}}; +const GUID IDXGIVkDevice::guid = {0x7a622cf6,0x627a,0x46b2,{0xb5,0x2f,0x36,0x0e,0xf3,0xda,0x83,0x1c}}; +const GUID IDXGIVkBackBuffer::guid = {0x5679becd,0x8547,0x4d93,{0x96,0xa1,0xe6,0x1a,0x1c,0xe7,0xef,0x37}}; +const GUID IDXGIVkPresenter::guid = {0x79352328,0x16f2,0x4f81,{0x97,0x46,0x9c,0x2e,0x2c,0xcd,0x43,0xcf}}; +const GUID IDXGIVkInteropDevice::guid = {0xe2ef5fa5,0xdc21,0x4af7,{0x90,0xc4,0xf6,0x7e,0xf6,0xa0,0x93,0x23}}; +const GUID IDXGIVkInteropSurface::guid = {0x5546cf8c,0x77e7,0x4341,{0xb0,0x5d,0x8d,0x4d,0x50,0x00,0xe7,0x7d}}; std::ostream& operator << (std::ostream& os, REFIID guid) { os << std::hex << std::setfill('0') From 62b0e34a73be155da1c0f0d987908800f54d58bc Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Fri, 20 Apr 2018 00:19:03 +0200 Subject: [PATCH 4/6] [d3d11] Implement IDXGIVkInteropDevice for D3D11Device --- src/d3d11/d3d11_context.cpp | 27 +++++++++ src/d3d11/d3d11_context.h | 6 ++ src/d3d11/d3d11_device.cpp | 7 +++ src/d3d11/d3d11_device.h | 2 + src/d3d11/d3d11_interop.cpp | 107 ++++++++++++++++++++++++++++++++++++ src/d3d11/d3d11_interop.h | 54 ++++++++++++++++++ src/d3d11/d3d11_main.cpp | 4 ++ src/d3d11/meson.build | 1 + src/dxgi/dxgi_interfaces.h | 2 +- src/dxvk/dxvk_adapter.cpp | 5 ++ src/dxvk/dxvk_adapter.h | 6 ++ src/dxvk/dxvk_context.cpp | 19 +++++++ src/dxvk/dxvk_context.h | 14 +++++ 13 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 src/d3d11/d3d11_interop.cpp create mode 100644 src/d3d11/d3d11_interop.h diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 6b418130..7675d0c1 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -2265,6 +2265,33 @@ namespace dxvk { } + void STDMETHODCALLTYPE D3D11DeviceContext::TransitionSurfaceLayout( + IDXGIVkInteropSurface* pSurface, + const VkImageSubresourceRange* pSubresources, + VkImageLayout OldLayout, + VkImageLayout NewLayout) { + // Get the underlying D3D11 resource + Com resource; + + pSurface->QueryInterface(__uuidof(ID3D11Resource), + reinterpret_cast(&resource)); + + // Get the texture from that resource + D3D11CommonTexture* texture = GetCommonTexture(resource.ptr()); + + EmitCs([ + cImage = texture->GetImage(), + cSubresources = *pSubresources, + cOldLayout = OldLayout, + cNewLayout = NewLayout + ] (DxvkContext* ctx) { + ctx->transformImage( + cImage, cSubresources, + cOldLayout, cNewLayout); + }); + } + + void D3D11DeviceContext::ApplyInputLayout() { if (m_state.ia.inputLayout != nullptr) { EmitCs([cInputLayout = m_state.ia.inputLayout] (DxvkContext* ctx) { diff --git a/src/d3d11/d3d11_context.h b/src/d3d11/d3d11_context.h index 8ebc65c8..a4c7df94 100644 --- a/src/d3d11/d3d11_context.h +++ b/src/d3d11/d3d11_context.h @@ -635,6 +635,12 @@ namespace dxvk { UINT NumBuffers, ID3D11Buffer** ppSOTargets) final; + void STDMETHODCALLTYPE TransitionSurfaceLayout( + IDXGIVkInteropSurface* pSurface, + const VkImageSubresourceRange* pSubresources, + VkImageLayout OldLayout, + VkImageLayout NewLayout); + protected: D3D11Device* const m_parent; diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index 5dc8a781..3facd7f9 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -7,6 +7,7 @@ #include "d3d11_context_imm.h" #include "d3d11_device.h" #include "d3d11_input_layout.h" +#include "d3d11_interop.h" #include "d3d11_present.h" #include "d3d11_query.h" #include "d3d11_sampler.h" @@ -21,6 +22,7 @@ namespace dxvk { D3D11DeviceContainer::~D3D11DeviceContainer() { + delete m_d3d11VkInterop; delete m_d3d11Presenter; delete m_d3d11Device; delete m_dxgiDevice; @@ -44,6 +46,11 @@ namespace dxvk { return S_OK; } + if (riid == __uuidof(IDXGIVkInteropDevice)) { + *ppvObject = ref(m_d3d11VkInterop); + return S_OK; + } + if (riid == __uuidof(ID3D11Device) || riid == __uuidof(ID3D11Device1)) { *ppvObject = ref(m_d3d11Device); diff --git a/src/d3d11/d3d11_device.h b/src/d3d11/d3d11_device.h index a4ed9f99..e6c338ba 100644 --- a/src/d3d11/d3d11_device.h +++ b/src/d3d11/d3d11_device.h @@ -29,6 +29,7 @@ namespace dxvk { class D3D11Texture1D; class D3D11Texture2D; class D3D11Texture3D; + class D3D11VkInterop; /** * \brief D3D11 device container @@ -54,6 +55,7 @@ namespace dxvk { IDXGIVkDevice* m_dxgiDevice = nullptr; D3D11Device* m_d3d11Device = nullptr; D3D11Presenter* m_d3d11Presenter = nullptr; + D3D11VkInterop* m_d3d11VkInterop = nullptr; }; diff --git a/src/d3d11/d3d11_interop.cpp b/src/d3d11/d3d11_interop.cpp new file mode 100644 index 00000000..0339a29b --- /dev/null +++ b/src/d3d11/d3d11_interop.cpp @@ -0,0 +1,107 @@ +#include "d3d11_context_imm.h" +#include "d3d11_interop.h" +#include "d3d11_device.h" + +#include "../dxvk/dxvk_adapter.h" +#include "../dxvk/dxvk_device.h" +#include "../dxvk/dxvk_instance.h" + +namespace dxvk { + + D3D11VkInterop::D3D11VkInterop( + IDXGIObject* pContainer, + ID3D11Device* pDevice) + : m_container (pContainer), + m_device (pDevice) { } + + + D3D11VkInterop::~D3D11VkInterop() { + + } + + + ULONG STDMETHODCALLTYPE D3D11VkInterop::AddRef() { + return m_container->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D11VkInterop::Release() { + return m_container->Release(); + } + + + HRESULT STDMETHODCALLTYPE D3D11VkInterop::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_container->QueryInterface(riid, ppvObject); + } + + + void STDMETHODCALLTYPE D3D11VkInterop::GetVulkanHandles( + VkInstance* pInstance, + VkPhysicalDevice* pPhysDev, + VkDevice* pDevice) { + auto device = static_cast(m_device)->GetDXVKDevice(); + auto adapter = device->adapter(); + auto instance = adapter->instance(); + + if (pDevice != nullptr) + *pDevice = device->handle(); + + if (pPhysDev != nullptr) + *pPhysDev = adapter->handle(); + + if (pInstance != nullptr) + *pInstance = instance->handle(); + } + + + void STDMETHODCALLTYPE D3D11VkInterop::GetSubmissionQueue( + VkQueue* pQueue, + uint32_t* pQueueFamilyIndex) { + auto device = static_cast(m_device)->GetDXVKDevice(); + DxvkDeviceQueue queue = device->graphicsQueue(); + + if (pQueue != nullptr) + *pQueue = queue.queueHandle; + + if (pQueueFamilyIndex != nullptr) + *pQueueFamilyIndex = queue.queueFamily; + } + + + void STDMETHODCALLTYPE D3D11VkInterop::TransitionSurfaceLayout( + IDXGIVkInteropSurface* pSurface, + const VkImageSubresourceRange* pSubresources, + VkImageLayout OldLayout, + VkImageLayout NewLayout) { + Com deviceContext = nullptr; + m_device->GetImmediateContext(&deviceContext); + + auto immediateContext = static_cast(deviceContext.ptr()); + + immediateContext->TransitionSurfaceLayout( + pSurface, pSubresources, OldLayout, NewLayout); + } + + + void STDMETHODCALLTYPE D3D11VkInterop::FlushRenderingCommands() { + Com deviceContext = nullptr; + m_device->GetImmediateContext(&deviceContext); + + auto immediateContext = static_cast(deviceContext.ptr()); + immediateContext->Flush(); + immediateContext->SynchronizeCsThread(); + } + + + void STDMETHODCALLTYPE D3D11VkInterop::LockSubmissionQueue() { + static_cast(m_device)->GetDXVKDevice()->lockSubmission(); + } + + + void STDMETHODCALLTYPE D3D11VkInterop::ReleaseSubmissionQueue() { + static_cast(m_device)->GetDXVKDevice()->unlockSubmission(); + } + +} \ No newline at end of file diff --git a/src/d3d11/d3d11_interop.h b/src/d3d11/d3d11_interop.h new file mode 100644 index 00000000..27865172 --- /dev/null +++ b/src/d3d11/d3d11_interop.h @@ -0,0 +1,54 @@ +#pragma once + +#include "../dxgi/dxgi_interfaces.h" + +#include "d3d11_include.h" + +namespace dxvk { + + class D3D11VkInterop : public ComObject { + + public: + + D3D11VkInterop( + IDXGIObject* pContainer, + ID3D11Device* pDevice); + ~D3D11VkInterop(); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + void STDMETHODCALLTYPE GetVulkanHandles( + VkInstance* pInstance, + VkPhysicalDevice* pPhysDev, + VkDevice* pDevice); + + void STDMETHODCALLTYPE GetSubmissionQueue( + VkQueue* pQueue, + uint32_t* pQueueFamilyIndex); + + void STDMETHODCALLTYPE TransitionSurfaceLayout( + IDXGIVkInteropSurface* pSurface, + const VkImageSubresourceRange* pSubresources, + VkImageLayout OldLayout, + VkImageLayout NewLayout); + + void STDMETHODCALLTYPE FlushRenderingCommands(); + + void STDMETHODCALLTYPE LockSubmissionQueue(); + + void STDMETHODCALLTYPE ReleaseSubmissionQueue(); + + private: + + IDXGIObject* m_container; + ID3D11Device* m_device; + + }; + +} \ No newline at end of file diff --git a/src/d3d11/d3d11_main.cpp b/src/d3d11/d3d11_main.cpp index 4d08403e..4cdc0aa5 100644 --- a/src/d3d11/d3d11_main.cpp +++ b/src/d3d11/d3d11_main.cpp @@ -5,6 +5,7 @@ #include "d3d11_device.h" #include "d3d11_enums.h" +#include "d3d11_interop.h" #include "d3d11_present.h" namespace dxvk { @@ -127,6 +128,9 @@ extern "C" { container->m_d3d11Presenter = new D3D11Presenter( container.ptr(), container->m_d3d11Device); + container->m_d3d11VkInterop = new D3D11VkInterop( + container.ptr(), container->m_d3d11Device); + if (ppDevice != nullptr) *ppDevice = ref(container->m_d3d11Device); diff --git a/src/d3d11/meson.build b/src/d3d11/meson.build index 41964028..a0cf8e3a 100644 --- a/src/d3d11/meson.build +++ b/src/d3d11/meson.build @@ -10,6 +10,7 @@ d3d11_src = [ 'd3d11_device.cpp', 'd3d11_enums.cpp', 'd3d11_input_layout.cpp', + 'd3d11_interop.cpp', 'd3d11_main.cpp', 'd3d11_options.cpp', 'd3d11_present.cpp', diff --git a/src/dxgi/dxgi_interfaces.h b/src/dxgi/dxgi_interfaces.h index 5fc268dc..5e86025d 100644 --- a/src/dxgi/dxgi_interfaces.h +++ b/src/dxgi/dxgi_interfaces.h @@ -221,7 +221,7 @@ IDXGIVkInteropDevice : public IUnknown { * \param [in] OldLayout Current image layout * \param [in] NewLayout Desired image layout */ - virtual HRESULT STDMETHODCALLTYPE TransitionSurfaceLayout( + virtual void STDMETHODCALLTYPE TransitionSurfaceLayout( IDXGIVkInteropSurface* pSurface, const VkImageSubresourceRange* pSubresources, VkImageLayout OldLayout, diff --git a/src/dxvk/dxvk_adapter.cpp b/src/dxvk/dxvk_adapter.cpp index 5cfaaff2..6e28366b 100644 --- a/src/dxvk/dxvk_adapter.cpp +++ b/src/dxvk/dxvk_adapter.cpp @@ -28,6 +28,11 @@ namespace dxvk { } + Rc DxvkAdapter::instance() const { + return m_instance; + } + + VkPhysicalDeviceProperties DxvkAdapter::deviceProperties() const { VkPhysicalDeviceProperties properties; m_vki->vkGetPhysicalDeviceProperties(m_handle, &properties); diff --git a/src/dxvk/dxvk_adapter.h b/src/dxvk/dxvk_adapter.h index d36382f5..aa693508 100644 --- a/src/dxvk/dxvk_adapter.h +++ b/src/dxvk/dxvk_adapter.h @@ -52,6 +52,12 @@ namespace dxvk { return m_handle; } + /** + * \brief Vulkan instance + * \returns Vulkan instance + */ + Rc instance() const; + /** * \brief Physical device properties * diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 927d0366..0362f9f7 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -1199,6 +1199,25 @@ namespace dxvk { } + void DxvkContext::transformImage( + const Rc& dstImage, + const VkImageSubresourceRange& dstSubresources, + VkImageLayout srcLayout, + VkImageLayout dstLayout) { + m_barriers.accessImage( + dstImage, dstSubresources, + srcLayout, + dstImage->info().stages, + dstImage->info().access, + dstLayout, + dstImage->info().stages, + dstImage->info().access); + m_barriers.recordCommands(m_cmd); + + m_cmd->trackResource(dstImage); + } + + void DxvkContext::updateBuffer( const Rc& buffer, VkDeviceSize offset, diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 5dd9b337..0c0f32fd 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -468,6 +468,20 @@ namespace dxvk { const VkImageSubresourceLayers& srcSubresources, VkFormat format); + /** + * \brief Transforms image subresource layouts + * + * \param [in] dstImage Image to transform + * \param [in] dstSubresources Subresources + * \param [in] srcLayout Current layout + * \param [in] dstLayout Desired layout + */ + void transformImage( + const Rc& dstImage, + const VkImageSubresourceRange& dstSubresources, + VkImageLayout srcLayout, + VkImageLayout dstLayout); + /** * \brief Updates a buffer * From 81a0fa4805ca877ac056a46098cd81dcee55ce32 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Fri, 20 Apr 2018 10:38:39 +0200 Subject: [PATCH 5/6] [d3d11] Implemented IDXGIVkInteropSurface for common textures --- src/d3d11/d3d11_texture.cpp | 68 +++++++++++++++++++++++++++++++++++++ src/d3d11/d3d11_texture.h | 37 ++++++++++++++++++++ src/dxgi/dxgi_interfaces.h | 6 +++- 3 files changed, 110 insertions(+), 1 deletion(-) diff --git a/src/d3d11/d3d11_texture.cpp b/src/d3d11/d3d11_texture.cpp index 1bfb0e6b..bedc3252 100644 --- a/src/d3d11/d3d11_texture.cpp +++ b/src/d3d11/d3d11_texture.cpp @@ -284,6 +284,74 @@ namespace dxvk { } + D3D11VkInteropSurface::D3D11VkInteropSurface( + IDXGIObject* pContainer, + D3D11CommonTexture* pTexture) + : m_container (pContainer), + m_texture (pTexture) { + + } + + + D3D11VkInteropSurface::~D3D11VkInteropSurface() { + + } + + + ULONG STDMETHODCALLTYPE D3D11VkInteropSurface::AddRef() { + return m_container->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D11VkInteropSurface::Release() { + return m_container->Release(); + } + + + HRESULT STDMETHODCALLTYPE D3D11VkInteropSurface::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_container->QueryInterface(riid, ppvObject); + } + + + HRESULT STDMETHODCALLTYPE D3D11VkInteropSurface::GetVulkanImageInfo( + VkImage* pHandle, + VkImageLayout* pLayout, + VkImageCreateInfo* pInfo) { + const Rc image = m_texture->GetImage(); + const DxvkImageCreateInfo& info = image->info(); + + if (pHandle != nullptr) + *pHandle = image->handle(); + + if (pLayout != nullptr) + *pLayout = info.layout; + + if (pInfo != nullptr) { + // We currently don't support any extended structures + if (pInfo->sType != VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO + || pInfo->pNext != nullptr) + return E_INVALIDARG; + + pInfo->flags = 0; + pInfo->imageType = info.type; + pInfo->format = info.format; + pInfo->extent = info.extent; + pInfo->mipLevels = info.mipLevels; + pInfo->arrayLayers = info.numLayers; + pInfo->samples = info.sampleCount; + pInfo->tiling = info.tiling; + pInfo->usage = info.usage; + pInfo->sharingMode = VK_SHARING_MODE_EXCLUSIVE; + pInfo->queueFamilyIndexCount = 0; + pInfo->initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + } + + return S_OK; + } + + /////////////////////////////////////////// // D 3 D 1 1 T E X T U R E 1 D D3D11Texture1D::D3D11Texture1D( diff --git a/src/d3d11/d3d11_texture.h b/src/d3d11/d3d11_texture.h index f9e5f1cb..a51331e4 100644 --- a/src/d3d11/d3d11_texture.h +++ b/src/d3d11/d3d11_texture.h @@ -190,6 +190,43 @@ namespace dxvk { }; + /** + * \brief Common texture interop class + * + * Provides access to the underlying Vulkan + * texture to external Vulkan libraries. + */ + class D3D11VkInteropSurface : public IDXGIVkInteropSurface { + + public: + + D3D11VkInteropSurface( + IDXGIObject* pContainer, + D3D11CommonTexture* pTexture); + + ~D3D11VkInteropSurface(); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + HRESULT STDMETHODCALLTYPE GetVulkanImageInfo( + VkImage* pHandle, + VkImageLayout* pLayout, + VkImageCreateInfo* pInfo); + + private: + + IDXGIObject* m_container; + D3D11CommonTexture* m_texture; + + }; + + /////////////////////////////////////////// // D 3 D 1 1 T E X T U R E 1 D class D3D11Texture1D : public D3D11DeviceChild { diff --git a/src/dxgi/dxgi_interfaces.h b/src/dxgi/dxgi_interfaces.h index 5e86025d..c32bffdd 100644 --- a/src/dxgi/dxgi_interfaces.h +++ b/src/dxgi/dxgi_interfaces.h @@ -152,13 +152,17 @@ IDXGIVkInteropSurface : public IUnknown { * * If \c pInfo is not \c nullptr, the following rules apply: * - \c pInfo->sType \e must be \c VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO - * - \c pInfo->pNext \e must be \c nullptr or point ti a supported + * - \c pInfo->pNext \e must be \c nullptr or point to a supported * extension-specific structure (currently none) * - \c pInfo->queueFamilyIndexCount must be the length of the * \c pInfo->pQueueFamilyIndices array, in \c uint32_t units. * - \c pInfo->pQueueFamilyIndices must point to a pre-allocated * array of \c uint32_t of size \c pInfo->pQueueFamilyIndices. * + * \note As of now, the sharing mode will always be + * \c VK_SHARING_MODE_EXCLUSIVE and no queue + * family indices will be written to the array. + * * After the call, the structure pointed to by \c pInfo can * be used to create an image with identical properties. * From 1ed1c434313ba59a91c64772215f2fecb54dc9fd Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Fri, 20 Apr 2018 11:12:54 +0200 Subject: [PATCH 6/6] [d3d11] Wire up D3D11VkInteropSurface to D3D11Texture*D classes --- src/d3d11/d3d11_texture.cpp | 26 ++++++++++++++++++++++---- src/d3d11/d3d11_texture.h | 13 ++++++++----- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/d3d11/d3d11_texture.cpp b/src/d3d11/d3d11_texture.cpp index bedc3252..9a28828a 100644 --- a/src/d3d11/d3d11_texture.cpp +++ b/src/d3d11/d3d11_texture.cpp @@ -285,7 +285,7 @@ namespace dxvk { D3D11VkInteropSurface::D3D11VkInteropSurface( - IDXGIObject* pContainer, + ID3D11DeviceChild* pContainer, D3D11CommonTexture* pTexture) : m_container (pContainer), m_texture (pTexture) { @@ -357,7 +357,8 @@ namespace dxvk { D3D11Texture1D::D3D11Texture1D( D3D11Device* pDevice, const D3D11_COMMON_TEXTURE_DESC* pDesc) - : m_texture(pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE1D) { + : m_texture(pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE1D), + m_interop(this, &m_texture) { } @@ -378,6 +379,11 @@ namespace dxvk { return S_OK; } + if (riid == __uuidof(IDXGIVkInteropSurface)) { + *ppvObject = ref(&m_interop); + return S_OK; + } + Logger::warn("D3D11Texture1D::QueryInterface: Unknown interface query"); Logger::warn(str::format(riid)); return E_NOINTERFACE; @@ -422,7 +428,8 @@ namespace dxvk { D3D11Texture2D::D3D11Texture2D( D3D11Device* pDevice, const D3D11_COMMON_TEXTURE_DESC* pDesc) - : m_texture(pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE2D) { + : m_texture(pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE2D), + m_interop(this, &m_texture) { } @@ -443,6 +450,11 @@ namespace dxvk { return S_OK; } + if (riid == __uuidof(IDXGIVkInteropSurface)) { + *ppvObject = ref(&m_interop); + return S_OK; + } + Logger::warn("D3D11Texture2D::QueryInterface: Unknown interface query"); Logger::warn(str::format(riid)); return E_NOINTERFACE; @@ -489,7 +501,8 @@ namespace dxvk { D3D11Texture3D::D3D11Texture3D( D3D11Device* pDevice, const D3D11_COMMON_TEXTURE_DESC* pDesc) - : m_texture(pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE3D) { + : m_texture(pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE3D), + m_interop(this, &m_texture) { } @@ -510,6 +523,11 @@ namespace dxvk { return S_OK; } + if (riid == __uuidof(IDXGIVkInteropSurface)) { + *ppvObject = ref(&m_interop); + return S_OK; + } + Logger::warn("D3D11Texture3D::QueryInterface: Unknown interface query"); Logger::warn(str::format(riid)); return E_NOINTERFACE; diff --git a/src/d3d11/d3d11_texture.h b/src/d3d11/d3d11_texture.h index a51331e4..fbfd0205 100644 --- a/src/d3d11/d3d11_texture.h +++ b/src/d3d11/d3d11_texture.h @@ -201,7 +201,7 @@ namespace dxvk { public: D3D11VkInteropSurface( - IDXGIObject* pContainer, + ID3D11DeviceChild* pContainer, D3D11CommonTexture* pTexture); ~D3D11VkInteropSurface(); @@ -221,7 +221,7 @@ namespace dxvk { private: - IDXGIObject* m_container; + ID3D11DeviceChild* m_container; D3D11CommonTexture* m_texture; }; @@ -262,7 +262,8 @@ namespace dxvk { private: - D3D11CommonTexture m_texture; + D3D11CommonTexture m_texture; + D3D11VkInteropSurface m_interop; }; @@ -302,7 +303,8 @@ namespace dxvk { private: - D3D11CommonTexture m_texture; + D3D11CommonTexture m_texture; + D3D11VkInteropSurface m_interop; }; @@ -342,7 +344,8 @@ namespace dxvk { private: - D3D11CommonTexture m_texture; + D3D11CommonTexture m_texture; + D3D11VkInteropSurface m_interop; };