Files
Seele/src/Engine/Graphics/Vulkan/Allocator.cpp
T

354 lines
12 KiB
C++
Raw Normal View History

2023-10-26 18:37:29 +02:00
#include "Allocator.h"
#include "Graphics.h"
2023-11-15 00:06:00 +01:00
#include "Resources.h"
2023-11-15 17:42:57 +01:00
#include "Enums.h"
#include "Command.h"
using namespace Seele::Vulkan;
2023-11-08 23:27:21 +01:00
SubAllocation::SubAllocation(PAllocation owner, VkDeviceSize requestedSize, VkDeviceSize allocatedOffset, VkDeviceSize allocatedSize, VkDeviceSize alignedOffset)
: owner(owner)
2023-11-08 23:27:21 +01:00
, requestedSize(requestedSize)
, allocatedOffset(allocatedOffset)
, allocatedSize(allocatedSize)
2023-11-08 23:27:21 +01:00
, alignedOffset(alignedOffset)
{
}
2020-04-12 15:47:19 +02:00
SubAllocation::~SubAllocation()
{
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
{
return owner->getHandle();
2020-04-12 15:47:19 +02:00
}
2023-11-15 00:06:00 +01:00
void *SubAllocation::map()
2020-04-12 15:47:19 +02:00
{
2023-11-15 00:06:00 +01:00
return (uint8 *)owner->map() + alignedOffset;
2020-04-12 15:47:19 +02:00
}
void SubAllocation::flushMemory()
{
owner->flushMemory();
2020-04-12 15:47:19 +02:00
}
2023-11-15 00:06:00 +01:00
void SubAllocation::invalidate()
2020-04-12 15:47:19 +02:00
{
2023-11-15 00:06:00 +01:00
owner->invalidate();
2020-04-12 15:47:19 +02:00
}
2023-11-15 17:42:57 +01:00
Allocation::Allocation(PGraphics graphics, PAllocator pool, VkDeviceSize size, uint8 memoryTypeIndex,
VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
: device(graphics->getDevice())
2023-11-15 17:42:57 +01:00
, pool(pool)
2023-11-16 22:58:47 +01:00
, bytesAllocated(size)
, bytesUsed(0)
2023-11-16 22:58:47 +01:00
, mappedPointer(nullptr)
2023-11-15 17:42:57 +01:00
, canMap((properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
, isMapped(false)
, properties(properties)
, memoryTypeIndex(memoryTypeIndex)
{
2023-11-15 00:06:00 +01:00
VkMemoryAllocateInfo allocInfo = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.pNext = dedicatedInfo,
.allocationSize = size,
.memoryTypeIndex = memoryTypeIndex,
};
isDedicated = dedicatedInfo != nullptr;
VK_CHECK(vkAllocateMemory(device, &allocInfo, nullptr, &allocatedMemory));
2023-11-08 23:27:21 +01:00
freeRanges[0] = size;
}
2020-04-12 15:47:19 +02:00
Allocation::~Allocation()
{
2023-11-13 09:07:23 +01:00
vkFreeMemory(device, allocatedMemory, nullptr);
2020-04-12 15:47:19 +02:00
}
2023-11-05 10:36:01 +01:00
OSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDeviceSize alignment)
{
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);
freeRanges.clear();
bytesUsed += requestedSize;
return suballoc;
}
else
{
return nullptr;
}
}
2023-11-08 23:27:21 +01:00
for (const auto& [lower, size] : freeRanges)
{
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);
2023-11-15 17:42:57 +01:00
if (size >= allocatedSize)
{
2023-11-16 22:58:47 +01:00
//std::cout << "Allocating " << lower << "-" << lower + allocatedSize << std::endl;
2023-11-08 23:27:21 +01:00
VkDeviceSize newSize = size - allocatedSize;
VkDeviceSize newLower = lower + allocatedSize;
2023-11-15 00:06:00 +01:00
OSubAllocation alloc = new SubAllocation(this, requestedSize, lower, allocatedSize, alignedOffset);
activeAllocations.add(alloc);
2023-11-08 23:27:21 +01:00
freeRanges.erase(lower);
2023-11-15 00:06:00 +01:00
if (newSize > 0)
{
freeRanges[newLower] = newSize;
}
2023-11-05 10:36:01 +01:00
bytesUsed += allocatedSize;
2023-11-15 00:06:00 +01:00
return alloc;
}
}
return nullptr;
}
2023-11-05 10:36:01 +01:00
void Allocation::markFree(PSubAllocation allocation)
2020-04-12 15:47:19 +02:00
{
2023-11-16 22:58:47 +01:00
//std::cout << "Freeing " << allocation->allocatedOffset << "-" << allocation->allocatedOffset + allocation->allocatedSize << std::endl;
2023-11-08 23:27:21 +01:00
assert(activeAllocations.find(allocation) != activeAllocations.end());
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)
{
2023-11-08 23:27:21 +01:00
if (lower + size == lowerBound)
{
2023-11-16 22:58:47 +01:00
freeRanges[lower] = size + allocation->allocatedSize;
2023-11-08 23:27:21 +01:00
freeRanges.erase(lowerBound);
lowerBound = lower;
break;
}
}
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);
bytesUsed -= allocation->allocatedSize;
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);
}
2023-11-15 00:06:00 +01:00
void Allocation::invalidate()
2023-11-05 10:36:01 +01:00
{
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)
: graphics(graphics)
2020-03-13 12:44:33 +01:00
{
vkGetPhysicalDeviceMemoryProperties(graphics->getPhysicalDevice(), &memProperties);
2023-11-05 10:36:01 +01:00
heaps.reserve(memProperties.memoryHeapCount);
for (size_t i = 0; i < memProperties.memoryHeapCount; ++i)
{
VkMemoryHeap memoryHeap = memProperties.memoryHeaps[i];
2023-11-05 10:36:01 +01:00
HeapInfo heapInfo;
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));
}
}
Allocator::~Allocator()
{
}
2023-11-05 10:36:01 +01:00
OSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
{
const VkMemoryRequirements &requirements = memRequirements2.memoryRequirements;
2023-02-13 14:56:13 +01:00
uint32 memoryTypeIndex = findMemoryType(requirements.memoryTypeBits, properties);
uint32 heapIndex = memProperties.memoryTypes[memoryTypeIndex].heapIndex;
2020-05-05 01:51:13 +02: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-16 22:58:47 +01:00
std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << 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
}
}
2023-11-05 10:36:01 +01:00
for (auto& alloc : heaps[heapIndex].allocations)
{
2023-02-13 14:56:13 +01:00
if(alloc->memoryTypeIndex == memoryTypeIndex)
{
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
}
}
}
2020-05-05 01:51:13 +02:00
// no suitable allocations found, allocate new block
2023-11-15 00:06:00 +01:00
OAllocation newAllocation = new Allocation(graphics, this, (requirements.size > DEFAULT_ALLOCATION) ? requirements.size : DEFAULT_ALLOCATION, memoryTypeIndex, properties, nullptr);
2022-04-17 09:10:20 +02:00
heaps[heapIndex].inUse += newAllocation->bytesAllocated;
2023-11-16 22:58:47 +01:00
std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << std::endl;
2023-11-13 09:07:23 +01:00
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);
}
2023-11-07 16:55:13 +01:00
void Allocator::free(PAllocation allocation)
{
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)
{
2023-11-07 16:55:13 +01:00
for (uint32 alloc = 0; alloc < heaps[heapIndex].allocations.size(); ++alloc)
{
2023-11-07 16:55:13 +01:00
if (heaps[heapIndex].allocations[alloc] == allocation)
{
2023-11-07 16:55:13 +01:00
heaps[heapIndex].inUse -= allocation->bytesAllocated;
2023-11-16 22:58:47 +01:00
std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << std::endl;
2023-11-08 23:27:21 +01:00
heaps[heapIndex].allocations.removeAt(alloc, false);
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++)
{
2023-02-13 14:56:13 +01:00
if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties)
{
2023-02-13 14:56:13 +01:00
return i;
}
}
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-15 00:06:00 +01:00
StagingBuffer::StagingBuffer(PGraphics graphics, OSubAllocation allocation, VkBuffer buffer, VkDeviceSize size)
: QueueOwnedResource(graphics->getFamilyMapping(), Gfx::QueueType::DEDICATED_TRANSFER)
, graphics(graphics)
, allocation(std::move(allocation))
2023-11-05 10:36:01 +01:00
, buffer(buffer)
2023-11-10 19:18:09 +01:00
, size(size)
2020-04-12 15:47:19 +02:00
{
}
StagingBuffer::~StagingBuffer()
{
2023-11-15 00:06:00 +01:00
graphics->getDestructionManager()->queueBuffer(
graphics->getDedicatedTransferCommands()->getCommands(), buffer);
2023-11-15 17:42:57 +01:00
graphics->getDestructionManager()->queueAllocation(
graphics->getDedicatedTransferCommands()->getCommands(), std::move(allocation));
2023-12-02 10:55:00 +01:00
graphics->getDedicatedTransferCommands()->submitCommands();
2023-11-05 10:36:01 +01:00
}
2023-11-15 00:06:00 +01:00
void* StagingBuffer::map()
2023-11-05 10:36:01 +01:00
{
2023-11-15 00:06:00 +01:00
return allocation->map();
2023-11-05 10:36:01 +01:00
}
2023-11-15 00:06:00 +01:00
void StagingBuffer::flush()
2023-11-05 10:36:01 +01:00
{
allocation->flushMemory();
}
2023-11-15 00:06:00 +01:00
void StagingBuffer::invalidate()
2023-11-05 10:36:01 +01:00
{
2023-11-15 00:06:00 +01:00
allocation->invalidate();
2023-11-05 10:36:01 +01:00
}
2023-11-15 00:06:00 +01:00
VkDeviceMemory StagingBuffer::getMemory() 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-15 00:06:00 +01:00
void StagingBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
2023-11-05 10:36:01 +01:00
{
2023-11-15 00:06:00 +01:00
assert(false);
}
void StagingBuffer::executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage,
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage)
{
assert(false);
2023-11-05 10:36:01 +01:00
}
2023-11-15 17:42:57 +01:00
StagingManager::StagingManager(PGraphics graphics, PAllocator pool)
: graphics(graphics), pool(pool)
2020-04-12 15:47:19 +02:00
{
}
StagingManager::~StagingManager()
{
}
2023-11-15 00:06:00 +01:00
OStagingBuffer StagingManager::create(uint64 size)
2020-04-12 15:47:19 +02:00
{
//std::cout << "Creating new stagingbuffer" << std::endl;
2022-01-12 14:40:26 +01:00
uint32 queueIndex = graphics->getFamilyMapping().getQueueTypeFamilyIndex(Gfx::QueueType::DEDICATED_TRANSFER);
2023-11-15 00:06:00 +01:00
VkBufferCreateInfo stagingBufferCreateInfo = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.size = size,
2023-11-22 13:18:54 +01:00
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
2023-11-15 00:06:00 +01:00
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 1,
.pQueueFamilyIndices = &queueIndex,
};
VkBuffer buffer;
VK_CHECK(vkCreateBuffer(graphics->getDevice(), &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,
};
2023-11-15 00:06:00 +01:00
vkGetBufferMemoryRequirements2(graphics->getDevice(), &bufferQuery, &memReqs);
2020-05-05 01:51:13 +02:00
2023-11-05 10:36:01 +01:00
OStagingBuffer stagingBuffer = new StagingBuffer(
2023-11-15 00:06:00 +01:00
graphics,
2023-11-15 17:42:57 +01:00
pool->allocate(memReqs, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT, buffer),
2023-11-05 10:36:01 +01:00
buffer,
2023-11-15 00:06:00 +01:00
size
2023-11-05 10:36:01 +01:00
);
2023-11-15 00:06:00 +01:00
vkBindBufferMemory(graphics->getDevice(), buffer, stagingBuffer->getMemory(), stagingBuffer->getOffset());
2023-11-15 00:06:00 +01:00
return stagingBuffer;
2020-04-12 15:47:19 +02:00
}