From 2b401725dc1d2e3e3c03aca35fce4671dd2f2b52 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sun, 14 Feb 2021 03:32:11 +0100 Subject: [PATCH] [dxvk] Do not transition non-shared images at the end of the command buffer Currently, if the frontend flushes the command list, we always transition render targets to their default layout. This may lead to some arbitrary GPU performance issues if the transitions are not free. Instead, keep all images that are only used internally in their attachment layout across command list boundaries, until they are unbound. --- src/dxvk/dxvk_context.cpp | 22 +++++++++++++++------- src/dxvk/dxvk_context.h | 3 ++- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index fc8127dc..a08e2353 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -65,8 +65,12 @@ namespace dxvk { Rc DxvkContext::endRecording() { - this->spillRenderPass(false); - + this->spillRenderPass(true); + + // Ensure that any shared images are in their + // default layout for the next submission + this->transitionRenderTargetLayouts(m_execBarriers, true); + m_sdmaBarriers.recordCommands(m_cmd); m_initBarriers.recordCommands(m_cmd); m_execBarriers.recordCommands(m_cmd); @@ -3456,7 +3460,7 @@ namespace dxvk { if (suspend) m_flags.set(DxvkContextFlag::GpRenderPassSuspended); else - this->transitionRenderTargetLayouts(m_gfxBarriers); + this->transitionRenderTargetLayouts(m_gfxBarriers, false); m_gfxBarriers.recordCommands(m_cmd); @@ -3467,7 +3471,7 @@ namespace dxvk { // We may end a previously suspended render pass if (m_flags.test(DxvkContextFlag::GpRenderPassSuspended)) { m_flags.clr(DxvkContextFlag::GpRenderPassSuspended); - this->transitionRenderTargetLayouts(m_gfxBarriers); + this->transitionRenderTargetLayouts(m_gfxBarriers, false); m_gfxBarriers.recordCommands(m_cmd); } @@ -4044,11 +4048,15 @@ namespace dxvk { void DxvkContext::transitionRenderTargetLayouts( - DxvkBarrierSet& barriers) { + DxvkBarrierSet& barriers, + bool sharedOnly) { + if (m_state.om.framebuffer == nullptr) + return; + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { const DxvkAttachment& color = m_state.om.framebuffer->getColorTarget(i); - if (color.view != nullptr) { + if (color.view != nullptr && (!sharedOnly || color.view->imageInfo().shared)) { this->transitionColorAttachment(barriers, color, m_rtLayouts.color[i]); m_rtLayouts.color[i] = color.view->imageInfo().layout; } @@ -4056,7 +4064,7 @@ namespace dxvk { const DxvkAttachment& depth = m_state.om.framebuffer->getDepthTarget(); - if (depth.view != nullptr) { + if (depth.view != nullptr && (!sharedOnly || depth.view->imageInfo().shared)) { this->transitionDepthAttachment(barriers, depth, m_rtLayouts.depth); m_rtLayouts.depth = depth.view->imageInfo().layout; } diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 9699cc1e..91458359 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -1146,7 +1146,8 @@ namespace dxvk { void applyRenderTargetStoreLayouts(); void transitionRenderTargetLayouts( - DxvkBarrierSet& barriers); + DxvkBarrierSet& barriers, + bool sharedOnly); void transitionColorAttachment( DxvkBarrierSet& barriers,