mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-19 05:52:11 +01:00
[dxvk] Remove old staging buffer code
This commit is contained in:
parent
8c1a56af89
commit
1c9bc235d0
@ -73,50 +73,6 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Rc<DxvkStagingBuffer> DxvkDevice::allocStagingBuffer(VkDeviceSize size) {
|
|
||||||
// In case we need a standard-size staging buffer, try
|
|
||||||
// to recycle an old one that has been returned earlier
|
|
||||||
if (size <= DefaultStagingBufferSize) {
|
|
||||||
const Rc<DxvkStagingBuffer> buffer
|
|
||||||
= m_recycledStagingBuffers.retrieveObject();
|
|
||||||
|
|
||||||
if (buffer != nullptr)
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Staging buffers only need to be able to handle transfer
|
|
||||||
// operations, and they need to be in host-visible memory.
|
|
||||||
DxvkBufferCreateInfo info;
|
|
||||||
info.size = size;
|
|
||||||
info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
|
||||||
info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT
|
|
||||||
| VK_PIPELINE_STAGE_HOST_BIT;
|
|
||||||
info.access = VK_ACCESS_TRANSFER_READ_BIT
|
|
||||||
| VK_ACCESS_HOST_WRITE_BIT;
|
|
||||||
|
|
||||||
VkMemoryPropertyFlags memFlags
|
|
||||||
= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
|
|
||||||
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
|
||||||
|
|
||||||
// Don't create buffers that are too small. A staging
|
|
||||||
// buffer should be able to serve multiple uploads.
|
|
||||||
if (info.size < DefaultStagingBufferSize)
|
|
||||||
info.size = DefaultStagingBufferSize;
|
|
||||||
|
|
||||||
return new DxvkStagingBuffer(this->createBuffer(info, memFlags));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void DxvkDevice::recycleStagingBuffer(const Rc<DxvkStagingBuffer>& buffer) {
|
|
||||||
// Drop staging buffers that are bigger than the
|
|
||||||
// standard ones to save memory, recycle the rest
|
|
||||||
if (buffer->size() == DefaultStagingBufferSize) {
|
|
||||||
m_recycledStagingBuffers.returnObject(buffer);
|
|
||||||
buffer->reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Rc<DxvkCommandList> DxvkDevice::createCommandList() {
|
Rc<DxvkCommandList> DxvkDevice::createCommandList() {
|
||||||
Rc<DxvkCommandList> cmdList = m_recycledCommandLists.retrieveObject();
|
Rc<DxvkCommandList> cmdList = m_recycledCommandLists.retrieveObject();
|
||||||
|
|
||||||
|
@ -58,8 +58,6 @@ namespace dxvk {
|
|||||||
friend class DxvkContext;
|
friend class DxvkContext;
|
||||||
friend class DxvkSubmissionQueue;
|
friend class DxvkSubmissionQueue;
|
||||||
friend class DxvkDescriptorPoolTracker;
|
friend class DxvkDescriptorPoolTracker;
|
||||||
|
|
||||||
constexpr static VkDeviceSize DefaultStagingBufferSize = 4 * 1024 * 1024;
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DxvkDevice(
|
DxvkDevice(
|
||||||
@ -153,29 +151,6 @@ namespace dxvk {
|
|||||||
*/
|
*/
|
||||||
DxvkDeviceOptions options() const;
|
DxvkDeviceOptions options() const;
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Allocates a staging buffer
|
|
||||||
*
|
|
||||||
* Returns a staging buffer that is at least as large
|
|
||||||
* as the requested size. It is usually bigger so that
|
|
||||||
* a single staging buffer may serve multiple allocations.
|
|
||||||
* \param [in] size Minimum buffer size
|
|
||||||
* \returns The staging buffer
|
|
||||||
*/
|
|
||||||
Rc<DxvkStagingBuffer> allocStagingBuffer(
|
|
||||||
VkDeviceSize size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Recycles a staging buffer
|
|
||||||
*
|
|
||||||
* When a staging buffer is no longer needed, it should
|
|
||||||
* be returned to the device so that it can be reused
|
|
||||||
* for subsequent allocations.
|
|
||||||
* \param [in] buffer The buffer
|
|
||||||
*/
|
|
||||||
void recycleStagingBuffer(
|
|
||||||
const Rc<DxvkStagingBuffer>& buffer);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Creates a command list
|
* \brief Creates a command list
|
||||||
* \returns The command list
|
* \returns The command list
|
||||||
@ -437,7 +412,6 @@ namespace dxvk {
|
|||||||
|
|
||||||
DxvkRecycler<DxvkCommandList, 16> m_recycledCommandLists;
|
DxvkRecycler<DxvkCommandList, 16> m_recycledCommandLists;
|
||||||
DxvkRecycler<DxvkDescriptorPool, 16> m_recycledDescriptorPools;
|
DxvkRecycler<DxvkDescriptorPool, 16> m_recycledDescriptorPools;
|
||||||
DxvkRecycler<DxvkStagingBuffer, 4> m_recycledStagingBuffers;
|
|
||||||
|
|
||||||
DxvkSubmissionQueue m_submissionQueue;
|
DxvkSubmissionQueue m_submissionQueue;
|
||||||
|
|
||||||
|
@ -3,94 +3,6 @@
|
|||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
DxvkStagingBuffer::DxvkStagingBuffer(
|
|
||||||
const Rc<DxvkBuffer>& buffer)
|
|
||||||
: m_buffer(buffer), m_bufferSize(buffer->info().size){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DxvkStagingBuffer::~DxvkStagingBuffer() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
VkDeviceSize DxvkStagingBuffer::size() const {
|
|
||||||
return m_bufferSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
VkDeviceSize DxvkStagingBuffer::freeBytes() const {
|
|
||||||
return m_bufferSize >= m_bufferOffset
|
|
||||||
? m_bufferSize - m_bufferOffset
|
|
||||||
: VkDeviceSize(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool DxvkStagingBuffer::alloc(
|
|
||||||
VkDeviceSize size,
|
|
||||||
DxvkStagingBufferSlice& slice) {
|
|
||||||
if (m_bufferOffset + size > m_bufferSize)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto physSlice = m_buffer->getSliceHandle(m_bufferOffset, size);
|
|
||||||
slice.buffer = physSlice.handle;
|
|
||||||
slice.offset = physSlice.offset;
|
|
||||||
slice.mapPtr = physSlice.mapPtr;
|
|
||||||
|
|
||||||
m_bufferOffset = align(m_bufferOffset + size, 64);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void DxvkStagingBuffer::reset() {
|
|
||||||
m_bufferOffset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DxvkStagingAlloc::DxvkStagingAlloc(DxvkDevice* device)
|
|
||||||
: m_device(device) { }
|
|
||||||
|
|
||||||
|
|
||||||
DxvkStagingAlloc::~DxvkStagingAlloc() {
|
|
||||||
this->reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DxvkStagingBufferSlice DxvkStagingAlloc::alloc(VkDeviceSize size) {
|
|
||||||
Rc<DxvkStagingBuffer> selectedBuffer;
|
|
||||||
|
|
||||||
// Try a worst-fit allocation strategy on the existing staging
|
|
||||||
// buffers first. This should keep the amount of wasted space
|
|
||||||
// small, especially if there are large allocations.
|
|
||||||
for (const auto& buf : m_stagingBuffers) {
|
|
||||||
if (selectedBuffer == nullptr || (buf->freeBytes() > selectedBuffer->freeBytes()))
|
|
||||||
selectedBuffer = buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have no suitable buffer, allocate one from the device
|
|
||||||
// that is *at least* as large as the amount of data we need
|
|
||||||
// to upload. Usually it will be bigger.
|
|
||||||
DxvkStagingBufferSlice slice;
|
|
||||||
|
|
||||||
if ((selectedBuffer == nullptr) || (!selectedBuffer->alloc(size, slice))) {
|
|
||||||
selectedBuffer = m_device->allocStagingBuffer(size);
|
|
||||||
selectedBuffer->alloc(size, slice);
|
|
||||||
m_stagingBuffers.push_back(selectedBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
return slice;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void DxvkStagingAlloc::reset() {
|
|
||||||
for (const auto& buf : m_stagingBuffers)
|
|
||||||
m_device->recycleStagingBuffer(buf);
|
|
||||||
|
|
||||||
m_stagingBuffers.resize(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DxvkStagingDataAlloc::DxvkStagingDataAlloc(const Rc<DxvkDevice>& device)
|
DxvkStagingDataAlloc::DxvkStagingDataAlloc(const Rc<DxvkDevice>& device)
|
||||||
: m_device(device) {
|
: m_device(device) {
|
||||||
|
|
||||||
|
@ -7,120 +7,6 @@
|
|||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
class DxvkDevice;
|
class DxvkDevice;
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Staging buffer slice
|
|
||||||
*
|
|
||||||
* Provides the application with a
|
|
||||||
* pointer to the mapped buffer.
|
|
||||||
*/
|
|
||||||
struct DxvkStagingBufferSlice {
|
|
||||||
VkBuffer buffer = VK_NULL_HANDLE;
|
|
||||||
VkDeviceSize offset = 0;
|
|
||||||
void* mapPtr = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Staging uffer
|
|
||||||
*
|
|
||||||
* A mapped buffer that can be used for fast data
|
|
||||||
* transfer operations from the host to the GPU.
|
|
||||||
* Implements a linear sub-allocator for staging
|
|
||||||
* buffer slices.
|
|
||||||
*/
|
|
||||||
class DxvkStagingBuffer : public RcObject {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
DxvkStagingBuffer(
|
|
||||||
const Rc<DxvkBuffer>& buffer);
|
|
||||||
~DxvkStagingBuffer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Buffer size, in bytes
|
|
||||||
* \returns Buffer size, in bytes
|
|
||||||
*/
|
|
||||||
VkDeviceSize size() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Number of bytes still available
|
|
||||||
* \returns Number of bytes still available
|
|
||||||
*/
|
|
||||||
VkDeviceSize freeBytes() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Allocates a staging buffer slice
|
|
||||||
*
|
|
||||||
* This may fail if the amount of data requested is
|
|
||||||
* larger than the amount of data still available.
|
|
||||||
* \param [in] size Requested allocation size
|
|
||||||
* \param [out] slice Allocated staging buffer slice
|
|
||||||
* \returns \c true on success, \c false on failure
|
|
||||||
*/
|
|
||||||
bool alloc(
|
|
||||||
VkDeviceSize size,
|
|
||||||
DxvkStagingBufferSlice& slice);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Resets staging buffer
|
|
||||||
*
|
|
||||||
* Resets the allocator and thus frees
|
|
||||||
* all slices allocated from the buffer.
|
|
||||||
*/
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
Rc<DxvkBuffer> m_buffer;
|
|
||||||
|
|
||||||
VkDeviceSize m_bufferSize = 0;
|
|
||||||
VkDeviceSize m_bufferOffset = 0;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Staging buffer allocator
|
|
||||||
*
|
|
||||||
* Convenient allocator for staging buffer slices
|
|
||||||
* which creates new staging buffers on demand.
|
|
||||||
*/
|
|
||||||
class DxvkStagingAlloc {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
DxvkStagingAlloc(DxvkDevice* device);
|
|
||||||
~DxvkStagingAlloc();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Allocates a staging buffer slice
|
|
||||||
*
|
|
||||||
* This \e may create a new staging buffer
|
|
||||||
* if needed. This method should not fail.
|
|
||||||
* \param [in] size Required amount of memory
|
|
||||||
* \returns Allocated staging buffer slice
|
|
||||||
*/
|
|
||||||
DxvkStagingBufferSlice alloc(
|
|
||||||
VkDeviceSize size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Resets staging buffer allocator
|
|
||||||
*
|
|
||||||
* Returns all buffers to the device so that
|
|
||||||
* they can be recycled. Buffers must not be
|
|
||||||
* in use when this is called.
|
|
||||||
*/
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
DxvkDevice* const m_device;
|
|
||||||
|
|
||||||
std::vector<Rc<DxvkStagingBuffer>> m_stagingBuffers;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Staging data allocator
|
* \brief Staging data allocator
|
||||||
|
Loading…
x
Reference in New Issue
Block a user