1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-01 16:24:12 +01: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)
: m_parent(pParent),
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_device->createCommandList());
}
@ -81,20 +82,22 @@ namespace dxvk {
const D3D11_SUBRESOURCE_DATA* pInitialData) {
std::lock_guard<dxvk::mutex> lock(m_mutex);
DxvkBufferSlice bufferSlice = pBuffer->GetBufferSlice();
Rc<DxvkBuffer> buffer = pBuffer->GetBuffer();
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_context->uploadBuffer(
bufferSlice.buffer(),
pInitialData->pSysMem);
m_context->uploadBuffer(buffer,
stagingSlice.buffer(),
stagingSlice.offset());
} else {
m_transferCommands += 1;
m_context->initBuffer(
bufferSlice.buffer());
m_context->initBuffer(buffer);
}
FlushImplicit();
@ -284,6 +287,8 @@ namespace dxvk {
m_transferCommands = 0;
m_transferMemory = 0;
m_stagingBuffer.reset();
}

View File

@ -1,5 +1,7 @@
#pragma once
#include "../dxvk/dxvk_staging.h"
#include "d3d11_buffer.h"
#include "d3d11_texture.h"
@ -18,6 +20,9 @@ namespace dxvk {
class D3D11Initializer {
constexpr static size_t MaxTransferMemory = 32 * 1024 * 1024;
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:
D3D11Initializer(
@ -45,6 +50,8 @@ namespace dxvk {
D3D11Device* m_parent;
Rc<DxvkDevice> m_device;
Rc<DxvkContext> m_context;
DxvkStagingBuffer m_stagingBuffer;
size_t m_transferCommands = 0;
size_t m_transferMemory = 0;

View File

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

View File

@ -1151,14 +1151,17 @@ namespace dxvk {
/**
* \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] data The data to copy to the buffer
* \param [in] source Staging buffer containing data
* \param [in] sourceOffset Offset into staging buffer
*/
void uploadBuffer(
const Rc<DxvkBuffer>& buffer,
const void* data);
const Rc<DxvkBuffer>& source,
VkDeviceSize sourceOffset);
/**
* \brief Uses transfer queue to initialize image