implementing renderpass and vieport
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
using namespace Seele::Vulkan;
|
||||
|
||||
SubAllocation::SubAllocation(Allocation* owner, uint32 allocatedOffset, uint32 size, uint32 alignedOffset, uint32 allocatedSize)
|
||||
SubAllocation::SubAllocation(Allocation* owner, VkDeviceSize allocatedOffset, VkDeviceSize size, VkDeviceSize alignedOffset, VkDeviceSize allocatedSize)
|
||||
: owner(owner)
|
||||
, size(size)
|
||||
, allocatedOffset(allocatedOffset)
|
||||
@@ -14,11 +14,43 @@ SubAllocation::SubAllocation(Allocation* owner, uint32 allocatedOffset, uint32 s
|
||||
{
|
||||
}
|
||||
|
||||
Allocation::Allocation(PGraphics graphics, Allocator* allocator, uint32 size, uint32 memoryTypeIndex, VkMemoryPropertyFlags properties, bool isDedicated)
|
||||
SubAllocation::~SubAllocation()
|
||||
{
|
||||
owner->markFree(this);
|
||||
}
|
||||
|
||||
VkDeviceMemory SubAllocation::getHandle() const
|
||||
{
|
||||
return owner->getHandle();
|
||||
}
|
||||
|
||||
bool SubAllocation::isReadable() const
|
||||
{
|
||||
return owner->isReadable();
|
||||
}
|
||||
|
||||
void* SubAllocation::getMappedPointer()
|
||||
{
|
||||
return (uint8*)owner->getMappedPointer() + alignedOffset;
|
||||
}
|
||||
|
||||
void SubAllocation::flushMemory()
|
||||
{
|
||||
owner->flushMemory();
|
||||
}
|
||||
|
||||
void SubAllocation::invalidateMemory()
|
||||
{
|
||||
owner->invalidateMemory();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -26,38 +58,52 @@ Allocation::Allocation(PGraphics graphics, Allocator* allocator, uint32 size, ui
|
||||
init::MemoryAllocateInfo();
|
||||
allocInfo.allocationSize = size;
|
||||
allocInfo.memoryTypeIndex = memoryTypeIndex;
|
||||
isDedicated = dedicatedInfo != nullptr;
|
||||
allocInfo.pNext = dedicatedInfo;
|
||||
VK_CHECK(vkAllocateMemory(device, &allocInfo, nullptr, &allocatedMemory));
|
||||
bytesAllocated = size;
|
||||
PSubAllocation freeRange = new SubAllocation(this, 0, size, 0, size);
|
||||
freeRanges.add(freeRange);
|
||||
freeRanges[0] = freeRange;
|
||||
|
||||
canMap = (properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
|
||||
isMapped = false;
|
||||
}
|
||||
|
||||
PSubAllocation Allocation::getSuballocation(uint32 requestedSize, uint32 alignment)
|
||||
Allocation::~Allocation()
|
||||
{
|
||||
allocator->free(this);
|
||||
}
|
||||
|
||||
PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDeviceSize alignment)
|
||||
{
|
||||
if (isDedicated)
|
||||
{
|
||||
if (activeAllocations.size() == 0)
|
||||
if (activeAllocations.empty())
|
||||
{
|
||||
assert(requestedSize == bytesAllocated);
|
||||
activeAllocations.add(freeRanges.back());
|
||||
PSubAllocation suballoc = freeRanges[0];
|
||||
activeAllocations[0] = suballoc.getHandle();
|
||||
freeRanges.clear();
|
||||
bytesUsed += requestedSize;
|
||||
return suballoc;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < freeRanges.size(); ++i)
|
||||
for (uint32 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;
|
||||
VkDeviceSize allocatedOffset = freeAllocation->allocatedOffset;
|
||||
VkDeviceSize alignedOffset = align(allocatedOffset, alignment);
|
||||
VkDeviceSize alignmentAdjustment = alignedOffset - allocatedOffset;
|
||||
VkDeviceSize size = alignmentAdjustment + requestedSize;
|
||||
if (freeAllocation->size == size)
|
||||
{
|
||||
freeRanges.remove(i);
|
||||
activeAllocations.add(freeAllocation);
|
||||
freeRanges.erase(allocatedOffset);
|
||||
activeAllocations[allocatedOffset] = freeAllocation.getHandle();
|
||||
bytesUsed += size;
|
||||
return freeAllocation;
|
||||
}
|
||||
else if (size < freeAllocation->allocatedSize)
|
||||
@@ -67,19 +113,61 @@ PSubAllocation Allocation::getSuballocation(uint32 requestedSize, uint32 alignme
|
||||
freeAllocation->allocatedOffset += allocatedOffset;
|
||||
freeAllocation->alignedOffset += allocatedOffset;
|
||||
PSubAllocation subAlloc = new SubAllocation(this, allocatedOffset, size, alignedOffset, size);
|
||||
activeAllocations.add(subAlloc);
|
||||
activeAllocations[allocatedOffset] = subAlloc.getHandle();
|
||||
freeRanges.erase(allocatedOffset);
|
||||
freeRanges[freeAllocation->allocatedOffset] = freeAllocation;
|
||||
bytesUsed += size;
|
||||
return subAlloc;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Allocation::markFree(SubAllocation* allocation)
|
||||
{
|
||||
VkDeviceSize lowerBound = allocation->allocatedOffset;
|
||||
VkDeviceSize upperBound = allocation->allocatedOffset + allocation->allocatedSize;
|
||||
PSubAllocation allocHandle;
|
||||
for(auto freeRange : freeRanges)
|
||||
{
|
||||
PSubAllocation freeAlloc = freeRange.value;
|
||||
if(freeAlloc->allocatedOffset + freeAlloc->allocatedSize + 1 == lowerBound)
|
||||
{
|
||||
freeAlloc->allocatedSize += allocation->allocatedSize;
|
||||
allocHandle = freeAlloc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto foundAlloc = freeRanges.find(upperBound + 1);
|
||||
if(foundAlloc != freeRanges.end())
|
||||
{
|
||||
if(allocHandle == nullptr)
|
||||
{
|
||||
allocHandle->allocatedSize += foundAlloc->value->allocatedSize;
|
||||
freeRanges.erase(foundAlloc->key);
|
||||
}
|
||||
else
|
||||
{
|
||||
allocHandle = foundAlloc->value;
|
||||
allocHandle->allocatedOffset -= allocation->allocatedSize;
|
||||
allocHandle->alignedOffset -= allocation->allocatedSize;
|
||||
}
|
||||
}
|
||||
if(allocHandle == nullptr)
|
||||
{
|
||||
allocHandle = new SubAllocation(this, allocation->alignedOffset, allocation->size, allocation->alignedOffset, allocation->allocatedSize);
|
||||
freeRanges[allocation->allocatedOffset] = allocHandle;
|
||||
}
|
||||
activeAllocations.erase(allocation->allocatedOffset);
|
||||
bytesUsed -= allocation->allocatedSize;
|
||||
}
|
||||
|
||||
Allocator::Allocator(PGraphics graphics)
|
||||
: graphics(graphics)
|
||||
{
|
||||
vkGetPhysicalDeviceMemoryProperties(graphics->getPhysicalDevice(), &memProperties);
|
||||
heaps.resize(memProperties.memoryHeapCount);
|
||||
for (size_t i = 0; i < memProperties.memoryHeapCount; i++)
|
||||
for (size_t i = 0; i < memProperties.memoryHeapCount; ++i)
|
||||
{
|
||||
VkMemoryHeap memoryHeap = memProperties.memoryHeaps[i];
|
||||
HeapInfo& heapInfo = heaps[i];
|
||||
@@ -89,25 +177,68 @@ Allocator::Allocator(PGraphics graphics)
|
||||
|
||||
Allocator::~Allocator()
|
||||
{
|
||||
for(auto heap : heaps)
|
||||
{
|
||||
for(auto alloc : heap.allocations)
|
||||
{
|
||||
assert(alloc->activeAllocations.empty());
|
||||
assert(alloc->freeRanges.size() == 1);
|
||||
}
|
||||
heap.allocations.clear();
|
||||
}
|
||||
graphics = nullptr;
|
||||
}
|
||||
|
||||
PSubAllocation Allocator::allocate(uint64 size, const VkMemoryRequirements2& memRequirements2, VkMemoryPropertyFlags properties)
|
||||
PSubAllocation Allocator::allocate(const VkMemoryRequirements2& memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo* dedicatedInfo)
|
||||
{
|
||||
// no suitable allocations found, allocate new block
|
||||
const VkMemoryRequirements& requirements = memRequirements2.memoryRequirements;
|
||||
uint32 memoryTypeIndex;
|
||||
uint8 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;
|
||||
|
||||
if(memRequirements2.pNext != nullptr)
|
||||
{
|
||||
VkMemoryDedicatedRequirements* dedicatedReq = (VkMemoryDedicatedRequirements*)memRequirements2.pNext;
|
||||
if(dedicatedReq->prefersDedicatedAllocation)
|
||||
{
|
||||
PAllocation newAllocation = new Allocation(graphics, this, requirements.size, memoryTypeIndex, properties, dedicatedInfo);
|
||||
heaps[heapIndex].allocations.add(newAllocation);
|
||||
return newAllocation->getSuballocation(requirements.size, requirements.alignment);
|
||||
}
|
||||
}
|
||||
for(auto alloc : heaps[heapIndex].allocations)
|
||||
{
|
||||
PSubAllocation suballoc = alloc->getSuballocation(requirements.size, requirements.alignment);
|
||||
if(suballoc != nullptr)
|
||||
{
|
||||
return suballoc;
|
||||
}
|
||||
}
|
||||
|
||||
// no suitable allocations found, allocate new block
|
||||
PAllocation newAllocation = new Allocation(graphics, this, (requirements.size > MemoryBlockSize) ? requirements.size : MemoryBlockSize, memoryTypeIndex, properties, nullptr);
|
||||
heaps[heapIndex].allocations.add(newAllocation);
|
||||
return newAllocation->getSuballocation(size, requirements.alignment);
|
||||
return newAllocation->getSuballocation(requirements.size, requirements.alignment);
|
||||
}
|
||||
|
||||
VkResult Allocator::findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties, uint32* typeIndex)
|
||||
void Allocator::free(Allocation* allocation)
|
||||
{
|
||||
for (int memoryIndex = 0; memoryIndex < memProperties.memoryTypeCount && typeBits; ++memoryIndex)
|
||||
for(auto heap : heaps)
|
||||
{
|
||||
for(uint32 i = 0; i < heap.allocations.size(); ++i)
|
||||
{
|
||||
if(heap.allocations[i] == allocation)
|
||||
{
|
||||
heap.allocations.remove(i, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VkResult Allocator::findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties, uint8* typeIndex)
|
||||
{
|
||||
for (uint8 memoryIndex = 0; memoryIndex < memProperties.memoryTypeCount && typeBits; ++memoryIndex)
|
||||
{
|
||||
if ((typeBits & 1) == 1)
|
||||
{
|
||||
@@ -121,4 +252,79 @@ VkResult Allocator::findMemoryType(uint32 typeBits, VkMemoryPropertyFlags proper
|
||||
}
|
||||
|
||||
return VK_ERROR_FORMAT_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
StagingBuffer::StagingBuffer()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
StagingBuffer::~StagingBuffer()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
StagingManager::StagingManager(PGraphics graphics, PAllocator allocator)
|
||||
: graphics(graphics)
|
||||
, allocator(allocator)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
StagingManager::~StagingManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void StagingManager::clearPending()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageFlags usage, bool bCPURead)
|
||||
{
|
||||
for(auto it = freeBuffers.begin(); it != freeBuffers.end(); ++it)
|
||||
{
|
||||
auto freeBuffer = *it;
|
||||
if(freeBuffer->allocation->getSize() == size && freeBuffer->allocation->isReadable() == bCPURead)
|
||||
{
|
||||
activeBuffers.add(freeBuffer.getHandle());
|
||||
freeBuffers.remove(it, false);
|
||||
return freeBuffer;
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
memReqs.memoryRequirements.alignment =
|
||||
(16 > memReqs.memoryRequirements.alignment) ?
|
||||
16 : memReqs.memoryRequirements.alignment;
|
||||
|
||||
stagingBuffer->allocation = allocator->allocate(memReqs, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | (bCPURead ? VK_MEMORY_PROPERTY_HOST_CACHED_BIT : VK_MEMORY_PROPERTY_HOST_COHERENT_BIT), stagingBuffer->buffer);
|
||||
stagingBuffer->bReadable = bCPURead;
|
||||
vkBindBufferMemory(graphics->getDevice(), stagingBuffer->buffer, stagingBuffer->getMemoryHandle(), stagingBuffer->getOffset());
|
||||
|
||||
activeBuffers.add(stagingBuffer.getHandle());
|
||||
return stagingBuffer;
|
||||
}
|
||||
|
||||
void StagingManager::releaseStagingBuffer(PStagingBuffer buffer)
|
||||
{
|
||||
freeBuffers.add(buffer);
|
||||
activeBuffers.remove(activeBuffers.find(buffer.getHandle()));
|
||||
}
|
||||
Reference in New Issue
Block a user