1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-04-01 09:25:24 +02:00

[dxvk,d3d11] Refactor uploadBuffer to consume a staging buffer

This commit is contained in:
Philip Rebohle 2024-10-05 09:07:06 +02:00 committed by Philip Rebohle
parent c27cae2f10
commit c92ee8ee07
4 changed files with 33 additions and 20 deletions

View File

@ -9,7 +9,8 @@ namespace dxvk {
D3D11Device* pParent) D3D11Device* pParent)
: m_parent(pParent), : m_parent(pParent),
m_device(pParent->GetDXVKDevice()), m_device(pParent->GetDXVKDevice()),
m_context(m_device->createContext(DxvkContextType::Supplementary)) { m_context(m_device->createContext(DxvkContextType::Supplementary)),
m_stagingBuffer(m_device, StagingBufferSize) {
m_context->beginRecording( m_context->beginRecording(
m_device->createCommandList()); m_device->createCommandList());
} }
@ -81,20 +82,22 @@ namespace dxvk {
const D3D11_SUBRESOURCE_DATA* pInitialData) { const D3D11_SUBRESOURCE_DATA* pInitialData) {
std::lock_guard<dxvk::mutex> lock(m_mutex); std::lock_guard<dxvk::mutex> lock(m_mutex);
DxvkBufferSlice bufferSlice = pBuffer->GetBufferSlice(); Rc<DxvkBuffer> buffer = pBuffer->GetBuffer();
if (pInitialData != nullptr && pInitialData->pSysMem != nullptr) { if (pInitialData != nullptr && pInitialData->pSysMem != nullptr) {
m_transferMemory += bufferSlice.length(); auto stagingSlice = m_stagingBuffer.alloc(buffer->info().size);
std::memcpy(stagingSlice.mapPtr(0), pInitialData->pSysMem, stagingSlice.length());
m_transferMemory += buffer->info().size;
m_transferCommands += 1; m_transferCommands += 1;
m_context->uploadBuffer( m_context->uploadBuffer(buffer,
bufferSlice.buffer(), stagingSlice.buffer(),
pInitialData->pSysMem); stagingSlice.offset());
} else { } else {
m_transferCommands += 1; m_transferCommands += 1;
m_context->initBuffer( m_context->initBuffer(buffer);
bufferSlice.buffer());
} }
FlushImplicit(); FlushImplicit();
@ -284,6 +287,8 @@ namespace dxvk {
m_transferCommands = 0; m_transferCommands = 0;
m_transferMemory = 0; m_transferMemory = 0;
m_stagingBuffer.reset();
} }

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include "../dxvk/dxvk_staging.h"
#include "d3d11_buffer.h" #include "d3d11_buffer.h"
#include "d3d11_texture.h" #include "d3d11_texture.h"
@ -18,6 +20,9 @@ namespace dxvk {
class D3D11Initializer { class D3D11Initializer {
constexpr static size_t MaxTransferMemory = 32 * 1024 * 1024; constexpr static size_t MaxTransferMemory = 32 * 1024 * 1024;
constexpr static size_t MaxTransferCommands = 512; constexpr static size_t MaxTransferCommands = 512;
// Use a staging buffer with a linear allocator to service small uploads
constexpr static VkDeviceSize StagingBufferSize = 1ull << 20;
public: public:
D3D11Initializer( D3D11Initializer(
@ -45,6 +50,8 @@ namespace dxvk {
D3D11Device* m_parent; D3D11Device* m_parent;
Rc<DxvkDevice> m_device; Rc<DxvkDevice> m_device;
Rc<DxvkContext> m_context; Rc<DxvkContext> m_context;
DxvkStagingBuffer m_stagingBuffer;
size_t m_transferCommands = 0; size_t m_transferCommands = 0;
size_t m_transferMemory = 0; size_t m_transferMemory = 0;

View File

@ -2537,20 +2537,18 @@ namespace dxvk {
void DxvkContext::uploadBuffer( void DxvkContext::uploadBuffer(
const Rc<DxvkBuffer>& buffer, const Rc<DxvkBuffer>& buffer,
const void* data) { const Rc<DxvkBuffer>& source,
VkDeviceSize sourceOffset) {
auto bufferSlice = buffer->getSliceHandle(); auto bufferSlice = buffer->getSliceHandle();
auto sourceSlice = source->getSliceHandle(sourceOffset, buffer->info().size);
auto stagingSlice = m_staging.alloc(bufferSlice.length);
auto stagingHandle = stagingSlice.getSliceHandle();
std::memcpy(stagingHandle.mapPtr, data, bufferSlice.length);
VkBufferCopy2 copyRegion = { VK_STRUCTURE_TYPE_BUFFER_COPY_2 }; VkBufferCopy2 copyRegion = { VK_STRUCTURE_TYPE_BUFFER_COPY_2 };
copyRegion.srcOffset = stagingHandle.offset; copyRegion.srcOffset = sourceSlice.offset;
copyRegion.dstOffset = bufferSlice.offset; copyRegion.dstOffset = bufferSlice.offset;
copyRegion.size = bufferSlice.length; copyRegion.size = bufferSlice.length;
VkCopyBufferInfo2 copyInfo = { VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2 }; VkCopyBufferInfo2 copyInfo = { VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2 };
copyInfo.srcBuffer = stagingHandle.handle; copyInfo.srcBuffer = sourceSlice.handle;
copyInfo.dstBuffer = bufferSlice.handle; copyInfo.dstBuffer = bufferSlice.handle;
copyInfo.regionCount = 1; copyInfo.regionCount = 1;
copyInfo.pRegions = &copyRegion; copyInfo.pRegions = &copyRegion;
@ -2574,7 +2572,7 @@ namespace dxvk {
buffer->info().stages, buffer->info().access); buffer->info().stages, buffer->info().access);
} }
m_cmd->trackResource<DxvkAccess::Read>(stagingSlice.buffer()); m_cmd->trackResource<DxvkAccess::Read>(source);
m_cmd->trackResource<DxvkAccess::Write>(buffer); m_cmd->trackResource<DxvkAccess::Write>(buffer);
} }

View File

@ -1151,14 +1151,17 @@ namespace dxvk {
/** /**
* \brief Uses transfer queue to initialize buffer * \brief Uses transfer queue to initialize buffer
* *
* Only safe to use if the buffer is not in use by the GPU. * Always replaces the entire buffer. Only safe to use
* if the buffer is currently not in use by the GPU.
* \param [in] buffer The buffer to initialize * \param [in] buffer The buffer to initialize
* \param [in] data The data to copy to the buffer * \param [in] source Staging buffer containing data
* \param [in] sourceOffset Offset into staging buffer
*/ */
void uploadBuffer( void uploadBuffer(
const Rc<DxvkBuffer>& buffer, const Rc<DxvkBuffer>& buffer,
const void* data); const Rc<DxvkBuffer>& source,
VkDeviceSize sourceOffset);
/** /**
* \brief Uses transfer queue to initialize image * \brief Uses transfer queue to initialize image