From ba698430cb76e4d0247fb073ffaccf7a46955815 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 10 Feb 2021 01:59:48 +0100 Subject: [PATCH] [dxvk] Suspend render pass when updating framebuffer Saves barriers in case some of the previously bound framebuffer arre reused in the new one. --- src/dxvk/dxvk_context.cpp | 81 ++++++++++++++++++++++++----------- src/dxvk/dxvk_context.h | 12 +++++- src/dxvk/dxvk_context_state.h | 1 + 3 files changed, 67 insertions(+), 27 deletions(-) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 77cd3bc1..5ba2d96c 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -3388,6 +3388,7 @@ namespace dxvk { this->flushClears(true); m_flags.set(DxvkContextFlag::GpRenderPassBound); + m_flags.clr(DxvkContextFlag::GpRenderPassSuspended); m_execBarriers.recordCommands(m_cmd); @@ -3413,7 +3414,7 @@ namespace dxvk { } - void DxvkContext::spillRenderPass(bool flushClears) { + void DxvkContext::spillRenderPass(bool suspend) { if (m_flags.test(DxvkContextFlag::GpRenderPassBound)) { m_flags.clr(DxvkContextFlag::GpRenderPassBound); @@ -3423,14 +3424,25 @@ namespace dxvk { m_queryManager.endQueries(m_cmd, VK_QUERY_TYPE_PIPELINE_STATISTICS); this->renderPassUnbindFramebuffer(); - this->transitionRenderTargetLayouts(m_gfxBarriers); + + if (suspend) + m_flags.set(DxvkContextFlag::GpRenderPassSuspended); + else + this->transitionRenderTargetLayouts(m_gfxBarriers); m_gfxBarriers.recordCommands(m_cmd); this->unbindGraphicsPipeline(); m_flags.clr(DxvkContextFlag::GpDirtyXfbCounters); - } else if (flushClears) { + } else if (!suspend) { + // We may end a previously suspended render pass + if (m_flags.test(DxvkContextFlag::GpRenderPassSuspended)) { + m_flags.clr(DxvkContextFlag::GpRenderPassSuspended); + this->transitionRenderTargetLayouts(m_gfxBarriers); + m_gfxBarriers.recordCommands(m_cmd); + } + // Execute deferred clears if necessary this->flushClears(false); } @@ -3958,7 +3970,7 @@ namespace dxvk { if (m_flags.test(DxvkContextFlag::GpDirtyFramebuffer)) { m_flags.clr(DxvkContextFlag::GpDirtyFramebuffer); - this->spillRenderPass(false); + this->spillRenderPass(true); auto fb = m_device->createFramebuffer(m_state.om.renderTargets); this->updateRenderTargetLayouts(fb, m_state.om.framebuffer); @@ -4009,16 +4021,7 @@ namespace dxvk { const DxvkAttachment& color = m_state.om.framebuffer->getColorTarget(i); if (color.view != nullptr) { - barriers.accessImage( - color.view->image(), - color.view->subresources(), - m_rtLayouts.color[i], - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - color.view->imageInfo().layout, - color.view->imageInfo().stages, - color.view->imageInfo().access); - + this->transitionColorAttachment(barriers, color, m_rtLayouts.color[i]); m_rtLayouts.color[i] = color.view->imageInfo().layout; } } @@ -4026,23 +4029,44 @@ namespace dxvk { const DxvkAttachment& depth = m_state.om.framebuffer->getDepthTarget(); if (depth.view != nullptr) { - barriers.accessImage( - depth.view->image(), - depth.view->subresources(), - m_rtLayouts.depth, - VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | - VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, - m_rtLayouts.depth != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL - ? VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT : 0, - depth.view->imageInfo().layout, - depth.view->imageInfo().stages, - depth.view->imageInfo().access); - + this->transitionDepthAttachment(barriers, depth, m_rtLayouts.depth); m_rtLayouts.depth = depth.view->imageInfo().layout; } } + void DxvkContext::transitionColorAttachment( + DxvkBarrierSet& barriers, + const DxvkAttachment& attachment, + VkImageLayout oldLayout) { + barriers.accessImage( + attachment.view->image(), + attachment.view->subresources(), oldLayout, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + attachment.view->imageInfo().layout, + attachment.view->imageInfo().stages, + attachment.view->imageInfo().access); + } + + + void DxvkContext::transitionDepthAttachment( + DxvkBarrierSet& barriers, + const DxvkAttachment& attachment, + VkImageLayout oldLayout) { + barriers.accessImage( + attachment.view->image(), + attachment.view->subresources(), oldLayout, + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + oldLayout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL + ? VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT : 0, + attachment.view->imageInfo().layout, + attachment.view->imageInfo().stages, + attachment.view->imageInfo().access); + } + + void DxvkContext::updateRenderTargetLayouts( const Rc& newFb, const Rc& oldFb) { @@ -4076,6 +4100,9 @@ namespace dxvk { if (found) layouts.color[j] = m_rtLayouts.color[i]; } + + if (!found && m_flags.test(DxvkContextFlag::GpRenderPassSuspended)) + this->transitionColorAttachment(m_execBarriers, oldAttachment, m_rtLayouts.color[i]); } } @@ -4090,6 +4117,8 @@ namespace dxvk { if (found) layouts.depth = m_rtLayouts.depth; + else if (m_flags.test(DxvkContextFlag::GpRenderPassSuspended)) + this->transitionDepthAttachment(m_execBarriers, oldAttachment, m_rtLayouts.depth); } } diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 7cf7d214..e5789c8e 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -1102,7 +1102,7 @@ namespace dxvk { bool useRenderPass); void startRenderPass(); - void spillRenderPass(bool flushClears = true); + void spillRenderPass(bool suspend = false); void renderPassBindFramebuffer( const Rc& framebuffer, @@ -1148,6 +1148,16 @@ namespace dxvk { void transitionRenderTargetLayouts( DxvkBarrierSet& barriers); + void transitionColorAttachment( + DxvkBarrierSet& barriers, + const DxvkAttachment& attachment, + VkImageLayout oldLayout); + + void transitionDepthAttachment( + DxvkBarrierSet& barriers, + const DxvkAttachment& attachment, + VkImageLayout oldLayout); + void updateRenderTargetLayouts( const Rc& newFb, const Rc& oldFb); diff --git a/src/dxvk/dxvk_context_state.h b/src/dxvk/dxvk_context_state.h index 48ddf0d2..5ddaa780 100644 --- a/src/dxvk/dxvk_context_state.h +++ b/src/dxvk/dxvk_context_state.h @@ -22,6 +22,7 @@ namespace dxvk { */ enum class DxvkContextFlag : uint32_t { GpRenderPassBound, ///< Render pass is currently bound + GpRenderPassSuspended, ///< Render pass is currently suspended GpXfbActive, ///< Transform feedback is enabled GpDirtyFramebuffer, ///< Framebuffer binding is out of date GpDirtyPipeline, ///< Graphics pipeline binding is out of date