1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-31 14:52:11 +01:00

[dxvk] Move surface creation to the backend

This commit is contained in:
Philip Rebohle 2025-01-12 15:58:58 +01:00 committed by Philip Rebohle
parent c707d9026f
commit 073806df7c
6 changed files with 66 additions and 76 deletions

View File

@ -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<DxvkAdapter> adapter = m_device->adapter();
return m_surfaceFactory->CreateSurface(
adapter->vki()->instance(),
adapter->handle(), pSurface);
}
void D3D11SwapChain::CreateRenderTargetViews() {
PresenterInfo info = m_presenter->info();

View File

@ -147,8 +147,6 @@ namespace dxvk {
void CreatePresenter();
VkResult CreateSurface(VkSurfaceKHR* pSurface);
void CreateRenderTargetViews();
void CreateBackBuffers();

View File

@ -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);
});
}

View File

@ -199,8 +199,6 @@ namespace dxvk {
void CreatePresenter();
VkResult CreateSurface(VkSurfaceKHR* pSurface);
void CreateRenderTargetViews();
HRESULT CreateBackBuffers(

View File

@ -10,10 +10,12 @@ namespace dxvk {
Presenter::Presenter(
const Rc<DxvkDevice>& device,
const Rc<sync::Signal>& 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<VkResult (VkSurfaceKHR*)>& 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));

View File

@ -1,6 +1,7 @@
#pragma once
#include <functional>
#include <queue>
#include <vector>
#include "../util/log/log.h"
@ -18,6 +19,8 @@
namespace dxvk {
using PresenterSurfaceProc = std::function<VkResult (VkSurfaceKHR*)>;
class DxvkDevice;
/**
@ -94,7 +97,8 @@ namespace dxvk {
Presenter(
const Rc<DxvkDevice>& device,
const Rc<sync::Signal>& 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<VkResult (VkSurfaceKHR*)>& fn);
/**
* \brief Changes presenter properties
*
@ -227,13 +222,14 @@ namespace dxvk {
private:
Rc<DxvkDevice> m_device;
Rc<sync::Signal> m_signal;
Rc<DxvkDevice> m_device;
Rc<sync::Signal> m_signal;
Rc<vk::InstanceFn> m_vki;
Rc<vk::DeviceFn> m_vkd;
Rc<vk::InstanceFn> m_vki;
Rc<vk::DeviceFn> 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<uint64_t> 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();