mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-23 18:19:41 +01:00
[dxvk] Fix image to image copies between overlapping subresources
This was broken for render targets because we would attempt to perform multiple layout transitions on the same subresources at once.
This commit is contained in:
parent
2ad721b46b
commit
c49a151d3c
@ -584,7 +584,8 @@ namespace dxvk {
|
||||
if (m_device->perfHints().preferFbDepthStencilCopy) {
|
||||
useFb |= (dstSubresource.aspectMask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
|
||||
&& (dstImage->info().usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
|
||||
&& (srcImage->info().usage & VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||
&& (srcImage->info().usage & VK_IMAGE_USAGE_SAMPLED_BIT)
|
||||
&& (srcImage != dstImage);
|
||||
}
|
||||
|
||||
if (!useFb) {
|
||||
@ -4199,17 +4200,38 @@ namespace dxvk {
|
||||
|
||||
auto dstFormatInfo = dstImage->formatInfo();
|
||||
|
||||
// If we copy between disjoint regions of the same image subresources,
|
||||
// make sure that we only do one single transition to GENERAL.
|
||||
bool hasOvelap = dstImage == srcImage && vk::checkSubresourceRangeOverlap(dstSubresourceRange, srcSubresourceRange);
|
||||
|
||||
VkImageSubresourceRange overlapSubresourceRange = { };
|
||||
overlapSubresourceRange.aspectMask = srcSubresource.aspectMask | dstSubresource.aspectMask;
|
||||
overlapSubresourceRange.baseArrayLayer = std::min(srcSubresource.baseArrayLayer, dstSubresource.baseArrayLayer);
|
||||
overlapSubresourceRange.baseMipLevel = srcSubresource.mipLevel;
|
||||
overlapSubresourceRange.layerCount = std::max(srcSubresource.baseArrayLayer, dstSubresource.baseArrayLayer)
|
||||
+ dstSubresource.layerCount - overlapSubresourceRange.baseArrayLayer;
|
||||
overlapSubresourceRange.levelCount = 1u;
|
||||
|
||||
flushPendingAccesses(*dstImage, dstSubresource, dstOffset, extent, DxvkAccess::Write);
|
||||
flushPendingAccesses(*srcImage, srcSubresource, srcOffset, extent, DxvkAccess::Read);
|
||||
|
||||
VkImageLayout dstImageLayout = dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
VkImageLayout srcImageLayout = srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
VkImageLayout dstImageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
VkImageLayout srcImageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
|
||||
if (hasOvelap) {
|
||||
addImageLayoutTransition(*dstImage, overlapSubresourceRange, dstImageLayout,
|
||||
VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_READ_BIT | VK_ACCESS_2_TRANSFER_WRITE_BIT, false);
|
||||
} else {
|
||||
dstImageLayout = dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
srcImageLayout = srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
|
||||
addImageLayoutTransition(*dstImage, dstSubresourceRange, dstImageLayout,
|
||||
VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT,
|
||||
dstImage->isFullSubresource(dstSubresource, extent));
|
||||
addImageLayoutTransition(*srcImage, srcSubresourceRange, srcImageLayout,
|
||||
VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_READ_BIT, false);
|
||||
}
|
||||
|
||||
addImageLayoutTransition(*dstImage, dstSubresourceRange, dstImageLayout,
|
||||
VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT,
|
||||
dstImage->isFullSubresource(dstSubresource, extent));
|
||||
addImageLayoutTransition(*srcImage, srcSubresourceRange, srcImageLayout,
|
||||
VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_READ_BIT, false);
|
||||
flushImageLayoutTransitions(DxvkCmdBuffer::ExecBuffer);
|
||||
|
||||
for (auto aspects = dstSubresource.aspectMask; aspects; ) {
|
||||
@ -4245,11 +4267,15 @@ namespace dxvk {
|
||||
m_cmd->cmdCopyImage(DxvkCmdBuffer::ExecBuffer, ©Info);
|
||||
}
|
||||
|
||||
accessImageRegion(DxvkCmdBuffer::ExecBuffer, *dstImage, dstSubresource, dstOffset, extent, dstImageLayout,
|
||||
VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, DxvkAccessOp::None);
|
||||
|
||||
accessImageRegion(DxvkCmdBuffer::ExecBuffer, *srcImage, srcSubresource, srcOffset, extent, srcImageLayout,
|
||||
VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_READ_BIT, DxvkAccessOp::None);
|
||||
if (hasOvelap) {
|
||||
accessImage(DxvkCmdBuffer::ExecBuffer, *dstImage, overlapSubresourceRange, dstImageLayout,
|
||||
VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT | VK_ACCESS_2_TRANSFER_READ_BIT, DxvkAccessOp::None);
|
||||
} else {
|
||||
accessImageRegion(DxvkCmdBuffer::ExecBuffer, *dstImage, dstSubresource, dstOffset, extent, dstImageLayout,
|
||||
VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, DxvkAccessOp::None);
|
||||
accessImageRegion(DxvkCmdBuffer::ExecBuffer, *srcImage, srcSubresource, srcOffset, extent, srcImageLayout,
|
||||
VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_READ_BIT, DxvkAccessOp::None);
|
||||
}
|
||||
|
||||
m_cmd->track(dstImage, DxvkAccess::Write);
|
||||
m_cmd->track(srcImage, DxvkAccess::Read);
|
||||
|
Loading…
x
Reference in New Issue
Block a user