From ac131126193379080c133e9689eed87d7aa1e48f Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Wed, 21 Sep 2022 20:28:09 +0000 Subject: [PATCH] [d3d9] Add ID3D9VkInteropTexture Provides access to the backing resource of a D3D9 texture. --- src/d3d9/d3d9_common_texture.cpp | 3 +- src/d3d9/d3d9_common_texture.h | 6 +++ src/d3d9/d3d9_interfaces.h | 46 ++++++++++++++++++++++ src/d3d9/d3d9_interop.cpp | 67 ++++++++++++++++++++++++++++++++ src/d3d9/d3d9_interop.h | 33 ++++++++++++++++ src/d3d9/d3d9_surface.cpp | 2 +- src/d3d9/d3d9_texture.cpp | 15 +++++++ src/d3d9/d3d9_texture.h | 2 +- src/d3d9/d3d9_volume.cpp | 2 +- 9 files changed, 172 insertions(+), 4 deletions(-) diff --git a/src/d3d9/d3d9_common_texture.cpp b/src/d3d9/d3d9_common_texture.cpp index 5b5c07115..b50bec821 100644 --- a/src/d3d9/d3d9_common_texture.cpp +++ b/src/d3d9/d3d9_common_texture.cpp @@ -12,10 +12,11 @@ namespace dxvk { D3D9CommonTexture::D3D9CommonTexture( D3D9DeviceEx* pDevice, + IUnknown* pInterface, const D3D9_COMMON_TEXTURE_DESC* pDesc, D3DRESOURCETYPE ResourceType, HANDLE* pSharedHandle) - : m_device(pDevice), m_desc(*pDesc), m_type(ResourceType) { + : m_device(pDevice), m_desc(*pDesc), m_type(ResourceType), m_d3d9Interop(pInterface, this) { if (m_desc.Format == D3D9Format::Unknown) m_desc.Format = (m_desc.Usage & D3DUSAGE_DEPTHSTENCIL) ? D3D9Format::D32 diff --git a/src/d3d9/d3d9_common_texture.h b/src/d3d9/d3d9_common_texture.h index 58c0827ba..f0cf03f26 100644 --- a/src/d3d9/d3d9_common_texture.h +++ b/src/d3d9/d3d9_common_texture.h @@ -4,6 +4,7 @@ #include "d3d9_util.h" #include "d3d9_caps.h" #include "d3d9_mem.h" +#include "d3d9_interop.h" #include "../dxvk/dxvk_device.h" @@ -72,6 +73,7 @@ namespace dxvk { D3D9CommonTexture( D3D9DeviceEx* pDevice, + IUnknown* pInterface, const D3D9_COMMON_TEXTURE_DESC* pDesc, D3DRESOURCETYPE ResourceType, HANDLE* pSharedHandle); @@ -474,6 +476,8 @@ namespace dxvk { */ void CreateBufferSubresource(UINT Subresource, bool Initialize); + ID3D9VkInteropTexture* GetVkInterop() { return &m_d3d9Interop; } + private: D3D9DeviceEx* m_device; @@ -523,6 +527,8 @@ namespace dxvk { std::array m_dirtyBoxes; + D3D9VkInteropTexture m_d3d9Interop; + Rc CreatePrimaryImage(D3DRESOURCETYPE ResourceType, bool TryOffscreenRT, HANDLE* pSharedHandle) const; Rc CreateResolveImage() const; diff --git a/src/d3d9/d3d9_interfaces.h b/src/d3d9/d3d9_interfaces.h index 9b4b77a2e..065e95cbd 100644 --- a/src/d3d9/d3d9_interfaces.h +++ b/src/d3d9/d3d9_interfaces.h @@ -30,8 +30,54 @@ ID3D9VkInteropInterface : public IUnknown { VkPhysicalDevice* pPhysicalDevice) = 0; }; +/** + * \brief D3D9 texture interface for Vulkan interop + * + * Provides access to the backing resource of a + * D3D9 texture. + */ +MIDL_INTERFACE("d56344f5-8d35-46fd-806d-94c351b472c1") +ID3D9VkInteropTexture : public IUnknown { + /** + * \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 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. + * + * 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 D3DERR_INVALIDCALL + */ + virtual HRESULT STDMETHODCALLTYPE GetVulkanImageInfo( + VkImage* pHandle, + VkImageLayout* pLayout, + VkImageCreateInfo* pInfo) = 0; +}; + #ifdef _MSC_VER struct __declspec(uuid("3461a81b-ce41-485b-b6b5-fcf08ba6a6bd")) ID3D9VkInteropInterface; +struct __declspec(uuid("d56344f5-8d35-46fd-806d-94c351b472c1")) ID3D9VkInteropTexture; #else __CRT_UUID_DECL(ID3D9VkInteropInterface, 0x3461a81b,0xce41,0x485b,0xb6,0xb5,0xfc,0xf0,0x8b,0xa6,0xa6,0xbd); +__CRT_UUID_DECL(ID3D9VkInteropTexture, 0xd56344f5,0x8d35,0x46fd,0x80,0x6d,0x94,0xc3,0x51,0xb4,0x72,0xc1); #endif diff --git a/src/d3d9/d3d9_interop.cpp b/src/d3d9/d3d9_interop.cpp index efa0c7b15..64ac0b367 100644 --- a/src/d3d9/d3d9_interop.cpp +++ b/src/d3d9/d3d9_interop.cpp @@ -1,5 +1,6 @@ #include "d3d9_interop.h" #include "d3d9_interface.h" +#include "d3d9_common_texture.h" namespace dxvk { @@ -46,4 +47,70 @@ namespace dxvk { } } + //////////////////////////////// + // Texture Interop + /////////////////////////////// + + D3D9VkInteropTexture::D3D9VkInteropTexture( + IUnknown* pInterface, + D3D9CommonTexture* pTexture) + : m_interface(pInterface) + , m_texture (pTexture) { + + } + + D3D9VkInteropTexture::~D3D9VkInteropTexture() { + + } + + ULONG STDMETHODCALLTYPE D3D9VkInteropTexture::AddRef() { + return m_interface->AddRef(); + } + + ULONG STDMETHODCALLTYPE D3D9VkInteropTexture::Release() { + return m_interface->Release(); + } + + HRESULT STDMETHODCALLTYPE D3D9VkInteropTexture::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_interface->QueryInterface(riid, ppvObject); + } + + HRESULT STDMETHODCALLTYPE D3D9VkInteropTexture::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 D3DERR_INVALIDCALL; + + 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; + } + } diff --git a/src/d3d9/d3d9_interop.h b/src/d3d9/d3d9_interop.h index 2f7f9b344..30596696f 100644 --- a/src/d3d9/d3d9_interop.h +++ b/src/d3d9/d3d9_interop.h @@ -5,6 +5,7 @@ namespace dxvk { class D3D9InterfaceEx; + class D3D9CommonTexture; class D3D9VkInteropInterface final : public ID3D9VkInteropInterface { @@ -36,4 +37,36 @@ namespace dxvk { }; + class D3D9VkInteropTexture final : public ID3D9VkInteropTexture { + + public: + + D3D9VkInteropTexture( + IUnknown* pInterface, + D3D9CommonTexture* pTexture); + + ~D3D9VkInteropTexture(); + + ULONG STDMETHODCALLTYPE AddRef(); + + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void** ppvObject); + + HRESULT STDMETHODCALLTYPE GetVulkanImageInfo( + VkImage* pHandle, + VkImageLayout* pLayout, + VkImageCreateInfo* pInfo); + + D3D9CommonTexture* GetCommonTexture() { return m_texture; } + + private: + + IUnknown* m_interface; + D3D9CommonTexture* m_texture; + + }; + } diff --git a/src/d3d9/d3d9_surface.cpp b/src/d3d9/d3d9_surface.cpp index 1ff2b4e33..91f917853 100644 --- a/src/d3d9/d3d9_surface.cpp +++ b/src/d3d9/d3d9_surface.cpp @@ -15,7 +15,7 @@ namespace dxvk { HANDLE* pSharedHandle) : D3D9SurfaceBase( pDevice, - new D3D9CommonTexture( pDevice, pDesc, D3DRTYPE_SURFACE, pSharedHandle), + new D3D9CommonTexture( pDevice, this, pDesc, D3DRTYPE_SURFACE, pSharedHandle), 0, 0, nullptr, pContainer) { } diff --git a/src/d3d9/d3d9_texture.cpp b/src/d3d9/d3d9_texture.cpp index 2f1d3ce6e..e1e3547c3 100644 --- a/src/d3d9/d3d9_texture.cpp +++ b/src/d3d9/d3d9_texture.cpp @@ -27,6 +27,11 @@ namespace dxvk { return S_OK; } + if (riid == __uuidof(ID3D9VkInteropTexture)) { + *ppvObject = ref(m_texture.GetVkInterop()); + return S_OK; + } + Logger::warn("D3D9Texture2D::QueryInterface: Unknown interface query"); Logger::warn(str::format(riid)); return E_NOINTERFACE; @@ -118,6 +123,11 @@ namespace dxvk { return S_OK; } + if (riid == __uuidof(ID3D9VkInteropTexture)) { + *ppvObject = ref(m_texture.GetVkInterop()); + return S_OK; + } + Logger::warn("D3D9Texture3D::QueryInterface: Unknown interface query"); Logger::warn(str::format(riid)); return E_NOINTERFACE; @@ -203,6 +213,11 @@ namespace dxvk { return S_OK; } + if (riid == __uuidof(ID3D9VkInteropTexture)) { + *ppvObject = ref(m_texture.GetVkInterop()); + return S_OK; + } + Logger::warn("D3D9TextureCube::QueryInterface: Unknown interface query"); Logger::warn(str::format(riid)); return E_NOINTERFACE; diff --git a/src/d3d9/d3d9_texture.h b/src/d3d9/d3d9_texture.h index 317f72ee5..fe9ff638a 100644 --- a/src/d3d9/d3d9_texture.h +++ b/src/d3d9/d3d9_texture.h @@ -26,7 +26,7 @@ namespace dxvk { D3DRESOURCETYPE ResourceType, HANDLE* pSharedHandle) : D3D9Resource ( pDevice ) - , m_texture ( pDevice, pDesc, ResourceType, pSharedHandle ) + , m_texture ( pDevice, this, pDesc, ResourceType, pSharedHandle ) , m_lod ( 0 ) { const uint32_t arraySlices = m_texture.Desc()->ArraySize; const uint32_t mipLevels = m_texture.Desc()->MipLevels; diff --git a/src/d3d9/d3d9_volume.cpp b/src/d3d9/d3d9_volume.cpp index 52886d80b..dff931f25 100644 --- a/src/d3d9/d3d9_volume.cpp +++ b/src/d3d9/d3d9_volume.cpp @@ -10,7 +10,7 @@ namespace dxvk { const D3D9_COMMON_TEXTURE_DESC* pDesc) : D3D9VolumeBase( pDevice, - new D3D9CommonTexture( pDevice, pDesc, D3DRTYPE_VOLUMETEXTURE, nullptr ), + new D3D9CommonTexture( pDevice, this, pDesc, D3DRTYPE_VOLUMETEXTURE, nullptr ), 0, 0, nullptr, nullptr) { }