From 073806df7cc6aa03c88b45c73efbb0aa798ad532 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sun, 12 Jan 2025 15:58:58 +0100 Subject: [PATCH] [dxvk] Move surface creation to the backend --- src/d3d11/d3d11_swapchain.cpp | 30 +++++++---------------- src/d3d11/d3d11_swapchain.h | 2 -- src/d3d9/d3d9_swapchain.cpp | 32 +++++++++--------------- src/d3d9/d3d9_swapchain.h | 2 -- src/dxvk/dxvk_presenter.cpp | 46 ++++++++++++++++++++++++----------- src/dxvk/dxvk_presenter.h | 30 +++++++++++------------ 6 files changed, 66 insertions(+), 76 deletions(-) diff --git a/src/d3d11/d3d11_swapchain.cpp b/src/d3d11/d3d11_swapchain.cpp index bfaaab772..7adcf0c9d 100644 --- a/src/d3d11/d3d11_swapchain.cpp +++ b/src/d3d11/d3d11_swapchain.cpp @@ -505,17 +505,6 @@ namespace dxvk { VkResult vr = m_presenter->recreateSwapChain(presenterDesc); - if (vr == VK_ERROR_SURFACE_LOST_KHR) { - vr = m_presenter->recreateSurface([this] (VkSurfaceKHR* surface) { - return CreateSurface(surface); - }); - - if (vr) - throw DxvkError(str::format("D3D11SwapChain: Failed to recreate surface: ", vr)); - - vr = m_presenter->recreateSwapChain(presenterDesc); - } - if (vr) throw DxvkError(str::format("D3D11SwapChain: Failed to recreate swap chain: ", vr)); @@ -537,20 +526,19 @@ namespace dxvk { presenterDesc.imageCount = PickImageCount(m_desc.BufferCount + 1); presenterDesc.numFormats = PickFormats(m_desc.Format, presenterDesc.formats); - m_presenter = new Presenter(m_device, m_frameLatencySignal, presenterDesc); + m_presenter = new Presenter(m_device, m_frameLatencySignal, presenterDesc, [ + cAdapter = m_device->adapter(), + cFactory = m_surfaceFactory + ] (VkSurfaceKHR* surface) { + return cFactory->CreateSurface( + cAdapter->vki()->instance(), + cAdapter->handle(), surface); + }); + m_presenter->setFrameRateLimit(m_targetFrameRate, GetActualFrameLatency()); } - VkResult D3D11SwapChain::CreateSurface(VkSurfaceKHR* pSurface) { - Rc adapter = m_device->adapter(); - - return m_surfaceFactory->CreateSurface( - adapter->vki()->instance(), - adapter->handle(), pSurface); - } - - void D3D11SwapChain::CreateRenderTargetViews() { PresenterInfo info = m_presenter->info(); diff --git a/src/d3d11/d3d11_swapchain.h b/src/d3d11/d3d11_swapchain.h index 0c474baf5..cffc60825 100644 --- a/src/d3d11/d3d11_swapchain.h +++ b/src/d3d11/d3d11_swapchain.h @@ -147,8 +147,6 @@ namespace dxvk { void CreatePresenter(); - VkResult CreateSurface(VkSurfaceKHR* pSurface); - void CreateRenderTargetViews(); void CreateBackBuffers(); diff --git a/src/d3d9/d3d9_swapchain.cpp b/src/d3d9/d3d9_swapchain.cpp index 391cec819..3e2c42b00 100644 --- a/src/d3d9/d3d9_swapchain.cpp +++ b/src/d3d9/d3d9_swapchain.cpp @@ -946,17 +946,6 @@ namespace dxvk { VkResult vr = m_wctx->presenter->recreateSwapChain(presenterDesc); - if (vr == VK_ERROR_SURFACE_LOST_KHR) { - vr = m_wctx->presenter->recreateSurface([this] (VkSurfaceKHR* surface) { - return CreateSurface(surface); - }); - - if (vr) - throw DxvkError(str::format("D3D9SwapChainEx: Failed to recreate surface: ", vr)); - - vr = m_wctx->presenter->recreateSwapChain(presenterDesc); - } - if (vr) throw DxvkError(str::format("D3D9SwapChainEx: Failed to recreate swap chain: ", vr)); @@ -976,17 +965,18 @@ namespace dxvk { presenterDesc.imageCount = PickImageCount(m_presentParams.BackBufferCount + 1); presenterDesc.numFormats = PickFormats(EnumerateFormat(m_presentParams.BackBufferFormat), presenterDesc.formats); - m_wctx->presenter = new Presenter(m_device, m_wctx->frameLatencySignal, presenterDesc); - } + m_wctx->presenter = new Presenter(m_device, + m_wctx->frameLatencySignal, presenterDesc, [ + cDevice = m_device, + cWindow = m_window + ] (VkSurfaceKHR* surface) { + auto vki = cDevice->adapter()->vki(); - - VkResult D3D9SwapChainEx::CreateSurface(VkSurfaceKHR* pSurface) { - auto vki = m_device->adapter()->vki(); - - return wsi::createSurface(m_window, - vki->getLoaderProc(), - vki->instance(), - pSurface); + return wsi::createSurface(cWindow, + vki->getLoaderProc(), + vki->instance(), + surface); + }); } diff --git a/src/d3d9/d3d9_swapchain.h b/src/d3d9/d3d9_swapchain.h index 8d804936b..9dfa56c10 100644 --- a/src/d3d9/d3d9_swapchain.h +++ b/src/d3d9/d3d9_swapchain.h @@ -199,8 +199,6 @@ namespace dxvk { void CreatePresenter(); - VkResult CreateSurface(VkSurfaceKHR* pSurface); - void CreateRenderTargetViews(); HRESULT CreateBackBuffers( diff --git a/src/dxvk/dxvk_presenter.cpp b/src/dxvk/dxvk_presenter.cpp index 27d6bb12c..006219d65 100644 --- a/src/dxvk/dxvk_presenter.cpp +++ b/src/dxvk/dxvk_presenter.cpp @@ -10,10 +10,12 @@ namespace dxvk { Presenter::Presenter( const Rc& device, const Rc& signal, - const PresenterDesc& desc) + const PresenterDesc& desc, + PresenterSurfaceProc&& proc) : m_device(device), m_signal(signal), m_vki(device->instance()->vki()), - m_vkd(device->vkd()) { + m_vkd(device->vkd()), + m_surfaceProc(std::move(proc)) { // Only enable FSE if the user explicitly opts in. On Windows, FSE // is required to support VRR or HDR, but blocks alt-tabbing or // overlapping windows, which breaks a number of games. @@ -158,25 +160,31 @@ namespace dxvk { } - VkResult Presenter::recreateSurface( - const std::function& fn) { + VkResult Presenter::recreateSwapChain(const PresenterDesc& desc) { + VkResult vr; + if (m_swapchain) destroySwapchain(); - if (m_surface) - destroySurface(); + if (m_surface) { + vr = createSwapChain(desc); - return fn(&m_surface); + if (vr == VK_ERROR_SURFACE_LOST_KHR) + destroySurface(); + } + + if (!m_surface) { + vr = createSurface(); + + if (vr == VK_SUCCESS) + vr = createSwapChain(desc); + } + + return vr; } - VkResult Presenter::recreateSwapChain(const PresenterDesc& desc) { - if (m_swapchain) - destroySwapchain(); - - if (!m_surface) - return VK_ERROR_SURFACE_LOST_KHR; - + VkResult Presenter::createSwapChain(const PresenterDesc& desc) { VkSurfaceFullScreenExclusiveInfoEXT fullScreenExclusiveInfo = { VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT }; fullScreenExclusiveInfo.fullScreenExclusive = m_fullscreenMode; @@ -653,6 +661,16 @@ namespace dxvk { } + VkResult Presenter::createSurface() { + VkResult vr = m_surfaceProc(&m_surface); + + if (vr != VK_SUCCESS) + Logger::err(str::format("Failed to create Vulkan surface: ", vr)); + + return vr; + } + + void Presenter::destroySwapchain() { if (m_signal != nullptr) m_signal->wait(m_lastFrameId.load(std::memory_order_acquire)); diff --git a/src/dxvk/dxvk_presenter.h b/src/dxvk/dxvk_presenter.h index 1cbf7edc2..82b9ed02d 100644 --- a/src/dxvk/dxvk_presenter.h +++ b/src/dxvk/dxvk_presenter.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include "../util/log/log.h" @@ -18,6 +19,8 @@ namespace dxvk { + using PresenterSurfaceProc = std::function; + class DxvkDevice; /** @@ -94,7 +97,8 @@ namespace dxvk { Presenter( const Rc& device, const Rc& signal, - const PresenterDesc& desc); + const PresenterDesc& desc, + PresenterSurfaceProc&& proc); ~Presenter(); @@ -160,15 +164,6 @@ namespace dxvk { VkPresentModeKHR mode, uint64_t frameId); - /** - * \brief Changes and takes ownership of surface - * - * The presenter will destroy the surface as necessary. - * \param [in] fn Surface create function - */ - VkResult recreateSurface( - const std::function& fn); - /** * \brief Changes presenter properties * @@ -227,13 +222,14 @@ namespace dxvk { private: - Rc m_device; - Rc m_signal; + Rc m_device; + Rc m_signal; - Rc m_vki; - Rc m_vkd; + Rc m_vki; + Rc m_vkd; - PresenterInfo m_info = { }; + PresenterInfo m_info = { }; + PresenterSurfaceProc m_surfaceProc; VkSurfaceKHR m_surface = VK_NULL_HANDLE; VkSwapchainKHR m_swapchain = VK_NULL_HANDLE; @@ -259,7 +255,7 @@ namespace dxvk { std::atomic m_lastFrameId = { 0ull }; - VkResult recreateSwapChainInternal( + VkResult createSwapChain( const PresenterDesc& desc); VkResult getSupportedFormats( @@ -291,6 +287,8 @@ namespace dxvk { uint32_t maxImageCount, uint32_t desired); + VkResult createSurface(); + void destroySwapchain(); void destroySurface();