mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-12 13:08:50 +01:00
[d3d9] Add support for shared IDirect3DTexture9 resources.
This commit is contained in:
parent
48046e009c
commit
6640cc350c
@ -3,6 +3,8 @@
|
||||
#include "d3d9_util.h"
|
||||
#include "d3d9_device.h"
|
||||
|
||||
#include "../util/util_shared_res.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace dxvk {
|
||||
@ -10,7 +12,8 @@ namespace dxvk {
|
||||
D3D9CommonTexture::D3D9CommonTexture(
|
||||
D3D9DeviceEx* pDevice,
|
||||
const D3D9_COMMON_TEXTURE_DESC* pDesc,
|
||||
D3DRESOURCETYPE ResourceType)
|
||||
D3DRESOURCETYPE ResourceType,
|
||||
HANDLE* pSharedHandle)
|
||||
: m_device(pDevice), m_desc(*pDesc), m_type(ResourceType) {
|
||||
if (m_desc.Format == D3D9Format::Unknown)
|
||||
m_desc.Format = (m_desc.Usage & D3DUSAGE_DEPTHSTENCIL)
|
||||
@ -26,6 +29,9 @@ namespace dxvk {
|
||||
for (uint32_t i = 0; i < subresources; i++) {
|
||||
SetNeedsUpload(i, true);
|
||||
}
|
||||
if (pSharedHandle) {
|
||||
throw DxvkError("D3D9: Incompatible pool type for texture sharing.");
|
||||
}
|
||||
}
|
||||
|
||||
m_mapping = pDevice->LookupFormat(m_desc.Format);
|
||||
@ -39,7 +45,7 @@ namespace dxvk {
|
||||
!(m_desc.Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL));
|
||||
|
||||
try {
|
||||
m_image = CreatePrimaryImage(ResourceType, plainSurface);
|
||||
m_image = CreatePrimaryImage(ResourceType, plainSurface, pSharedHandle);
|
||||
}
|
||||
catch (const DxvkError& e) {
|
||||
// D3DUSAGE_AUTOGENMIPMAP and offscreen plain is mutually exclusive
|
||||
@ -47,12 +53,17 @@ namespace dxvk {
|
||||
if (m_desc.Usage & D3DUSAGE_AUTOGENMIPMAP || plainSurface) {
|
||||
m_desc.Usage &= ~D3DUSAGE_AUTOGENMIPMAP;
|
||||
m_desc.MipLevels = 1;
|
||||
m_image = CreatePrimaryImage(ResourceType, false);
|
||||
m_image = CreatePrimaryImage(ResourceType, false, pSharedHandle);
|
||||
}
|
||||
else
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (pSharedHandle && *pSharedHandle == nullptr) {
|
||||
*pSharedHandle = m_image->sharedHandle();
|
||||
ExportImageInfo();
|
||||
}
|
||||
|
||||
CreateSampleView(0);
|
||||
|
||||
if (!IsManaged()) {
|
||||
@ -206,7 +217,7 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkImage> D3D9CommonTexture::CreatePrimaryImage(D3DRESOURCETYPE ResourceType, bool TryOffscreenRT) const {
|
||||
Rc<DxvkImage> D3D9CommonTexture::CreatePrimaryImage(D3DRESOURCETYPE ResourceType, bool TryOffscreenRT, HANDLE* pSharedHandle) const {
|
||||
DxvkImageCreateInfo imageInfo;
|
||||
imageInfo.type = GetImageTypeFromResourceType(ResourceType);
|
||||
imageInfo.format = m_mapping.ConversionFormatInfo.FormatColor != VK_FORMAT_UNDEFINED
|
||||
@ -230,6 +241,15 @@ namespace dxvk {
|
||||
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imageInfo.layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
imageInfo.shared = m_desc.IsBackBuffer;
|
||||
if (pSharedHandle) {
|
||||
imageInfo.sharing.type = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT;
|
||||
if (*pSharedHandle) {
|
||||
imageInfo.shared = true;
|
||||
imageInfo.sharing.mode = *pSharedHandle == INVALID_HANDLE_VALUE ? DxvkSharedHandleMode::Export : DxvkSharedHandleMode::Import;
|
||||
imageInfo.sharing.handle = *pSharedHandle;
|
||||
}
|
||||
// TODO: validate metadata?
|
||||
}
|
||||
|
||||
if (m_mapping.ConversionFormatInfo.FormatType != D3D9ConversionFormat_None) {
|
||||
imageInfo.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
|
||||
@ -280,7 +300,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)
|
||||
if (imageInfo.tiling == VK_IMAGE_TILING_OPTIMAL && imageInfo.sharing.mode == DxvkSharedHandleMode::None)
|
||||
imageInfo.layout = OptimizeLayout(imageInfo.usage);
|
||||
|
||||
// For some formats, we need to enable render target
|
||||
@ -456,6 +476,58 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void D3D9CommonTexture::ExportImageInfo() {
|
||||
/* From MSDN:
|
||||
Textures being shared from D3D9 to D3D11 have the following restrictions.
|
||||
|
||||
- Textures must be 2D
|
||||
- Only 1 mip level is allowed
|
||||
- Texture must have default usage
|
||||
- Texture must be write only
|
||||
- MSAA textures are not allowed
|
||||
- Bind flags must have SHADER_RESOURCE and RENDER_TARGET set
|
||||
- Only R10G10B10A2_UNORM, R16G16B16A16_FLOAT and R8G8B8A8_UNORM formats are allowed
|
||||
*/
|
||||
DXGI_FORMAT dxgiFormat = DXGI_FORMAT_UNKNOWN;
|
||||
|
||||
switch (m_desc.Format) {
|
||||
case D3D9Format::A2B10G10R10: dxgiFormat = DXGI_FORMAT_R10G10B10A2_UNORM; break;
|
||||
case D3D9Format::A16B16G16R16F: dxgiFormat = DXGI_FORMAT_R16G16B16A16_FLOAT; break;
|
||||
case D3D9Format::A8B8G8R8: dxgiFormat = DXGI_FORMAT_B8G8R8A8_UNORM; break;
|
||||
case D3D9Format::X8R8G8B8: dxgiFormat = DXGI_FORMAT_B8G8R8X8_UNORM; break;
|
||||
default:
|
||||
Logger::warn(str::format("D3D9: Unsupported format for shared textures", m_desc.Format));
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_desc.Depth == 1 && m_desc.MipLevels == 1 && m_desc.MultiSample == D3DMULTISAMPLE_NONE &&
|
||||
m_desc.Usage & D3DUSAGE_RENDERTARGET && dxgiFormat != DXGI_FORMAT_UNKNOWN) {
|
||||
HANDLE ntHandle = openKmtHandle(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 = dxgiFormat;
|
||||
metadata.SampleDesc.Count = 1;
|
||||
metadata.SampleDesc.Quality = 0;
|
||||
metadata.Usage = D3D11_USAGE_DEFAULT;
|
||||
metadata.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
|
||||
metadata.CPUAccessFlags = 0;
|
||||
metadata.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
|
||||
metadata.TextureLayout = D3D11_TEXTURE_LAYOUT_UNDEFINED;
|
||||
|
||||
if (ntHandle == INVALID_HANDLE_VALUE || !setSharedMetadata(ntHandle, &metadata, sizeof(metadata)))
|
||||
Logger::warn("D3D9: Failed to write shared resource info for a texture");
|
||||
|
||||
if (ntHandle != INVALID_HANDLE_VALUE)
|
||||
::CloseHandle(ntHandle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkImageView> D3D9CommonTexture::CreateView(
|
||||
UINT Layer,
|
||||
UINT Lod,
|
||||
@ -531,4 +603,4 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,8 @@ namespace dxvk {
|
||||
D3D9CommonTexture(
|
||||
D3D9DeviceEx* pDevice,
|
||||
const D3D9_COMMON_TEXTURE_DESC* pDesc,
|
||||
D3DRESOURCETYPE ResourceType);
|
||||
D3DRESOURCETYPE ResourceType,
|
||||
HANDLE* pSharedHandle);
|
||||
|
||||
~D3D9CommonTexture();
|
||||
|
||||
@ -513,7 +514,7 @@ namespace dxvk {
|
||||
*/
|
||||
VkDeviceSize GetMipSize(UINT Subresource) const;
|
||||
|
||||
Rc<DxvkImage> CreatePrimaryImage(D3DRESOURCETYPE ResourceType, bool TryOffscreenRT) const;
|
||||
Rc<DxvkImage> CreatePrimaryImage(D3DRESOURCETYPE ResourceType, bool TryOffscreenRT, HANDLE* pSharedHandle) const;
|
||||
|
||||
Rc<DxvkImage> CreateResolveImage() const;
|
||||
|
||||
@ -542,6 +543,8 @@ namespace dxvk {
|
||||
VkImageLayout OptimizeLayout(
|
||||
VkImageUsageFlags Usage) const;
|
||||
|
||||
void ExportImageInfo();
|
||||
|
||||
static VkImageViewType GetImageViewTypeFromResourceType(
|
||||
D3DRESOURCETYPE Dimension,
|
||||
UINT Layer);
|
||||
@ -550,4 +553,4 @@ namespace dxvk {
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -457,12 +457,17 @@ namespace dxvk {
|
||||
return D3DERR_INVALIDCALL;
|
||||
|
||||
try {
|
||||
const Com<D3D9Texture2D> texture = new D3D9Texture2D(this, &desc);
|
||||
|
||||
void* initialData = nullptr;
|
||||
|
||||
if (Pool == D3DPOOL_SYSTEMMEM && Levels == 1 && pSharedHandle != nullptr)
|
||||
if (Pool == D3DPOOL_SYSTEMMEM && Levels == 1 && pSharedHandle != nullptr) {
|
||||
initialData = *(reinterpret_cast<void**>(pSharedHandle));
|
||||
pSharedHandle = nullptr;
|
||||
}
|
||||
|
||||
if (pSharedHandle != nullptr && Pool != D3DPOOL_DEFAULT)
|
||||
return D3DERR_INVALIDCALL;
|
||||
|
||||
const Com<D3D9Texture2D> texture = new D3D9Texture2D(this, &desc, pSharedHandle);
|
||||
|
||||
m_initializer->InitTexture(texture->GetCommonTexture(), initialData);
|
||||
*ppTexture = texture.ref();
|
||||
@ -491,6 +496,9 @@ namespace dxvk {
|
||||
if (unlikely(ppVolumeTexture == nullptr))
|
||||
return D3DERR_INVALIDCALL;
|
||||
|
||||
if (pSharedHandle)
|
||||
Logger::err("CreateVolumeTexture: Shared volume textures not supported");
|
||||
|
||||
D3D9_COMMON_TEXTURE_DESC desc;
|
||||
desc.Width = Width;
|
||||
desc.Height = Height;
|
||||
@ -536,6 +544,9 @@ namespace dxvk {
|
||||
if (unlikely(ppCubeTexture == nullptr))
|
||||
return D3DERR_INVALIDCALL;
|
||||
|
||||
if (pSharedHandle)
|
||||
Logger::err("CreateCubeTexture: Shared cube textures not supported");
|
||||
|
||||
D3D9_COMMON_TEXTURE_DESC desc;
|
||||
desc.Width = EdgeLength;
|
||||
desc.Height = EdgeLength;
|
||||
@ -580,6 +591,9 @@ namespace dxvk {
|
||||
if (unlikely(ppVertexBuffer == nullptr))
|
||||
return D3DERR_INVALIDCALL;
|
||||
|
||||
if (pSharedHandle)
|
||||
Logger::err("CreateVertexBuffer: Shared vertex buffers not supported");
|
||||
|
||||
D3D9_BUFFER_DESC desc;
|
||||
desc.Format = D3D9Format::VERTEXDATA;
|
||||
desc.FVF = FVF;
|
||||
@ -616,6 +630,9 @@ namespace dxvk {
|
||||
if (unlikely(ppIndexBuffer == nullptr))
|
||||
return D3DERR_INVALIDCALL;
|
||||
|
||||
if (pSharedHandle)
|
||||
Logger::err("CreateIndexBuffer: Shared index buffers not supported");
|
||||
|
||||
D3D9_BUFFER_DESC desc;
|
||||
desc.Format = EnumerateFormat(Format);
|
||||
desc.Pool = Pool;
|
||||
@ -3459,7 +3476,7 @@ namespace dxvk {
|
||||
return D3DERR_INVALIDCALL;
|
||||
|
||||
try {
|
||||
const Com<D3D9Surface> surface = new D3D9Surface(this, &desc, nullptr);
|
||||
const Com<D3D9Surface> surface = new D3D9Surface(this, &desc, nullptr, pSharedHandle);
|
||||
m_initializer->InitTexture(surface->GetCommonTexture());
|
||||
*ppSurface = surface.ref();
|
||||
return D3D_OK;
|
||||
@ -3502,8 +3519,11 @@ namespace dxvk {
|
||||
if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc)))
|
||||
return D3DERR_INVALIDCALL;
|
||||
|
||||
if (pSharedHandle != nullptr && Pool != D3DPOOL_DEFAULT)
|
||||
return D3DERR_INVALIDCALL;
|
||||
|
||||
try {
|
||||
const Com<D3D9Surface> surface = new D3D9Surface(this, &desc, nullptr);
|
||||
const Com<D3D9Surface> surface = new D3D9Surface(this, &desc, nullptr, pSharedHandle);
|
||||
m_initializer->InitTexture(surface->GetCommonTexture());
|
||||
*ppSurface = surface.ref();
|
||||
return D3D_OK;
|
||||
@ -3549,7 +3569,7 @@ namespace dxvk {
|
||||
return D3DERR_INVALIDCALL;
|
||||
|
||||
try {
|
||||
const Com<D3D9Surface> surface = new D3D9Surface(this, &desc, nullptr);
|
||||
const Com<D3D9Surface> surface = new D3D9Surface(this, &desc, nullptr, pSharedHandle);
|
||||
m_initializer->InitTexture(surface->GetCommonTexture());
|
||||
*ppSurface = surface.ref();
|
||||
return D3D_OK;
|
||||
@ -7296,7 +7316,7 @@ namespace dxvk {
|
||||
if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc)))
|
||||
return D3DERR_NOTAVAILABLE;
|
||||
|
||||
m_autoDepthStencil = new D3D9Surface(this, &desc, nullptr);
|
||||
m_autoDepthStencil = new D3D9Surface(this, &desc, nullptr, nullptr);
|
||||
m_initializer->InitTexture(m_autoDepthStencil->GetCommonTexture());
|
||||
SetDepthStencilSurface(m_autoDepthStencil.ptr());
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "d3d9_include.h"
|
||||
#include <d3d9.h>
|
||||
#include "d3d9_options.h"
|
||||
|
||||
#include "../dxvk/dxvk_adapter.h"
|
||||
@ -220,4 +220,4 @@ namespace dxvk {
|
||||
bool m_d32supportFinal;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,6 @@
|
||||
#include "../util/config/config.h"
|
||||
#include "../dxvk/dxvk_device.h"
|
||||
|
||||
#include "d3d9_include.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
enum class D3D9FloatEmulation {
|
||||
@ -161,4 +159,4 @@ namespace dxvk {
|
||||
bool allowDirectBufferMapping;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -9,10 +9,11 @@ namespace dxvk {
|
||||
D3D9Surface::D3D9Surface(
|
||||
D3D9DeviceEx* pDevice,
|
||||
const D3D9_COMMON_TEXTURE_DESC* pDesc,
|
||||
IUnknown* pContainer)
|
||||
IUnknown* pContainer,
|
||||
HANDLE* pSharedHandle)
|
||||
: D3D9SurfaceBase(
|
||||
pDevice,
|
||||
new D3D9CommonTexture( pDevice, pDesc, D3DRTYPE_SURFACE),
|
||||
new D3D9CommonTexture( pDevice, pDesc, D3DRTYPE_SURFACE, pSharedHandle),
|
||||
0, 0,
|
||||
nullptr,
|
||||
pContainer) { }
|
||||
|
@ -20,7 +20,8 @@ namespace dxvk {
|
||||
D3D9Surface(
|
||||
D3D9DeviceEx* pDevice,
|
||||
const D3D9_COMMON_TEXTURE_DESC* pDesc,
|
||||
IUnknown* pContainer);
|
||||
IUnknown* pContainer,
|
||||
HANDLE* pSharedHandle);
|
||||
|
||||
D3D9Surface(
|
||||
D3D9DeviceEx* pDevice,
|
||||
@ -63,4 +64,4 @@ namespace dxvk {
|
||||
D3D9GDIDesc m_dcDesc;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1038,7 +1038,7 @@ namespace dxvk {
|
||||
desc.IsAttachmentOnly = FALSE;
|
||||
|
||||
for (uint32_t i = 0; i < m_backBuffers.size(); i++)
|
||||
m_backBuffers[i] = new D3D9Surface(m_parent, &desc, this);
|
||||
m_backBuffers[i] = new D3D9Surface(m_parent, &desc, this, nullptr);
|
||||
|
||||
auto swapImage = m_backBuffers[0]->GetCommonTexture()->GetImage();
|
||||
|
||||
|
@ -8,8 +8,9 @@ namespace dxvk {
|
||||
|
||||
D3D9Texture2D::D3D9Texture2D(
|
||||
D3D9DeviceEx* pDevice,
|
||||
const D3D9_COMMON_TEXTURE_DESC* pDesc)
|
||||
: D3D9Texture2DBase( pDevice, pDesc, D3DRTYPE_TEXTURE ) { }
|
||||
const D3D9_COMMON_TEXTURE_DESC* pDesc,
|
||||
HANDLE* pSharedHandle)
|
||||
: D3D9Texture2DBase( pDevice, pDesc, D3DRTYPE_TEXTURE, pSharedHandle ) { }
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE D3D9Texture2D::QueryInterface(REFIID riid, void** ppvObject) {
|
||||
@ -97,7 +98,7 @@ namespace dxvk {
|
||||
D3D9Texture3D::D3D9Texture3D(
|
||||
D3D9DeviceEx* pDevice,
|
||||
const D3D9_COMMON_TEXTURE_DESC* pDesc)
|
||||
: D3D9Texture3DBase( pDevice, pDesc, D3DRTYPE_VOLUMETEXTURE ) { }
|
||||
: D3D9Texture3DBase( pDevice, pDesc, D3DRTYPE_VOLUMETEXTURE, nullptr ) { }
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE D3D9Texture3D::QueryInterface(REFIID riid, void** ppvObject) {
|
||||
@ -179,7 +180,7 @@ namespace dxvk {
|
||||
D3D9TextureCube::D3D9TextureCube(
|
||||
D3D9DeviceEx* pDevice,
|
||||
const D3D9_COMMON_TEXTURE_DESC* pDesc)
|
||||
: D3D9TextureCubeBase( pDevice, pDesc, D3DRTYPE_CUBETEXTURE ) { }
|
||||
: D3D9TextureCubeBase( pDevice, pDesc, D3DRTYPE_CUBETEXTURE, nullptr ) { }
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE D3D9TextureCube::QueryInterface(REFIID riid, void** ppvObject) {
|
||||
@ -262,4 +263,4 @@ namespace dxvk {
|
||||
return D3D_OK;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -23,9 +23,10 @@ namespace dxvk {
|
||||
D3D9BaseTexture(
|
||||
D3D9DeviceEx* pDevice,
|
||||
const D3D9_COMMON_TEXTURE_DESC* pDesc,
|
||||
D3DRESOURCETYPE ResourceType)
|
||||
D3DRESOURCETYPE ResourceType,
|
||||
HANDLE* pSharedHandle)
|
||||
: D3D9Resource<Base...> ( pDevice )
|
||||
, m_texture ( pDevice, pDesc, ResourceType )
|
||||
, m_texture ( pDevice, pDesc, ResourceType, pSharedHandle )
|
||||
, m_lod ( 0 ) {
|
||||
const uint32_t arraySlices = m_texture.Desc()->ArraySize;
|
||||
const uint32_t mipLevels = m_texture.Desc()->MipLevels;
|
||||
@ -130,7 +131,8 @@ namespace dxvk {
|
||||
|
||||
D3D9Texture2D(
|
||||
D3D9DeviceEx* pDevice,
|
||||
const D3D9_COMMON_TEXTURE_DESC* pDesc);
|
||||
const D3D9_COMMON_TEXTURE_DESC* pDesc,
|
||||
HANDLE* pSharedHandle);
|
||||
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);
|
||||
|
||||
@ -240,4 +242,4 @@ namespace dxvk {
|
||||
dst = src;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ namespace dxvk {
|
||||
const D3D9_COMMON_TEXTURE_DESC* pDesc)
|
||||
: D3D9VolumeBase(
|
||||
pDevice,
|
||||
new D3D9CommonTexture( pDevice, pDesc, D3DRTYPE_VOLUMETEXTURE ),
|
||||
new D3D9CommonTexture( pDevice, pDesc, D3DRTYPE_VOLUMETEXTURE, nullptr ),
|
||||
0, 0,
|
||||
nullptr,
|
||||
nullptr) { }
|
||||
@ -109,4 +109,4 @@ namespace dxvk {
|
||||
m_face, m_mipLevel);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user