From 11bbc07ea18c2f5faaf05025206e16318fb74fee Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Mon, 19 Jul 2021 16:53:00 +0200 Subject: [PATCH] [dxvk] Support destination pitch in packImageData --- src/d3d11/d3d11_context.cpp | 2 +- src/d3d11/d3d11_initializer.cpp | 2 +- src/dxvk/dxvk_util.cpp | 54 ++++++++++++++++++++++----------- src/dxvk/dxvk_util.h | 17 ++++++++--- 4 files changed, 51 insertions(+), 24 deletions(-) diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 575e6a52..5f6f58e2 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -1021,7 +1021,7 @@ namespace dxvk { auto stagingSlice = AllocStagingBuffer(util::computeImageDataSize(packedFormat, extent)); util::packImageData(stagingSlice.mapPtr(0), - pSrcData, SrcRowPitch, SrcDepthPitch, + pSrcData, SrcRowPitch, SrcDepthPitch, 0, 0, dstTexture->GetVkImageType(), extent, 1, formatInfo, formatInfo->aspectMask); diff --git a/src/d3d11/d3d11_initializer.cpp b/src/d3d11/d3d11_initializer.cpp index 0368a9b2..2bace428 100644 --- a/src/d3d11/d3d11_initializer.cpp +++ b/src/d3d11/d3d11_initializer.cpp @@ -171,7 +171,7 @@ namespace dxvk { if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) { util::packImageData(pTexture->GetMappedBuffer(id)->mapPtr(0), pInitialData[id].pSysMem, pInitialData[id].SysMemPitch, pInitialData[id].SysMemSlicePitch, - pTexture->GetVkImageType(), mipLevelExtent, 1, formatInfo, formatInfo->aspectMask); + 0, 0, pTexture->GetVkImageType(), mipLevelExtent, 1, formatInfo, formatInfo->aspectMask); } } } diff --git a/src/dxvk/dxvk_util.cpp b/src/dxvk/dxvk_util.cpp index 94a398da..4dcf6aca 100644 --- a/src/dxvk/dxvk_util.cpp +++ b/src/dxvk/dxvk_util.cpp @@ -76,8 +76,10 @@ namespace dxvk::util { void packImageData( void* dstBytes, const void* srcBytes, - VkDeviceSize rowPitch, - VkDeviceSize slicePitch, + VkDeviceSize srcRowPitch, + VkDeviceSize srcSlicePitch, + VkDeviceSize dstRowPitchIn, + VkDeviceSize dstSlicePitchIn, VkImageType imageType, VkExtent3D imageExtent, uint32_t imageLayers, @@ -85,7 +87,7 @@ namespace dxvk::util { VkImageAspectFlags aspectMask) { for (uint32_t i = 0; i < imageLayers; i++) { auto dstData = reinterpret_cast< char*>(dstBytes); - auto srcData = reinterpret_cast(srcBytes) + i * slicePitch; + auto srcData = reinterpret_cast(srcBytes); for (auto aspects = aspectMask; aspects; ) { auto aspect = vk::getNextAspect(aspects); @@ -105,36 +107,54 @@ namespace dxvk::util { VkDeviceSize bytesPerSlice = blockCount.height * bytesPerRow; VkDeviceSize bytesTotal = blockCount.depth * bytesPerSlice; - const bool directCopy = ((bytesPerRow == rowPitch ) || (blockCount.height == 1)) - && ((bytesPerSlice == slicePitch) || (blockCount.depth == 1)); + VkDeviceSize dstRowPitch = dstRowPitchIn ? dstRowPitchIn : bytesPerRow; + VkDeviceSize dstSlicePitch = dstSlicePitchIn ? dstSlicePitchIn : bytesPerSlice; + + const bool directCopy = ((bytesPerRow == srcRowPitch && bytesPerRow == dstRowPitch ) || (blockCount.height == 1)) + && ((bytesPerSlice == srcSlicePitch && bytesPerSlice == dstSlicePitch) || (blockCount.depth == 1)); if (directCopy) { std::memcpy(dstData, srcData, bytesTotal); - dstData += bytesTotal; switch (imageType) { - case VK_IMAGE_TYPE_1D: srcData += bytesPerRow; break; - case VK_IMAGE_TYPE_2D: srcData += blockCount.height * rowPitch; break; - case VK_IMAGE_TYPE_3D: srcData += blockCount.depth * slicePitch; break; + case VK_IMAGE_TYPE_1D: + srcData += srcRowPitch; + dstData += dstRowPitch; + break; + case VK_IMAGE_TYPE_2D: + srcData += blockCount.height * srcRowPitch; + dstData += blockCount.height * dstRowPitch; + break; + case VK_IMAGE_TYPE_3D: + srcData += blockCount.depth * srcSlicePitch; + dstData += blockCount.depth * dstSlicePitch; + break; default: ; } } else { for (uint32_t i = 0; i < blockCount.depth; i++) { for (uint32_t j = 0; j < blockCount.height; j++) { std::memcpy( - dstData + j * bytesPerRow, - srcData + j * rowPitch, + dstData + j * dstRowPitch, + srcData + j * srcRowPitch, bytesPerRow); } - + switch (imageType) { - case VK_IMAGE_TYPE_1D: srcData += bytesPerRow; break; - case VK_IMAGE_TYPE_2D: srcData += blockCount.height * rowPitch; break; - case VK_IMAGE_TYPE_3D: srcData += slicePitch; break; + case VK_IMAGE_TYPE_1D: + srcData += srcRowPitch; + dstData += dstRowPitch; + break; + case VK_IMAGE_TYPE_2D: + srcData += blockCount.height * srcRowPitch; + dstData += blockCount.height * dstRowPitch; + break; + case VK_IMAGE_TYPE_3D: + srcData += srcSlicePitch; + dstData += dstSlicePitch; + break; default: ; } - - dstData += bytesPerSlice; } } } diff --git a/src/dxvk/dxvk_util.h b/src/dxvk/dxvk_util.h index d6244095..4527f14e 100644 --- a/src/dxvk/dxvk_util.h +++ b/src/dxvk/dxvk_util.h @@ -40,12 +40,17 @@ namespace dxvk::util { VkDeviceSize pitchPerLayer); /** - * \brief Writes tightly packed image data to a buffer + * \brief Repacks image data to a buffer * + * Note that passing destination pitches of 0 means that the data is + * tightly packed, while a source pitch of 0 will not show this behaviour + * in order to match client API behaviour for initialization. * \param [in] dstBytes Destination buffer pointer * \param [in] srcBytes Pointer to source data - * \param [in] rowPitch Number of bytes between rows - * \param [in] slicePitch Number of bytes between layers + * \param [in] srcRowPitch Number of bytes between rows to read + * \param [in] srcSlicePitch Number of bytes between layers to read + * \param [in] dstRowPitch Number of bytes between rows to write + * \param [in] dstSlicePitch Number of bytes between layers to write * \param [in] imageType Image type (2D, 3D etc) * \param [in] imageExtent Image extent, in pixels * \param [in] imageLayers Image layer count @@ -55,8 +60,10 @@ namespace dxvk::util { void packImageData( void* dstBytes, const void* srcBytes, - VkDeviceSize rowPitch, - VkDeviceSize slicePitch, + VkDeviceSize srcRowPitch, + VkDeviceSize srcSlicePitch, + VkDeviceSize dstRowPitchIn, + VkDeviceSize dstSlicePitchIn, VkImageType imageType, VkExtent3D imageExtent, uint32_t imageLayers,