Skip to content

Commit

Permalink
[d3d9] Add ID3D9VkInteropDevice::CreateImage to create custom texture…
Browse files Browse the repository at this point in the history
…/surfaces
  • Loading branch information
AlpyneDreams committed Oct 12, 2024
1 parent 48c57c1 commit 7731f0f
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 5 deletions.
3 changes: 2 additions & 1 deletion src/d3d9/d3d9_common_texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,8 @@ namespace dxvk {
imageInfo.numLayers = m_desc.ArraySize;
imageInfo.mipLevels = m_desc.MipLevels;
imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT
| VK_IMAGE_USAGE_TRANSFER_DST_BIT;
| VK_IMAGE_USAGE_TRANSFER_DST_BIT
| m_desc.ImageUsage;
imageInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT
| m_device->GetEnabledShaderStages();
imageInfo.access = VK_ACCESS_TRANSFER_READ_BIT
Expand Down
3 changes: 3 additions & 0 deletions src/d3d9/d3d9_common_texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ namespace dxvk {
bool IsBackBuffer;
bool IsAttachmentOnly;
bool IsLockable;

// Additional paramters for ID3D9VkInteropDevice
VkImageUsageFlags ImageUsage = 0;
};

struct D3D9ColorView {
Expand Down
34 changes: 33 additions & 1 deletion src/d3d9/d3d9_interfaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ ID3D9VkInteropInterface : public IUnknown {
* \brief D3D9 texture interface for Vulkan interop
*
* Provides access to the backing resource of a
* D3D9 texture.
* D3D9 texture or surface.
*/
MIDL_INTERFACE("d56344f5-8d35-46fd-806d-94c351b472c1")
ID3D9VkInteropTexture : public IUnknown {
Expand Down Expand Up @@ -74,6 +74,27 @@ ID3D9VkInteropTexture : public IUnknown {
VkImageCreateInfo* pInfo) = 0;
};


/**
* \brief D3D9 image description
*/
struct D3D9VkExtImageDesc {
D3DRESOURCETYPE Type; // Can be SURFACE, TEXTURE, CUBETEXTURE, VOLUMETEXTURE
UINT Width;
UINT Height;
UINT Depth; // Can be > 1 for VOLUMETEXTURE
UINT MipLevels; // Can be > 1 for TEXTURE, CUBETEXTURE, VOLUMETEXTURE
DWORD Usage;
D3DFORMAT Format;
D3DPOOL Pool;
D3DMULTISAMPLE_TYPE MultiSample; // Must be NONE unless Type is SURFACE
DWORD MultisampleQuality;
bool Discard; // Depth stencils only
bool IsAttachmentOnly; // If false, then VK_IMAGE_USAGE_SAMPLED_BIT will be added
bool IsLockable;
VkImageUsageFlags ImageUsage; // Additional image usage flags
};

/**
* \brief D3D9 device interface for Vulkan interop
*
Expand Down Expand Up @@ -194,6 +215,17 @@ ID3D9VkInteropDevice : public IUnknown {
virtual bool STDMETHODCALLTYPE WaitForResource(
IDirect3DResource9* pResource,
DWORD MapFlags) = 0;

/**
* \brief Creates a custom image/surface/texture
*
* \param [in] desc Image description
* \param [out, retval] ppResult Pointer to a resource of the D3DRESOURCETYPE given by desc.Type
* \returns D3D_OK, D3DERR_INVALIDCALL, or D3DERR_OUTOFVIDEOMEMORY
*/
virtual HRESULT STDMETHODCALLTYPE CreateImage(
const D3D9VkExtImageDesc* desc,
IDirect3DResource9** ppResult) = 0;
};

/**
Expand Down
104 changes: 104 additions & 0 deletions src/d3d9/d3d9_interop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "d3d9_device.h"
#include "d3d9_texture.h"
#include "d3d9_buffer.h"
#include "d3d9_initializer.h"

namespace dxvk {

Expand Down Expand Up @@ -239,4 +240,107 @@ namespace dxvk {
return m_device->WaitForResource(GetDxvkResource(pResource), DxvkCsThread::SynchronizeAll, MapFlags);
}

HRESULT STDMETHODCALLTYPE D3D9VkInteropDevice::CreateImage(
const D3D9VkExtImageDesc* params,
IDirect3DResource9** ppResult) {
InitReturnPtr(ppResult);

if (unlikely(ppResult == nullptr))
return D3DERR_INVALIDCALL;

if (unlikely(params == nullptr))
return D3DERR_INVALIDCALL;

/////////////////////////////
// Image desc validation

// Cannot create a volume by itself, use D3DRTYPE_VOLUMETEXTURE
if (unlikely(params->Type == D3DRTYPE_VOLUME))
return D3DERR_INVALIDCALL;

// Only allowed: SURFACE, TEXTURE, CUBETEXTURE, VOLUMETEXTURE
if (unlikely(params->Type < D3DRTYPE_SURFACE || params->Type > D3DRTYPE_CUBETEXTURE))
return D3DERR_INVALIDCALL;

// Only volume textures can have depth > 1
if (unlikely(params->Type != D3DRTYPE_VOLUMETEXTURE && params->Depth > 1))
return D3DERR_INVALIDCALL;

if (params->Type == D3DRTYPE_SURFACE) {
// Surfaces can only have 1 mip level
if (unlikely(params->MipLevels > 1))
return D3DERR_INVALIDCALL;

if (unlikely(params->MultiSample > D3DMULTISAMPLE_16_SAMPLES))
return D3DERR_INVALIDCALL;
} else {
// Textures can't be multisampled
if (unlikely(params->MultiSample != D3DMULTISAMPLE_NONE))
return D3DERR_INVALIDCALL;
}

D3D9_COMMON_TEXTURE_DESC desc;
desc.Width = params->Width;
desc.Height = params->Height;
desc.Depth = params->Depth;
desc.ArraySize = params->Type == D3DRTYPE_CUBETEXTURE ? 6 : 1;
desc.MipLevels = params->MipLevels;
desc.Usage = params->Usage;
desc.Format = EnumerateFormat(params->Format);
desc.Pool = params->Pool;
desc.Discard = params->Discard;
desc.MultiSample = params->MultiSample;
desc.MultisampleQuality = params->MultisampleQuality;
desc.IsBackBuffer = FALSE;
desc.IsAttachmentOnly = params->IsAttachmentOnly;
desc.IsLockable = params->IsLockable;
desc.ImageUsage = params->ImageUsage;

D3DRESOURCETYPE textureType = params->Type;
if (params->Type == D3DRTYPE_SURFACE)
textureType = D3DRTYPE_TEXTURE;
else if (params->Type == D3DRTYPE_VOLUME)
textureType = D3DRTYPE_VOLUMETEXTURE;

if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(m_device, textureType, &desc)))
return D3DERR_INVALIDCALL;

switch (params->Type) {
case D3DRTYPE_SURFACE:
return CreateTextureResource<D3D9Surface>(desc, ppResult);

case D3DRTYPE_TEXTURE:
return CreateTextureResource<D3D9Texture2D>(desc, ppResult);

case D3DRTYPE_VOLUMETEXTURE:
return CreateTextureResource<D3D9Texture3D>(desc, ppResult);

case D3DRTYPE_CUBETEXTURE:
return CreateTextureResource<D3D9TextureCube>(desc, ppResult);

default:
return D3DERR_INVALIDCALL;
}
}

template <typename ResourceType>
HRESULT D3D9VkInteropDevice::CreateTextureResource(
const D3D9_COMMON_TEXTURE_DESC& desc,
IDirect3DResource9** ppResult) {
try {
const Com<ResourceType> texture = new ResourceType(m_device, &desc);
m_device->m_initializer->InitTexture(texture->GetCommonTexture());
*ppResult = texture.ref();

if (desc.Pool == D3DPOOL_DEFAULT)
m_device->m_losableResourceCounter++;

return D3D_OK;
}
catch (const DxvkError& e) {
Logger::err(e.message());
return D3DERR_OUTOFVIDEOMEMORY;
}
}

}
10 changes: 10 additions & 0 deletions src/d3d9/d3d9_interop.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace dxvk {
class D3D9InterfaceEx;
class D3D9CommonTexture;
class D3D9DeviceEx;
struct D3D9_COMMON_TEXTURE_DESC;

class D3D9VkInteropInterface final : public ID3D9VkInteropInterface {

Expand Down Expand Up @@ -118,8 +119,17 @@ namespace dxvk {
IDirect3DResource9* pResource,
DWORD MapFlags);

HRESULT STDMETHODCALLTYPE CreateImage(
const D3D9VkExtImageDesc* desc,
IDirect3DResource9** ppResult);

private:

template <typename ResourceType>
HRESULT CreateTextureResource(
const D3D9_COMMON_TEXTURE_DESC& desc,
IDirect3DResource9** ppResult);

D3D9DeviceEx* m_device;
D3D9DeviceLock m_lock;

Expand Down
4 changes: 2 additions & 2 deletions src/d3d9/d3d9_surface.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ namespace dxvk {
D3D9Surface(
D3D9DeviceEx* pDevice,
const D3D9_COMMON_TEXTURE_DESC* pDesc,
IUnknown* pContainer,
HANDLE* pSharedHandle);
IUnknown* pContainer = nullptr,
HANDLE* pSharedHandle = nullptr);

D3D9Surface(
D3D9DeviceEx* pDevice,
Expand Down
2 changes: 1 addition & 1 deletion src/d3d9/d3d9_texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ namespace dxvk {
D3D9Texture2D(
D3D9DeviceEx* pDevice,
const D3D9_COMMON_TEXTURE_DESC* pDesc,
HANDLE* pSharedHandle);
HANDLE* pSharedHandle = nullptr);

HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);

Expand Down

0 comments on commit 7731f0f

Please sign in to comment.