diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 55f27544..89910623 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -561,8 +561,16 @@ namespace dxvk { if (m_state.om.framebuffer->isFullSize(imageView) && this->checkFramebufferBarrier().isClear()) attachmentIndex = m_state.om.framebuffer->findAttachment(imageView); - if (attachmentIndex < 1) - this->spillRenderPass(); + // Suspend works here because we'll end up with one of these scenarios: + // 1) The render pass gets ended for good, in which case we emit barriers + // 2) The clear gets folded into render pass ops, so the layout is correct + // 3) The clear gets executed separately, in which case updateFramebuffer + // will indirectly emit barriers for the given render target. + // If there is overlap, we need to explicitly transition affected attachments. + if (attachmentIndex < 1) { + this->spillRenderPass(true); + this->prepareImage(m_execBarriers, imageView->image(), imageView->subresources()); + } } if (m_flags.test(DxvkContextFlag::GpRenderPassBound)) diff --git a/src/vulkan/vulkan_util.h b/src/vulkan/vulkan_util.h index 97108ea6..e8e31804 100644 --- a/src/vulkan/vulkan_util.h +++ b/src/vulkan/vulkan_util.h @@ -58,6 +58,15 @@ namespace dxvk::vk { return subres; } + inline bool checkSubresourceRangeOverlap( + const VkImageSubresourceRange& a, + const VkImageSubresourceRange& b) { + return a.baseMipLevel < b.baseMipLevel + b.levelCount + && a.baseMipLevel + a.levelCount > b.baseMipLevel + && a.baseArrayLayer < b.baseArrayLayer + b.layerCount + && a.baseArrayLayer + a.layerCount > b.baseArrayLayer; + } + }