1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-04 07:24:15 +01:00

[d3d9] Add DxvkD3D8Bridge for d3d8 interop

This commit is contained in:
Alpyne 2023-06-21 16:49:38 +01:00 committed by Joshie
parent b77928b6fe
commit d6e7e3e780
7 changed files with 229 additions and 2 deletions

103
src/d3d9/d3d9_bridge.cpp Normal file
View File

@ -0,0 +1,103 @@
#include "d3d9_device.h"
#include "d3d9_interface.h"
#include "d3d9_bridge.h"
#include "d3d9_swapchain.h"
#include "d3d9_surface.h"
namespace dxvk {
DxvkD3D8Bridge::DxvkD3D8Bridge(D3D9DeviceEx* pDevice)
: m_device(pDevice) {
}
DxvkD3D8Bridge::~DxvkD3D8Bridge() {
}
ULONG STDMETHODCALLTYPE DxvkD3D8Bridge::AddRef() {
return m_device->AddRef();
}
ULONG STDMETHODCALLTYPE DxvkD3D8Bridge::Release() {
return m_device->Release();
}
HRESULT STDMETHODCALLTYPE DxvkD3D8Bridge::QueryInterface(
REFIID riid,
void** ppvObject) {
return m_device->QueryInterface(riid, ppvObject);
}
HRESULT DxvkD3D8Bridge::UpdateTextureFromBuffer(
IDirect3DSurface9* pDestSurface,
IDirect3DSurface9* pSrcSurface,
const RECT* pSrcRect,
const POINT* pDestPoint) {
auto lock = m_device->LockDevice();
D3D9Surface* dst = static_cast<D3D9Surface*>(pDestSurface);
D3D9Surface* src = static_cast<D3D9Surface*>(pSrcSurface);
if (unlikely(dst == nullptr || src == nullptr))
return D3DERR_INVALIDCALL;
D3D9CommonTexture* srcTextureInfo = src->GetCommonTexture();
D3D9CommonTexture* dstTextureInfo = dst->GetCommonTexture();
VkOffset3D srcOffset = { 0u, 0u, 0u };
VkOffset3D dstOffset = { 0u, 0u, 0u };
VkExtent3D texLevelExtent = srcTextureInfo->GetExtentMip(src->GetSubresource());
VkExtent3D extent = texLevelExtent;
srcOffset = { pSrcRect->left,
pSrcRect->top,
0u };
extent = { uint32_t(pSrcRect->right - pSrcRect->left), uint32_t(pSrcRect->bottom - pSrcRect->top), 1 };
// TODO: Validate extents like in D3D9DeviceEx::UpdateSurface
dstOffset = { pDestPoint->x,
pDestPoint->y,
0u };
m_device->UpdateTextureFromBuffer(
srcTextureInfo, dstTextureInfo,
src->GetSubresource(), dst->GetSubresource(),
srcOffset, extent, dstOffset
);
dstTextureInfo->SetNeedsReadback(dst->GetSubresource(), true);
if (dstTextureInfo->IsAutomaticMip())
m_device->MarkTextureMipsDirty(dstTextureInfo);
return D3D_OK;
}
DxvkD3D8InterfaceBridge::DxvkD3D8InterfaceBridge(D3D9InterfaceEx* pObject)
: m_interface(pObject) {
}
DxvkD3D8InterfaceBridge::~DxvkD3D8InterfaceBridge() {
}
ULONG STDMETHODCALLTYPE DxvkD3D8InterfaceBridge::AddRef() {
return m_interface->AddRef();
}
ULONG STDMETHODCALLTYPE DxvkD3D8InterfaceBridge::Release() {
return m_interface->Release();
}
HRESULT STDMETHODCALLTYPE DxvkD3D8InterfaceBridge::QueryInterface(
REFIID riid,
void** ppvObject) {
return m_interface->QueryInterface(riid, ppvObject);
}
const Config* DxvkD3D8InterfaceBridge::GetConfig() const {
return &m_interface->GetInstance()->config();
}
}

103
src/d3d9/d3d9_bridge.h Normal file
View File

@ -0,0 +1,103 @@
#pragma once
#include <windows.h>
#include "../util/config/config.h"
#include "../vulkan/vulkan_loader.h"
/**
* The D3D9 bridge allows D3D8 to access DXVK internals.
* For Vulkan interop without needing DXVK internals, see d3d9_interop.h.
*
* NOTE: You must include "d3d9_include.h" or "d3d8_include.h" before this header.
*/
/**
* \brief D3D9 device interface for D3D8 interop
*/
MIDL_INTERFACE("D3D9D3D8-42A9-4C1E-AA97-BEEFCAFE2000")
IDxvkD3D8Bridge : public IUnknown {
// D3D8 keeps D3D9 objects contained in a namespace.
#ifdef DXVK_D3D9_NAMESPACE
using IDirect3DSurface9 = d3d9::IDirect3DSurface9;
#endif
/**
* \brief Updates a D3D9 surface from a D3D9 buffer
*
* \param [in] pDestSurface Destination surface (typically in VRAM)
* \param [in] pSrcSurface Source surface (typically in system memory)
* \param [in] pSrcRect Source rectangle
* \param [in] pDestPoint Destination (top-left) point
*/
virtual HRESULT UpdateTextureFromBuffer(
IDirect3DSurface9* pDestSurface,
IDirect3DSurface9* pSrcSurface,
const RECT* pSrcRect,
const POINT* pDestPoint) = 0;
};
/**
* \brief D3D9 instance interface for D3D8 interop
*/
MIDL_INTERFACE("D3D9D3D8-A407-773E-18E9-CAFEBEEF3000")
IDxvkD3D8InterfaceBridge : public IUnknown {
/**
* \brief Retrieves the DXVK configuration
* \returns The DXVK Config object
*/
virtual const dxvk::Config* GetConfig() const = 0;
};
#if defined(_MSC_VER)
struct DECLSPEC_UUID("D3D9D3D8-42A9-4C1E-AA97-BEEFCAFE2000") IDxvkD3D8Bridge;
struct DECLSPEC_UUID("D3D9D3D8-A407-773E-18E9-CAFEBEEF3000") IDxvkD3D8InterfaceBridge;
#else
__CRT_UUID_DECL(IDxvkD3D8Bridge, 0xD3D9D3D8, 0x42A9, 0x4C1E, 0xAA, 0x97, 0xBE, 0xEF, 0xCA, 0xFE, 0x20, 0x00);
__CRT_UUID_DECL(IDxvkD3D8InterfaceBridge, 0xD3D9D3D8, 0xA407, 0x773E, 0x18, 0xE9, 0xCA, 0xFE, 0xBE, 0xEF, 0x30, 0x00);
#endif
namespace dxvk {
class D3D9DeviceEx;
class D3D9InterfaceEx;
class DxvkD3D8Bridge : public IDxvkD3D8Bridge {
public:
DxvkD3D8Bridge(D3D9DeviceEx* pDevice);
~DxvkD3D8Bridge();
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid,
void** ppvObject);
HRESULT UpdateTextureFromBuffer(
IDirect3DSurface9* pDestSurface,
IDirect3DSurface9* pSrcSurface,
const RECT* pSrcRect,
const POINT* pDestPoint);
private:
D3D9DeviceEx* m_device;
};
class DxvkD3D8InterfaceBridge : public IDxvkD3D8InterfaceBridge {
public:
DxvkD3D8InterfaceBridge(D3D9InterfaceEx* pObject);
~DxvkD3D8InterfaceBridge();
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid,
void** ppvObject);
const Config* GetConfig() const;
protected:
D3D9InterfaceEx* m_interface;
};
}

View File

@ -56,7 +56,8 @@ namespace dxvk {
, m_csThread ( dxvkDevice, dxvkDevice->createContext(DxvkContextType::Primary) )
, m_csChunk ( AllocCsChunk() )
, m_d3d9Interop ( this )
, m_d3d9On12 ( this ) {
, m_d3d9On12 ( this )
, m_d3d8Bridge ( this ) {
// If we can SWVP, then we use an extended constant set
// as SWVP has many more slots available than HWVP.
bool canSWVP = CanSWVP();
@ -218,6 +219,11 @@ namespace dxvk {
*ppvObject = ref(this);
return S_OK;
}
if (riid == __uuidof(IDxvkD3D8Bridge)) {
*ppvObject = ref(&m_d3d8Bridge);
return S_OK;
}
if (riid == __uuidof(ID3D9VkInteropDevice)) {
*ppvObject = ref(&m_d3d9Interop);

View File

@ -32,6 +32,8 @@
#include <cstdint>
#include <unordered_set>
#include "d3d9_bridge.h"
#include <vector>
#include <type_traits>
#include <unordered_map>
@ -127,6 +129,7 @@ namespace dxvk {
friend class D3D9SwapChainEx;
friend class D3D9ConstantBuffer;
friend class D3D9UserDefinedAnnotation;
friend class DxvkD3D8Bridge;
friend D3D9VkInteropDevice;
public:
@ -1364,6 +1367,7 @@ namespace dxvk {
D3D9VkInteropDevice m_d3d9Interop;
D3D9On12 m_d3d9On12;
DxvkD3D8Bridge m_d3d8Bridge;
};
}

View File

@ -3,6 +3,7 @@
#include "d3d9_monitor.h"
#include "d3d9_caps.h"
#include "d3d9_device.h"
#include "d3d9_bridge.h"
#include "../util/util_singleton.h"
@ -14,6 +15,7 @@ namespace dxvk {
D3D9InterfaceEx::D3D9InterfaceEx(bool bExtended)
: m_instance ( g_dxvkInstance.acquire() )
, m_d3d8Bridge ( this )
, m_extended ( bExtended )
, m_d3d9Options ( nullptr, m_instance->config() )
, m_d3d9Interop ( this ) {
@ -86,6 +88,11 @@ namespace dxvk {
return S_OK;
}
if (riid == __uuidof(IDxvkD3D8InterfaceBridge)) {
*ppvObject = ref(&m_d3d8Bridge);
return S_OK;
}
if (riid == __uuidof(ID3D9VkInteropInterface)) {
*ppvObject = ref(&m_d3d9Interop);
return S_OK;

View File

@ -1,6 +1,7 @@
#pragma once
#include "d3d9_adapter.h"
#include "d3d9_bridge.h"
#include "d3d9_interop.h"
#include "../dxvk/dxvk_instance.h"
@ -140,6 +141,8 @@ namespace dxvk {
Rc<DxvkInstance> m_instance;
DxvkD3D8InterfaceBridge m_d3d8Bridge;
bool m_extended;
D3D9Options m_d3d9Options;

View File

@ -45,7 +45,8 @@ d3d9_src = [
'd3d9_mem.cpp',
'd3d9_window.cpp',
'd3d9_interop.cpp',
'd3d9_on_12.cpp'
'd3d9_on_12.cpp',
'd3d9_bridge.cpp'
]
d3d9_ld_args = []