From 48046e009c9d3d8bd4f8128d4e893990908c2819 Mon Sep 17 00:00:00 2001 From: Derek Lesho Date: Wed, 23 Feb 2022 16:18:07 -0500 Subject: [PATCH] [d3d11] Add support for shared ID3D11Texture2D resources. --- src/d3d11/d3d11_device.cpp | 71 +++++++++++++++++++++++++++++++----- src/d3d11/d3d11_device.h | 6 +++ src/d3d11/d3d11_resource.cpp | 33 +++++++++++++---- src/d3d11/d3d11_texture.cpp | 70 +++++++++++++++++++++++++++++++---- src/d3d11/d3d11_texture.h | 9 +++-- 5 files changed, 162 insertions(+), 27 deletions(-) diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index e6bfc978..0855c875 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -23,6 +23,8 @@ #include "d3d11_texture.h" #include "d3d11_video.h" +#include "../util/util_shared_res.h" + namespace dxvk { constexpr uint32_t D3D11DXGIDevice::DefaultFrameLatency; @@ -207,7 +209,7 @@ namespace dxvk { return S_FALSE; try { - Com texture = new D3D11Texture2D(this, &desc); + Com texture = new D3D11Texture2D(this, &desc, nullptr); m_initializer->InitTexture(texture->GetCommonTexture(), pInitialData); *ppTexture2D = texture.ref(); return S_OK; @@ -1388,10 +1390,8 @@ namespace dxvk { HANDLE hResource, REFIID ReturnedInterface, void** ppResource) { - InitReturnPtr(ppResource); - - Logger::err("D3D11Device::OpenSharedResource: Not implemented"); - return E_NOTIMPL; + return OpenSharedResourceGeneric( + hResource, ReturnedInterface, ppResource); } @@ -1399,10 +1399,8 @@ namespace dxvk { HANDLE hResource, REFIID ReturnedInterface, void** ppResource) { - InitReturnPtr(ppResource); - - Logger::err("D3D11Device::OpenSharedResource1: Not implemented"); - return E_NOTIMPL; + return OpenSharedResourceGeneric( + hResource, ReturnedInterface, ppResource); } @@ -2260,6 +2258,61 @@ namespace dxvk { } + template + HRESULT D3D11Device::OpenSharedResourceGeneric( + HANDLE hResource, + REFIID ReturnedInterface, + void** ppResource) { + InitReturnPtr(ppResource); + + if (ppResource == nullptr) + return S_FALSE; + + HANDLE ntHandle = IsKmtHandle ? openKmtHandle(hResource) : hResource; + + if (ntHandle == INVALID_HANDLE_VALUE) { + Logger::warn(str::format("D3D11Device::OpenSharedResourceGeneric: Handle not found: ", hResource)); + return E_INVALIDARG; + } + + DxvkSharedTextureMetadata metadata; + bool ret = getSharedMetadata(ntHandle, &metadata, sizeof(metadata), NULL); + + if (IsKmtHandle) + ::CloseHandle(ntHandle); + + if (!ret) { + Logger::warn("D3D11Device::OpenSharedResourceGeneric: Failed to get shared resource info for a texture"); + return E_INVALIDARG; + } + + D3D11_COMMON_TEXTURE_DESC d3d11Desc; + d3d11Desc.Width = metadata.Width; + d3d11Desc.Height = metadata.Height; + d3d11Desc.Depth = 1, + d3d11Desc.MipLevels = metadata.MipLevels; + d3d11Desc.ArraySize = metadata.ArraySize; + d3d11Desc.Format = metadata.Format; + d3d11Desc.SampleDesc = metadata.SampleDesc; + d3d11Desc.Usage = metadata.Usage; + d3d11Desc.BindFlags = metadata.BindFlags; + d3d11Desc.CPUAccessFlags = metadata.CPUAccessFlags; + d3d11Desc.MiscFlags = metadata.MiscFlags; + d3d11Desc.TextureLayout = metadata.TextureLayout; + + // Only 2D textures may be shared + try { + const Com texture = new D3D11Texture2D(this, &d3d11Desc, hResource); + texture->QueryInterface(ReturnedInterface, ppResource); + return S_OK; + } + catch (const DxvkError& e) { + Logger::err(e.message()); + return E_INVALIDARG; + } + } + + template void D3D11Device::CopySubresourceData( Void* pData, diff --git a/src/d3d11/d3d11_device.h b/src/d3d11/d3d11_device.h index 7de5cf91..7643f8f4 100644 --- a/src/d3d11/d3d11_device.h +++ b/src/d3d11/d3d11_device.h @@ -473,6 +473,12 @@ namespace dxvk { VkFormat Format, VkImageType Type) const; + template + HRESULT OpenSharedResourceGeneric( + HANDLE hResource, + REFIID ReturnedInterface, + void** ppResource); + uint32_t GetViewPlaneIndex( ID3D11Resource* pResource, DXGI_FORMAT ViewFormat); diff --git a/src/d3d11/d3d11_resource.cpp b/src/d3d11/d3d11_resource.cpp index 5ee5fbf9..d05f003a 100644 --- a/src/d3d11/d3d11_resource.cpp +++ b/src/d3d11/d3d11_resource.cpp @@ -81,9 +81,17 @@ namespace dxvk { HRESULT STDMETHODCALLTYPE D3D11DXGIResource::GetSharedHandle( HANDLE* pSharedHandle) { - InitReturnPtr(pSharedHandle); - Logger::err("D3D11DXGIResource::GetSharedHandle: Stub"); - return E_NOTIMPL; + auto texture = GetCommonTexture(m_resource); + if (texture == nullptr || pSharedHandle == nullptr) + return E_INVALIDARG; + + HANDLE kmtHandle = texture->GetImage()->sharedHandle(); + + if (kmtHandle == INVALID_HANDLE_VALUE) + return E_INVALIDARG; + + *pSharedHandle = kmtHandle; + return S_OK; } @@ -132,9 +140,20 @@ namespace dxvk { DWORD dwAccess, LPCWSTR lpName, HANDLE* pHandle) { - InitReturnPtr(pHandle); - Logger::err("D3D11DXGIResource::CreateSharedHandle: Stub"); - return E_NOTIMPL; + auto texture = GetCommonTexture(m_resource); + if (texture == nullptr || pHandle == nullptr) + return E_INVALIDARG; + + if (lpName) + Logger::warn("Naming shared resources not supported"); + + HANDLE handle = texture->GetImage()->sharedHandle(); + + if (handle == INVALID_HANDLE_VALUE) + return E_INVALIDARG; + + *pHandle = handle; + return S_OK; } @@ -235,4 +254,4 @@ namespace dxvk { return ResourceReleasePrivate(pResource, dim); } -} \ No newline at end of file +} diff --git a/src/d3d11/d3d11_texture.cpp b/src/d3d11/d3d11_texture.cpp index ee1cc5f4..5277ca22 100644 --- a/src/d3d11/d3d11_texture.cpp +++ b/src/d3d11/d3d11_texture.cpp @@ -2,6 +2,8 @@ #include "d3d11_gdi.h" #include "d3d11_texture.h" +#include "../util/util_shared_res.h" + namespace dxvk { D3D11CommonTexture::D3D11CommonTexture( @@ -10,7 +12,8 @@ namespace dxvk { const D3D11_COMMON_TEXTURE_DESC* pDesc, D3D11_RESOURCE_DIMENSION Dimension, DXGI_USAGE DxgiUsage, - VkImage vkImage) + VkImage vkImage, + HANDLE hSharedHandle) : m_interface(pInterface), m_device(pDevice), m_dimension(Dimension), m_desc(*pDesc), m_dxgiUsage(DxgiUsage) { DXGI_VK_FORMAT_MODE formatMode = GetFormatMode(); DXGI_VK_FORMAT_INFO formatInfo = m_device->LookupFormat(m_desc.Format, formatMode); @@ -38,6 +41,22 @@ namespace dxvk { imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; imageInfo.shared = vkImage != VK_NULL_HANDLE; + // Normalise hSharedhandle to INVALID_HANDLE_VALUE to allow passing in nullptr + if (hSharedHandle == nullptr) + hSharedHandle = INVALID_HANDLE_VALUE; + + if (m_desc.MiscFlags & (D3D11_RESOURCE_MISC_SHARED|D3D11_RESOURCE_MISC_SHARED_NTHANDLE)) { + if (m_desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) + Logger::warn("D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX: not supported."); + + imageInfo.shared = true; + imageInfo.sharing.mode = hSharedHandle == INVALID_HANDLE_VALUE ? DxvkSharedHandleMode::Export : DxvkSharedHandleMode::Import; + imageInfo.sharing.type = m_desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_NTHANDLE + ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT + : VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT; + imageInfo.sharing.handle = hSharedHandle; + } + if (!pDevice->GetOptions()->disableMsaa) DecodeSampleCount(m_desc.SampleDesc.Count, &imageInfo.sampleCount); @@ -175,7 +194,7 @@ namespace dxvk { // We must keep LINEAR images in GENERAL layout, but we // can choose a better layout for the image based on how // it is going to be used by the game. - if (imageInfo.tiling == VK_IMAGE_TILING_OPTIMAL && !isMultiPlane) + if (imageInfo.tiling == VK_IMAGE_TILING_OPTIMAL && !isMultiPlane && imageInfo.sharing.mode == DxvkSharedHandleMode::None) imageInfo.layout = OptimizeLayout(imageInfo.usage); // For some formats, we need to enable sampled and/or @@ -210,6 +229,9 @@ namespace dxvk { m_image = m_device->GetDXVKDevice()->createImage(imageInfo, memoryProperties); else m_image = m_device->GetDXVKDevice()->createImageFromVkImage(imageInfo, vkImage); + + if (imageInfo.sharing.mode == DxvkSharedHandleMode::Export) + ExportImageInfo(); } @@ -410,7 +432,7 @@ namespace dxvk { // Use the maximum possible mip level count if the supplied // mip level count is either unspecified (0) or invalid - const uint32_t maxMipLevelCount = pDesc->SampleDesc.Count <= 1 + const uint32_t maxMipLevelCount = (pDesc->SampleDesc.Count <= 1) ? util::computeMipLevelCount({ pDesc->Width, pDesc->Height, pDesc->Depth }) : 1u; @@ -591,6 +613,37 @@ namespace dxvk { } + void D3D11CommonTexture::ExportImageInfo() { + HANDLE hSharedHandle; + + if (m_desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED) + hSharedHandle = openKmtHandle( m_image->sharedHandle() ); + else + hSharedHandle = m_image->sharedHandle(); + + DxvkSharedTextureMetadata metadata; + + metadata.Width = m_desc.Width; + metadata.Height = m_desc.Height; + metadata.MipLevels = m_desc.MipLevels; + metadata.ArraySize = m_desc.ArraySize; + metadata.Format = m_desc.Format; + metadata.SampleDesc = m_desc.SampleDesc; + metadata.Usage = m_desc.Usage; + metadata.BindFlags = m_desc.BindFlags; + metadata.CPUAccessFlags = m_desc.CPUAccessFlags; + metadata.MiscFlags = m_desc.MiscFlags; + metadata.TextureLayout = m_desc.TextureLayout; + + if (hSharedHandle == INVALID_HANDLE_VALUE || !setSharedMetadata(hSharedHandle, &metadata, sizeof(metadata))) { + Logger::warn("D3D11: Failed to write shared resource info for a texture"); + } + + if (hSharedHandle != INVALID_HANDLE_VALUE) + CloseHandle(hSharedHandle); + } + + D3D11CommonTexture::MappedBuffer D3D11CommonTexture::CreateMappedBuffer(UINT MipLevel) const { const DxvkFormatInfo* formatInfo = imageFormatInfo( m_device->LookupPackedFormat(m_desc.Format, GetFormatMode()).Format); @@ -932,7 +985,7 @@ namespace dxvk { D3D11Device* pDevice, const D3D11_COMMON_TEXTURE_DESC* pDesc) : D3D11DeviceChild(pDevice), - m_texture (this, pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE1D, 0, VK_NULL_HANDLE), + m_texture (this, pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE1D, 0, VK_NULL_HANDLE, nullptr), m_interop (this, &m_texture), m_surface (this, &m_texture), m_resource(this), @@ -1028,9 +1081,10 @@ namespace dxvk { // D 3 D 1 1 T E X T U R E 2 D D3D11Texture2D::D3D11Texture2D( D3D11Device* pDevice, - const D3D11_COMMON_TEXTURE_DESC* pDesc) + const D3D11_COMMON_TEXTURE_DESC* pDesc, + HANDLE hSharedHandle) : D3D11DeviceChild(pDevice), - m_texture (this, pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE2D, 0, VK_NULL_HANDLE), + m_texture (this, pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE2D, 0, VK_NULL_HANDLE, hSharedHandle), m_interop (this, &m_texture), m_surface (this, &m_texture), m_resource(this), @@ -1045,7 +1099,7 @@ namespace dxvk { DXGI_USAGE DxgiUsage, VkImage vkImage) : D3D11DeviceChild(pDevice), - m_texture (this, pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE2D, DxgiUsage, vkImage), + m_texture (this, pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE2D, DxgiUsage, vkImage, nullptr), m_interop (this, &m_texture), m_surface (this, &m_texture), m_resource(this), @@ -1161,7 +1215,7 @@ namespace dxvk { D3D11Device* pDevice, const D3D11_COMMON_TEXTURE_DESC* pDesc) : D3D11DeviceChild(pDevice), - m_texture (this, pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE3D, 0, VK_NULL_HANDLE), + m_texture (this, pDevice, pDesc, D3D11_RESOURCE_DIMENSION_TEXTURE3D, 0, VK_NULL_HANDLE, nullptr), m_interop (this, &m_texture), m_resource(this), m_d3d10 (this) { diff --git a/src/d3d11/d3d11_texture.h b/src/d3d11/d3d11_texture.h index b08291fc..e12e35d1 100644 --- a/src/d3d11/d3d11_texture.h +++ b/src/d3d11/d3d11_texture.h @@ -78,7 +78,8 @@ namespace dxvk { const D3D11_COMMON_TEXTURE_DESC* pDesc, D3D11_RESOURCE_DIMENSION Dimension, DXGI_USAGE DxgiUsage, - VkImage vkImage); + VkImage vkImage, + HANDLE hSharedHandle); ~D3D11CommonTexture(); @@ -418,13 +419,14 @@ namespace dxvk { D3D11_COMMON_TEXTURE_MAP_MODE DetermineMapMode( const DxvkImageCreateInfo* pImageInfo) const; + + void ExportImageInfo(); static VkImageType GetImageTypeFromResourceDim( D3D11_RESOURCE_DIMENSION Dimension); static VkImageLayout OptimizeLayout( VkImageUsageFlags Usage); - }; @@ -599,7 +601,8 @@ namespace dxvk { D3D11Texture2D( D3D11Device* pDevice, - const D3D11_COMMON_TEXTURE_DESC* pDesc); + const D3D11_COMMON_TEXTURE_DESC* pDesc, + HANDLE hSharedHandle); D3D11Texture2D( D3D11Device* pDevice,