From 15aabcb87863f7aed1b1a36b4646c2c72c2ebea1 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Mon, 18 Jun 2018 22:30:00 +0200 Subject: [PATCH] [dxvk] Optimize barriers around vkCmdCopyImage We don't need to force layout transitions and emit double pipeline barriers in case the GENERAL layout is being used for both images. This is somewhat common for images used by compute shaders, and this optimization ensures that only required barriers are emitted. --- src/dxvk/dxvk_context.cpp | 70 ++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 07b6da9c3..11ba23136 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -707,27 +707,39 @@ namespace dxvk { srcSubresource.baseArrayLayer, srcSubresource.layerCount }; - m_barriers.recordCommands(m_cmd); - - m_barriers.accessImage( - dstImage, dstSubresourceRange, - dstImage->mipLevelExtent(dstSubresource.mipLevel) == extent - ? VK_IMAGE_LAYOUT_UNDEFINED - : dstImage->info().layout, - dstImage->info().stages, - dstImage->info().access, - dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_TRANSFER_WRITE_BIT); + if (m_barriers.isImageDirty(dstImage, dstSubresourceRange, DxvkAccess::Write) + || m_barriers.isImageDirty(srcImage, srcSubresourceRange, DxvkAccess::Write)) + m_barriers.recordCommands(m_cmd); - m_barriers.accessImage( - srcImage, srcSubresourceRange, - srcImage->info().layout, - srcImage->info().stages, - srcImage->info().access, - srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL), - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_TRANSFER_READ_BIT); + VkImageLayout dstImageLayout = dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + VkImageLayout srcImageLayout = srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + + if (dstImageLayout != dstImage->info().layout) { + VkImageLayout dstInitImageLayout = dstImage->info().layout; + + if (dstImage->mipLevelExtent(dstSubresource.mipLevel) == extent) + dstInitImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + m_barriers.accessImage( + dstImage, dstSubresourceRange, + dstInitImageLayout, + dstImage->info().stages, + dstImage->info().access, + dstImageLayout, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT); + } + + if (srcImageLayout != srcImage->info().layout) { + m_barriers.accessImage( + srcImage, srcSubresourceRange, + srcImage->info().layout, + srcImage->info().stages, + srcImage->info().access, + srcImageLayout, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_READ_BIT); + } m_barriers.recordCommands(m_cmd); @@ -740,8 +752,8 @@ namespace dxvk { imageRegion.extent = extent; m_cmd->cmdCopyImage( - srcImage->handle(), srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL), - dstImage->handle(), dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + srcImage->handle(), srcImageLayout, + dstImage->handle(), dstImageLayout, 1, &imageRegion); } else { const VkDeviceSize transferBufferSize = std::max( @@ -771,8 +783,7 @@ namespace dxvk { bufferImageCopy.imageExtent = extent; m_cmd->cmdCopyImageToBuffer( - srcImage->handle(), - srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL), + srcImage->handle(), srcImageLayout, tmpSlice.handle(), 1, &bufferImageCopy); m_barriers.accessBuffer(tmpSlice, @@ -786,10 +797,9 @@ namespace dxvk { bufferImageCopy.imageSubresource = dstSubresource; bufferImageCopy.imageOffset = dstOffset; - m_cmd->cmdCopyBufferToImage(tmpSlice.handle(), - dstImage->handle(), - dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), - 1, &bufferImageCopy); + m_cmd->cmdCopyBufferToImage( + tmpSlice.handle(), dstImage->handle(), + dstImageLayout, 1, &bufferImageCopy); m_barriers.accessBuffer(tmpSlice, VK_PIPELINE_STAGE_TRANSFER_BIT, @@ -802,7 +812,7 @@ namespace dxvk { m_barriers.accessImage( dstImage, dstSubresourceRange, - dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + dstImageLayout, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, dstImage->info().layout, @@ -811,7 +821,7 @@ namespace dxvk { m_barriers.accessImage( srcImage, srcSubresourceRange, - srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL), + srcImageLayout, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_READ_BIT, srcImage->info().layout,