From c7c90830c4dd378286fcb9623649ad58d3a9b762 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Fri, 28 Jun 2019 19:49:19 +0200 Subject: [PATCH] [dxvk] Implement image uploads on SDMA --- src/dxvk/dxvk_context.cpp | 65 +++++++++++++++++++++++++++++++++++++++ src/dxvk/dxvk_context.h | 17 ++++++++++ 2 files changed, 82 insertions(+) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 07f38208..98a5b385 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -2085,6 +2085,71 @@ namespace dxvk { } + void DxvkContext::uploadImage( + const Rc& image, + const VkImageSubresourceLayers& subresources, + const void* data, + VkDeviceSize pitchPerRow, + VkDeviceSize pitchPerLayer) { + const DxvkFormatInfo* formatInfo = image->formatInfo(); + + VkOffset3D imageOffset = { 0, 0, 0 }; + VkExtent3D imageExtent = image->mipLevelExtent(subresources.mipLevel); + + // Allocate staging buffer slice and copy data to it + VkExtent3D elementCount = util::computeBlockCount( + imageExtent, formatInfo->blockSize); + elementCount.depth *= subresources.layerCount; + + auto stagingSlice = m_staging.alloc(CACHE_LINE_SIZE, + formatInfo->elementSize * util::flattenImageExtent(elementCount)); + auto stagingHandle = stagingSlice.getSliceHandle(); + + util::packImageData(stagingHandle.mapPtr, data, + elementCount, formatInfo->elementSize, + pitchPerRow, pitchPerLayer); + + // Discard previous subresource contents + m_sdmaAcquires.accessImage(image, + vk::makeSubresourceRange(subresources), + VK_IMAGE_LAYOUT_UNDEFINED, 0, 0, + image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT); + + m_sdmaAcquires.recordCommands(m_cmd); + + // Perform copy on the transfer queue + VkBufferImageCopy region; + region.bufferOffset = stagingHandle.offset; + region.bufferRowLength = 0; + region.bufferImageHeight = 0; + region.imageSubresource = subresources; + region.imageOffset = imageOffset; + region.imageExtent = imageExtent; + + m_cmd->cmdCopyBufferToImage(DxvkCmdBuffer::SdmaBuffer, + stagingHandle.handle, image->handle(), + image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + 1, ®ion); + + // Transfer ownership to graphics queue + m_sdmaBarriers.releaseImage(m_initBarriers, + image, vk::makeSubresourceRange(subresources), + m_device->queues().transfer.queueFamily, + image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL), + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + m_device->queues().graphics.queueFamily, + image->info().layout, + image->info().stages, + image->info().access); + + m_cmd->trackResource(image); + m_cmd->trackResource(stagingSlice.buffer()); + } + + void DxvkContext::setViewports( uint32_t viewportCount, const VkViewport* viewports, diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 013630cf..495dfde7 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -783,6 +783,23 @@ namespace dxvk { const Rc& buffer, const void* data); + /** + * \brief Uses transfer queue to initialize image + * + * Only safe to use if the image is not in use by the GPU. + * \param [in] image The image to initialize + * \param [in] subresources Subresources to initialize + * \param [in] data Source data + * \param [in] pitchPerRow Row pitch of the source data + * \param [in] pitchPerLayer Layer pitch of the source data + */ + void uploadImage( + const Rc& image, + const VkImageSubresourceLayers& subresources, + const void* data, + VkDeviceSize pitchPerRow, + VkDeviceSize pitchPerLayer); + /** * \brief Sets viewports *