From ed57019e13927fa72d5283353df2e9c28b232105 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 19 May 2021 18:21:30 +0200 Subject: [PATCH] [dxvk] Support multi-plane formats in copyImage --- src/dxvk/dxvk_context.cpp | 42 ++++++++++++++++++++++++++++----------- src/vulkan/vulkan_util.h | 11 +++++++--- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index fbf5b480..526cc210 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -3051,7 +3051,9 @@ namespace dxvk { VkExtent3D extent) { auto dstSubresourceRange = vk::makeSubresourceRange(dstSubresource); auto srcSubresourceRange = vk::makeSubresourceRange(srcSubresource); - + + auto dstFormatInfo = dstImage->formatInfo(); + if (m_execBarriers.isImageDirty(dstImage, dstSubresourceRange, DxvkAccess::Write) || m_execBarriers.isImageDirty(srcImage, srcSubresourceRange, DxvkAccess::Write)) m_execBarriers.recordCommands(m_cmd); @@ -3086,17 +3088,33 @@ namespace dxvk { m_execAcquires.recordCommands(m_cmd); - VkImageCopy imageRegion; - imageRegion.srcSubresource = srcSubresource; - imageRegion.srcOffset = srcOffset; - imageRegion.dstSubresource = dstSubresource; - imageRegion.dstOffset = dstOffset; - imageRegion.extent = extent; - - m_cmd->cmdCopyImage(DxvkCmdBuffer::ExecBuffer, - srcImage->handle(), srcImageLayout, - dstImage->handle(), dstImageLayout, - 1, &imageRegion); + for (auto aspects = dstSubresource.aspectMask; aspects; ) { + auto aspect = vk::getNextAspect(aspects); + + VkImageCopy imageRegion; + imageRegion.srcSubresource = srcSubresource; + imageRegion.srcSubresource.aspectMask = aspect; + imageRegion.srcOffset = srcOffset; + imageRegion.dstSubresource = dstSubresource; + imageRegion.dstSubresource.aspectMask = aspect; + imageRegion.dstOffset = dstOffset; + imageRegion.extent = extent; + + if (dstFormatInfo->flags.test(DxvkFormatFlag::MultiPlane)) { + auto plane = &dstFormatInfo->planes[vk::getPlaneIndex(aspect)]; + imageRegion.srcOffset.x /= plane->blockSize.width; + imageRegion.srcOffset.y /= plane->blockSize.height; + imageRegion.dstOffset.x /= plane->blockSize.width; + imageRegion.dstOffset.y /= plane->blockSize.height; + imageRegion.extent.width /= plane->blockSize.width; + imageRegion.extent.height /= plane->blockSize.height; + } + + m_cmd->cmdCopyImage(DxvkCmdBuffer::ExecBuffer, + srcImage->handle(), srcImageLayout, + dstImage->handle(), dstImageLayout, + 1, &imageRegion); + } m_execBarriers.accessImage( dstImage, dstSubresourceRange, diff --git a/src/vulkan/vulkan_util.h b/src/vulkan/vulkan_util.h index 1d517b14..e0715cf5 100644 --- a/src/vulkan/vulkan_util.h +++ b/src/vulkan/vulkan_util.h @@ -115,9 +115,14 @@ namespace dxvk::vk { } inline VkImageAspectFlags getNextAspect(VkImageAspectFlags& mask) { - VkImageAspectFlags result = mask & -mask; - mask &= ~result; - return result; + if (likely(mask & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))) { + // Depth-stencil isn't considered multi-planar + return std::exchange(mask, VkImageAspectFlags(0)); + } else { + VkImageAspectFlags result = mask & -mask; + mask &= ~result; + return result; + } } }