From d7db413cac0c76371846d309a39413d23c85af9b Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 10 Feb 2021 17:12:29 +0100 Subject: [PATCH] [dxvk] Introduce prepareImage This transitions any framebuffer attachment that is currently in the wrong layout back to its default layout before it is used by functions that expec it to be in the default layout. --- src/dxvk/dxvk_context.cpp | 44 +++++++++++++++++++++++++++++++++++++++ src/dxvk/dxvk_context.h | 5 +++++ 2 files changed, 49 insertions(+) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 83dfc5ce..55f27544 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -4126,6 +4126,50 @@ namespace dxvk { } + void DxvkContext::prepareImage( + DxvkBarrierSet& barriers, + const Rc& image, + const VkImageSubresourceRange& subresources) { + // Images that can't be used as attachments are always in their + // default layout, so we don't have to do anything in this case + if (!(image->info().usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT))) + return; + + // Flush clears if there are any since they may affect the image + if (!m_deferredClears.empty()) + this->spillRenderPass(false); + + // All images are in their default layout for suspended passes + if (!m_flags.test(DxvkContextFlag::GpRenderPassSuspended)) + return; + + // 3D images require special care because they only have one + // layer, but views may address individual 2D slices as layers + bool is3D = image->info().type == VK_IMAGE_TYPE_3D; + + // Transition any attachment with overlapping subresources + if (image->info().usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) { + for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { + const DxvkAttachment& attachment = m_state.om.framebuffer->getColorTarget(i); + + if (attachment.view != nullptr && attachment.view->image() == image + && (is3D || vk::checkSubresourceRangeOverlap(attachment.view->subresources(), subresources))) { + this->transitionColorAttachment(barriers, attachment, m_rtLayouts.color[i]); + m_rtLayouts.color[i] = image->info().layout; + } + } + } else { + const DxvkAttachment& attachment = m_state.om.framebuffer->getDepthTarget(); + + if (attachment.view != nullptr && attachment.view->image() == image + && (is3D || vk::checkSubresourceRangeOverlap(attachment.view->subresources(), subresources))) { + this->transitionDepthAttachment(barriers, attachment, m_rtLayouts.depth); + m_rtLayouts.depth = image->info().layout; + } + } + } + + bool DxvkContext::updateIndexBufferBinding() { if (unlikely(!m_state.vi.indexBuffer.defined())) return false; diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index e5789c8e..bbd9ce7e 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -1162,6 +1162,11 @@ namespace dxvk { const Rc& newFb, const Rc& oldFb); + void prepareImage( + DxvkBarrierSet& barriers, + const Rc& image, + const VkImageSubresourceRange& subresources); + bool updateIndexBufferBinding(); void updateVertexBufferBindings();