From e137f049eee9ef72b356b12e3eccd4957edd7c11 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Mon, 7 Oct 2024 11:12:56 +0200 Subject: [PATCH] [dxvk] Make buffer<->image copy format checks more robust There are situations where the source format may not match the image format but the copy is valid nonetheless. --- src/dxvk/dxvk_context.cpp | 24 ++++++++++++++++++------ src/dxvk/dxvk_context.h | 4 ++++ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index dc5933c96..6eba8b9e7 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -502,8 +502,7 @@ namespace dxvk { VkDeviceSize rowAlignment, VkDeviceSize sliceAlignment, VkFormat srcFormat) { - bool useFb = (srcFormat && srcFormat != dstImage->info().format) || - (dstImage->formatInfo()->aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)); + bool useFb = !formatsAreCopyCompatible(dstImage->info().format, srcFormat); if (useFb) { copyBufferToImageFb(dstImage, dstSubresource, dstOffset, dstExtent, @@ -630,8 +629,7 @@ namespace dxvk { VkImageSubresourceLayers srcSubresource, VkOffset3D srcOffset, VkExtent3D srcExtent) { - bool useFb = (dstFormat && dstFormat != srcImage->info().format) || - (srcImage->formatInfo()->aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)); + bool useFb = !formatsAreCopyCompatible(srcImage->info().format, dstFormat); if (useFb) { copyImageToBufferFb(dstBuffer, dstOffset, rowAlignment, sliceAlignment, @@ -2148,8 +2146,7 @@ namespace dxvk { // Always use framebuffer path for depth-stencil images since we know // they are writeable and can't use Vulkan transfer queues. Stencil // data is interleaved and needs to be decoded manually anyway. - bool useFb = (format && format != image->info().format) || - (image->formatInfo()->aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)); + bool useFb = !formatsAreCopyCompatible(image->info().format, format); if (useFb) uploadImageFb(image, source, sourceOffset, format); @@ -6978,6 +6975,21 @@ namespace dxvk { } + bool DxvkContext::formatsAreCopyCompatible( + VkFormat imageFormat, + VkFormat bufferFormat) { + if (!bufferFormat) + bufferFormat = imageFormat; + + // Depth-stencil data is packed differently in client APIs than what + // we can do in Vulkan, and these formats cannot be reinterpreted. + auto imageFormatInfo = lookupFormatInfo(imageFormat); + auto bufferFormatInfo = lookupFormatInfo(bufferFormat); + + return !((imageFormatInfo->aspectMask | bufferFormatInfo->aspectMask) & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)); + } + + VkFormat DxvkContext::sanitizeTexelBufferFormat( VkFormat srcFormat) { switch (srcFormat) { diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 6fc69b4dc..4d1b72d01 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -1778,6 +1778,10 @@ namespace dxvk { void splitCommands(); + static bool formatsAreCopyCompatible( + VkFormat imageFormat, + VkFormat bufferFormat); + static VkFormat sanitizeTexelBufferFormat( VkFormat srcFormat);