From 970deb452e32074d817d60b9f8dae23e3b2ebac4 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Fri, 21 Jun 2019 15:56:41 +0200 Subject: [PATCH] [dxvk] Implement new staging buffer allocator --- src/dxvk/dxvk_staging.cpp | 56 +++++++++++++++++++++++++++++++++++++++ src/dxvk/dxvk_staging.h | 40 ++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/src/dxvk/dxvk_staging.cpp b/src/dxvk/dxvk_staging.cpp index 943a5053..4ea8a66f 100644 --- a/src/dxvk/dxvk_staging.cpp +++ b/src/dxvk/dxvk_staging.cpp @@ -89,5 +89,61 @@ namespace dxvk { m_stagingBuffers.resize(0); } + + + DxvkStagingDataAlloc::DxvkStagingDataAlloc(const Rc& device) + : m_device(device) { + + } + + + DxvkStagingDataAlloc::~DxvkStagingDataAlloc() { + + } + + + DxvkBufferSlice DxvkStagingDataAlloc::alloc(VkDeviceSize align, VkDeviceSize size) { + if (size > MaxBufferSize) + return DxvkBufferSlice(createBuffer(size)); + + if (m_buffer == nullptr) + m_buffer = createBuffer(MaxBufferSize); + + if (!m_buffer->isInUse()) + m_offset = 0; + + m_offset = dxvk::align(m_offset, align); + + if (m_offset + size > MaxBufferSize) { + m_offset = 0; + + if (m_buffers.size() < MaxBufferCount) + m_buffers.push(std::move(m_buffer)); + + if (!m_buffers.front()->isInUse()) { + m_buffer = std::move(m_buffers.front()); + m_buffers.pop(); + } else { + m_buffer = createBuffer(MaxBufferSize); + } + } + + DxvkBufferSlice slice(m_buffer, m_offset, size); + m_offset = dxvk::align(m_offset + size, align); + return slice; + } + + + Rc DxvkStagingDataAlloc::createBuffer(VkDeviceSize size) { + DxvkBufferCreateInfo info; + info.size = size; + info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT; + info.access = VK_ACCESS_TRANSFER_READ_BIT; + + return m_device->createBuffer(info, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + } } diff --git a/src/dxvk/dxvk_staging.h b/src/dxvk/dxvk_staging.h index 6d876dc9..f76c9ecf 100644 --- a/src/dxvk/dxvk_staging.h +++ b/src/dxvk/dxvk_staging.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "dxvk_buffer.h" namespace dxvk { @@ -118,5 +120,43 @@ namespace dxvk { std::vector> m_stagingBuffers; }; + + + /** + * \brief Staging data allocator + * + * Allocates buffer slices for resource uploads, + * while trying to keep the number of allocations + * but also the amount of allocated memory low. + */ + class DxvkStagingDataAlloc { + constexpr static VkDeviceSize MaxBufferSize = 1 << 24; // 16 MiB + constexpr static uint32_t MaxBufferCount = 2; + public: + + DxvkStagingDataAlloc(const Rc& device); + + ~DxvkStagingDataAlloc(); + + /** + * \brief Alloctaes a staging buffer slice + * + * \param [in] align Alignment of the allocation + * \param [in] size Size of the allocation + * \returns Staging buffer slice + */ + DxvkBufferSlice alloc(VkDeviceSize align, VkDeviceSize size); + + private: + + Rc m_device; + Rc m_buffer; + VkDeviceSize m_offset = 0; + + std::queue> m_buffers; + + Rc createBuffer(VkDeviceSize size); + + }; }