diff --git a/patches/dxvk/dxvk-async.patch b/patches/dxvk/dxvk-async.patch deleted file mode 100644 index 315726097d..0000000000 --- a/patches/dxvk/dxvk-async.patch +++ /dev/null @@ -1,290 +0,0 @@ -diff --git a/meson.build b/meson.build -index f044c8f4..36b22d39 100644 ---- a/meson.build -+++ b/meson.build -@@ -1,4 +1,4 @@ --project('dxvk', ['c', 'cpp'], version : 'v2.0', meson_version : '>= 0.49', default_options : [ 'cpp_std=c++17', 'warning_level=2' ]) -+project('dxvk', ['c', 'cpp'], version : 'v2.0-async', meson_version : '>= 0.49', default_options : [ 'cpp_std=c++17', 'warning_level=2' ]) - - cpu_family = target_machine.cpu_family() - -@@ -122,7 +122,7 @@ glsl_generator = generator(glsl_compiler, - ) - - dxvk_version = vcs_tag( -- command: ['git', 'describe', '--dirty=+'], -+ command: ['git', 'describe', '--dirty=-async'], - input: 'version.h.in', - output: 'version.h', - ) -diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp -index 6486d267..cc59297e 100644 ---- a/src/dxvk/dxvk_context.cpp -+++ b/src/dxvk/dxvk_context.cpp -@@ -4540,7 +4540,8 @@ namespace dxvk { - : DxvkContextFlag::GpDirtyRasterizerState); - - // Retrieve and bind actual Vulkan pipeline handle -- auto pipelineInfo = m_state.gp.pipeline->getPipelineHandle(m_state.gp.state); -+ auto pipelineInfo = m_state.gp.pipeline->getPipelineHandle( -+ m_state.gp.state, this->checkAsyncCompilationCompat()); - - if (unlikely(!pipelineInfo.first)) - return false; -@@ -4890,7 +4891,7 @@ namespace dxvk { - } - - -- void DxvkContext::updateFramebuffer() { -+ void DxvkContext::updateFramebuffer(bool isDraw) { - if (m_flags.test(DxvkContextFlag::GpDirtyFramebuffer)) { - m_flags.clr(DxvkContextFlag::GpDirtyFramebuffer); - -@@ -4914,6 +4915,11 @@ namespace dxvk { - m_state.gp.state.omSwizzle[i] = DxvkOmAttachmentSwizzle(mapping); - } - -+ if (isDraw) { -+ for (uint32_t i = 0; i < fbInfo.numAttachments(); i++) -+ fbInfo.getAttachment(i).view->setRtBindingFrameId(m_device->getCurrentFrameId()); -+ } -+ - m_flags.set(DxvkContextFlag::GpDirtyPipelineState); - } - } -@@ -5363,7 +5369,7 @@ namespace dxvk { - } - - if (m_flags.test(DxvkContextFlag::GpDirtyFramebuffer)) -- this->updateFramebuffer(); -+ this->updateFramebuffer(true); - - if (!m_flags.test(DxvkContextFlag::GpRenderPassBound)) - this->startRenderPass(); -@@ -5774,6 +5780,14 @@ namespace dxvk { - return true; - } - -+ bool DxvkContext::checkAsyncCompilationCompat() { -+ bool fbCompat = true; -+ for (uint32_t i = 0; fbCompat && i < m_state.om.framebufferInfo.numAttachments(); i++) { -+ const auto& attachment = m_state.om.framebufferInfo.getAttachment(i); -+ fbCompat &= attachment.view->getRtBindingAsyncCompilationCompat(); -+ } -+ return fbCompat; -+ } - - DxvkGraphicsPipeline* DxvkContext::lookupGraphicsPipeline( - const DxvkGraphicsPipelineShaders& shaders) { -diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h -index fe24c556..0930bd81 100644 ---- a/src/dxvk/dxvk_context.h -+++ b/src/dxvk/dxvk_context.h -@@ -1493,7 +1493,7 @@ namespace dxvk { - DxvkFramebufferInfo makeFramebufferInfo( - const DxvkRenderTargets& renderTargets); - -- void updateFramebuffer(); -+ void updateFramebuffer(bool isDraw = false); - - void applyRenderTargetLoadLayouts(); - -@@ -1576,6 +1576,8 @@ namespace dxvk { - const Rc& buffer, - VkDeviceSize copySize); - -+ bool checkAsyncCompilationCompat(); -+ - DxvkGraphicsPipeline* lookupGraphicsPipeline( - const DxvkGraphicsPipelineShaders& shaders); - -diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp -index c0ecbbb4..f4e4fd4f 100644 ---- a/src/dxvk/dxvk_graphics.cpp -+++ b/src/dxvk/dxvk_graphics.cpp -@@ -899,7 +899,8 @@ namespace dxvk { - - - std::pair DxvkGraphicsPipeline::getPipelineHandle( -- const DxvkGraphicsPipelineStateInfo& state) { -+ const DxvkGraphicsPipelineStateInfo& state, -+ bool async) { - DxvkGraphicsPipelineInstance* instance = this->findInstance(state); - - if (unlikely(!instance)) { -@@ -922,28 +923,36 @@ namespace dxvk { - if (!this->validatePipelineState(state, true)) - return std::make_pair(VK_NULL_HANDLE, DxvkGraphicsPipelineType::FastPipeline); - -+ bool useAsync = m_device->config().enableAsync && async; -+ - // Prevent other threads from adding new instances and check again -- std::unique_lock lock(m_mutex); -+ std::unique_lock lock(useAsync ? m_asyncMutex : m_mutex); - instance = this->findInstance(state); - - if (!instance) { -- // Keep pipeline object locked, at worst we're going to stall -- // a state cache worker and the current thread needs priority. -- bool canCreateBasePipeline = this->canCreateBasePipeline(state); -- instance = this->createInstance(state, canCreateBasePipeline); -- -- // Unlock here since we may dispatch the pipeline to a worker, -- // which will then acquire it to increment the use counter. -- lock.unlock(); -- -- // If necessary, compile an optimized pipeline variant -- if (!instance->fastHandle.load()) -+ if (useAsync) { -+ lock.unlock(); - m_workers->compileGraphicsPipeline(this, state, DxvkPipelinePriority::Low); -- -- // Only store pipelines in the state cache that cannot benefit -- // from pipeline libraries, or if that feature is disabled. -- if (!canCreateBasePipeline) -- this->writePipelineStateToCache(state); -+ return std::make_pair(VK_NULL_HANDLE, DxvkGraphicsPipelineType::FastPipeline); -+ } else { -+ // Keep pipeline object locked, at worst we're going to stall -+ // a state cache worker and the current thread needs priority. -+ bool canCreateBasePipeline = this->canCreateBasePipeline(state); -+ instance = this->createInstance(state, canCreateBasePipeline); -+ -+ // Unlock here since we may dispatch the pipeline to a worker, -+ // which will then acquire it to increment the use counter. -+ lock.unlock(); -+ -+ // If necessary, compile an optimized pipeline variant -+ if (!instance->fastHandle.load()) -+ m_workers->compileGraphicsPipeline(this, state, DxvkPipelinePriority::Low); -+ -+ // Only store pipelines in the state cache that cannot benefit -+ // from pipeline libraries, or if that feature is disabled. -+ if (!canCreateBasePipeline) -+ this->writePipelineStateToCache(state); -+ } - } - } - -diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h -index cfc424cd..437c73a9 100644 ---- a/src/dxvk/dxvk_graphics.h -+++ b/src/dxvk/dxvk_graphics.h -@@ -521,10 +521,12 @@ namespace dxvk { - * Retrieves a pipeline handle for the given pipeline - * state. If necessary, a new pipeline will be created. - * \param [in] state Pipeline state vector -+ * \param [in] async Compile asynchronously - * \returns Pipeline handle and handle type - */ - std::pair getPipelineHandle( -- const DxvkGraphicsPipelineStateInfo& state); -+ const DxvkGraphicsPipelineStateInfo& state, -+ bool async); - - /** - * \brief Compiles a pipeline -@@ -576,6 +578,8 @@ namespace dxvk { - - alignas(CACHE_LINE_SIZE) - dxvk::mutex m_mutex; -+ alignas(CACHE_LINE_SIZE) -+ dxvk::mutex m_asyncMutex; - sync::List m_pipelines; - uint32_t m_useCount = 0; - -diff --git a/src/dxvk/dxvk_image.h b/src/dxvk/dxvk_image.h -index 285c5e9e..989a240f 100644 ---- a/src/dxvk/dxvk_image.h -+++ b/src/dxvk/dxvk_image.h -@@ -547,6 +547,37 @@ namespace dxvk { - view->imageSubresources()); - } - -+ /** -+ * \brief Sets render target usage frame number -+ * -+ * The image view will track internally when -+ * it was last used as a render target. This -+ * info is used for async shader compilation. -+ * \param [in] frameId Frame number -+ */ -+ void setRtBindingFrameId(uint32_t frameId) { -+ if (frameId != m_rtBindingFrameId) { -+ if (frameId == m_rtBindingFrameId + 1) -+ m_rtBindingFrameCount += 1; -+ else -+ m_rtBindingFrameCount = 0; -+ -+ m_rtBindingFrameId = frameId; -+ } -+ } -+ -+ /** -+ * \brief Checks for async pipeline compatibility -+ * -+ * Asynchronous pipeline compilation may be enabled if the -+ * render target has been drawn to in the previous frames. -+ * \param [in] frameId Current frame ID -+ * \returns \c true if async compilation is supported -+ */ -+ bool getRtBindingAsyncCompilationCompat() const { -+ return m_rtBindingFrameCount >= 5; -+ } -+ - private: - - Rc m_vkd; -@@ -555,6 +586,9 @@ namespace dxvk { - DxvkImageViewCreateInfo m_info; - VkImageView m_views[ViewCount]; - -+ uint32_t m_rtBindingFrameId = 0; -+ uint32_t m_rtBindingFrameCount = 0; -+ - void createView(VkImageViewType type, uint32_t numLayers); - - }; -diff --git a/src/dxvk/dxvk_options.cpp b/src/dxvk/dxvk_options.cpp -index 00f284aa..f13429eb 100644 ---- a/src/dxvk/dxvk_options.cpp -+++ b/src/dxvk/dxvk_options.cpp -@@ -10,6 +10,14 @@ namespace dxvk { - trackPipelineLifetime = config.getOption("dxvk.trackPipelineLifetime", Tristate::Auto); - useRawSsbo = config.getOption("dxvk.useRawSsbo", Tristate::Auto); - hud = config.getOption("dxvk.hud", ""); -+ -+ if (env::getEnvVar("DXVK_ASYNC") == "1") -+ enableAsync = true; -+ else -+ enableAsync = config.getOption("dxvk.enableAsync", false); -+ -+ if (enableAsync) -+ enableGraphicsPipelineLibrary = Tristate::False; - } - - } -diff --git a/src/dxvk/dxvk_options.h b/src/dxvk/dxvk_options.h -index da5bf406..05a7823e 100644 ---- a/src/dxvk/dxvk_options.h -+++ b/src/dxvk/dxvk_options.h -@@ -2,6 +2,8 @@ - - #include "../util/config/config.h" - -+#include "dxvk_include.h" -+ - namespace dxvk { - - struct DxvkOptions { -@@ -24,6 +26,9 @@ namespace dxvk { - /// Enables pipeline lifetime tracking - Tristate trackPipelineLifetime; - -+ // Enable async pipelines -+ bool enableAsync; -+ - /// Shader-related options - Tristate useRawSsbo; - - diff --git a/patches/protonprep-valve-staging.sh b/patches/protonprep-valve-staging.sh index bf3ebc8760..a803177922 100755 --- a/patches/protonprep-valve-staging.sh +++ b/patches/protonprep-valve-staging.sh @@ -13,9 +13,6 @@ # https://github.com/doitsujin/dxvk/pull/2675 echo "DXVK: [dxgi] Leave fullscreen mode when window looses focus" patch -Np1 < ../patches/dxvk/2675.patch - - echo "DXVK: add dxvk async patch" - patch -Np1 < ../patches/dxvk/dxvk-async.patch echo "DXVK: Fix Secret World: Legends patcher crash" patch -Np1 < ../patches/dxvk/secret-world.patch