From ad9f71fa02989a2a509488d2c35ff33cd6ae284b Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 29 Nov 2017 07:55:44 +0100 Subject: [PATCH] [dxgi] Implemented DxgiSwapChain::GetBuffer and more of Present --- src/d3d11/d3d11_device.cpp | 58 ++++++++++++---- src/d3d11/d3d11_device.h | 15 +++-- src/d3d11/d3d11_include.h | 3 +- src/d3d11/d3d11_interfaces.h | 50 ++++++++++++++ src/d3d11/d3d11_texture.cpp | 9 ++- src/d3d11/d3d11_texture.h | 3 +- src/dxgi/dxgi_interfaces.h | 4 +- src/dxgi/dxgi_swapchain.cpp | 127 +++++++++++++++++++++-------------- src/dxgi/dxgi_swapchain.h | 13 +++- src/dxvk/dxvk_device.h | 1 + src/util/com/com_guid.cpp | 4 ++ src/util/com/com_guid.h | 3 + 12 files changed, 211 insertions(+), 79 deletions(-) create mode 100644 src/d3d11/d3d11_interfaces.h diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index 7cdaf51a..20a1d3af 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -3,6 +3,7 @@ #include "d3d11_buffer.h" #include "d3d11_context.h" #include "d3d11_device.h" +#include "d3d11_texture.h" namespace dxvk { @@ -28,6 +29,7 @@ namespace dxvk { HRESULT D3D11Device::QueryInterface(REFIID riid, void** ppvObject) { COM_QUERY_IFACE(riid, ppvObject, IUnknown); COM_QUERY_IFACE(riid, ppvObject, ID3D11Device); + COM_QUERY_IFACE(riid, ppvObject, ID3D11DevicePrivate); if (riid == __uuidof(IDXGIDevicePrivate) || riid == __uuidof(IDXGIDevice)) @@ -42,20 +44,8 @@ namespace dxvk { const D3D11_BUFFER_DESC* pDesc, const D3D11_SUBRESOURCE_DATA* pInitialData, ID3D11Buffer** ppBuffer) { - if (ppBuffer == nullptr) - return S_OK; - - try { - *ppBuffer = ref(new D3D11Buffer(this, *pDesc)); - - if (pInitialData != nullptr) - Logger::warn("D3D11Device::CreateBuffer: pInitialData != NULL not supported"); - - return S_OK; - } catch (const DxvkError& e) { - Logger::err(e.message()); - return E_FAIL; - } + Logger::err("D3D11Device::CreateBuffer: Not implemented"); + return E_NOTIMPL; } @@ -384,6 +374,46 @@ namespace dxvk { } + HRESULT D3D11Device::WrapSwapChainBackBuffer( + const Rc& image, + const DXGI_SWAP_CHAIN_DESC* pSwapChainDesc, + IUnknown** ppInterface) { + UINT bindFlags = 0; + + if (pSwapChainDesc->BufferUsage & DXGI_USAGE_RENDER_TARGET_OUTPUT) + bindFlags |= D3D11_BIND_RENDER_TARGET; + + if (pSwapChainDesc->BufferUsage & DXGI_USAGE_SHADER_INPUT) + bindFlags |= D3D11_BIND_SHADER_RESOURCE; + + D3D11_TEXTURE2D_DESC desc; + desc.Width = pSwapChainDesc->BufferDesc.Width; + desc.Height = pSwapChainDesc->BufferDesc.Height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = pSwapChainDesc->BufferDesc.Format; + desc.SampleDesc = pSwapChainDesc->SampleDesc; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = bindFlags; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + *ppInterface = ref(new D3D11Texture2D(this, desc, image)); + return S_OK; + } + + + HRESULT D3D11Device::FlushRenderingCommands() { + m_context->Flush(); + return S_OK; + } + + + Rc D3D11Device::GetDXVKDevice() { + return m_dxvkDevice; + } + + bool D3D11Device::CheckFeatureLevelSupport( D3D_FEATURE_LEVEL featureLevel) { return featureLevel <= D3D_FEATURE_LEVEL_11_0; diff --git a/src/d3d11/d3d11_device.h b/src/d3d11/d3d11_device.h index 45e1f247..eed41459 100644 --- a/src/d3d11/d3d11_device.h +++ b/src/d3d11/d3d11_device.h @@ -3,7 +3,7 @@ #include #include -#include "d3d11_include.h" +#include "d3d11_interfaces.h" #include "../util/com/com_private_data.h" @@ -12,7 +12,7 @@ namespace dxvk { class DxgiAdapter; class D3D11DeviceContext; - class D3D11Device : public ComObject { + class D3D11Device : public ComObject { public: @@ -215,9 +215,14 @@ namespace dxvk { UINT GetExceptionMode() final; - DxvkDevice* GetDXVKDevice() { - return m_dxvkDevice.ptr(); - } + HRESULT WrapSwapChainBackBuffer( + const Rc& image, + const DXGI_SWAP_CHAIN_DESC* pSwapChainDesc, + IUnknown** ppInterface) final; + + HRESULT FlushRenderingCommands() final; + + Rc GetDXVKDevice() final; static bool CheckFeatureLevelSupport( D3D_FEATURE_LEVEL featureLevel); diff --git a/src/d3d11/d3d11_include.h b/src/d3d11/d3d11_include.h index a31da5f5..c84a3501 100644 --- a/src/d3d11/d3d11_include.h +++ b/src/d3d11/d3d11_include.h @@ -1,4 +1,5 @@ #pragma once -#include +#include "../dxgi/dxgi_include.h" + #include diff --git a/src/d3d11/d3d11_interfaces.h b/src/d3d11/d3d11_interfaces.h new file mode 100644 index 00000000..d49b3be7 --- /dev/null +++ b/src/d3d11/d3d11_interfaces.h @@ -0,0 +1,50 @@ +#pragma once + +#include "../dxvk/dxvk_device.h" + +#include "d3d11_include.h" + +/** + * \brief Private device interface + * + * This interface is used by \ref DxgiSwapChain + * in order to communicate with the device. + */ +MIDL_INTERFACE("ab2a2a58-d2ac-4ca0-9ad9-a260cafa00c8") +ID3D11DevicePrivate : public ID3D11Device { + static const GUID guid; + + /** + * \brief Wraps swap chain image into a texture interface + * + * Creates an interface to the back buffer image of a + * swap chain. This interface will be returned by the + * swap chain's \c GetBuffer method. + * \param [in] image Image to wrap + * \param [in] pSwapChainDesc Swap chain properties + * \param [in] ppInterface Target interface + * \returns \c S_OK on success + */ + virtual HRESULT WrapSwapChainBackBuffer( + const dxvk::Rc& image, + const DXGI_SWAP_CHAIN_DESC* pSwapChainDesc, + IUnknown** ppInterface) = 0; + + /** + * \brief Flushes the immediate context + * + * Used by the swap chain's \c Present method to + * ensure that all rendering commands get dispatched + * before presenting the swap chain's back buffer. + * \returns \c S_OK on success + */ + virtual HRESULT FlushRenderingCommands() = 0; + + /** + * \brief Underlying DXVK device + * \returns DXVK device handle + */ + virtual dxvk::Rc GetDXVKDevice() = 0; +}; + +DXVK_DEFINE_GUID(ID3D11DevicePrivate); \ No newline at end of file diff --git a/src/d3d11/d3d11_texture.cpp b/src/d3d11/d3d11_texture.cpp index 2e15f48c..f3f77509 100644 --- a/src/d3d11/d3d11_texture.cpp +++ b/src/d3d11/d3d11_texture.cpp @@ -5,8 +5,11 @@ namespace dxvk { D3D11Texture2D::D3D11Texture2D( D3D11Device* device, - const D3D11_TEXTURE2D_DESC& desc) - : m_device(device), m_desc(desc) { + const D3D11_TEXTURE2D_DESC& desc, + const Rc& image) + : m_device(device), + m_desc (desc), + m_image (image) { } @@ -36,7 +39,7 @@ namespace dxvk { *pResourceDimension = D3D11_RESOURCE_DIMENSION_TEXTURE2D; } - + void D3D11Texture2D::GetDesc(D3D11_TEXTURE2D_DESC *pDesc) { *pDesc = m_desc; } diff --git a/src/d3d11/d3d11_texture.h b/src/d3d11/d3d11_texture.h index 90491536..2ae275c1 100644 --- a/src/d3d11/d3d11_texture.h +++ b/src/d3d11/d3d11_texture.h @@ -14,7 +14,8 @@ namespace dxvk { D3D11Texture2D( D3D11Device* device, - const D3D11_TEXTURE2D_DESC& desc); + const D3D11_TEXTURE2D_DESC& desc, + const Rc& image); ~D3D11Texture2D(); HRESULT QueryInterface( diff --git a/src/dxgi/dxgi_interfaces.h b/src/dxgi/dxgi_interfaces.h index af784c7c..b66e849a 100644 --- a/src/dxgi/dxgi_interfaces.h +++ b/src/dxgi/dxgi_interfaces.h @@ -9,7 +9,7 @@ namespace dxvk { } /** - * \brief DXVK adapter + * \brief Private DXGI adapter interface * * The implementation of \c IDXGIAdapter holds a * \ref DxvkAdapter which can be retrieved using @@ -24,7 +24,7 @@ IDXGIAdapterPrivate : public IDXGIAdapter1 { /** - * \brief DXVK device + * \brief Private DXGI device interface * * The implementation of \c IDXGIDevice stores a * \ref DxvkDevice which can be retrieved using diff --git a/src/dxgi/dxgi_swapchain.cpp b/src/dxgi/dxgi_swapchain.cpp index c186f2af..7db1f634 100644 --- a/src/dxgi/dxgi_swapchain.cpp +++ b/src/dxgi/dxgi_swapchain.cpp @@ -12,10 +12,21 @@ namespace dxvk { // Retrieve a device pointer that allows us to // communicate with the underlying D3D device - if (FAILED(pDevice->QueryInterface(__uuidof(IDXGIDevicePrivate), + if (FAILED(pDevice->QueryInterface(__uuidof(ID3D11DevicePrivate), reinterpret_cast(&m_device)))) throw DxvkError("DxgiSwapChain::DxgiSwapChain: Invalid device"); + // Retrieve the adapter, which is going + // to be used to enumerate displays. + Com device; + + if (FAILED(pDevice->QueryInterface(__uuidof(IDXGIDevice), + reinterpret_cast(&device)))) + throw DxvkError("DxgiSwapChain::DxgiSwapChain: Invalid device"); + + if (FAILED(device->GetAdapter(&m_adapter))) + throw DxvkError("DxgiSwapChain::DxgiSwapChain: Failed to retrieve adapter"); + // Initialize frame statistics m_stats.PresentCount = 0; m_stats.PresentRefreshCount = 0; @@ -39,7 +50,7 @@ namespace dxvk { if (FAILED(this->SetFullscreenState(!pDesc->Windowed, nullptr))) throw DxvkError("DxgiSwapChain::DxgiSwapChain: Failed to set initial fullscreen state"); - // Create swap chain + // TODO clean up here Rc dxvkDevice = m_device->GetDXVKDevice(); Rc dxvkAdapter = dxvkDevice->adapter(); @@ -65,6 +76,7 @@ namespace dxvk { m_swapchain = dxvkDevice->createSwapchain( m_surface, swapchainProperties); + this->createBackBuffer(); } @@ -103,8 +115,7 @@ namespace dxvk { return DXGI_ERROR_INVALID_CALL; } - Logger::err("DxgiSwapChain::GetBuffer: Not implemented"); - return E_NOTIMPL; + return m_backBufferIface->QueryInterface(riid, ppSurface); } @@ -123,12 +134,7 @@ namespace dxvk { return DXGI_ERROR_DRIVER_INTERNAL_ERROR; } - Com adapter; - - if (FAILED(m_device->GetAdapter(&adapter))) - return DXGI_ERROR_DRIVER_INTERNAL_ERROR; - - return adapter->EnumOutputs(displayId, ppOutput); + return m_adapter->EnumOutputs(displayId, ppOutput); } @@ -182,47 +188,56 @@ namespace dxvk { HRESULT DxgiSwapChain::Present(UINT SyncInterval, UINT Flags) { std::lock_guard lock(m_mutex); - // TODO implement sync interval - // TODO implement flags + try { + // Submit pending rendering commands + // before recording the present code. + m_device->FlushRenderingCommands(); - auto dxvkDevice = m_device->GetDXVKDevice(); - - auto framebuffer = m_swapchain->getFramebuffer(m_acquireSync); - auto framebufferSize = framebuffer->size(); - - m_context->beginRecording(m_commandList); - m_context->bindFramebuffer(framebuffer); - - // TODO render back buffer into the swap image, - // the clear operation is only a placeholder. - VkClearAttachment clearAttachment; - clearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - clearAttachment.colorAttachment = 0; - clearAttachment.clearValue.color.float32[0] = 1.0f; - clearAttachment.clearValue.color.float32[1] = 1.0f; - clearAttachment.clearValue.color.float32[2] = 1.0f; - clearAttachment.clearValue.color.float32[3] = 1.0f; - - VkClearRect clearArea; - clearArea.rect = VkRect2D { { 0, 0 }, framebufferSize.width, framebufferSize.height }; - clearArea.baseArrayLayer = 0; - clearArea.layerCount = framebufferSize.layers; - - m_context->clearRenderTarget( - clearAttachment, - clearArea); - - m_context->endRecording(); - - dxvkDevice->submitCommandList(m_commandList, - m_acquireSync, m_presentSync); - - m_swapchain->present( m_presentSync); - - // FIXME Make sure that the semaphores and the command - // list can be safely used without stalling the device. - dxvkDevice->waitForIdle(); - return S_OK; + // TODO implement sync interval + // TODO implement flags + + auto dxvkDevice = m_device->GetDXVKDevice(); + + auto framebuffer = m_swapchain->getFramebuffer(m_acquireSync); + auto framebufferSize = framebuffer->size(); + + m_context->beginRecording(m_commandList); + m_context->bindFramebuffer(framebuffer); + + // TODO render back buffer into the swap image, + // the clear operation is only a placeholder. + VkClearAttachment clearAttachment; + clearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + clearAttachment.colorAttachment = 0; + clearAttachment.clearValue.color.float32[0] = 1.0f; + clearAttachment.clearValue.color.float32[1] = 1.0f; + clearAttachment.clearValue.color.float32[2] = 1.0f; + clearAttachment.clearValue.color.float32[3] = 1.0f; + + VkClearRect clearArea; + clearArea.rect = VkRect2D { { 0, 0 }, framebufferSize.width, framebufferSize.height }; + clearArea.baseArrayLayer = 0; + clearArea.layerCount = framebufferSize.layers; + + m_context->clearRenderTarget( + clearAttachment, + clearArea); + + m_context->endRecording(); + + dxvkDevice->submitCommandList(m_commandList, + m_acquireSync, m_presentSync); + + m_swapchain->present(m_presentSync); + + // FIXME Make sure that the semaphores and the command + // list can be safely used without stalling the device. + dxvkDevice->waitForIdle(); + return S_OK; + } catch (const DxvkError& err) { + Logger::err(err.message()); + return DXGI_ERROR_DRIVER_INTERNAL_ERROR; + } } @@ -237,9 +252,11 @@ namespace dxvk { m_desc.BufferDesc.Width = Width; m_desc.BufferDesc.Height = Height; m_desc.BufferDesc.Format = NewFormat; - m_desc.BufferCount = BufferCount; m_desc.Flags = SwapChainFlags; + if (BufferCount != 0) + m_desc.BufferCount = BufferCount; + try { // TODO implement return S_OK; @@ -328,4 +345,12 @@ namespace dxvk { return S_OK; } + + void DxgiSwapChain::createBackBuffer() { + // TODO create DXVK image and image virw + + if (FAILED(m_device->WrapSwapChainBackBuffer(m_backBuffer, &m_desc, &m_backBufferIface))) + throw DxvkError("DxgiSwapChain::createBackBuffer: Failed to create back buffer"); + } + } diff --git a/src/dxgi/dxgi_swapchain.h b/src/dxgi/dxgi_swapchain.h index 95f62357..00ee2c6c 100644 --- a/src/dxgi/dxgi_swapchain.h +++ b/src/dxgi/dxgi_swapchain.h @@ -9,6 +9,8 @@ #include "dxgi_interfaces.h" #include "dxgi_object.h" +#include "../d3d11/d3d11_interfaces.h" + namespace dxvk { class DxgiFactory; @@ -78,8 +80,9 @@ namespace dxvk { std::mutex m_mutex; - Com m_factory; - Com m_device; + Com m_factory; + Com m_adapter; + Com m_device; DXGI_SWAP_CHAIN_DESC m_desc; DXGI_FRAME_STATISTICS m_stats; @@ -94,6 +97,12 @@ namespace dxvk { Rc m_acquireSync; Rc m_presentSync; + Rc m_backBuffer; + Rc m_backBufferView; + Com m_backBufferIface; + + void createBackBuffer(); + }; } diff --git a/src/dxvk/dxvk_device.h b/src/dxvk/dxvk_device.h index 6365f3d2..3b531ac3 100644 --- a/src/dxvk/dxvk_device.h +++ b/src/dxvk/dxvk_device.h @@ -6,6 +6,7 @@ #include "dxvk_constant_state.h" #include "dxvk_context.h" #include "dxvk_framebuffer.h" +#include "dxvk_image.h" #include "dxvk_memory.h" #include "dxvk_pipemgr.h" #include "dxvk_renderpass.h" diff --git a/src/util/com/com_guid.cpp b/src/util/com/com_guid.cpp index 6f32fdb9..1d653367 100644 --- a/src/util/com/com_guid.cpp +++ b/src/util/com/com_guid.cpp @@ -1,10 +1,14 @@ #include "com_guid.h" +#include "../../d3d11/d3d11_interfaces.h" + #include "../../dxgi/dxgi_interfaces.h" const GUID IDXGIAdapterPrivate::guid = {0x907bf281,0xea3c,0x43b4,{0xa8,0xe4,0x9f,0x23,0x11,0x07,0xb4,0xff}}; const GUID IDXGIDevicePrivate::guid = {0x7a622cf6,0x627a,0x46b2,{0xb5,0x2f,0x36,0x0e,0xf3,0xda,0x83,0x1c}}; +const GUID ID3D11DevicePrivate::guid = {0xab2a2a58,0xd2ac,0x4ca0,{0x9a,0xd9,0xa2,0x60,0xca,0xfa,0x00,0xc8}}; + std::ostream& operator << (std::ostream& os, REFIID guid) { os.width(8); os << std::hex << guid.Data1 << '-'; diff --git a/src/util/com/com_guid.h b/src/util/com/com_guid.h index 7f34d8b2..510fd0cf 100644 --- a/src/util/com/com_guid.h +++ b/src/util/com/com_guid.h @@ -4,4 +4,7 @@ #include "com_include.h" +#define DXVK_DEFINE_GUID(iface) \ + template<> inline GUID const& __mingw_uuidof () { return iface::guid; } + std::ostream& operator << (std::ostream& os, REFIID guid);