diff options
author | Joshua Ashton <joshua@froggi.es> | 2021-03-11 07:40:50 +0300 |
---|---|---|
committer | Joshua Ashton <joshua@froggi.es> | 2021-03-11 07:40:50 +0300 |
commit | 604d86161ceb7c35fc56adc09ee41af775398d61 (patch) | |
tree | 273a99c959eccad21f22c82b40ef429f66e9d86a | |
parent | 68e6676d68bca6a6bdd851cb4f573dae01e5e256 (diff) |
[dxvk] Use image memory barriers for readbackreadback-barrier-work
Targets only the specific subresource of the bound color attachments.
From the Vulkan spec:
Each of the synchronization scopes and access scopes of a vkCmdPipelineBarrier2KHR or vkCmdPipelineBarrier command inside a render pass instance must be a subset of the scopes of one of the self-dependencies for the current subpass.
-rw-r--r-- | src/d3d9/d3d9_device.cpp | 24 | ||||
-rw-r--r-- | src/dxvk/dxvk_context.cpp | 23 | ||||
-rw-r--r-- | src/dxvk/dxvk_context.h | 6 |
3 files changed, 45 insertions, 8 deletions
diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index c04a16a8..7bdc49c6 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -5738,9 +5738,27 @@ namespace dxvk { void D3D9DeviceEx::PrepareDraw(D3DPRIMITIVETYPE PrimitiveType) { if (unlikely(m_activeHazardsRT != 0)) { - EmitCs([](DxvkContext* ctx) { - ctx->emitRenderTargetReadbackBarrier(); - }); + for (uint32_t rt = m_activeHazardsRT; rt; rt &= rt - 1) { + // Guaranteed to not be nullptr... + auto surface = m_state.renderTargets[bit::tzcnt(rt)]; + + const Rc<DxvkImage>& image = + surface->GetCommonTexture()->GetImage(); + + VkImageSubresourceRange subresources = { + VK_IMAGE_ASPECT_COLOR_BIT, + surface->GetMipLevel(), 1, + surface->GetFace(), 1 + }; + + EmitCs([ + cImage = image, + cSubresources = subresources + ](DxvkContext* ctx) { + ctx->emitRenderTargetReadbackBarrier( + cImage, cSubresources); + }); + } if (m_d3d9Options.generalHazards) MarkRenderHazards(); diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index b14c9877..40196b5e 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -1427,13 +1427,28 @@ namespace dxvk { } - void DxvkContext::emitRenderTargetReadbackBarrier() { + void DxvkContext::emitRenderTargetReadbackBarrier( + const Rc<DxvkImage>& image, + const VkImageSubresourceRange& subresources) { if (m_flags.test(DxvkContextFlag::GpRenderPassBound)) { - emitMemoryBarrier(VK_DEPENDENCY_BY_REGION_BIT, + VkImageMemoryBarrier barrier; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.pNext = nullptr; + barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + barrier.oldLayout = image->info().layout; + barrier.newLayout = image->info().layout; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = image->m_image.image; + barrier.subresourceRange = subresources; + + m_cmd->cmdPipelineBarrier( + DxvkCmdBuffer::ExecBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_ACCESS_SHADER_READ_BIT); + VK_DEPENDENCY_BY_REGION_BIT, + 0, nullptr, 0, nullptr, 1, &barrier); } } diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 4b5231f3..7362ac93 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -615,8 +615,12 @@ namespace dxvk { * * Use between draw calls if the fragment shader * reads one of the currently bound render targets. + * \param [in] image Image + * \param [in] subresources Image subresources */ - void emitRenderTargetReadbackBarrier(); + void emitRenderTargetReadbackBarrier( + const Rc<DxvkImage>& image, + const VkImageSubresourceRange& subresources); /** * \brief Generates mip maps |