mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-28 02:19:26 +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
653532376c
commit
12707dafff
@ -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