124 lines
3.8 KiB
C++
124 lines
3.8 KiB
C++
#include "VulkanAllocator.h"
|
|
#include "VulkanGraphics.h"
|
|
#include "VulkanInitializer.h"
|
|
#include "Math/MemCRC.h"
|
|
|
|
using namespace Seele::Vulkan;
|
|
|
|
SubAllocation::SubAllocation(Allocation* owner, uint32 allocatedOffset, uint32 size, uint32 alignedOffset, uint32 allocatedSize)
|
|
: owner(owner)
|
|
, size(size)
|
|
, allocatedOffset(allocatedOffset)
|
|
, alignedOffset(alignedOffset)
|
|
, allocatedSize(allocatedSize)
|
|
{
|
|
}
|
|
|
|
Allocation::Allocation(PGraphics graphics, Allocator* allocator, uint32 size, uint32 memoryTypeIndex, VkMemoryPropertyFlags properties, bool isDedicated)
|
|
: device(graphics->getDevice())
|
|
, allocator(allocator)
|
|
, bytesAllocated(0)
|
|
, bytesUsed(0)
|
|
, properties(properties)
|
|
, memoryTypeIndex(memoryTypeIndex)
|
|
{
|
|
VkMemoryAllocateInfo allocInfo =
|
|
init::MemoryAllocateInfo();
|
|
allocInfo.allocationSize = size;
|
|
allocInfo.memoryTypeIndex = memoryTypeIndex;
|
|
VK_CHECK(vkAllocateMemory(device, &allocInfo, nullptr, &allocatedMemory));
|
|
bytesAllocated = size;
|
|
PSubAllocation freeRange = new SubAllocation(this, 0, size, 0, size);
|
|
freeRanges.add(freeRange);
|
|
}
|
|
|
|
PSubAllocation Allocation::getSuballocation(uint32 requestedSize, uint32 alignment)
|
|
{
|
|
if (isDedicated)
|
|
{
|
|
if (activeAllocations.size() == 0)
|
|
{
|
|
assert(requestedSize == bytesAllocated);
|
|
activeAllocations.add(freeRanges.back());
|
|
freeRanges.clear();
|
|
}
|
|
else
|
|
{
|
|
return nullptr;
|
|
}
|
|
}
|
|
for (int i = 0; i < freeRanges.size(); ++i)
|
|
{
|
|
PSubAllocation freeAllocation = freeRanges[i];
|
|
uint32 allocatedOffset = freeAllocation->allocatedOffset;
|
|
uint32 alignedOffset = align(allocatedOffset, alignment);
|
|
uint32 alignmentAdjustment = alignedOffset - allocatedOffset;
|
|
uint32 size = alignmentAdjustment + requestedSize;
|
|
if (freeAllocation->size == size)
|
|
{
|
|
freeRanges.remove(i);
|
|
activeAllocations.add(freeAllocation);
|
|
return freeAllocation;
|
|
}
|
|
else if (size < freeAllocation->allocatedSize)
|
|
{
|
|
freeAllocation->size -= size;
|
|
freeAllocation->allocatedSize -= size;
|
|
freeAllocation->allocatedOffset += allocatedOffset;
|
|
freeAllocation->alignedOffset += allocatedOffset;
|
|
PSubAllocation subAlloc = new SubAllocation(this, allocatedOffset, size, alignedOffset, size);
|
|
activeAllocations.add(subAlloc);
|
|
return subAlloc;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Allocator::Allocator(PGraphics graphics)
|
|
: graphics(graphics)
|
|
{
|
|
vkGetPhysicalDeviceMemoryProperties(graphics->getPhysicalDevice(), &memProperties);
|
|
heaps.resize(memProperties.memoryHeapCount);
|
|
for (size_t i = 0; i < memProperties.memoryHeapCount; i++)
|
|
{
|
|
VkMemoryHeap memoryHeap = memProperties.memoryHeaps[i];
|
|
HeapInfo& heapInfo = heaps[i];
|
|
heapInfo.maxSize = memoryHeap.size;
|
|
}
|
|
}
|
|
|
|
Allocator::~Allocator()
|
|
{
|
|
}
|
|
|
|
PSubAllocation Allocator::allocate(uint64 size, const VkMemoryRequirements2& memRequirements2, VkMemoryPropertyFlags properties)
|
|
{
|
|
// no suitable allocations found, allocate new block
|
|
const VkMemoryRequirements& requirements = memRequirements2.memoryRequirements;
|
|
uint32 memoryTypeIndex;
|
|
VK_CHECK(findMemoryType(requirements.memoryTypeBits, properties, &memoryTypeIndex));
|
|
|
|
bool isDedicated = memRequirements2.pNext != nullptr;
|
|
PAllocation newAllocation = new Allocation(graphics, this, MemoryBlockSize, memoryTypeIndex, properties, isDedicated);
|
|
uint32 heapIndex = memProperties.memoryTypes[memoryTypeIndex].heapIndex;
|
|
heaps[heapIndex].allocations.add(newAllocation);
|
|
return newAllocation->getSuballocation(size, requirements.alignment);
|
|
}
|
|
|
|
VkResult Allocator::findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties, uint32* typeIndex)
|
|
{
|
|
for (int memoryIndex = 0; memoryIndex < memProperties.memoryTypeCount && typeBits; ++memoryIndex)
|
|
{
|
|
if ((typeBits & 1) == 1)
|
|
{
|
|
if ((memProperties.memoryTypes[memoryIndex].propertyFlags & properties) == properties)
|
|
{
|
|
*typeIndex = memoryIndex;
|
|
return VK_SUCCESS;
|
|
}
|
|
}
|
|
typeBits >>= 1;
|
|
}
|
|
|
|
return VK_ERROR_FORMAT_NOT_SUPPORTED;
|
|
} |