mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-05 01:24:14 +01:00
[d3d9] Add ID3D9VkInteropDevice
Provides access to the device and instance handles as well as the queue that is used for rendering.
This commit is contained in:
parent
e976218e17
commit
d221bb7a9c
@ -54,7 +54,8 @@ namespace dxvk {
|
||||
, m_multithread ( BehaviorFlags & D3DCREATE_MULTITHREADED )
|
||||
, m_isSWVP ( (BehaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING) ? true : false )
|
||||
, m_csThread ( dxvkDevice, dxvkDevice->createContext(DxvkContextType::Primary) )
|
||||
, m_csChunk ( AllocCsChunk() ) {
|
||||
, m_csChunk ( AllocCsChunk() )
|
||||
, m_d3d9Interop ( this ) {
|
||||
// If we can SWVP, then we use an extended constant set
|
||||
// as SWVP has many more slots available than HWVP.
|
||||
bool canSWVP = CanSWVP();
|
||||
@ -191,6 +192,11 @@ namespace dxvk {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (riid == __uuidof(ID3D9VkInteropDevice)) {
|
||||
*ppvObject = ref(&m_d3d9Interop);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// We want to ignore this if the extended device is queried and we weren't made extended.
|
||||
if (riid == __uuidof(IDirect3DDevice9Ex))
|
||||
return E_NOINTERFACE;
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "d3d9_swvp_emu.h"
|
||||
|
||||
#include "d3d9_spec_constants.h"
|
||||
#include "d3d9_interop.h"
|
||||
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
@ -118,6 +119,7 @@ namespace dxvk {
|
||||
friend class D3D9SwapChainEx;
|
||||
friend class D3D9ConstantBuffer;
|
||||
friend class D3D9UserDefinedAnnotation;
|
||||
friend D3D9VkInteropDevice;
|
||||
public:
|
||||
|
||||
D3D9DeviceEx(
|
||||
@ -1317,6 +1319,8 @@ namespace dxvk {
|
||||
#ifdef D3D9_ALLOW_UNMAPPING
|
||||
lru_list<D3D9CommonTexture*> m_mappedTextures;
|
||||
#endif
|
||||
|
||||
D3D9VkInteropDevice m_d3d9Interop;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -74,10 +74,134 @@ ID3D9VkInteropTexture : public IUnknown {
|
||||
VkImageCreateInfo* pInfo) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief D3D9 device interface for Vulkan interop
|
||||
*
|
||||
* Provides access to the device and instance handles
|
||||
* as well as the queue that is used for rendering.
|
||||
*/
|
||||
MIDL_INTERFACE("2eaa4b89-0107-4bdb-87f7-0f541c493ce0")
|
||||
ID3D9VkInteropDevice : public IUnknown {
|
||||
/**
|
||||
* \brief Queries Vulkan handles used by DXVK
|
||||
*
|
||||
* \param [out] pInstance The Vulkan instance
|
||||
* \param [out] pPhysDev The physical device
|
||||
* \param [out] pDevide The device handle
|
||||
*/
|
||||
virtual void STDMETHODCALLTYPE GetVulkanHandles(
|
||||
VkInstance* pInstance,
|
||||
VkPhysicalDevice* pPhysDev,
|
||||
VkDevice* pDevice) = 0;
|
||||
|
||||
/**
|
||||
* \brief Queries the rendering queue used by DXVK
|
||||
*
|
||||
* \param [out] pQueue The Vulkan queue handle
|
||||
* \param [out] pQueueIndex Queue index
|
||||
* \param [out] pQueueFamilyIndex Queue family index
|
||||
*/
|
||||
virtual void STDMETHODCALLTYPE GetSubmissionQueue(
|
||||
VkQueue* pQueue,
|
||||
uint32_t* pQueueIndex,
|
||||
uint32_t* pQueueFamilyIndex) = 0;
|
||||
|
||||
/**
|
||||
* \brief Transitions a Texture to a given layout
|
||||
*
|
||||
* Executes an explicit image layout transition on the
|
||||
* D3D device. Note that the image subresources \e must
|
||||
* be transitioned back to its original layout before
|
||||
* using it again from D3D9.
|
||||
* Synchronization is left up to the caller.
|
||||
* This function merely emits a call to transition the
|
||||
* texture on the DXVK internal command stream.
|
||||
* \param [in] pTexture The image to transform
|
||||
* \param [in] pSubresources Subresources to transform
|
||||
* \param [in] OldLayout Current image layout
|
||||
* \param [in] NewLayout Desired image layout
|
||||
*/
|
||||
virtual void STDMETHODCALLTYPE TransitionTextureLayout(
|
||||
ID3D9VkInteropTexture* pTexture,
|
||||
const VkImageSubresourceRange* pSubresources,
|
||||
VkImageLayout OldLayout,
|
||||
VkImageLayout NewLayout) = 0;
|
||||
|
||||
/**
|
||||
* \brief Flushes outstanding D3D rendering commands
|
||||
*
|
||||
* Must be called before submitting Vulkan commands
|
||||
* to the rendering queue if those commands use the
|
||||
* backing resource of a D3D9 object.
|
||||
*/
|
||||
virtual void STDMETHODCALLTYPE FlushRenderingCommands() = 0;
|
||||
|
||||
/**
|
||||
* \brief Locks submission queue
|
||||
*
|
||||
* Should be called immediately before submitting
|
||||
* Vulkan commands to the rendering queue in order
|
||||
* to prevent DXVK from using the queue.
|
||||
*
|
||||
* While the submission queue is locked, no D3D9
|
||||
* methods must be called from the locking thread,
|
||||
* or otherwise a deadlock might occur.
|
||||
*/
|
||||
virtual void STDMETHODCALLTYPE LockSubmissionQueue() = 0;
|
||||
|
||||
/**
|
||||
* \brief Releases submission queue
|
||||
*
|
||||
* Should be called immediately after submitting
|
||||
* Vulkan commands to the rendering queue in order
|
||||
* to allow DXVK to submit new commands.
|
||||
*/
|
||||
virtual void STDMETHODCALLTYPE ReleaseSubmissionQueue() = 0;
|
||||
|
||||
/**
|
||||
* \brief Locks the device
|
||||
*
|
||||
* Can be called to ensure no D3D9 device methods
|
||||
* can be executed until UnlockDevice has been called.
|
||||
*
|
||||
* This will do nothing if the D3DCREATE_MULTITHREADED
|
||||
* is not set.
|
||||
*/
|
||||
virtual void STDMETHODCALLTYPE LockDevice() = 0;
|
||||
|
||||
/**
|
||||
* \brief Unlocks the device
|
||||
*
|
||||
* Must only be called after a call to LockDevice.
|
||||
*/
|
||||
virtual void STDMETHODCALLTYPE UnlockDevice() = 0;
|
||||
|
||||
/**
|
||||
* \brief Wait for a resource to finish being used
|
||||
*
|
||||
* Waits for the GPU resource associated with the
|
||||
* resource to finish being used by the GPU.
|
||||
*
|
||||
* Valid D3DLOCK flags:
|
||||
* - D3DLOCK_READONLY: Only waits for writes
|
||||
* - D3DLOCK_DONOTWAIT: Does not wait for the resource (may flush)
|
||||
*
|
||||
* \param [in] pResource Resource to be waited upon
|
||||
* \param [in] MapFlags D3DLOCK flags
|
||||
* \returns true if the resource is ready to use,
|
||||
* false if the resource is till in use
|
||||
*/
|
||||
virtual bool STDMETHODCALLTYPE WaitForResource(
|
||||
IDirect3DResource9* pResource,
|
||||
DWORD MapFlags) = 0;
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
struct __declspec(uuid("3461a81b-ce41-485b-b6b5-fcf08ba6a6bd")) ID3D9VkInteropInterface;
|
||||
struct __declspec(uuid("d56344f5-8d35-46fd-806d-94c351b472c1")) ID3D9VkInteropTexture;
|
||||
struct __declspec(uuid("2eaa4b89-0107-4bdb-87f7-0f541c493ce0")) ID3D9VkInteropDevice;
|
||||
#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);
|
||||
__CRT_UUID_DECL(ID3D9VkInteropDevice, 0x2eaa4b89,0x0107,0x4bdb,0x87,0xf7,0x0f,0x54,0x1c,0x49,0x3c,0xe0);
|
||||
#endif
|
||||
|
@ -1,6 +1,9 @@
|
||||
#include "d3d9_interop.h"
|
||||
#include "d3d9_interface.h"
|
||||
#include "d3d9_common_texture.h"
|
||||
#include "d3d9_device.h"
|
||||
#include "d3d9_texture.h"
|
||||
#include "d3d9_buffer.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
@ -113,4 +116,127 @@ namespace dxvk {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
// Device Interop
|
||||
///////////////////////////////
|
||||
|
||||
D3D9VkInteropDevice::D3D9VkInteropDevice(
|
||||
D3D9DeviceEx* pInterface)
|
||||
: m_device(pInterface) {
|
||||
|
||||
}
|
||||
|
||||
D3D9VkInteropDevice::~D3D9VkInteropDevice() {
|
||||
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE D3D9VkInteropDevice::AddRef() {
|
||||
return m_device->AddRef();
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE D3D9VkInteropDevice::Release() {
|
||||
return m_device->Release();
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE D3D9VkInteropDevice::QueryInterface(
|
||||
REFIID riid,
|
||||
void** ppvObject) {
|
||||
return m_device->QueryInterface(riid, ppvObject);
|
||||
}
|
||||
|
||||
void STDMETHODCALLTYPE D3D9VkInteropDevice::GetVulkanHandles(
|
||||
VkInstance* pInstance,
|
||||
VkPhysicalDevice* pPhysDev,
|
||||
VkDevice* pDevice) {
|
||||
auto device = m_device->GetDXVKDevice();
|
||||
auto adapter = device->adapter();
|
||||
auto instance = device->instance();
|
||||
|
||||
if (pDevice != nullptr)
|
||||
*pDevice = device->handle();
|
||||
|
||||
if (pPhysDev != nullptr)
|
||||
*pPhysDev = adapter->handle();
|
||||
|
||||
if (pInstance != nullptr)
|
||||
*pInstance = instance->handle();
|
||||
}
|
||||
|
||||
void STDMETHODCALLTYPE D3D9VkInteropDevice::GetSubmissionQueue(
|
||||
VkQueue* pQueue,
|
||||
uint32_t* pQueueIndex,
|
||||
uint32_t* pQueueFamilyIndex) {
|
||||
auto device = m_device->GetDXVKDevice();
|
||||
DxvkDeviceQueue queue = device->queues().graphics;
|
||||
|
||||
if (pQueue != nullptr)
|
||||
*pQueue = queue.queueHandle;
|
||||
|
||||
if (pQueueIndex != nullptr)
|
||||
*pQueueIndex = queue.queueIndex;
|
||||
|
||||
if (pQueueFamilyIndex != nullptr)
|
||||
*pQueueFamilyIndex = queue.queueFamily;
|
||||
}
|
||||
|
||||
void STDMETHODCALLTYPE D3D9VkInteropDevice::TransitionTextureLayout(
|
||||
ID3D9VkInteropTexture* pTexture,
|
||||
const VkImageSubresourceRange* pSubresources,
|
||||
VkImageLayout OldLayout,
|
||||
VkImageLayout NewLayout) {
|
||||
auto texture = static_cast<D3D9VkInteropTexture *>(pTexture)->GetCommonTexture();
|
||||
|
||||
m_device->EmitCs([
|
||||
cImage = texture->GetImage(),
|
||||
cSubresources = *pSubresources,
|
||||
cOldLayout = OldLayout,
|
||||
cNewLayout = NewLayout
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->transformImage(
|
||||
cImage, cSubresources,
|
||||
cOldLayout, cNewLayout);
|
||||
});
|
||||
}
|
||||
|
||||
void STDMETHODCALLTYPE D3D9VkInteropDevice::FlushRenderingCommands() {
|
||||
m_device->Flush();
|
||||
m_device->SynchronizeCsThread(DxvkCsThread::SynchronizeAll);
|
||||
}
|
||||
|
||||
void STDMETHODCALLTYPE D3D9VkInteropDevice::LockSubmissionQueue() {
|
||||
m_device->GetDXVKDevice()->lockSubmission();
|
||||
}
|
||||
|
||||
void STDMETHODCALLTYPE D3D9VkInteropDevice::ReleaseSubmissionQueue() {
|
||||
m_device->GetDXVKDevice()->unlockSubmission();
|
||||
}
|
||||
|
||||
void STDMETHODCALLTYPE D3D9VkInteropDevice::LockDevice() {
|
||||
m_lock = m_device->LockDevice();
|
||||
}
|
||||
|
||||
void STDMETHODCALLTYPE D3D9VkInteropDevice::UnlockDevice() {
|
||||
m_lock = D3D9DeviceLock();
|
||||
}
|
||||
|
||||
static Rc<DxvkResource> GetDxvkResource(IDirect3DResource9 *pResource) {
|
||||
switch (pResource->GetType()) {
|
||||
case D3DRTYPE_SURFACE: return static_cast<D3D9Surface*> (pResource)->GetCommonTexture()->GetImage();
|
||||
// Does not inherit from IDirect3DResource9... lol.
|
||||
//case D3DRTYPE_VOLUME: return static_cast<D3D9Volume*> (pResource)->GetCommonTexture()->GetImage();
|
||||
case D3DRTYPE_TEXTURE: return static_cast<D3D9Texture2D*> (pResource)->GetCommonTexture()->GetImage();
|
||||
case D3DRTYPE_VOLUMETEXTURE: return static_cast<D3D9Texture3D*> (pResource)->GetCommonTexture()->GetImage();
|
||||
case D3DRTYPE_CUBETEXTURE: return static_cast<D3D9TextureCube*> (pResource)->GetCommonTexture()->GetImage();
|
||||
case D3DRTYPE_VERTEXBUFFER: return static_cast<D3D9VertexBuffer*>(pResource)->GetCommonBuffer()->GetBuffer<D3D9_COMMON_BUFFER_TYPE_REAL>();
|
||||
case D3DRTYPE_INDEXBUFFER: return static_cast<D3D9IndexBuffer*> (pResource)->GetCommonBuffer()->GetBuffer<D3D9_COMMON_BUFFER_TYPE_REAL>();
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool STDMETHODCALLTYPE D3D9VkInteropDevice::WaitForResource(
|
||||
IDirect3DResource9* pResource,
|
||||
DWORD MapFlags) {
|
||||
return m_device->WaitForResource(GetDxvkResource(pResource), DxvkCsThread::SynchronizeAll, MapFlags);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "d3d9_interfaces.h"
|
||||
#include "d3d9_multithread.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
class D3D9InterfaceEx;
|
||||
class D3D9CommonTexture;
|
||||
class D3D9DeviceEx;
|
||||
|
||||
class D3D9VkInteropInterface final : public ID3D9VkInteropInterface {
|
||||
|
||||
@ -69,4 +71,58 @@ namespace dxvk {
|
||||
|
||||
};
|
||||
|
||||
class D3D9VkInteropDevice final : public ID3D9VkInteropDevice {
|
||||
|
||||
public:
|
||||
|
||||
D3D9VkInteropDevice(
|
||||
D3D9DeviceEx* pInterface);
|
||||
|
||||
~D3D9VkInteropDevice();
|
||||
|
||||
ULONG STDMETHODCALLTYPE AddRef();
|
||||
|
||||
ULONG STDMETHODCALLTYPE Release();
|
||||
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(
|
||||
REFIID riid,
|
||||
void** ppvObject);
|
||||
|
||||
void STDMETHODCALLTYPE GetVulkanHandles(
|
||||
VkInstance* pInstance,
|
||||
VkPhysicalDevice* pPhysDev,
|
||||
VkDevice* pDevice);
|
||||
|
||||
void STDMETHODCALLTYPE GetSubmissionQueue(
|
||||
VkQueue* pQueue,
|
||||
uint32_t* pQueueIndex,
|
||||
uint32_t* pQueueFamilyIndex);
|
||||
|
||||
void STDMETHODCALLTYPE TransitionTextureLayout(
|
||||
ID3D9VkInteropTexture* pTexture,
|
||||
const VkImageSubresourceRange* pSubresources,
|
||||
VkImageLayout OldLayout,
|
||||
VkImageLayout NewLayout);
|
||||
|
||||
void STDMETHODCALLTYPE FlushRenderingCommands();
|
||||
|
||||
void STDMETHODCALLTYPE LockSubmissionQueue();
|
||||
|
||||
void STDMETHODCALLTYPE ReleaseSubmissionQueue();
|
||||
|
||||
void STDMETHODCALLTYPE LockDevice();
|
||||
|
||||
void STDMETHODCALLTYPE UnlockDevice();
|
||||
|
||||
bool STDMETHODCALLTYPE WaitForResource(
|
||||
IDirect3DResource9* pResource,
|
||||
DWORD MapFlags);
|
||||
|
||||
private:
|
||||
|
||||
D3D9DeviceEx* m_device;
|
||||
D3D9DeviceLock m_lock;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user