From 0434b2316766c0580fff1c35d7fa43113ce3294d Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Fri, 24 Jan 2025 22:28:10 +0100 Subject: [PATCH] [dxvk] Fix initializing buffers with non-dword sizes Fixes #4641. This should be very rare in general though. --- src/dxvk/dxvk_context.cpp | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index b85939807ba..91a23710fea 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -1038,9 +1038,40 @@ namespace dxvk { const Rc& buffer) { auto slice = buffer->getSliceHandle(); - m_cmd->cmdFillBuffer(DxvkCmdBuffer::InitBuffer, - slice.handle, slice.offset, - dxvk::align(slice.length, 4), 0); + // Buffer size may be misaligned, in which case we have + // to use a plain buffer copy to fill the last few bytes. + constexpr VkDeviceSize MinCopyAndFillSize = 1u << 20; + + VkDeviceSize copySize = slice.length & 3u; + VkDeviceSize fillSize = slice.length - copySize; + + // If the buffer is small, just dispatch one single copy + if (copySize && slice.length < MinCopyAndFillSize) { + copySize = slice.length; + fillSize = 0u; + } + + if (fillSize) { + m_cmd->cmdFillBuffer(DxvkCmdBuffer::InitBuffer, + slice.handle, slice.offset, fillSize, 0u); + } + + if (copySize) { + auto zero = createZeroBuffer(copySize)->getSliceHandle(); + + VkBufferCopy2 copyRegion = { VK_STRUCTURE_TYPE_BUFFER_COPY_2 }; + copyRegion.srcOffset = zero.offset; + copyRegion.dstOffset = slice.offset + fillSize; + copyRegion.size = copySize; + + VkCopyBufferInfo2 copyInfo = { VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2 }; + copyInfo.srcBuffer = zero.handle; + copyInfo.dstBuffer = slice.handle; + copyInfo.regionCount = 1; + copyInfo.pRegions = ©Region; + + m_cmd->cmdCopyBuffer(DxvkCmdBuffer::InitBuffer, ©Info); + } accessMemory(DxvkCmdBuffer::InitBuffer, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT,