2023-10-26 18:37:29 +02:00
|
|
|
#include "Allocator.h"
|
|
|
|
|
#include "Graphics.h"
|
|
|
|
|
#include "Initializer.h"
|
2020-03-20 01:27:40 +01:00
|
|
|
|
|
|
|
|
using namespace Seele::Vulkan;
|
|
|
|
|
|
2023-11-08 23:27:21 +01:00
|
|
|
SubAllocation::SubAllocation(PAllocation owner, VkDeviceSize requestedSize, VkDeviceSize allocatedOffset, VkDeviceSize allocatedSize, VkDeviceSize alignedOffset)
|
2021-11-14 20:36:53 +01:00
|
|
|
: owner(owner)
|
2023-11-08 23:27:21 +01:00
|
|
|
, requestedSize(requestedSize)
|
2021-11-14 20:36:53 +01:00
|
|
|
, allocatedOffset(allocatedOffset)
|
|
|
|
|
, allocatedSize(allocatedSize)
|
2023-11-08 23:27:21 +01:00
|
|
|
, alignedOffset(alignedOffset)
|
2020-03-20 01:27:40 +01:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-12 15:47:19 +02:00
|
|
|
SubAllocation::~SubAllocation()
|
|
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
owner->markFree(this);
|
2020-04-12 15:47:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-06 14:47:21 +01:00
|
|
|
VkDeviceMemory SubAllocation::getHandle() const
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
return owner->getHandle();
|
2020-04-12 15:47:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-06 14:47:21 +01:00
|
|
|
bool SubAllocation::isReadable() const
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
return owner->isReadable();
|
2020-04-12 15:47:19 +02:00
|
|
|
}
|
|
|
|
|
|
2020-05-05 01:51:13 +02:00
|
|
|
void *SubAllocation::getMappedPointer()
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
return (uint8 *)owner->getMappedPointer() + alignedOffset;
|
2020-04-12 15:47:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SubAllocation::flushMemory()
|
|
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
owner->flushMemory();
|
2020-04-12 15:47:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SubAllocation::invalidateMemory()
|
|
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
owner->invalidateMemory();
|
2020-04-12 15:47:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-01 23:12:30 +01:00
|
|
|
Allocation::Allocation(PGraphics graphics, PAllocator allocator, VkDeviceSize size, uint8 memoryTypeIndex,
|
2021-11-14 20:36:53 +01:00
|
|
|
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
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
VkMemoryAllocateInfo allocInfo =
|
|
|
|
|
init::MemoryAllocateInfo();
|
|
|
|
|
allocInfo.allocationSize = size;
|
|
|
|
|
allocInfo.memoryTypeIndex = memoryTypeIndex;
|
|
|
|
|
isDedicated = dedicatedInfo != nullptr;
|
|
|
|
|
allocInfo.pNext = dedicatedInfo;
|
2023-11-13 09:07:23 +01:00
|
|
|
//std::cout << "New allocation" << std::endl;
|
2021-11-14 20:36:53 +01:00
|
|
|
VK_CHECK(vkAllocateMemory(device, &allocInfo, nullptr, &allocatedMemory));
|
|
|
|
|
bytesAllocated = size;
|
2023-11-08 23:27:21 +01:00
|
|
|
freeRanges[0] = size;
|
2020-04-12 15:47:19 +02:00
|
|
|
|
2021-11-14 20:36:53 +01:00
|
|
|
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()
|
|
|
|
|
{
|
2023-11-13 09:07:23 +01:00
|
|
|
vkFreeMemory(device, allocatedMemory, nullptr);
|
2023-11-08 23:27:21 +01:00
|
|
|
assert(bytesUsed == 0);
|
2020-04-12 15:47:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-05 10:36:01 +01:00
|
|
|
OSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDeviceSize alignment)
|
2020-03-20 01:27:40 +01:00
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
if (isDedicated)
|
|
|
|
|
{
|
|
|
|
|
if (activeAllocations.empty() && requestedSize == bytesAllocated)
|
|
|
|
|
{
|
2023-11-08 23:27:21 +01:00
|
|
|
OSubAllocation suballoc = new SubAllocation(this, requestedSize, 0, requestedSize, 0);
|
2023-11-05 10:36:01 +01:00
|
|
|
activeAllocations.add(suballoc);
|
2021-11-14 20:36:53 +01:00
|
|
|
freeRanges.clear();
|
|
|
|
|
bytesUsed += requestedSize;
|
|
|
|
|
return suballoc;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-11-08 23:27:21 +01:00
|
|
|
for (const auto& [lower, size] : freeRanges)
|
2021-11-14 20:36:53 +01:00
|
|
|
{
|
2023-11-08 23:27:21 +01:00
|
|
|
VkDeviceSize alignedOffset = lower + alignment - 1;
|
2023-11-05 10:36:01 +01:00
|
|
|
alignedOffset /= alignment;
|
|
|
|
|
alignedOffset *= alignment;
|
2023-11-08 23:27:21 +01:00
|
|
|
VkDeviceSize allocatedSize = requestedSize + (alignedOffset - lower);
|
|
|
|
|
if (size == allocatedSize)
|
2021-11-14 20:36:53 +01:00
|
|
|
{
|
2023-11-08 23:27:21 +01:00
|
|
|
OSubAllocation alloc = new SubAllocation(this, requestedSize, lower, allocatedSize, alignedOffset);
|
|
|
|
|
activeAllocations.add(alloc);
|
|
|
|
|
freeRanges.erase(lower);
|
2023-11-05 10:36:01 +01:00
|
|
|
bytesUsed += allocatedSize;
|
2023-11-12 16:11:27 +01:00
|
|
|
return alloc;
|
2021-11-14 20:36:53 +01:00
|
|
|
}
|
2023-11-08 23:27:21 +01:00
|
|
|
else if (allocatedSize < size)
|
2021-11-14 20:36:53 +01:00
|
|
|
{
|
2023-11-08 23:27:21 +01:00
|
|
|
VkDeviceSize newSize = size - allocatedSize;
|
|
|
|
|
VkDeviceSize newLower = lower + allocatedSize;
|
|
|
|
|
OSubAllocation subAlloc = new SubAllocation(this, requestedSize, lower, allocatedSize, alignedOffset);
|
2023-11-05 10:36:01 +01:00
|
|
|
activeAllocations.add(subAlloc);
|
2023-11-08 23:27:21 +01:00
|
|
|
freeRanges.erase(lower);
|
|
|
|
|
freeRanges[newLower] = newSize;
|
2023-11-05 10:36:01 +01:00
|
|
|
bytesUsed += allocatedSize;
|
2023-11-12 16:11:27 +01:00
|
|
|
return subAlloc;
|
2021-11-14 20:36:53 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
2020-03-20 01:27:40 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-05 10:36:01 +01:00
|
|
|
void Allocation::markFree(PSubAllocation allocation)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
2023-11-08 23:27:21 +01:00
|
|
|
assert(activeAllocations.find(allocation) != activeAllocations.end());
|
2021-11-14 20:36:53 +01:00
|
|
|
VkDeviceSize lowerBound = allocation->allocatedOffset;
|
|
|
|
|
VkDeviceSize upperBound = allocation->allocatedOffset + allocation->allocatedSize;
|
2023-11-08 23:27:21 +01:00
|
|
|
freeRanges[lowerBound] = allocation->allocatedSize;
|
|
|
|
|
for (const auto& [lower, size] : freeRanges)
|
2021-11-14 20:36:53 +01:00
|
|
|
{
|
2023-11-08 23:27:21 +01:00
|
|
|
if (lower + size == lowerBound)
|
2021-11-14 20:36:53 +01:00
|
|
|
{
|
2023-11-08 23:27:21 +01:00
|
|
|
freeRanges[lower] = upperBound;
|
|
|
|
|
freeRanges.erase(lowerBound);
|
|
|
|
|
lowerBound = lower;
|
|
|
|
|
break;
|
2021-11-14 20:36:53 +01:00
|
|
|
}
|
|
|
|
|
}
|
2023-11-08 23:27:21 +01:00
|
|
|
if (freeRanges.find(upperBound) != freeRanges.end())
|
|
|
|
|
{
|
|
|
|
|
freeRanges[lowerBound] += freeRanges[upperBound];
|
|
|
|
|
freeRanges.erase(upperBound);
|
|
|
|
|
}
|
|
|
|
|
activeAllocations.remove(allocation, false);
|
2021-11-14 20:36:53 +01:00
|
|
|
bytesUsed -= allocation->allocatedSize;
|
2023-11-08 23:27:21 +01:00
|
|
|
if (bytesUsed == 0)
|
2022-04-17 09:10:20 +02:00
|
|
|
{
|
|
|
|
|
allocator->free(this);
|
|
|
|
|
}
|
2020-04-12 15:47:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-05 10:36:01 +01:00
|
|
|
void Allocation::flushMemory()
|
|
|
|
|
{
|
|
|
|
|
VkMappedMemoryRange range = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
|
|
|
|
|
.pNext = 0,
|
|
|
|
|
.memory = allocatedMemory,
|
|
|
|
|
.offset = 0,
|
|
|
|
|
.size = bytesAllocated,
|
|
|
|
|
};
|
|
|
|
|
vkFlushMappedMemoryRanges(device, 1, &range);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Allocation::invalidateMemory()
|
|
|
|
|
{
|
|
|
|
|
VkMappedMemoryRange range = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
|
|
|
|
|
.pNext = 0,
|
|
|
|
|
.memory = allocatedMemory,
|
|
|
|
|
.size = bytesAllocated,
|
|
|
|
|
};
|
|
|
|
|
vkInvalidateMappedMemoryRanges(device, 1, &range);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-01 02:17:49 +02:00
|
|
|
Allocator::Allocator(PGraphics graphics)
|
2021-11-14 20:36:53 +01:00
|
|
|
: graphics(graphics)
|
2020-03-13 12:44:33 +01:00
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
vkGetPhysicalDeviceMemoryProperties(graphics->getPhysicalDevice(), &memProperties);
|
2023-11-05 10:36:01 +01:00
|
|
|
heaps.reserve(memProperties.memoryHeapCount);
|
2021-11-14 20:36:53 +01:00
|
|
|
for (size_t i = 0; i < memProperties.memoryHeapCount; ++i)
|
|
|
|
|
{
|
|
|
|
|
VkMemoryHeap memoryHeap = memProperties.memoryHeaps[i];
|
2023-11-05 10:36:01 +01:00
|
|
|
HeapInfo heapInfo;
|
2021-11-14 20:36:53 +01:00
|
|
|
heapInfo.maxSize = memoryHeap.size;
|
2023-11-13 09:07:23 +01:00
|
|
|
//std::cout << "Creating heap " << i << " with properties " << memoryHeap.flags << " size " << memoryHeap.size << std::endl;
|
2023-11-05 10:36:01 +01:00
|
|
|
heaps.add(std::move(heapInfo));
|
2021-11-14 20:36:53 +01:00
|
|
|
}
|
2020-03-20 01:27:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Allocator::~Allocator()
|
|
|
|
|
{
|
2023-11-05 10:36:01 +01:00
|
|
|
for (auto& heap : heaps)
|
2021-11-14 20:36:53 +01:00
|
|
|
{
|
2023-11-05 10:36:01 +01:00
|
|
|
for (auto& alloc : heap.allocations)
|
2021-11-14 20:36:53 +01:00
|
|
|
{
|
|
|
|
|
assert(alloc->activeAllocations.empty());
|
|
|
|
|
assert(alloc->freeRanges.size() == 1);
|
|
|
|
|
}
|
|
|
|
|
heap.allocations.clear();
|
|
|
|
|
}
|
|
|
|
|
graphics = nullptr;
|
2020-03-20 01:27:40 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-05 10:36:01 +01:00
|
|
|
OSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
|
2020-03-20 01:27:40 +01:00
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
const VkMemoryRequirements &requirements = memRequirements2.memoryRequirements;
|
2023-02-13 14:56:13 +01:00
|
|
|
uint32 memoryTypeIndex = findMemoryType(requirements.memoryTypeBits, properties);
|
2021-11-14 20:36:53 +01:00
|
|
|
uint32 heapIndex = memProperties.memoryTypes[memoryTypeIndex].heapIndex;
|
2020-05-05 01:51:13 +02:00
|
|
|
|
2021-11-14 20:36:53 +01:00
|
|
|
if (memRequirements2.pNext != nullptr)
|
|
|
|
|
{
|
|
|
|
|
VkMemoryDedicatedRequirements *dedicatedReq = (VkMemoryDedicatedRequirements *)memRequirements2.pNext;
|
|
|
|
|
if (dedicatedReq->prefersDedicatedAllocation)
|
|
|
|
|
{
|
2023-11-05 10:36:01 +01:00
|
|
|
OAllocation newAllocation = new Allocation(graphics, this, requirements.size, memoryTypeIndex, properties, dedicatedInfo);
|
2022-04-17 09:10:20 +02:00
|
|
|
heaps[heapIndex].inUse += newAllocation->bytesAllocated;
|
2023-11-13 09:07:23 +01:00
|
|
|
//std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize << "%" << std::endl;
|
2023-11-05 10:36:01 +01:00
|
|
|
heaps[heapIndex].allocations.add(std::move(newAllocation));
|
|
|
|
|
return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment);
|
2021-12-22 11:42:07 +01:00
|
|
|
}
|
2021-11-14 20:36:53 +01:00
|
|
|
}
|
2023-11-05 10:36:01 +01:00
|
|
|
for (auto& alloc : heaps[heapIndex].allocations)
|
2021-11-14 20:36:53 +01:00
|
|
|
{
|
2023-02-13 14:56:13 +01:00
|
|
|
if(alloc->memoryTypeIndex == memoryTypeIndex)
|
2021-11-14 20:36:53 +01:00
|
|
|
{
|
2023-11-05 10:36:01 +01:00
|
|
|
OSubAllocation suballoc = alloc->getSuballocation(requirements.size, requirements.alignment);
|
2023-02-13 14:56:13 +01:00
|
|
|
if (suballoc != nullptr)
|
|
|
|
|
{
|
2023-11-08 23:27:21 +01:00
|
|
|
return std::move(suballoc);
|
2023-02-13 14:56:13 +01:00
|
|
|
}
|
2021-11-14 20:36:53 +01:00
|
|
|
}
|
|
|
|
|
}
|
2020-05-05 01:51:13 +02:00
|
|
|
|
2021-11-14 20:36:53 +01:00
|
|
|
// no suitable allocations found, allocate new block
|
2023-11-05 10:36:01 +01:00
|
|
|
OAllocation newAllocation = new Allocation(graphics, this, (requirements.size > MemoryBlockSize) ? requirements.size : (VkDeviceSize)MemoryBlockSize, memoryTypeIndex, properties, nullptr);
|
2022-04-17 09:10:20 +02:00
|
|
|
heaps[heapIndex].inUse += newAllocation->bytesAllocated;
|
2023-11-13 09:07:23 +01:00
|
|
|
//std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize << "%" << std::endl;
|
|
|
|
|
heaps[heapIndex].allocations.add(std::move(newAllocation));
|
2023-11-05 10:36:01 +01:00
|
|
|
return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment);
|
2020-03-20 01:27:40 +01:00
|
|
|
}
|
|
|
|
|
|
2023-11-07 16:55:13 +01:00
|
|
|
void Allocator::free(PAllocation allocation)
|
2020-03-20 01:27:40 +01:00
|
|
|
{
|
2023-11-13 09:07:23 +01:00
|
|
|
//std::cout << "Freeing allocation" << std::endl;
|
2023-11-07 16:55:13 +01:00
|
|
|
for (uint32 heapIndex = 0; heapIndex < heaps.size(); ++heapIndex)
|
2021-11-14 20:36:53 +01:00
|
|
|
{
|
2023-11-07 16:55:13 +01:00
|
|
|
for (uint32 alloc = 0; alloc < heaps[heapIndex].allocations.size(); ++alloc)
|
2021-11-14 20:36:53 +01:00
|
|
|
{
|
2023-11-07 16:55:13 +01:00
|
|
|
if (heaps[heapIndex].allocations[alloc] == allocation)
|
2021-11-14 20:36:53 +01:00
|
|
|
{
|
2023-11-07 16:55:13 +01:00
|
|
|
heaps[heapIndex].inUse -= allocation->bytesAllocated;
|
2023-11-13 09:07:23 +01:00
|
|
|
//std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize << "%" << std::endl;
|
2023-11-08 23:27:21 +01:00
|
|
|
heaps[heapIndex].allocations.removeAt(alloc, false);
|
2021-11-14 20:36:53 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-04-12 15:47:19 +02:00
|
|
|
}
|
2023-02-13 14:56:13 +01:00
|
|
|
uint32 Allocator::findMemoryType(uint32 typeFilter, VkMemoryPropertyFlags properties)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
2023-02-13 14:56:13 +01:00
|
|
|
for (uint32 i = 0; i < memProperties.memoryTypeCount; i++)
|
2021-11-14 20:36:53 +01:00
|
|
|
{
|
2023-02-13 14:56:13 +01:00
|
|
|
if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties)
|
2021-11-14 20:36:53 +01:00
|
|
|
{
|
2023-02-13 14:56:13 +01:00
|
|
|
return i;
|
2021-11-14 20:36:53 +01:00
|
|
|
}
|
|
|
|
|
}
|
2020-05-05 01:51:13 +02:00
|
|
|
|
2023-02-13 14:56:13 +01:00
|
|
|
throw std::runtime_error("error finding memory");
|
2020-04-12 15:47:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-10 19:18:09 +01:00
|
|
|
StagingBuffer::StagingBuffer(OSubAllocation allocation, VkBuffer buffer, VkDeviceSize size, VkBufferUsageFlags usage, uint8 readable)
|
2023-11-05 10:36:01 +01:00
|
|
|
: allocation(std::move(allocation))
|
|
|
|
|
, buffer(buffer)
|
2023-11-10 19:18:09 +01:00
|
|
|
, size(size)
|
2023-11-05 10:36:01 +01:00
|
|
|
, usage(usage)
|
|
|
|
|
, readable(readable)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
StagingBuffer::~StagingBuffer()
|
|
|
|
|
{
|
2023-11-05 10:36:01 +01:00
|
|
|
assert(allocation == nullptr);
|
|
|
|
|
// buffer went out of scope without being cleaned up
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void* StagingBuffer::getMappedPointer()
|
|
|
|
|
{
|
|
|
|
|
return allocation->getMappedPointer();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void StagingBuffer::flushMappedMemory()
|
|
|
|
|
{
|
|
|
|
|
allocation->flushMemory();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void StagingBuffer::invalidateMemory()
|
|
|
|
|
{
|
|
|
|
|
allocation->invalidateMemory();
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-06 14:47:21 +01:00
|
|
|
VkDeviceMemory StagingBuffer::getMemoryHandle() const
|
2023-11-05 10:36:01 +01:00
|
|
|
{
|
|
|
|
|
return allocation->getHandle();
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-06 14:47:21 +01:00
|
|
|
VkDeviceSize StagingBuffer::getOffset() const
|
2023-11-05 10:36:01 +01:00
|
|
|
{
|
|
|
|
|
return allocation->getOffset();
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-06 14:47:21 +01:00
|
|
|
uint64 StagingBuffer::getSize() const
|
2023-11-05 10:36:01 +01:00
|
|
|
{
|
2023-11-10 19:18:09 +01:00
|
|
|
return size;
|
2023-11-05 10:36:01 +01:00
|
|
|
}
|
|
|
|
|
|
2020-04-12 15:47:19 +02:00
|
|
|
StagingManager::StagingManager(PGraphics graphics, PAllocator allocator)
|
2021-11-14 20:36:53 +01:00
|
|
|
: graphics(graphics), allocator(allocator)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
StagingManager::~StagingManager()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void StagingManager::clearPending()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-05 10:36:01 +01:00
|
|
|
OStagingBuffer StagingManager::allocateStagingBuffer(uint64 size, VkBufferUsageFlags usage, bool readable)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
2021-11-14 20:36:53 +01:00
|
|
|
for (auto it = freeBuffers.begin(); it != freeBuffers.end(); ++it)
|
|
|
|
|
{
|
2023-11-05 10:36:01 +01:00
|
|
|
auto& freeBuffer = *it;
|
|
|
|
|
if (freeBuffer->getSize() == size && freeBuffer->isReadable() == readable && freeBuffer->getUsage() == usage)
|
2021-11-14 20:36:53 +01:00
|
|
|
{
|
|
|
|
|
//std::cout << "Reusing staging buffer" << std::endl;
|
2023-11-05 10:36:01 +01:00
|
|
|
activeBuffers.add(freeBuffer);
|
2023-11-06 14:47:21 +01:00
|
|
|
OStagingBuffer owner = std::move(freeBuffer);
|
2021-11-14 20:36:53 +01:00
|
|
|
freeBuffers.remove(it, false);
|
2023-11-08 23:27:21 +01:00
|
|
|
return std::move(owner);
|
2021-11-14 20:36:53 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//std::cout << "Creating new stagingbuffer" << std::endl;
|
2023-11-05 10:36:01 +01:00
|
|
|
VkBuffer buffer;
|
2021-11-14 20:36:53 +01:00
|
|
|
VkBufferCreateInfo stagingBufferCreateInfo = init::BufferCreateInfo(usage, size);
|
|
|
|
|
stagingBufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
2022-01-12 14:40:26 +01:00
|
|
|
uint32 queueIndex = graphics->getFamilyMapping().getQueueTypeFamilyIndex(Gfx::QueueType::DEDICATED_TRANSFER);
|
|
|
|
|
stagingBufferCreateInfo.queueFamilyIndexCount = 1;
|
|
|
|
|
stagingBufferCreateInfo.pQueueFamilyIndices = &queueIndex;
|
2021-11-14 20:36:53 +01:00
|
|
|
VkDevice vulkanDevice = graphics->getDevice();
|
2020-04-12 15:47:19 +02:00
|
|
|
|
2023-11-05 10:36:01 +01:00
|
|
|
VK_CHECK(vkCreateBuffer(vulkanDevice, &stagingBufferCreateInfo, nullptr, &buffer));
|
2020-04-12 15:47:19 +02:00
|
|
|
|
2023-11-05 10:36:01 +01:00
|
|
|
VkMemoryDedicatedRequirements dedicatedReqs = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
|
|
|
|
|
.pNext = nullptr,
|
|
|
|
|
};
|
|
|
|
|
VkMemoryRequirements2 memReqs = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
|
|
|
|
|
.pNext = &dedicatedReqs,
|
|
|
|
|
};
|
|
|
|
|
VkBufferMemoryRequirementsInfo2 bufferQuery = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
|
|
|
|
|
.pNext = nullptr,
|
|
|
|
|
.buffer = buffer,
|
|
|
|
|
};
|
2021-11-14 20:36:53 +01:00
|
|
|
vkGetBufferMemoryRequirements2(vulkanDevice, &bufferQuery, &memReqs);
|
2020-04-12 15:47:19 +02:00
|
|
|
|
2021-11-14 20:36:53 +01:00
|
|
|
memReqs.memoryRequirements.alignment =
|
|
|
|
|
(16 > memReqs.memoryRequirements.alignment) ? 16 : memReqs.memoryRequirements.alignment;
|
2020-05-05 01:51:13 +02:00
|
|
|
|
2023-11-05 10:36:01 +01:00
|
|
|
OStagingBuffer stagingBuffer = new StagingBuffer(
|
|
|
|
|
allocator->allocate(memReqs, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | (readable ? VK_MEMORY_PROPERTY_HOST_COHERENT_BIT : VK_MEMORY_PROPERTY_HOST_CACHED_BIT), buffer),
|
|
|
|
|
buffer,
|
2023-11-10 19:18:09 +01:00
|
|
|
size,
|
2023-11-05 10:36:01 +01:00
|
|
|
usage,
|
|
|
|
|
readable
|
|
|
|
|
);
|
|
|
|
|
vkBindBufferMemory(graphics->getDevice(), buffer, stagingBuffer->getMemoryHandle(), stagingBuffer->getOffset());
|
|
|
|
|
|
|
|
|
|
activeBuffers.add(stagingBuffer);
|
2021-11-14 20:36:53 +01:00
|
|
|
|
2023-11-08 23:27:21 +01:00
|
|
|
return std::move(stagingBuffer);
|
2020-04-12 15:47:19 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-05 10:36:01 +01:00
|
|
|
void StagingManager::releaseStagingBuffer(OStagingBuffer buffer)
|
2020-04-12 15:47:19 +02:00
|
|
|
{
|
2023-11-07 16:55:13 +01:00
|
|
|
if (buffer == nullptr)
|
2023-11-06 14:47:21 +01:00
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-11-05 10:36:01 +01:00
|
|
|
activeBuffers.remove(buffer);
|
|
|
|
|
freeBuffers.add(std::move(buffer));
|
2020-03-20 01:27:40 +01:00
|
|
|
}
|