2020-03-13 12:44:33 +01:00
|
|
|
#include "VulkanAllocator.h"
|
|
|
|
|
#include "VulkanGraphics.h"
|
2020-03-20 01:27:40 +01:00
|
|
|
#include "VulkanInitializer.h"
|
|
|
|
|
|
|
|
|
|
using namespace Seele::Vulkan;
|
|
|
|
|
|
2020-05-05 01:51:13 +02:00
|
|
|
SubAllocation::SubAllocation(Allocation *owner, VkDeviceSize allocatedOffset, VkDeviceSize size, VkDeviceSize alignedOffset, VkDeviceSize allocatedSize)
|
|
|
|
|
: owner(owner), size(size), allocatedOffset(allocatedOffset), alignedOffset(alignedOffset), allocatedSize(allocatedSize)
|
2020-03-20 01:27:40 +01:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-12 15:47:19 +02:00
|
|
|
SubAllocation::~SubAllocation()
|
|
|
|
|
{
|
|
|
|
|
owner->markFree(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkDeviceMemory SubAllocation::getHandle() const
|
|
|
|
|
{
|
|
|
|
|
return owner->getHandle();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SubAllocation::isReadable() const
|
|
|
|
|
{
|
|
|
|
|
return owner->isReadable();
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-05 01:51:13 +02:00
|
|
|
void *SubAllocation::getMappedPointer()
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
2020-05-05 01:51:13 +02:00
|
|
|
return (uint8 *)owner->getMappedPointer() + alignedOffset;
|
2020-04-12 15:47:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SubAllocation::flushMemory()
|
|
|
|
|
{
|
|
|
|
|
owner->flushMemory();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SubAllocation::invalidateMemory()
|
|
|
|
|
{
|
|
|
|
|
owner->invalidateMemory();
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-05 01:51:13 +02:00
|
|
|
Allocation::Allocation(PGraphics graphics, Allocator *allocator, VkDeviceSize size, uint8 memoryTypeIndex,
|
|
|
|
|
VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
|
|
|
|
|
: device(graphics->getDevice()), allocator(allocator), bytesAllocated(0), bytesUsed(0), readable(properties & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT), properties(properties), memoryTypeIndex(memoryTypeIndex)
|
2020-03-20 01:27:40 +01:00
|
|
|
{
|
|
|
|
|
VkMemoryAllocateInfo allocInfo =
|
|
|
|
|
init::MemoryAllocateInfo();
|
|
|
|
|
allocInfo.allocationSize = size;
|
|
|
|
|
allocInfo.memoryTypeIndex = memoryTypeIndex;
|
2020-04-12 15:47:19 +02:00
|
|
|
isDedicated = dedicatedInfo != nullptr;
|
|
|
|
|
allocInfo.pNext = dedicatedInfo;
|
2020-03-20 01:27:40 +01:00
|
|
|
VK_CHECK(vkAllocateMemory(device, &allocInfo, nullptr, &allocatedMemory));
|
|
|
|
|
bytesAllocated = size;
|
|
|
|
|
PSubAllocation freeRange = new SubAllocation(this, 0, size, 0, size);
|
2020-04-12 15:47:19 +02:00
|
|
|
freeRanges[0] = freeRange;
|
|
|
|
|
|
|
|
|
|
canMap = (properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
|
|
|
|
|
isMapped = false;
|
2020-03-20 01:27:40 +01:00
|
|
|
}
|
|
|
|
|
|
2020-04-12 15:47:19 +02:00
|
|
|
Allocation::~Allocation()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDeviceSize alignment)
|
2020-03-20 01:27:40 +01:00
|
|
|
{
|
2020-06-02 11:46:18 +02:00
|
|
|
std::scoped_lock lck(lock);
|
2020-03-20 01:27:40 +01:00
|
|
|
if (isDedicated)
|
|
|
|
|
{
|
2020-06-02 11:46:18 +02:00
|
|
|
if (activeAllocations.empty() && requestedSize == bytesAllocated)
|
2020-03-20 01:27:40 +01:00
|
|
|
{
|
2020-04-12 15:47:19 +02:00
|
|
|
PSubAllocation suballoc = freeRanges[0];
|
|
|
|
|
activeAllocations[0] = suballoc.getHandle();
|
2020-03-20 01:27:40 +01:00
|
|
|
freeRanges.clear();
|
2020-04-12 15:47:19 +02:00
|
|
|
bytesUsed += requestedSize;
|
|
|
|
|
return suballoc;
|
2020-03-20 01:27:40 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-06-02 11:46:18 +02:00
|
|
|
for (auto it : freeRanges)
|
2020-03-20 01:27:40 +01:00
|
|
|
{
|
2020-06-02 11:46:18 +02:00
|
|
|
PSubAllocation freeAllocation = it.value;
|
2020-04-12 15:47:19 +02:00
|
|
|
VkDeviceSize allocatedOffset = freeAllocation->allocatedOffset;
|
|
|
|
|
VkDeviceSize alignedOffset = align(allocatedOffset, alignment);
|
|
|
|
|
VkDeviceSize alignmentAdjustment = alignedOffset - allocatedOffset;
|
|
|
|
|
VkDeviceSize size = alignmentAdjustment + requestedSize;
|
2020-03-20 01:27:40 +01:00
|
|
|
if (freeAllocation->size == size)
|
|
|
|
|
{
|
2020-04-12 15:47:19 +02:00
|
|
|
freeRanges.erase(allocatedOffset);
|
|
|
|
|
activeAllocations[allocatedOffset] = freeAllocation.getHandle();
|
|
|
|
|
bytesUsed += size;
|
2020-03-20 01:27:40 +01:00
|
|
|
return freeAllocation;
|
|
|
|
|
}
|
|
|
|
|
else if (size < freeAllocation->allocatedSize)
|
|
|
|
|
{
|
|
|
|
|
freeAllocation->size -= size;
|
|
|
|
|
freeAllocation->allocatedSize -= size;
|
2020-05-05 01:51:13 +02:00
|
|
|
freeAllocation->allocatedOffset += size;
|
|
|
|
|
freeAllocation->alignedOffset += size;
|
2020-03-24 21:05:32 +01:00
|
|
|
PSubAllocation subAlloc = new SubAllocation(this, allocatedOffset, size, alignedOffset, size);
|
2020-04-12 15:47:19 +02:00
|
|
|
activeAllocations[allocatedOffset] = subAlloc.getHandle();
|
|
|
|
|
freeRanges.erase(allocatedOffset);
|
|
|
|
|
freeRanges[freeAllocation->allocatedOffset] = freeAllocation;
|
|
|
|
|
bytesUsed += size;
|
2020-03-20 01:27:40 +01:00
|
|
|
return subAlloc;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-05 01:51:13 +02:00
|
|
|
void Allocation::markFree(SubAllocation *allocation)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
2020-06-02 11:46:18 +02:00
|
|
|
// Dont free if it is already a free allocation, since they also mark themselves on deletion
|
2020-09-19 14:36:50 +02:00
|
|
|
if (freeRanges.find(allocation->allocatedOffset) != nullptr)
|
2020-06-02 11:46:18 +02:00
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-04-12 15:47:19 +02:00
|
|
|
VkDeviceSize lowerBound = allocation->allocatedOffset;
|
|
|
|
|
VkDeviceSize upperBound = allocation->allocatedOffset + allocation->allocatedSize;
|
|
|
|
|
PSubAllocation allocHandle;
|
2020-06-02 11:46:18 +02:00
|
|
|
std::scoped_lock lck(lock);
|
|
|
|
|
//Join lower bound
|
2020-05-05 01:51:13 +02:00
|
|
|
for (auto freeRange : freeRanges)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
|
|
|
|
PSubAllocation freeAlloc = freeRange.value;
|
2020-06-02 11:46:18 +02:00
|
|
|
if (freeAlloc->allocatedOffset + freeAlloc->allocatedSize == lowerBound)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
2020-06-02 11:46:18 +02:00
|
|
|
//extend freeAlloc by the allocatedSize
|
2020-04-12 15:47:19 +02:00
|
|
|
freeAlloc->allocatedSize += allocation->allocatedSize;
|
|
|
|
|
allocHandle = freeAlloc;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-06-02 11:46:18 +02:00
|
|
|
//Join upper bound
|
|
|
|
|
auto foundAlloc = freeRanges.find(upperBound);
|
2020-05-05 01:51:13 +02:00
|
|
|
if (foundAlloc != freeRanges.end())
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
2020-06-02 11:46:18 +02:00
|
|
|
// There is a free allocation ending where the new free one ends
|
|
|
|
|
if (allocHandle != nullptr)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
2020-06-02 11:46:18 +02:00
|
|
|
// extend allocHandle by another foundAlloc->allocatedSize bytes
|
2020-04-12 15:47:19 +02:00
|
|
|
allocHandle->allocatedSize += foundAlloc->value->allocatedSize;
|
|
|
|
|
freeRanges.erase(foundAlloc->key);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-06-02 11:46:18 +02:00
|
|
|
// set foundAlloc back by size amount
|
2020-04-12 15:47:19 +02:00
|
|
|
allocHandle = foundAlloc->value;
|
2020-06-02 11:46:18 +02:00
|
|
|
// remove from offset map since key changes
|
|
|
|
|
freeRanges.erase(foundAlloc->key);
|
2020-04-12 15:47:19 +02:00
|
|
|
allocHandle->allocatedOffset -= allocation->allocatedSize;
|
|
|
|
|
allocHandle->alignedOffset -= allocation->allocatedSize;
|
2020-06-02 11:46:18 +02:00
|
|
|
// place back at correct offset
|
|
|
|
|
freeRanges[allocHandle->allocatedOffset] = allocHandle;
|
2020-04-12 15:47:19 +02:00
|
|
|
}
|
|
|
|
|
}
|
2020-05-05 01:51:13 +02:00
|
|
|
if (allocHandle == nullptr)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
|
|
|
|
allocHandle = new SubAllocation(this, allocation->alignedOffset, allocation->size, allocation->alignedOffset, allocation->allocatedSize);
|
|
|
|
|
freeRanges[allocation->allocatedOffset] = allocHandle;
|
|
|
|
|
}
|
|
|
|
|
activeAllocations.erase(allocation->allocatedOffset);
|
|
|
|
|
bytesUsed -= allocation->allocatedSize;
|
2020-06-02 11:46:18 +02:00
|
|
|
|
|
|
|
|
// TODO: delete allocation when bytesUsed == 0
|
2020-04-12 15:47:19 +02:00
|
|
|
}
|
|
|
|
|
|
2020-04-01 02:17:49 +02:00
|
|
|
Allocator::Allocator(PGraphics graphics)
|
2020-03-13 12:44:33 +01:00
|
|
|
: graphics(graphics)
|
|
|
|
|
{
|
|
|
|
|
vkGetPhysicalDeviceMemoryProperties(graphics->getPhysicalDevice(), &memProperties);
|
|
|
|
|
heaps.resize(memProperties.memoryHeapCount);
|
2020-04-12 15:47:19 +02:00
|
|
|
for (size_t i = 0; i < memProperties.memoryHeapCount; ++i)
|
2020-03-13 12:44:33 +01:00
|
|
|
{
|
2020-03-16 13:29:17 +01:00
|
|
|
VkMemoryHeap memoryHeap = memProperties.memoryHeaps[i];
|
2020-05-05 01:51:13 +02:00
|
|
|
HeapInfo &heapInfo = heaps[i];
|
2020-03-16 13:29:17 +01:00
|
|
|
heapInfo.maxSize = memoryHeap.size;
|
2020-03-13 12:44:33 +01:00
|
|
|
}
|
2020-03-20 01:27:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Allocator::~Allocator()
|
|
|
|
|
{
|
2020-06-02 11:46:18 +02:00
|
|
|
std::scoped_lock lck(lock);
|
2020-05-05 01:51:13 +02:00
|
|
|
for (auto heap : heaps)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
2020-05-05 01:51:13 +02:00
|
|
|
for (auto alloc : heap.allocations)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
|
|
|
|
assert(alloc->activeAllocations.empty());
|
|
|
|
|
assert(alloc->freeRanges.size() == 1);
|
|
|
|
|
}
|
|
|
|
|
heap.allocations.clear();
|
|
|
|
|
}
|
|
|
|
|
graphics = nullptr;
|
2020-03-20 01:27:40 +01:00
|
|
|
}
|
|
|
|
|
|
2020-05-05 01:51:13 +02:00
|
|
|
PSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
|
2020-03-20 01:27:40 +01:00
|
|
|
{
|
2020-06-02 11:46:18 +02:00
|
|
|
std::scoped_lock lck(lock);
|
2020-05-05 01:51:13 +02:00
|
|
|
const VkMemoryRequirements &requirements = memRequirements2.memoryRequirements;
|
2020-04-12 15:47:19 +02:00
|
|
|
uint8 memoryTypeIndex;
|
2020-03-20 01:27:40 +01:00
|
|
|
VK_CHECK(findMemoryType(requirements.memoryTypeBits, properties, &memoryTypeIndex));
|
|
|
|
|
uint32 heapIndex = memProperties.memoryTypes[memoryTypeIndex].heapIndex;
|
2020-05-05 01:51:13 +02:00
|
|
|
|
|
|
|
|
if (memRequirements2.pNext != nullptr)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
2020-05-05 01:51:13 +02:00
|
|
|
VkMemoryDedicatedRequirements *dedicatedReq = (VkMemoryDedicatedRequirements *)memRequirements2.pNext;
|
|
|
|
|
if (dedicatedReq->prefersDedicatedAllocation)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
|
|
|
|
PAllocation newAllocation = new Allocation(graphics, this, requirements.size, memoryTypeIndex, properties, dedicatedInfo);
|
|
|
|
|
heaps[heapIndex].allocations.add(newAllocation);
|
|
|
|
|
return newAllocation->getSuballocation(requirements.size, requirements.alignment);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-05-05 01:51:13 +02:00
|
|
|
for (auto alloc : heaps[heapIndex].allocations)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
|
|
|
|
PSubAllocation suballoc = alloc->getSuballocation(requirements.size, requirements.alignment);
|
2020-05-05 01:51:13 +02:00
|
|
|
if (suballoc != nullptr)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
|
|
|
|
return suballoc;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-05-05 01:51:13 +02:00
|
|
|
|
2020-04-12 15:47:19 +02:00
|
|
|
// no suitable allocations found, allocate new block
|
|
|
|
|
PAllocation newAllocation = new Allocation(graphics, this, (requirements.size > MemoryBlockSize) ? requirements.size : MemoryBlockSize, memoryTypeIndex, properties, nullptr);
|
2020-03-20 01:27:40 +01:00
|
|
|
heaps[heapIndex].allocations.add(newAllocation);
|
2020-04-12 15:47:19 +02:00
|
|
|
return newAllocation->getSuballocation(requirements.size, requirements.alignment);
|
2020-03-20 01:27:40 +01:00
|
|
|
}
|
|
|
|
|
|
2020-05-05 01:51:13 +02:00
|
|
|
void Allocator::free(Allocation *allocation)
|
2020-03-20 01:27:40 +01:00
|
|
|
{
|
2020-06-02 11:46:18 +02:00
|
|
|
std::scoped_lock lck(lock);
|
2020-05-05 01:51:13 +02:00
|
|
|
for (auto heap : heaps)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
2020-05-05 01:51:13 +02:00
|
|
|
for (uint32 i = 0; i < heap.allocations.size(); ++i)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
2020-05-05 01:51:13 +02:00
|
|
|
if (heap.allocations[i] == allocation)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
|
|
|
|
heap.allocations.remove(i, false);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-05 01:51:13 +02:00
|
|
|
VkResult Allocator::findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties, uint8 *typeIndex)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
|
|
|
|
for (uint8 memoryIndex = 0; memoryIndex < memProperties.memoryTypeCount && typeBits; ++memoryIndex)
|
2020-03-13 12:44:33 +01:00
|
|
|
{
|
2020-03-20 01:27:40 +01:00
|
|
|
if ((typeBits & 1) == 1)
|
|
|
|
|
{
|
|
|
|
|
if ((memProperties.memoryTypes[memoryIndex].propertyFlags & properties) == properties)
|
|
|
|
|
{
|
|
|
|
|
*typeIndex = memoryIndex;
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
typeBits >>= 1;
|
2020-03-13 12:44:33 +01:00
|
|
|
}
|
2020-05-05 01:51:13 +02:00
|
|
|
|
2020-03-20 01:27:40 +01:00
|
|
|
return VK_ERROR_FORMAT_NOT_SUPPORTED;
|
2020-04-12 15:47:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
StagingBuffer::StagingBuffer()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
StagingBuffer::~StagingBuffer()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
StagingManager::StagingManager(PGraphics graphics, PAllocator allocator)
|
2020-05-05 01:51:13 +02:00
|
|
|
: graphics(graphics), allocator(allocator)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
StagingManager::~StagingManager()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void StagingManager::clearPending()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageFlags usage, bool bCPURead)
|
|
|
|
|
{
|
2020-09-19 14:36:50 +02:00
|
|
|
|
|
|
|
|
std::unique_lock l(lock);
|
2020-05-05 01:51:13 +02:00
|
|
|
for (auto it = freeBuffers.begin(); it != freeBuffers.end(); ++it)
|
|
|
|
|
{
|
2020-04-12 15:47:19 +02:00
|
|
|
auto freeBuffer = *it;
|
2020-05-05 01:51:13 +02:00
|
|
|
if (freeBuffer->allocation->getSize() == size && freeBuffer->allocation->isReadable() == bCPURead)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
|
|
|
|
activeBuffers.add(freeBuffer.getHandle());
|
|
|
|
|
freeBuffers.remove(it, false);
|
|
|
|
|
return freeBuffer;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-09-19 14:36:50 +02:00
|
|
|
|
2020-04-12 15:47:19 +02:00
|
|
|
PStagingBuffer stagingBuffer = new StagingBuffer();
|
|
|
|
|
VkBufferCreateInfo stagingBufferCreateInfo = init::BufferCreateInfo(usage, size);
|
|
|
|
|
VkDevice vulkanDevice = graphics->getDevice();
|
|
|
|
|
|
|
|
|
|
VK_CHECK(vkCreateBuffer(vulkanDevice, &stagingBufferCreateInfo, nullptr, &stagingBuffer->buffer));
|
|
|
|
|
|
|
|
|
|
VkMemoryDedicatedRequirements dedicatedReqs;
|
|
|
|
|
dedicatedReqs.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
|
|
|
|
|
dedicatedReqs.pNext = nullptr;
|
|
|
|
|
VkMemoryRequirements2 memReqs;
|
|
|
|
|
memReqs.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
|
|
|
|
|
memReqs.pNext = &dedicatedReqs;
|
|
|
|
|
VkBufferMemoryRequirementsInfo2 bufferQuery;
|
|
|
|
|
bufferQuery.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2;
|
|
|
|
|
bufferQuery.pNext = nullptr;
|
|
|
|
|
bufferQuery.buffer = stagingBuffer->buffer;
|
|
|
|
|
vkGetBufferMemoryRequirements2(vulkanDevice, &bufferQuery, &memReqs);
|
|
|
|
|
|
2020-05-05 01:51:13 +02:00
|
|
|
memReqs.memoryRequirements.alignment =
|
|
|
|
|
(16 > memReqs.memoryRequirements.alignment) ? 16 : memReqs.memoryRequirements.alignment;
|
2020-04-12 15:47:19 +02:00
|
|
|
|
2020-05-05 01:51:13 +02:00
|
|
|
stagingBuffer->allocation = allocator->allocate(memReqs, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | (bCPURead ? VK_MEMORY_PROPERTY_HOST_COHERENT_BIT : VK_MEMORY_PROPERTY_HOST_CACHED_BIT), stagingBuffer->buffer);
|
2020-04-12 15:47:19 +02:00
|
|
|
stagingBuffer->bReadable = bCPURead;
|
|
|
|
|
vkBindBufferMemory(graphics->getDevice(), stagingBuffer->buffer, stagingBuffer->getMemoryHandle(), stagingBuffer->getOffset());
|
2020-05-05 01:51:13 +02:00
|
|
|
|
2020-04-12 15:47:19 +02:00
|
|
|
activeBuffers.add(stagingBuffer.getHandle());
|
2020-09-19 14:36:50 +02:00
|
|
|
|
2020-04-12 15:47:19 +02:00
|
|
|
return stagingBuffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void StagingManager::releaseStagingBuffer(PStagingBuffer buffer)
|
|
|
|
|
{
|
2020-09-19 14:36:50 +02:00
|
|
|
std::unique_lock l(lock);
|
2020-04-12 15:47:19 +02:00
|
|
|
freeBuffers.add(buffer);
|
|
|
|
|
activeBuffers.remove(activeBuffers.find(buffer.getHandle()));
|
2020-03-20 01:27:40 +01:00
|
|
|
}
|