From a558f82b5f56cdf55f897a3092bb1da8f9085d2c Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sun, 4 Aug 2019 16:28:32 +0200 Subject: [PATCH] [dxvk] Implement asynchronous presentation option in the backend --- dxvk.conf | 13 +++++++++++++ src/dxvk/dxvk_options.cpp | 1 + src/dxvk/dxvk_options.h | 3 +++ src/dxvk/dxvk_queue.cpp | 26 ++++++++++++++++++++------ src/dxvk/dxvk_queue.h | 1 + 5 files changed, 38 insertions(+), 6 deletions(-) diff --git a/dxvk.conf b/dxvk.conf index b33036cc..ed5839b6 100644 --- a/dxvk.conf +++ b/dxvk.conf @@ -183,6 +183,19 @@ # dxvk.numCompilerThreads = 0 +# Toggles asynchronous present. +# +# Off-loads presentation to the queue submission thread in +# order to reduce stalling on the main rendering thread and +# improve performance. +# +# Supported values: +# - Auto: Enable on certain drivers +# - True / False: Always enable / disable + +# dxvk.asyncPresent = Auto + + # Toggles raw SSBO usage. # # Uses storage buffers to implement raw and structured buffer diff --git a/src/dxvk/dxvk_options.cpp b/src/dxvk/dxvk_options.cpp index 61fe1018..394feabb 100644 --- a/src/dxvk/dxvk_options.cpp +++ b/src/dxvk/dxvk_options.cpp @@ -6,6 +6,7 @@ namespace dxvk { enableStateCache = config.getOption ("dxvk.enableStateCache", true); enableTransferQueue = config.getOption ("dxvk.enableTransferQueue", true); numCompilerThreads = config.getOption ("dxvk.numCompilerThreads", 0); + asyncPresent = config.getOption("dxvk.asyncPresent", Tristate::Auto); useRawSsbo = config.getOption("dxvk.useRawSsbo", Tristate::Auto); useEarlyDiscard = config.getOption("dxvk.useEarlyDiscard", Tristate::Auto); hud = config.getOption("dxvk.hud", ""); diff --git a/src/dxvk/dxvk_options.h b/src/dxvk/dxvk_options.h index 5b58eead..447294b5 100644 --- a/src/dxvk/dxvk_options.h +++ b/src/dxvk/dxvk_options.h @@ -18,6 +18,9 @@ namespace dxvk { /// when using the state cache int32_t numCompilerThreads; + /// Asynchronous presentation + Tristate asyncPresent; + /// Shader-related options Tristate useRawSsbo; Tristate useEarlyDiscard; diff --git a/src/dxvk/dxvk_queue.cpp b/src/dxvk/dxvk_queue.cpp index e2b1a5f6..0c88f87b 100644 --- a/src/dxvk/dxvk_queue.cpp +++ b/src/dxvk/dxvk_queue.cpp @@ -7,7 +7,12 @@ namespace dxvk { : m_device(device), m_submitThread([this] () { submitCmdLists(); }), m_finishThread([this] () { finishCmdLists(); }) { - + // Asynchronous presentation seems to increase the + // likelyhood of hangs on Nvidia for some reason. + m_asyncPresent = !m_device->adapter()->matchesDriver( + DxvkGpuVendor::Nvidia, VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR, 0, 0); + + applyTristate(m_asyncPresent, m_device->config().asyncPresent); } @@ -43,12 +48,21 @@ namespace dxvk { void DxvkSubmissionQueue::present(DxvkPresentInfo presentInfo, DxvkSubmitStatus* status) { std::unique_lock lock(m_mutex); - DxvkSubmitEntry entry = { }; - entry.status = status; - entry.present = std::move(presentInfo); + if (m_asyncPresent) { + DxvkSubmitEntry entry = { }; + entry.status = status; + entry.present = std::move(presentInfo); - m_submitQueue.push(std::move(entry)); - m_appendCond.notify_all(); + m_submitQueue.push(std::move(entry)); + m_appendCond.notify_all(); + } else { + m_submitCond.wait(lock, [this] { + return m_submitQueue.empty(); + }); + + VkResult result = presentInfo.presenter->presentImage(presentInfo.waitSync); + status->result.store(result); + } } diff --git a/src/dxvk/dxvk_queue.h b/src/dxvk/dxvk_queue.h index 50ea26b5..bef9494e 100644 --- a/src/dxvk/dxvk_queue.h +++ b/src/dxvk/dxvk_queue.h @@ -156,6 +156,7 @@ namespace dxvk { private: DxvkDevice* m_device; + bool m_asyncPresent; std::atomic m_stopped = { false }; std::atomic m_pending = { 0u };