From ff9d6e322663308739f11f0d0acb5ffebb1fee7c Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 27 May 2021 17:56:55 +0200 Subject: [PATCH] [d3d11] Use staging buffer and copyBufferToImage for UpdateSubresource Reduces number of copies and also fixes problems with multi-plane formats. --- src/d3d11/d3d11_context.cpp | 54 ++++++++++++++++++++++--------------- src/d3d11/d3d11_context.h | 3 +++ 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 637b0a3f..04b24411 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -1218,38 +1218,33 @@ namespace dxvk { || !util::isBlockAligned(offset, extent, formatInfo->blockSize, mipExtent)) return; - const VkExtent3D regionExtent = util::computeBlockCount(extent, formatInfo->blockSize); - - const VkDeviceSize bytesPerRow = regionExtent.width * formatInfo->elementSize; - const VkDeviceSize bytesPerLayer = regionExtent.height * bytesPerRow; - const VkDeviceSize bytesTotal = regionExtent.depth * bytesPerLayer; - - DxvkDataSlice imageDataBuffer = AllocUpdateBufferSlice(bytesTotal); - - util::packImageData(imageDataBuffer.ptr(), pSrcData, - regionExtent, formatInfo->elementSize, - SrcRowPitch, SrcDepthPitch); + auto image = textureInfo->GetImage(); + auto stagingSlice = AllocStagingBuffer(util::computeImageDataSize(packedFormat, extent)); + + util::packImageData(stagingSlice.mapPtr(0), + pSrcData, SrcRowPitch, SrcDepthPitch, + image->info().type, extent, 1, + formatInfo, formatInfo->aspectMask); EmitCs([ - cDstImage = textureInfo->GetImage(), + cDstImage = std::move(image), cDstLayers = layers, cDstOffset = offset, cDstExtent = extent, - cSrcData = std::move(imageDataBuffer), - cSrcBytesPerRow = bytesPerRow, - cSrcBytesPerLayer = bytesPerLayer, + cStagingSlice = std::move(stagingSlice), cPackedFormat = packedFormat ] (DxvkContext* ctx) { if (cDstLayers.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { - ctx->updateImage(cDstImage, cDstLayers, - cDstOffset, cDstExtent, cSrcData.ptr(), - cSrcBytesPerRow, cSrcBytesPerLayer); + ctx->copyBufferToImage(cDstImage, + cDstLayers, cDstOffset, cDstExtent, + cStagingSlice.buffer(), + cStagingSlice.offset(), 0); } else { - ctx->updateDepthStencilImage(cDstImage, cDstLayers, + ctx->copyPackedBufferToDepthStencilImage(cDstImage, cDstLayers, VkOffset2D { cDstOffset.x, cDstOffset.y }, VkExtent2D { cDstExtent.width, cDstExtent.height }, - cSrcData.ptr(), cSrcBytesPerRow, cSrcBytesPerLayer, - cPackedFormat); + cStagingSlice.buffer(), + cStagingSlice.offset(), cPackedFormat); } }); @@ -4310,6 +4305,23 @@ namespace dxvk { } + DxvkBufferSlice D3D11DeviceContext::AllocStagingBuffer( + VkDeviceSize Size) { + DxvkBufferCreateInfo info; + info.size = Size; + info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT + | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT + | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT + | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + info.access = VK_ACCESS_TRANSFER_READ_BIT + | VK_ACCESS_SHADER_READ_BIT; + + return DxvkBufferSlice(m_device->createBuffer(info, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)); + } + + DxvkCsChunkRef D3D11DeviceContext::AllocCsChunk() { return m_parent->AllocCsChunk(m_csFlags); } diff --git a/src/d3d11/d3d11_context.h b/src/d3d11/d3d11_context.h index bb488768..6bbd625d 100644 --- a/src/d3d11/d3d11_context.h +++ b/src/d3d11/d3d11_context.h @@ -906,6 +906,9 @@ namespace dxvk { DxvkDataSlice AllocUpdateBufferSlice(size_t Size); + DxvkBufferSlice AllocStagingBuffer( + VkDeviceSize Size); + DxvkCsChunkRef AllocCsChunk(); static void InitDefaultPrimitiveTopology(