Files
Seele/src/Engine/Graphics/Vulkan/VulkanAllocator.h
T

230 lines
5.2 KiB
C++
Raw Normal View History

2020-03-13 12:44:33 +01:00
#pragma once
#include "MinimalEngine.h"
#include "VulkanGraphicsEnums.h"
#include "Containers/Map.h"
#include "Containers/Array.h"
2020-06-02 11:46:18 +02:00
#include <mutex>
2020-03-13 12:44:33 +01:00
namespace Seele
{
2020-04-12 15:47:19 +02:00
namespace Vulkan
{
2021-04-01 16:40:14 +02:00
DECLARE_REF(Graphics)
2020-04-12 15:47:19 +02:00
class Allocation;
class Allocator;
class SubAllocation
{
public:
SubAllocation(Allocation *owner, VkDeviceSize allocatedOffset, VkDeviceSize size, VkDeviceSize alignedOffset, VkDeviceSize allocatedSize);
~SubAllocation();
VkDeviceMemory getHandle() const;
inline VkDeviceSize getSize() const
2020-03-13 12:44:33 +01:00
{
2020-04-12 15:47:19 +02:00
return size;
}
2020-04-12 15:47:19 +02:00
inline VkDeviceSize getOffset() const
{
return alignedOffset;
}
inline bool isReadable() const;
void *getMappedPointer();
void flushMemory();
void invalidateMemory();
private:
Allocation *owner;
VkDeviceSize size;
2021-04-01 16:40:14 +02:00
VkDeviceSize allocatedOffset;
2020-04-12 15:47:19 +02:00
VkDeviceSize alignedOffset;
VkDeviceSize allocatedSize;
friend class Allocation;
friend class Allocator;
};
2021-04-01 16:40:14 +02:00
DEFINE_REF(SubAllocation)
2020-04-12 15:47:19 +02:00
class Allocation
{
public:
Allocation(PGraphics graphics, Allocator *allocator, VkDeviceSize size, uint8 memoryTypeIndex,
VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo = nullptr);
~Allocation();
PSubAllocation getSuballocation(VkDeviceSize size, VkDeviceSize alignment);
void markFree(SubAllocation *alloc);
inline VkDeviceMemory getHandle() const
{
return allocatedMemory;
}
inline void *getMappedPointer()
{
if (!canMap)
{
return nullptr;
}
if (!isMapped)
{
vkMapMemory(device, allocatedMemory, 0, bytesAllocated, 0, &mappedPointer);
isMapped = true;
}
return mappedPointer;
}
inline bool isReadable() const
{
return readable;
}
void flushMemory()
{
VkMappedMemoryRange range;
range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
range.pNext = 0;
range.memory = allocatedMemory;
range.size = bytesAllocated;
range.offset = 0;
vkFlushMappedMemoryRanges(device, 1, &range);
}
void invalidateMemory()
{
VkMappedMemoryRange range;
range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
range.pNext = 0;
range.memory = allocatedMemory;
range.size = bytesAllocated;
vkInvalidateMappedMemoryRanges(device, 1, &range);
}
private:
VkDevice device;
2021-04-01 16:40:14 +02:00
Allocator *allocator;
2020-04-12 15:47:19 +02:00
VkDeviceSize bytesAllocated;
VkDeviceSize bytesUsed;
2021-04-01 16:40:14 +02:00
VkDeviceMemory allocatedMemory;
2022-04-15 23:45:44 +02:00
std::map<VkDeviceSize, SubAllocation *> activeAllocations;
std::map<VkDeviceSize, PSubAllocation> freeRanges;
2020-06-02 11:46:18 +02:00
std::mutex lock;
2020-04-12 15:47:19 +02:00
void *mappedPointer;
uint8 isDedicated : 1;
uint8 canMap : 1;
uint8 isMapped : 1;
uint8 readable : 1;
2021-04-01 16:40:14 +02:00
VkMemoryPropertyFlags properties;
uint8 memoryTypeIndex;
2020-04-12 15:47:19 +02:00
friend class Allocator;
};
2021-04-01 16:40:14 +02:00
DEFINE_REF(Allocation)
2020-04-12 15:47:19 +02:00
class Allocator
{
public:
Allocator(PGraphics graphics);
~Allocator();
PSubAllocation allocate(const VkMemoryRequirements2 &requirements, VkMemoryPropertyFlags props,
VkMemoryDedicatedAllocateInfo *dedicatedInfo = nullptr);
inline PSubAllocation allocate(const VkMemoryRequirements2 &requirements, VkMemoryPropertyFlags props,
VkBuffer buffer)
{
VkMemoryDedicatedAllocateInfo allocInfo;
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
allocInfo.pNext = nullptr;
allocInfo.buffer = buffer;
allocInfo.image = VK_NULL_HANDLE;
return allocate(requirements, props, &allocInfo);
}
inline PSubAllocation allocate(const VkMemoryRequirements2 &requirements, VkMemoryPropertyFlags props,
VkImage image)
{
VkMemoryDedicatedAllocateInfo allocInfo;
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
allocInfo.pNext = nullptr;
allocInfo.buffer = VK_NULL_HANDLE;
allocInfo.image = image;
return allocate(requirements, props, &allocInfo);
}
void free(Allocation *allocation);
private:
enum
{
2022-02-24 22:38:26 +01:00
MemoryBlockSize = 16 * 1024 * 1024 // 16MB
2020-04-12 15:47:19 +02:00
};
struct HeapInfo
{
VkDeviceSize maxSize = 0;
Array<PAllocation> allocations;
};
Array<HeapInfo> heaps;
VkResult findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties, uint8 *typeIndex);
2020-06-02 11:46:18 +02:00
std::mutex lock;
2020-04-12 15:47:19 +02:00
PGraphics graphics;
VkPhysicalDeviceMemoryProperties memProperties;
};
2021-04-01 16:40:14 +02:00
DEFINE_REF(Allocator)
2020-04-12 15:47:19 +02:00
class StagingBuffer
{
public:
StagingBuffer();
~StagingBuffer();
void *getMappedPointer()
{
return allocation->getMappedPointer();
}
void flushMappedMemory()
{
allocation->flushMemory();
}
void invalidateMemory()
{
allocation->invalidateMemory();
}
VkBuffer getHandle() const
{
return buffer;
}
VkDeviceMemory getMemoryHandle() const
{
return allocation->getHandle();
}
VkDeviceSize getOffset() const
{
return allocation->getOffset();
}
uint32 getSize() const
{
return size;
}
bool isReadable() const
{
return bReadable;
}
2020-04-12 15:47:19 +02:00
private:
PSubAllocation allocation;
VkBuffer buffer;
uint32 size;
VkBufferUsageFlags usage;
2020-04-12 15:47:19 +02:00
uint8 bReadable;
friend class StagingManager;
};
2021-04-01 16:40:14 +02:00
DEFINE_REF(StagingBuffer)
2020-04-12 15:47:19 +02:00
class StagingManager
{
public:
StagingManager(PGraphics graphics, PAllocator allocator);
~StagingManager();
PStagingBuffer allocateStagingBuffer(uint32 size, VkBufferUsageFlags usageFlags = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, bool bCPURead = false);
void releaseStagingBuffer(PStagingBuffer buffer);
void clearPending();
private:
PGraphics graphics;
PAllocator allocator;
Array<PStagingBuffer> freeBuffers;
Array<StagingBuffer *> activeBuffers;
2020-09-19 14:36:50 +02:00
std::mutex lock;
2020-04-12 15:47:19 +02:00
};
2021-04-01 16:40:14 +02:00
DEFINE_REF(StagingManager)
2020-04-12 15:47:19 +02:00
} // namespace Vulkan
} // namespace Seele