From 5c89a688790d7c27b9c1d251b98a2dd19b7f3886 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Mon, 10 Sep 2018 18:22:09 +0200 Subject: [PATCH] [dxvk] Implement render target state tracking for async compilation This ensures that we always render to targets which are only used once. --- src/dxvk/dxvk_context.cpp | 18 +++++++++++++++++- src/dxvk/dxvk_context.h | 2 ++ src/dxvk/dxvk_graphics.cpp | 9 +++++---- src/dxvk/dxvk_graphics.h | 4 +++- src/dxvk/dxvk_image.h | 20 ++++++++++++-------- 5 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 1c94c156..9461dae8 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -1976,7 +1976,8 @@ namespace dxvk { m_gpActivePipeline = m_state.gp.pipeline != nullptr && m_state.om.framebuffer != nullptr ? m_state.gp.pipeline->getPipelineHandle(m_state.gp.state, - m_state.om.framebuffer->getRenderPass(), m_cmd->statCounters()) + m_state.om.framebuffer->getRenderPass(), m_cmd->statCounters(), + this->checkAsyncCompilationCompat()) : VK_NULL_HANDLE; if (m_gpActivePipeline != VK_NULL_HANDLE) { @@ -2253,6 +2254,9 @@ namespace dxvk { ? util::invertComponentMapping(attachment->info().swizzle) : VkComponentMapping(); } + + for (uint32_t i = 0; i < fb->numAttachments(); i++) + fb->getAttachment(i).view->setRtBindingFrameId(m_device->getCurrentFrameId()); m_flags.set(DxvkContextFlag::GpDirtyPipelineState); } @@ -2521,5 +2525,17 @@ namespace dxvk { } } } + + + bool DxvkContext::checkAsyncCompilationCompat() { + bool fbCompat = m_device->config().useAsyncPipeCompiler; + + for (uint32_t i = 0; fbCompat && i < m_state.om.framebuffer->numAttachments(); i++) { + const auto& attachment = m_state.om.framebuffer->getAttachment(i); + fbCompat &= attachment.view->getRtBindingAsyncCompilationCompat(); + } + + return fbCompat; + } } \ No newline at end of file diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 3ee6964e..d98e0dad 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -728,6 +728,8 @@ namespace dxvk { void commitComputeInitBarriers(); void commitComputePostBarriers(); + + bool checkAsyncCompilationCompat(); Rc getTransferBuffer(VkDeviceSize size); diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 0e02b8bb..69df1747 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -102,9 +102,10 @@ namespace dxvk { VkPipeline DxvkGraphicsPipeline::getPipelineHandle( const DxvkGraphicsPipelineStateInfo& state, const DxvkRenderPass& renderPass, - DxvkStatCounters& stats) { + DxvkStatCounters& stats, + bool async) { VkRenderPass renderPassHandle = renderPass.getDefaultHandle(); - + { std::lock_guard lock(m_mutex); DxvkGraphicsPipelineInstance* pipeline = @@ -124,7 +125,7 @@ namespace dxvk { VkPipeline newPipelineBase = m_basePipeline.load(); VkPipeline newPipelineHandle = VK_NULL_HANDLE; - if (m_compiler == nullptr) { + if (!async) { newPipelineHandle = this->compilePipeline( state, renderPassHandle, newPipelineBase); } @@ -154,7 +155,7 @@ namespace dxvk { m_basePipeline.compare_exchange_strong(newPipelineBase, newPipelineHandle); // Compile pipeline asynchronously if requested - if (m_compiler != nullptr) + if (async) m_compiler->queueCompilation(this, newPipeline); return newPipelineHandle; diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h index 6c075225..0032bd9e 100644 --- a/src/dxvk/dxvk_graphics.h +++ b/src/dxvk/dxvk_graphics.h @@ -195,12 +195,14 @@ namespace dxvk { * \param [in] state Pipeline state vector * \param [in] renderPass The render pass * \param [in,out] stats Stat counter + * \param [in] async Compile asynchronously * \returns Pipeline handle */ VkPipeline getPipelineHandle( const DxvkGraphicsPipelineStateInfo& state, const DxvkRenderPass& renderPass, - DxvkStatCounters& stats); + DxvkStatCounters& stats, + bool async); /** * \brief Compiles optimized pipeline diff --git a/src/dxvk/dxvk_image.h b/src/dxvk/dxvk_image.h index 18c8ae7f..b4291937 100644 --- a/src/dxvk/dxvk_image.h +++ b/src/dxvk/dxvk_image.h @@ -386,9 +386,13 @@ namespace dxvk { * \param [in] frameId Frame number */ void setRtBindingFrameId(uint32_t frameId) { - if (m_rtBindingCurrFrame != frameId) { - m_rtBindingPrevFrame = m_rtBindingCurrFrame; - m_rtBindingCurrFrame = frameId; + if (frameId != m_rtBindingFrameId) { + if (frameId == m_rtBindingFrameId + 1) + m_rtBindingFrameCount += 1; + else + m_rtBindingFrameCount = 0; + + m_rtBindingFrameId = frameId; } } @@ -396,12 +400,12 @@ namespace dxvk { * \brief Checks for async pipeline compatibility * * Asynchronous pipeline compilation may be enabled if the - * render target has been used during the previous frame. + * 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 getRtBindingAsyncShadersCompatibility(uint32_t frameId) const { - return m_rtBindingPrevFrame == frameId - 1; + bool getRtBindingAsyncCompilationCompat() const { + return m_rtBindingFrameCount >= 5; } private: @@ -412,8 +416,8 @@ namespace dxvk { DxvkImageViewCreateInfo m_info; VkImageView m_views[ViewCount]; - uint32_t m_rtBindingCurrFrame = 0; - uint32_t m_rtBindingPrevFrame = 0; + uint32_t m_rtBindingFrameId = 0; + uint32_t m_rtBindingFrameCount = 0; void createView(VkImageViewType type, uint32_t numLayers);