diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 6b418130..7675d0c1 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -2265,6 +2265,33 @@ namespace dxvk { } + void STDMETHODCALLTYPE D3D11DeviceContext::TransitionSurfaceLayout( + IDXGIVkInteropSurface* pSurface, + const VkImageSubresourceRange* pSubresources, + VkImageLayout OldLayout, + VkImageLayout NewLayout) { + // Get the underlying D3D11 resource + Com resource; + + pSurface->QueryInterface(__uuidof(ID3D11Resource), + reinterpret_cast(&resource)); + + // Get the texture from that resource + D3D11CommonTexture* texture = GetCommonTexture(resource.ptr()); + + EmitCs([ + cImage = texture->GetImage(), + cSubresources = *pSubresources, + cOldLayout = OldLayout, + cNewLayout = NewLayout + ] (DxvkContext* ctx) { + ctx->transformImage( + cImage, cSubresources, + cOldLayout, cNewLayout); + }); + } + + void D3D11DeviceContext::ApplyInputLayout() { if (m_state.ia.inputLayout != nullptr) { EmitCs([cInputLayout = m_state.ia.inputLayout] (DxvkContext* ctx) { diff --git a/src/d3d11/d3d11_context.h b/src/d3d11/d3d11_context.h index 8ebc65c8..a4c7df94 100644 --- a/src/d3d11/d3d11_context.h +++ b/src/d3d11/d3d11_context.h @@ -635,6 +635,12 @@ namespace dxvk { UINT NumBuffers, ID3D11Buffer** ppSOTargets) final; + void STDMETHODCALLTYPE TransitionSurfaceLayout( + IDXGIVkInteropSurface* pSurface, + const VkImageSubresourceRange* pSubresources, + VkImageLayout OldLayout, + VkImageLayout NewLayout); + protected: D3D11Device* const m_parent; diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index 5dc8a781..3facd7f9 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -7,6 +7,7 @@ #include "d3d11_context_imm.h" #include "d3d11_device.h" #include "d3d11_input_layout.h" +#include "d3d11_interop.h" #include "d3d11_present.h" #include "d3d11_query.h" #include "d3d11_sampler.h" @@ -21,6 +22,7 @@ namespace dxvk { D3D11DeviceContainer::~D3D11DeviceContainer() { + delete m_d3d11VkInterop; delete m_d3d11Presenter; delete m_d3d11Device; delete m_dxgiDevice; @@ -44,6 +46,11 @@ namespace dxvk { return S_OK; } + if (riid == __uuidof(IDXGIVkInteropDevice)) { + *ppvObject = ref(m_d3d11VkInterop); + return S_OK; + } + if (riid == __uuidof(ID3D11Device) || riid == __uuidof(ID3D11Device1)) { *ppvObject = ref(m_d3d11Device); diff --git a/src/d3d11/d3d11_device.h b/src/d3d11/d3d11_device.h index a4ed9f99..e6c338ba 100644 --- a/src/d3d11/d3d11_device.h +++ b/src/d3d11/d3d11_device.h @@ -29,6 +29,7 @@ namespace dxvk { class D3D11Texture1D; class D3D11Texture2D; class D3D11Texture3D; + class D3D11VkInterop; /** * \brief D3D11 device container @@ -54,6 +55,7 @@ namespace dxvk { IDXGIVkDevice* m_dxgiDevice = nullptr; D3D11Device* m_d3d11Device = nullptr; D3D11Presenter* m_d3d11Presenter = nullptr; + D3D11VkInterop* m_d3d11VkInterop = nullptr; }; diff --git a/src/d3d11/d3d11_interop.cpp b/src/d3d11/d3d11_interop.cpp new file mode 100644 index 00000000..0339a29b --- /dev/null +++ b/src/d3d11/d3d11_interop.cpp @@ -0,0 +1,107 @@ +#include "d3d11_context_imm.h" +#include "d3d11_interop.h" +#include "d3d11_device.h" + +#include "../dxvk/dxvk_adapter.h" +#include "../dxvk/dxvk_device.h" +#include "../dxvk/dxvk_instance.h" + +namespace dxvk { + + D3D11VkInterop::D3D11VkInterop( + IDXGIObject* pContainer, + ID3D11Device* pDevice) + : m_container (pContainer), + m_device (pDevice) { } + + + D3D11VkInterop::~D3D11VkInterop() { + + } + + + ULONG STDMETHODCALLTYPE D3D11VkInterop::AddRef() { + return m_container->AddRef(); + } + + + ULONG STDMETHODCALLTYPE D3D11VkInterop::Release() { + return m_container->Release(); + } + + + HRESULT STDMETHODCALLTYPE D3D11VkInterop::QueryInterface( + REFIID riid, + void** ppvObject) { + return m_container->QueryInterface(riid, ppvObject); + } + + + void STDMETHODCALLTYPE D3D11VkInterop::GetVulkanHandles( + VkInstance* pInstance, + VkPhysicalDevice* pPhysDev, + VkDevice* pDevice) { + auto device = static_cast(m_device)->GetDXVKDevice(); + auto adapter = device->adapter(); + auto instance = adapter->instance(); + + if (pDevice != nullptr) + *pDevice = device->handle(); + + if (pPhysDev != nullptr) + *pPhysDev = adapter->handle(); + + if (pInstance != nullptr) + *pInstance = instance->handle(); + } + + + void STDMETHODCALLTYPE D3D11VkInterop::GetSubmissionQueue( + VkQueue* pQueue, + uint32_t* pQueueFamilyIndex) { + auto device = static_cast(m_device)->GetDXVKDevice(); + DxvkDeviceQueue queue = device->graphicsQueue(); + + if (pQueue != nullptr) + *pQueue = queue.queueHandle; + + if (pQueueFamilyIndex != nullptr) + *pQueueFamilyIndex = queue.queueFamily; + } + + + void STDMETHODCALLTYPE D3D11VkInterop::TransitionSurfaceLayout( + IDXGIVkInteropSurface* pSurface, + const VkImageSubresourceRange* pSubresources, + VkImageLayout OldLayout, + VkImageLayout NewLayout) { + Com deviceContext = nullptr; + m_device->GetImmediateContext(&deviceContext); + + auto immediateContext = static_cast(deviceContext.ptr()); + + immediateContext->TransitionSurfaceLayout( + pSurface, pSubresources, OldLayout, NewLayout); + } + + + void STDMETHODCALLTYPE D3D11VkInterop::FlushRenderingCommands() { + Com deviceContext = nullptr; + m_device->GetImmediateContext(&deviceContext); + + auto immediateContext = static_cast(deviceContext.ptr()); + immediateContext->Flush(); + immediateContext->SynchronizeCsThread(); + } + + + void STDMETHODCALLTYPE D3D11VkInterop::LockSubmissionQueue() { + static_cast(m_device)->GetDXVKDevice()->lockSubmission(); + } + + + void STDMETHODCALLTYPE D3D11VkInterop::ReleaseSubmissionQueue() { + static_cast(m_device)->GetDXVKDevice()->unlockSubmission(); + } + +} \ No newline at end of file diff --git a/src/d3d11/d3d11_interop.h b/src/d3d11/d3d11_interop.h new file mode 100644 index 00000000..27865172 --- /dev/null +++ b/src/d3d11/d3d11_interop.h @@ -0,0 +1,54 @@ +#pragma once + +#include "../dxgi/dxgi_interfaces.h" + +#include "d3d11_include.h" + +namespace dxvk { + + class D3D11VkInterop : public ComObject { + + public: + + D3D11VkInterop( + IDXGIObject* pContainer, + ID3D11Device* pDevice); + ~D3D11VkInterop(); + + 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* pQueueFamilyIndex); + + void STDMETHODCALLTYPE TransitionSurfaceLayout( + IDXGIVkInteropSurface* pSurface, + const VkImageSubresourceRange* pSubresources, + VkImageLayout OldLayout, + VkImageLayout NewLayout); + + void STDMETHODCALLTYPE FlushRenderingCommands(); + + void STDMETHODCALLTYPE LockSubmissionQueue(); + + void STDMETHODCALLTYPE ReleaseSubmissionQueue(); + + private: + + IDXGIObject* m_container; + ID3D11Device* m_device; + + }; + +} \ No newline at end of file diff --git a/src/d3d11/d3d11_main.cpp b/src/d3d11/d3d11_main.cpp index 4d08403e..4cdc0aa5 100644 --- a/src/d3d11/d3d11_main.cpp +++ b/src/d3d11/d3d11_main.cpp @@ -5,6 +5,7 @@ #include "d3d11_device.h" #include "d3d11_enums.h" +#include "d3d11_interop.h" #include "d3d11_present.h" namespace dxvk { @@ -127,6 +128,9 @@ extern "C" { container->m_d3d11Presenter = new D3D11Presenter( container.ptr(), container->m_d3d11Device); + container->m_d3d11VkInterop = new D3D11VkInterop( + container.ptr(), container->m_d3d11Device); + if (ppDevice != nullptr) *ppDevice = ref(container->m_d3d11Device); diff --git a/src/d3d11/meson.build b/src/d3d11/meson.build index 41964028..a0cf8e3a 100644 --- a/src/d3d11/meson.build +++ b/src/d3d11/meson.build @@ -10,6 +10,7 @@ d3d11_src = [ 'd3d11_device.cpp', 'd3d11_enums.cpp', 'd3d11_input_layout.cpp', + 'd3d11_interop.cpp', 'd3d11_main.cpp', 'd3d11_options.cpp', 'd3d11_present.cpp', diff --git a/src/dxgi/dxgi_interfaces.h b/src/dxgi/dxgi_interfaces.h index 5fc268dc..5e86025d 100644 --- a/src/dxgi/dxgi_interfaces.h +++ b/src/dxgi/dxgi_interfaces.h @@ -221,7 +221,7 @@ IDXGIVkInteropDevice : public IUnknown { * \param [in] OldLayout Current image layout * \param [in] NewLayout Desired image layout */ - virtual HRESULT STDMETHODCALLTYPE TransitionSurfaceLayout( + virtual void STDMETHODCALLTYPE TransitionSurfaceLayout( IDXGIVkInteropSurface* pSurface, const VkImageSubresourceRange* pSubresources, VkImageLayout OldLayout, diff --git a/src/dxvk/dxvk_adapter.cpp b/src/dxvk/dxvk_adapter.cpp index 5cfaaff2..6e28366b 100644 --- a/src/dxvk/dxvk_adapter.cpp +++ b/src/dxvk/dxvk_adapter.cpp @@ -28,6 +28,11 @@ namespace dxvk { } + Rc DxvkAdapter::instance() const { + return m_instance; + } + + VkPhysicalDeviceProperties DxvkAdapter::deviceProperties() const { VkPhysicalDeviceProperties properties; m_vki->vkGetPhysicalDeviceProperties(m_handle, &properties); diff --git a/src/dxvk/dxvk_adapter.h b/src/dxvk/dxvk_adapter.h index d36382f5..aa693508 100644 --- a/src/dxvk/dxvk_adapter.h +++ b/src/dxvk/dxvk_adapter.h @@ -52,6 +52,12 @@ namespace dxvk { return m_handle; } + /** + * \brief Vulkan instance + * \returns Vulkan instance + */ + Rc instance() const; + /** * \brief Physical device properties * diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 927d0366..0362f9f7 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -1199,6 +1199,25 @@ namespace dxvk { } + void DxvkContext::transformImage( + const Rc& dstImage, + const VkImageSubresourceRange& dstSubresources, + VkImageLayout srcLayout, + VkImageLayout dstLayout) { + m_barriers.accessImage( + dstImage, dstSubresources, + srcLayout, + dstImage->info().stages, + dstImage->info().access, + dstLayout, + dstImage->info().stages, + dstImage->info().access); + m_barriers.recordCommands(m_cmd); + + m_cmd->trackResource(dstImage); + } + + void DxvkContext::updateBuffer( const Rc& buffer, VkDeviceSize offset, diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 5dd9b337..0c0f32fd 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -468,6 +468,20 @@ namespace dxvk { const VkImageSubresourceLayers& srcSubresources, VkFormat format); + /** + * \brief Transforms image subresource layouts + * + * \param [in] dstImage Image to transform + * \param [in] dstSubresources Subresources + * \param [in] srcLayout Current layout + * \param [in] dstLayout Desired layout + */ + void transformImage( + const Rc& dstImage, + const VkImageSubresourceRange& dstSubresources, + VkImageLayout srcLayout, + VkImageLayout dstLayout); + /** * \brief Updates a buffer *