Adding VMA

This commit is contained in:
Dynamitos
2024-01-17 17:57:59 +01:00
parent 29710de146
commit 524f26d921
18 changed files with 783 additions and 911 deletions
+334 -334
View File
@@ -1,371 +1,371 @@
#include "Allocator.h"
#include "Graphics.h"
#include "Resources.h"
#include "Enums.h"
#include "Command.h"
// #include "Allocator.h"
// #include "Graphics.h"
// #include "Resources.h"
// #include "Enums.h"
// #include "Command.h"
using namespace Seele::Vulkan;
// using namespace Seele::Vulkan;
SubAllocation::SubAllocation(PAllocation owner, VkDeviceSize requestedSize, VkDeviceSize allocatedOffset, VkDeviceSize allocatedSize, VkDeviceSize alignedOffset)
: owner(owner)
, requestedSize(requestedSize)
, allocatedOffset(allocatedOffset)
, allocatedSize(allocatedSize)
, alignedOffset(alignedOffset)
{
}
// SubAllocation::SubAllocation(PAllocation owner, VkDeviceSize requestedSize, VkDeviceSize allocatedOffset, VkDeviceSize allocatedSize, VkDeviceSize alignedOffset)
// : owner(owner)
// , requestedSize(requestedSize)
// , allocatedOffset(allocatedOffset)
// , allocatedSize(allocatedSize)
// , alignedOffset(alignedOffset)
// {
// }
SubAllocation::~SubAllocation()
{
owner->markFree(this);
}
// SubAllocation::~SubAllocation()
// {
// owner->markFree(this);
// }
VkDeviceMemory SubAllocation::getHandle() const
{
return owner->getHandle();
}
// VkDeviceMemory SubAllocation::getHandle() const
// {
// return owner->getHandle();
// }
void *SubAllocation::map()
{
return (uint8 *)owner->map() + alignedOffset;
}
// void *SubAllocation::map()
// {
// return (uint8 *)owner->map() + alignedOffset;
// }
void SubAllocation::flushMemory()
{
owner->flushMemory();
}
// void SubAllocation::flushMemory()
// {
// owner->flushMemory();
// }
void SubAllocation::invalidate()
{
owner->invalidate();
}
// void SubAllocation::invalidate()
// {
// owner->invalidate();
// }
Allocation::Allocation(PGraphics graphics, PAllocator pool, VkDeviceSize size, uint8 memoryTypeIndex,
VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
: device(graphics->getDevice())
, pool(pool)
, bytesAllocated(size)
, bytesUsed(0)
, mappedPointer(nullptr)
, canMap((properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
, isMapped(false)
, properties(properties)
, memoryTypeIndex(memoryTypeIndex)
{
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));
freeRanges[0] = size;
}
// Allocation::Allocation(PGraphics graphics, PAllocator pool, VkDeviceSize size, uint8 memoryTypeIndex,
// VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
// : device(graphics->getDevice())
// , pool(pool)
// , bytesAllocated(size)
// , bytesUsed(0)
// , mappedPointer(nullptr)
// , canMap((properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
// , isMapped(false)
// , properties(properties)
// , memoryTypeIndex(memoryTypeIndex)
// {
// 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));
// freeRanges[0] = size;
// }
Allocation::~Allocation()
{
vkFreeMemory(device, allocatedMemory, nullptr);
}
// Allocation::~Allocation()
// {
// vkFreeMemory(device, allocatedMemory, nullptr);
// }
OSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDeviceSize alignment)
{
if (isDedicated)
{
if (activeAllocations.empty() && requestedSize == bytesAllocated)
{
OSubAllocation suballoc = new SubAllocation(this, requestedSize, 0, requestedSize, 0);
activeAllocations.add(suballoc);
freeRanges.clear();
bytesUsed += requestedSize;
return suballoc;
}
else
{
return nullptr;
}
}
for (const auto& [lower, size] : freeRanges)
{
VkDeviceSize alignedOffset = lower + alignment - 1;
alignedOffset /= alignment;
alignedOffset *= alignment;
VkDeviceSize allocatedSize = requestedSize + (alignedOffset - lower);
if (size >= allocatedSize)
{
//std::cout << "Allocating " << lower << "-" << lower + allocatedSize << std::endl;
VkDeviceSize newSize = size - allocatedSize;
VkDeviceSize newLower = lower + allocatedSize;
OSubAllocation alloc = new SubAllocation(this, requestedSize, lower, allocatedSize, alignedOffset);
activeAllocations.add(alloc);
freeRanges.erase(lower);
if (newSize > 0)
{
freeRanges[newLower] = newSize;
}
bytesUsed += allocatedSize;
return alloc;
}
}
return nullptr;
}
// OSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDeviceSize alignment)
// {
// if (isDedicated)
// {
// if (activeAllocations.empty() && requestedSize == bytesAllocated)
// {
// OSubAllocation suballoc = new SubAllocation(this, requestedSize, 0, requestedSize, 0);
// activeAllocations.add(suballoc);
// freeRanges.clear();
// bytesUsed += requestedSize;
// return suballoc;
// }
// else
// {
// return nullptr;
// }
// }
// for (const auto& [lower, size] : freeRanges)
// {
// VkDeviceSize alignedOffset = lower + alignment - 1;
// alignedOffset /= alignment;
// alignedOffset *= alignment;
// VkDeviceSize allocatedSize = requestedSize + (alignedOffset - lower);
// if (size >= allocatedSize)
// {
// //std::cout << "Allocating " << lower << "-" << lower + allocatedSize << std::endl;
// VkDeviceSize newSize = size - allocatedSize;
// VkDeviceSize newLower = lower + allocatedSize;
// OSubAllocation alloc = new SubAllocation(this, requestedSize, lower, allocatedSize, alignedOffset);
// activeAllocations.add(alloc);
// freeRanges.erase(lower);
// if (newSize > 0)
// {
// freeRanges[newLower] = newSize;
// }
// bytesUsed += allocatedSize;
// return alloc;
// }
// }
// return nullptr;
// }
void Allocation::markFree(PSubAllocation allocation)
{
//std::cout << "Freeing " << allocation->allocatedOffset << "-" << allocation->allocatedOffset + allocation->allocatedSize << std::endl;
assert(activeAllocations.find(allocation) != activeAllocations.end());
VkDeviceSize lowerBound = allocation->allocatedOffset;
VkDeviceSize upperBound = allocation->allocatedOffset + allocation->allocatedSize;
freeRanges[lowerBound] = allocation->allocatedSize;
for (const auto& [lower, size] : freeRanges)
{
if (lower + size == lowerBound)
{
freeRanges[lower] = size + allocation->allocatedSize;
freeRanges.erase(lowerBound);
lowerBound = lower;
break;
}
}
if (freeRanges.find(upperBound) != freeRanges.end())
{
freeRanges[lowerBound] += freeRanges[upperBound];
freeRanges.erase(upperBound);
}
activeAllocations.remove(allocation, false);
bytesUsed -= allocation->allocatedSize;
//if (activeAllocations.size() == 0)
//{
// pool->free(this);
//}
}
// void Allocation::markFree(PSubAllocation allocation)
// {
// //std::cout << "Freeing " << allocation->allocatedOffset << "-" << allocation->allocatedOffset + allocation->allocatedSize << std::endl;
// assert(activeAllocations.find(allocation) != activeAllocations.end());
// VkDeviceSize lowerBound = allocation->allocatedOffset;
// VkDeviceSize upperBound = allocation->allocatedOffset + allocation->allocatedSize;
// freeRanges[lowerBound] = allocation->allocatedSize;
// for (const auto& [lower, size] : freeRanges)
// {
// if (lower + size == lowerBound)
// {
// freeRanges[lower] = size + allocation->allocatedSize;
// freeRanges.erase(lowerBound);
// lowerBound = lower;
// break;
// }
// }
// if (freeRanges.find(upperBound) != freeRanges.end())
// {
// freeRanges[lowerBound] += freeRanges[upperBound];
// freeRanges.erase(upperBound);
// }
// activeAllocations.remove(allocation, false);
// bytesUsed -= allocation->allocatedSize;
// //if (activeAllocations.size() == 0)
// //{
// // pool->free(this);
// //}
// }
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::flushMemory()
// {
// VkMappedMemoryRange range = {
// .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
// .pNext = 0,
// .memory = allocatedMemory,
// .offset = 0,
// .size = bytesAllocated,
// };
// vkFlushMappedMemoryRanges(device, 1, &range);
// }
void Allocation::invalidate()
{
VkMappedMemoryRange range = {
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
.pNext = 0,
.memory = allocatedMemory,
.size = bytesAllocated,
};
vkInvalidateMappedMemoryRanges(device, 1, &range);
}
// void Allocation::invalidate()
// {
// VkMappedMemoryRange range = {
// .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
// .pNext = 0,
// .memory = allocatedMemory,
// .size = bytesAllocated,
// };
// vkInvalidateMappedMemoryRanges(device, 1, &range);
// }
Allocator::Allocator(PGraphics graphics)
: graphics(graphics)
{
vkGetPhysicalDeviceMemoryProperties(graphics->getPhysicalDevice(), &memProperties);
heaps.reserve(memProperties.memoryHeapCount);
for (size_t i = 0; i < memProperties.memoryHeapCount; ++i)
{
VkMemoryHeap memoryHeap = memProperties.memoryHeaps[i];
HeapInfo heapInfo;
heapInfo.maxSize = memoryHeap.size;
//std::cout << "Creating heap " << i << " with properties " << memoryHeap.flags << " size " << memoryHeap.size << std::endl;
heaps.add(std::move(heapInfo));
}
}
// Allocator::Allocator(PGraphics graphics)
// : graphics(graphics)
// {
// vkGetPhysicalDeviceMemoryProperties(graphics->getPhysicalDevice(), &memProperties);
// heaps.reserve(memProperties.memoryHeapCount);
// for (size_t i = 0; i < memProperties.memoryHeapCount; ++i)
// {
// VkMemoryHeap memoryHeap = memProperties.memoryHeaps[i];
// HeapInfo heapInfo;
// heapInfo.maxSize = memoryHeap.size;
// //std::cout << "Creating heap " << i << " with properties " << memoryHeap.flags << " size " << memoryHeap.size << std::endl;
// heaps.add(std::move(heapInfo));
// }
// }
Allocator::~Allocator()
{
}
// Allocator::~Allocator()
// {
// }
OSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
{
const VkMemoryRequirements &requirements = memRequirements2.memoryRequirements;
uint32 memoryTypeIndex = findMemoryType(requirements.memoryTypeBits, properties);
uint32 heapIndex = memProperties.memoryTypes[memoryTypeIndex].heapIndex;
// OSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
// {
// const VkMemoryRequirements &requirements = memRequirements2.memoryRequirements;
// uint32 memoryTypeIndex = findMemoryType(requirements.memoryTypeBits, properties);
// uint32 heapIndex = memProperties.memoryTypes[memoryTypeIndex].heapIndex;
if (memRequirements2.pNext != nullptr)
{
VkMemoryDedicatedRequirements *dedicatedReq = (VkMemoryDedicatedRequirements *)memRequirements2.pNext;
if (dedicatedReq->prefersDedicatedAllocation)
{
OAllocation newAllocation = new Allocation(graphics, this, requirements.size, memoryTypeIndex, properties, dedicatedInfo);
heaps[heapIndex].inUse += newAllocation->bytesAllocated;
std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << std::endl;
heaps[heapIndex].allocations.add(std::move(newAllocation));
return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment);
}
}
for (auto& alloc : heaps[heapIndex].allocations)
{
if(alloc->memoryTypeIndex == memoryTypeIndex)
{
OSubAllocation suballoc = alloc->getSuballocation(requirements.size, requirements.alignment);
if (suballoc != nullptr)
{
return suballoc;
}
}
}
// if (memRequirements2.pNext != nullptr)
// {
// VkMemoryDedicatedRequirements *dedicatedReq = (VkMemoryDedicatedRequirements *)memRequirements2.pNext;
// if (dedicatedReq->prefersDedicatedAllocation)
// {
// OAllocation newAllocation = new Allocation(graphics, this, requirements.size, memoryTypeIndex, properties, dedicatedInfo);
// heaps[heapIndex].inUse += newAllocation->bytesAllocated;
// std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << std::endl;
// heaps[heapIndex].allocations.add(std::move(newAllocation));
// return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment);
// }
// }
// for (auto& alloc : heaps[heapIndex].allocations)
// {
// if(alloc->memoryTypeIndex == memoryTypeIndex)
// {
// OSubAllocation suballoc = alloc->getSuballocation(requirements.size, requirements.alignment);
// if (suballoc != nullptr)
// {
// return suballoc;
// }
// }
// }
// no suitable allocations found, allocate new block
OAllocation newAllocation = new Allocation(graphics, this, (requirements.size > DEFAULT_ALLOCATION) ? requirements.size : DEFAULT_ALLOCATION, memoryTypeIndex, properties, nullptr);
heaps[heapIndex].inUse += newAllocation->bytesAllocated;
std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << std::endl;
heaps[heapIndex].allocations.add(std::move(newAllocation));
return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment);
}
// // no suitable allocations found, allocate new block
// OAllocation newAllocation = new Allocation(graphics, this, (requirements.size > DEFAULT_ALLOCATION) ? requirements.size : DEFAULT_ALLOCATION, memoryTypeIndex, properties, nullptr);
// heaps[heapIndex].inUse += newAllocation->bytesAllocated;
// std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << std::endl;
// heaps[heapIndex].allocations.add(std::move(newAllocation));
// return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment);
// }
void Allocator::free(PAllocation allocation)
{
for (uint32 heapIndex = 0; heapIndex < heaps.size(); ++heapIndex)
{
for (uint32 alloc = 0; alloc < heaps[heapIndex].allocations.size(); ++alloc)
{
if (heaps[heapIndex].allocations[alloc] == allocation)
{
heaps[heapIndex].allocations.removeAt(alloc, false);
}
}
}
}
// void Allocator::free(PAllocation allocation)
// {
// for (uint32 heapIndex = 0; heapIndex < heaps.size(); ++heapIndex)
// {
// for (uint32 alloc = 0; alloc < heaps[heapIndex].allocations.size(); ++alloc)
// {
// if (heaps[heapIndex].allocations[alloc] == allocation)
// {
// heaps[heapIndex].allocations.removeAt(alloc, false);
// }
// }
// }
// }
void Allocator::print()
{
for (uint32 heapIndex = 0; heapIndex < heaps.size(); ++heapIndex)
{
std::cout << "Heap " << heapIndex << std::endl;
for (uint32 alloc = 0; alloc < heaps[heapIndex].allocations.size(); ++alloc)
{
std::cout << "[" << alloc << "]: " << (float)heaps[heapIndex].allocations[alloc]->bytesUsed / heaps[heapIndex].allocations[alloc]->bytesAllocated << std::endl;
}
}
}
// void Allocator::print()
// {
// for (uint32 heapIndex = 0; heapIndex < heaps.size(); ++heapIndex)
// {
// std::cout << "Heap " << heapIndex << std::endl;
// for (uint32 alloc = 0; alloc < heaps[heapIndex].allocations.size(); ++alloc)
// {
// std::cout << "[" << alloc << "]: " << (float)heaps[heapIndex].allocations[alloc]->bytesUsed / heaps[heapIndex].allocations[alloc]->bytesAllocated << std::endl;
// }
// }
// }
uint32 Allocator::findMemoryType(uint32 typeFilter, VkMemoryPropertyFlags properties)
{
for (uint32 i = 0; i < memProperties.memoryTypeCount; i++)
{
if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties)
{
return i;
}
}
// uint32 Allocator::findMemoryType(uint32 typeFilter, VkMemoryPropertyFlags properties)
// {
// for (uint32 i = 0; i < memProperties.memoryTypeCount; i++)
// {
// if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties)
// {
// return i;
// }
// }
throw std::runtime_error("error finding memory");
}
// throw std::runtime_error("error finding memory");
// }
StagingBuffer::StagingBuffer(PGraphics graphics, OSubAllocation allocation, VkBuffer buffer, VkDeviceSize size, Gfx::QueueType owner)
: owner(owner)
, allocation(std::move(allocation))
, graphics(graphics)
, buffer(buffer)
, size(size)
{
}
// StagingBuffer::StagingBuffer(PGraphics graphics, OSubAllocation allocation, VkBuffer buffer, VkDeviceSize size, Gfx::QueueType owner)
// : owner(owner)
// , allocation(std::move(allocation))
// , graphics(graphics)
// , buffer(buffer)
// , size(size)
// {
// }
StagingBuffer::~StagingBuffer()
{
graphics->getDestructionManager()->queueBuffer(
graphics->getQueueCommands(owner)->getCommands(), buffer);
graphics->getDestructionManager()->queueAllocation(
graphics->getQueueCommands(owner)->getCommands(), std::move(allocation));
}
// StagingBuffer::~StagingBuffer()
// {
// graphics->getDestructionManager()->queueBuffer(
// graphics->getQueueCommands(owner)->getCommands(), buffer);
// graphics->getDestructionManager()->queueAllocation(
// graphics->getQueueCommands(owner)->getCommands(), std::move(allocation));
// }
void* StagingBuffer::map()
{
return allocation->map();
}
// void* StagingBuffer::map()
// {
// return allocation->map();
// }
void StagingBuffer::flush()
{
allocation->flushMemory();
}
// void StagingBuffer::flush()
// {
// allocation->flushMemory();
// }
void StagingBuffer::invalidate()
{
allocation->invalidate();
}
// void StagingBuffer::invalidate()
// {
// allocation->invalidate();
// }
VkDeviceMemory StagingBuffer::getMemory() const
{
return allocation->getHandle();
}
// VkDeviceMemory StagingBuffer::getMemory() const
// {
// return allocation->getHandle();
// }
VkDeviceSize StagingBuffer::getOffset() const
{
return allocation->getOffset();
}
// VkDeviceSize StagingBuffer::getOffset() const
// {
// return allocation->getOffset();
// }
StagingManager::StagingManager(PGraphics graphics, PAllocator pool)
: graphics(graphics), pool(pool)
{
}
// StagingManager::StagingManager(PGraphics graphics, PAllocator pool)
// : graphics(graphics), pool(pool)
// {
// }
StagingManager::~StagingManager()
{
}
// StagingManager::~StagingManager()
// {
// }
OStagingBuffer StagingManager::create(uint64 size, Gfx::QueueType owner)
{
//vkDeviceWaitIdle(graphics->getDevice());
//std::cout << "Creating new stagingbuffer" << std::endl;
for (uint32 i = 0; i < freeBuffers.size(); ++i)
{
if (size <= freeBuffers[i]->getSize() && owner == freeBuffers[i]->getOwner())
{
OStagingBuffer result = std::move(freeBuffers[i]);
freeBuffers.removeAt(i);
return result;
}
}
uint32 queueIndex = graphics->getFamilyMapping().getQueueTypeFamilyIndex(owner);
VkBufferCreateInfo stagingBufferCreateInfo = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.size = size,
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 1,
.pQueueFamilyIndices = &queueIndex,
};
// OStagingBuffer StagingManager::create(uint64 size, Gfx::QueueType owner)
// {
// //vkDeviceWaitIdle(graphics->getDevice());
// //std::cout << "Creating new stagingbuffer" << std::endl;
// for (uint32 i = 0; i < freeBuffers.size(); ++i)
// {
// if (size <= freeBuffers[i]->getSize() && owner == freeBuffers[i]->getOwner())
// {
// OStagingBuffer result = std::move(freeBuffers[i]);
// freeBuffers.removeAt(i);
// return result;
// }
// }
// uint32 queueIndex = graphics->getFamilyMapping().getQueueTypeFamilyIndex(owner);
// VkBufferCreateInfo stagingBufferCreateInfo = {
// .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
// .pNext = nullptr,
// .flags = 0,
// .size = size,
// .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
// .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
// .queueFamilyIndexCount = 1,
// .pQueueFamilyIndices = &queueIndex,
// };
VkBuffer buffer;
VK_CHECK(vkCreateBuffer(graphics->getDevice(), &stagingBufferCreateInfo, nullptr, &buffer));
// VkBuffer buffer;
// VK_CHECK(vkCreateBuffer(graphics->getDevice(), &stagingBufferCreateInfo, nullptr, &buffer));
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,
};
vkGetBufferMemoryRequirements2(graphics->getDevice(), &bufferQuery, &memReqs);
// 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,
// };
// vkGetBufferMemoryRequirements2(graphics->getDevice(), &bufferQuery, &memReqs);
OStagingBuffer stagingBuffer = new StagingBuffer(
graphics,
pool->allocate(memReqs, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT, buffer),
buffer,
size,
owner
);
vkBindBufferMemory(graphics->getDevice(), buffer, stagingBuffer->getMemory(), stagingBuffer->getOffset());
// OStagingBuffer stagingBuffer = new StagingBuffer(
// graphics,
// pool->allocate(memReqs, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT, buffer),
// buffer,
// size,
// owner
// );
// vkBindBufferMemory(graphics->getDevice(), buffer, stagingBuffer->getMemory(), stagingBuffer->getOffset());
return stagingBuffer;
}
// return stagingBuffer;
// }
void StagingManager::release(OStagingBuffer)
{
//freeBuffers.add(std::move(buffer));
}
// void StagingManager::release(OStagingBuffer)
// {
// //freeBuffers.add(std::move(buffer));
// }
+186 -186
View File
@@ -1,196 +1,196 @@
#pragma once
#include "MinimalEngine.h"
#include "Enums.h"
#include "Containers/Map.h"
#include "Containers/Array.h"
#include "Graphics/Resources.h"
#include <mutex>
// #pragma once
// #include "MinimalEngine.h"
// #include "Enums.h"
// #include "Containers/Map.h"
// #include "Containers/Array.h"
// #include "Graphics/Resources.h"
// #include <mutex>
namespace Seele
{
namespace Vulkan
{
DECLARE_REF(Graphics)
DECLARE_REF(Allocator)
DECLARE_REF(Allocation)
class SubAllocation
{
public:
SubAllocation(PAllocation owner, VkDeviceSize requestedSize, VkDeviceSize allocatedOffset, VkDeviceSize allocatedSize, VkDeviceSize alignedOffset);
~SubAllocation();
VkDeviceMemory getHandle() const;
// namespace Seele
// {
// namespace Vulkan
// {
// DECLARE_REF(Graphics)
// DECLARE_REF(Allocator)
// DECLARE_REF(Allocation)
// class SubAllocation
// {
// public:
// SubAllocation(PAllocation owner, VkDeviceSize requestedSize, VkDeviceSize allocatedOffset, VkDeviceSize allocatedSize, VkDeviceSize alignedOffset);
// ~SubAllocation();
// VkDeviceMemory getHandle() const;
constexpr VkDeviceSize getSize() const
{
return requestedSize;
}
// constexpr VkDeviceSize getSize() const
// {
// return requestedSize;
// }
constexpr VkDeviceSize getOffset() const
{
return alignedOffset;
}
// constexpr VkDeviceSize getOffset() const
// {
// return alignedOffset;
// }
void *map();
void flushMemory();
void invalidate();
// void *map();
// void flushMemory();
// void invalidate();
private:
PAllocation owner;
VkDeviceSize requestedSize;
VkDeviceSize allocatedOffset;
VkDeviceSize allocatedSize;
VkDeviceSize alignedOffset;
friend class Allocation;
friend class Allocator;
};
DEFINE_REF(SubAllocation)
class Allocation
{
public:
Allocation(PGraphics graphics, PAllocator pool, VkDeviceSize size, uint8 memoryTypeIndex,
VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo = nullptr);
Allocation(const Allocation& other) = delete;
Allocation& operator=(const Allocation& other) = delete;
~Allocation();
OSubAllocation getSuballocation(VkDeviceSize size, VkDeviceSize alignment);
void markFree(PSubAllocation alloc);
constexpr VkDeviceMemory getHandle() const
{
return allocatedMemory;
}
constexpr VkMemoryPropertyFlags getProperties() const
{
return properties;
}
constexpr void* map()
{
if (!canMap)
{
return nullptr;
}
if (!isMapped)
{
vkMapMemory(device, allocatedMemory, 0, bytesAllocated, 0, &mappedPointer);
isMapped = true;
}
return mappedPointer;
}
// private:
// PAllocation owner;
// VkDeviceSize requestedSize;
// VkDeviceSize allocatedOffset;
// VkDeviceSize allocatedSize;
// VkDeviceSize alignedOffset;
// friend class Allocation;
// friend class Allocator;
// };
// DEFINE_REF(SubAllocation)
// class Allocation
// {
// public:
// Allocation(PGraphics graphics, PAllocator pool, VkDeviceSize size, uint8 memoryTypeIndex,
// VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo = nullptr);
// Allocation(const Allocation& other) = delete;
// Allocation& operator=(const Allocation& other) = delete;
// ~Allocation();
// OSubAllocation getSuballocation(VkDeviceSize size, VkDeviceSize alignment);
// void markFree(PSubAllocation alloc);
// constexpr VkDeviceMemory getHandle() const
// {
// return allocatedMemory;
// }
// constexpr VkMemoryPropertyFlags getProperties() const
// {
// return properties;
// }
// constexpr void* map()
// {
// if (!canMap)
// {
// return nullptr;
// }
// if (!isMapped)
// {
// vkMapMemory(device, allocatedMemory, 0, bytesAllocated, 0, &mappedPointer);
// isMapped = true;
// }
// return mappedPointer;
// }
void flushMemory();
void invalidate();
// void flushMemory();
// void invalidate();
private:
VkDevice device;
PAllocator pool;
VkDeviceSize bytesAllocated;
VkDeviceSize bytesUsed;
VkDeviceMemory allocatedMemory;
Array<PSubAllocation> activeAllocations;
Map<VkDeviceSize, VkDeviceSize> freeRanges;
void *mappedPointer;
uint8 canMap : 1;
uint8 isMapped : 1;
uint8 isDedicated : 1;
VkMemoryPropertyFlags properties;
uint8 memoryTypeIndex;
friend class Allocator;
};
DEFINE_REF(Allocation)
// private:
// VkDevice device;
// PAllocator pool;
// VkDeviceSize bytesAllocated;
// VkDeviceSize bytesUsed;
// VkDeviceMemory allocatedMemory;
// Array<PSubAllocation> activeAllocations;
// Map<VkDeviceSize, VkDeviceSize> freeRanges;
// void *mappedPointer;
// uint8 canMap : 1;
// uint8 isMapped : 1;
// uint8 isDedicated : 1;
// VkMemoryPropertyFlags properties;
// uint8 memoryTypeIndex;
// friend class Allocator;
// };
// DEFINE_REF(Allocation)
class Allocator
{
public:
Allocator(PGraphics graphics);
~Allocator();
OSubAllocation allocate(const VkMemoryRequirements2 &requirements, VkMemoryPropertyFlags props,
VkMemoryDedicatedAllocateInfo *dedicatedInfo = nullptr);
OSubAllocation allocate(const VkMemoryRequirements2 &requirements, VkMemoryPropertyFlags props,
VkBuffer buffer)
{
VkMemoryDedicatedAllocateInfo allocInfo = {
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
.pNext = nullptr,
.image = VK_NULL_HANDLE,
.buffer = buffer,
};
return allocate(requirements, props, &allocInfo);
}
OSubAllocation allocate(const VkMemoryRequirements2 &requirements, VkMemoryPropertyFlags props,
VkImage image)
{
VkMemoryDedicatedAllocateInfo allocInfo = {
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
.pNext = nullptr,
.image = image,
.buffer = VK_NULL_HANDLE,
};
return allocate(requirements, props, &allocInfo);
}
// class Allocator
// {
// public:
// Allocator(PGraphics graphics);
// ~Allocator();
// OSubAllocation allocate(const VkMemoryRequirements2 &requirements, VkMemoryPropertyFlags props,
// VkMemoryDedicatedAllocateInfo *dedicatedInfo = nullptr);
// OSubAllocation allocate(const VkMemoryRequirements2 &requirements, VkMemoryPropertyFlags props,
// VkBuffer buffer)
// {
// VkMemoryDedicatedAllocateInfo allocInfo = {
// .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
// .pNext = nullptr,
// .image = VK_NULL_HANDLE,
// .buffer = buffer,
// };
// return allocate(requirements, props, &allocInfo);
// }
// OSubAllocation allocate(const VkMemoryRequirements2 &requirements, VkMemoryPropertyFlags props,
// VkImage image)
// {
// VkMemoryDedicatedAllocateInfo allocInfo = {
// .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
// .pNext = nullptr,
// .image = image,
// .buffer = VK_NULL_HANDLE,
// };
// return allocate(requirements, props, &allocInfo);
// }
void free(PAllocation allocation);
void print();
private:
static constexpr VkDeviceSize DEFAULT_ALLOCATION = 16 * 1024 * 1024; // 16MB
struct HeapInfo
{
VkDeviceSize maxSize = 0;
VkDeviceSize inUse = 0;
Array<OAllocation> allocations;
HeapInfo() = default;
HeapInfo(const HeapInfo& other) = delete;
HeapInfo(HeapInfo&& other) = default;
HeapInfo& operator=(const HeapInfo& other) = delete;
HeapInfo& operator=(HeapInfo&& other) = default;
};
Array<HeapInfo> heaps;
uint32 findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties);
PGraphics graphics;
VkPhysicalDeviceMemoryProperties memProperties;
};
DEFINE_REF(Allocator)
class StagingBuffer
{
public:
StagingBuffer(PGraphics graphics, OSubAllocation allocation, VkBuffer buffer, VkDeviceSize size, Gfx::QueueType owner);
~StagingBuffer();
void* map();
void flush();
void invalidate();
constexpr VkBuffer getHandle() const
{
return buffer;
}
VkDeviceMemory getMemory() const;
VkDeviceSize getOffset() const;
constexpr uint64 getSize() const
{
return size;
}
constexpr Gfx::QueueType getOwner() const
{
return owner;
}
private:
Gfx::QueueType owner;
OSubAllocation allocation;
PGraphics graphics;
VkBuffer buffer;
VkDeviceSize size;
};
DEFINE_REF(StagingBuffer)
// void free(PAllocation allocation);
// void print();
// private:
// static constexpr VkDeviceSize DEFAULT_ALLOCATION = 16 * 1024 * 1024; // 16MB
// struct HeapInfo
// {
// VkDeviceSize maxSize = 0;
// VkDeviceSize inUse = 0;
// Array<OAllocation> allocations;
// HeapInfo() = default;
// HeapInfo(const HeapInfo& other) = delete;
// HeapInfo(HeapInfo&& other) = default;
// HeapInfo& operator=(const HeapInfo& other) = delete;
// HeapInfo& operator=(HeapInfo&& other) = default;
// };
// Array<HeapInfo> heaps;
// uint32 findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties);
// PGraphics graphics;
// VkPhysicalDeviceMemoryProperties memProperties;
// };
// DEFINE_REF(Allocator)
// class StagingBuffer
// {
// public:
// StagingBuffer(PGraphics graphics, OSubAllocation allocation, VkBuffer buffer, VkDeviceSize size, Gfx::QueueType owner);
// ~StagingBuffer();
// void* map();
// void flush();
// void invalidate();
// constexpr VkBuffer getHandle() const
// {
// return buffer;
// }
// VkDeviceMemory getMemory() const;
// VkDeviceSize getOffset() const;
// constexpr uint64 getSize() const
// {
// return size;
// }
// constexpr Gfx::QueueType getOwner() const
// {
// return owner;
// }
// private:
// Gfx::QueueType owner;
// OSubAllocation allocation;
// PGraphics graphics;
// VkBuffer buffer;
// VkDeviceSize size;
// };
// DEFINE_REF(StagingBuffer)
class StagingManager
{
public:
StagingManager(PGraphics graphics, PAllocator pool);
~StagingManager();
OStagingBuffer create(uint64 size, Gfx::QueueType owner);
void release(OStagingBuffer buffer);
private:
PGraphics graphics;
PAllocator pool;
Array<OStagingBuffer> freeBuffers;
};
DEFINE_REF(StagingManager)
} // namespace Vulkan
} // namespace Seele
// class StagingManager
// {
// public:
// StagingManager(PGraphics graphics, PAllocator pool);
// ~StagingManager();
// OStagingBuffer create(uint64 size, Gfx::QueueType owner);
// void release(OStagingBuffer buffer);
// private:
// PGraphics graphics;
// PAllocator pool;
// Array<OStagingBuffer> freeBuffers;
// };
// DEFINE_REF(StagingManager)
// } // namespace Vulkan
// } // namespace Seele
+109 -270
View File
@@ -8,74 +8,52 @@ struct PendingBuffer
{
uint64 offset;
uint64 size;
OStagingBuffer stagingBuffer;
VkBuffer stagingBuffer;
VmaAllocation allocation;
void *mappedMemory;
Gfx::QueueType prevQueue;
bool writeOnly;
};
static Map<Vulkan::Buffer*, PendingBuffer> pendingBuffers;
static Map<Vulkan::Buffer *, PendingBuffer> pendingBuffers;
Buffer::Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool dynamic)
: graphics(graphics)
, currentBuffer(0)
, size(size)
, owner(queueType)
Buffer::Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType &queueType, bool dynamic)
: graphics(graphics), currentBuffer(0), size(size), owner(queueType)
{
if(dynamic)
if (dynamic)
{
numBuffers = Gfx::numFramesBuffered;
}
}
else
{
numBuffers = 1;
}
usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
uint32 queueFamilyIndex = graphics->getFamilyMapping().getQueueTypeFamilyIndex(queueType);
VkBufferCreateInfo info = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr,
.size = size,
.usage = usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 1,
.pQueueFamilyIndices = &queueFamilyIndex,
};
VkBufferMemoryRequirementsInfo2 bufferReqInfo = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
.pNext = nullptr,
};
VkMemoryDedicatedRequirements dedicatedRequirements = {
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
.pNext = nullptr,
};
VkMemoryRequirements2 memRequirements = {
.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
.pNext = &dedicatedRequirements,
VmaAllocationCreateInfo allocInfo = {
.usage = VMA_MEMORY_USAGE_AUTO,
.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
};
for (uint32 i = 0; i < numBuffers; ++i)
{
VK_CHECK(vkCreateBuffer(graphics->getDevice(), &info, nullptr, &buffers[i].buffer));
bufferReqInfo.buffer = buffers[i].buffer;
vkGetBufferMemoryRequirements2(graphics->getDevice(), &bufferReqInfo, &memRequirements);
buffers[i].allocation = graphics->getAllocator()->allocate(memRequirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, buffers[i].buffer);
vkBindBufferMemory(graphics->getDevice(), buffers[i].buffer, buffers[i].allocation->getHandle(), buffers[i].allocation->getOffset());
vmaCreateBuffer(graphics->getAllocator(), &info, &allocInfo, &buffers[i].buffer, &buffers[i].allocation, &buffers[i].info);
vmaGetAllocationMemoryProperties(graphics->getAllocator(), buffers[i].allocation, &buffers[i].properties);
}
}
Buffer::~Buffer()
{
for(uint32 i = 0; i < numBuffers; ++i)
{
for (uint32 i = 0; i < numBuffers; ++i)
{
graphics->getDestructionManager()->queueBuffer(graphics->getQueueCommands(owner)->getCommands(), buffers[i].buffer);
}
}
VkDeviceSize Buffer::getOffset() const
{
return buffers[currentBuffer].allocation->getOffset();
}
void Buffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
{
Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping();
@@ -145,12 +123,12 @@ void Buffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
}
void Buffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage)
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage)
{
PCommand commandBuffer = graphics->getQueueCommands(owner)->getCommands();
VkBufferMemoryBarrier barrier = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.pNext = nullptr,
.pNext = nullptr,
.srcAccessMask = srcAccess,
.dstAccessMask = dstAccess,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
@@ -159,7 +137,7 @@ void Buffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlag
.size = size,
};
VkBufferMemoryBarrier dynamicBarriers[Gfx::numFramesBuffered];
for(uint32 i = 0; i < numBuffers; ++i)
for (uint32 i = 0; i < numBuffers; ++i)
{
dynamicBarriers[i] = barrier;
dynamicBarriers[i].buffer = buffers[i].buffer;
@@ -167,12 +145,12 @@ void Buffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlag
vkCmdPipelineBarrier(commandBuffer->getHandle(), srcStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr);
}
void * Buffer::map(bool writeOnly)
void *Buffer::map(bool writeOnly)
{
return mapRegion(0, size, writeOnly);
}
void * Buffer::mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly)
void *Buffer::mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly)
{
void *data = nullptr;
@@ -183,50 +161,30 @@ void * Buffer::mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly)
pending.size = regionSize;
if (writeOnly)
{
//requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER);
OStagingBuffer stagingBuffer = graphics->getStagingManager()->create(regionSize, owner);
data = stagingBuffer->map();
pending.stagingBuffer = std::move(stagingBuffer);
if (buffers[currentBuffer].properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
{
VK_CHECK(vmaMapMemory(graphics->getAllocator(), buffers[currentBuffer].allocation, &pending.mappedMemory));
}
else
{
VkBufferCreateInfo stagingInfo = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
.size = regionSize,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
};
VmaAllocationCreateInfo allocInfo = {
.usage = VMA_MEMORY_USAGE_AUTO,
};
VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &stagingInfo, &allocInfo, &pending.stagingBuffer, &pending.allocation, nullptr));
vmaMapMemory(graphics->getAllocator(), pending.allocation, &pending.mappedMemory);
}
}
else
{
PCommand current = graphics->getQueueCommands(owner)->getCommands();
current->waitForCommand();
requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER);
VkCommandBuffer handle = graphics->getQueueCommands(owner)->getCommands()->getHandle();
VkBufferMemoryBarrier barrier = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.buffer = buffers[currentBuffer].buffer,
.offset = 0,
.size = size,
};
vkCmdPipelineBarrier(handle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr);
OStagingBuffer stagingBuffer = graphics->getStagingManager()->create(size, owner);
VkBufferCopy regions = {
.srcOffset = 0,
.dstOffset = 0,
.size = size,
};
vkCmdCopyBuffer(handle, buffers[currentBuffer].buffer, stagingBuffer->getHandle(), 1, &regions);
graphics->getQueueCommands(owner)->submitCommands();
vkQueueWaitIdle(graphics->getQueueCommands(owner)->getQueue()->getHandle());
stagingBuffer->map(); // this maps the memory if not mapped already
stagingBuffer->flush();
data = stagingBuffer->map();
pending.stagingBuffer = std::move(stagingBuffer);
assert(false);
}
pendingBuffers[this] = std::move(pending);
@@ -239,60 +197,62 @@ void Buffer::unmap()
auto found = pendingBuffers.find(this);
if (found != pendingBuffers.end())
{
PendingBuffer& pending = found->value;
pending.stagingBuffer->flush();
PendingBuffer &pending = found->value;
vmaFlushAllocation(graphics->getAllocator(), pending.allocation, 0, VK_WHOLE_SIZE);
if (pending.writeOnly)
{
PStagingBuffer stagingBuffer = pending.stagingBuffer;
PCommand command = graphics->getQueueCommands(owner)->getCommands();
VkCommandBuffer cmdHandle = command->getHandle();
if (buffers[currentBuffer].properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
{
vmaUnmapMemory(graphics->getAllocator(), buffers[currentBuffer].allocation);
}
else
{
vmaUnmapMemory(graphics->getAllocator(), pending.allocation);
PCommand command = graphics->getQueueCommands(owner)->getCommands();
VkCommandBuffer cmdHandle = command->getHandle();
VkBufferCopy region = {
.srcOffset = 0,
.dstOffset = pending.offset,
.size = pending.size,
};
VkBufferMemoryBarrier barrier = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.buffer = buffers[currentBuffer].buffer,
.offset = 0,
.size = size,
};
vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr);
vkCmdCopyBuffer(cmdHandle, stagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, &region);
barrier = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.buffer = buffers[currentBuffer].buffer,
.offset = 0,
.size = size,
};
vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr);
VkBufferCopy region = {
.srcOffset = 0,
.dstOffset = pending.offset,
.size = pending.size,
};
VkBufferMemoryBarrier barrier = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT,
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.buffer = buffers[currentBuffer].buffer,
.offset = 0,
.size = size,
};
vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr);
vkCmdCopyBuffer(cmdHandle, pending.stagingBuffer, buffers[currentBuffer].buffer, 1, &region);
barrier = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.buffer = buffers[currentBuffer].buffer,
.offset = 0,
.size = size,
};
vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr);
vmaDestroyBuffer(graphics->getAllocator(), pending.stagingBuffer, pending.allocation);
}
}
//requestOwnershipTransfer(pending.prevQueue);
graphics->getStagingManager()->release(std::move(pending.stagingBuffer));
// requestOwnershipTransfer(pending.prevQueue);
pendingBuffers.erase(this);
}
}
UniformBuffer::UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo &createInfo)
: Gfx::UniformBuffer(graphics->getFamilyMapping(), createInfo.sourceData)
, Vulkan::Buffer(graphics, createInfo.sourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, currentOwner, createInfo.dynamic)
, dedicatedStagingBuffer(nullptr)
: Gfx::UniformBuffer(graphics->getFamilyMapping(), createInfo.sourceData), Vulkan::Buffer(graphics, createInfo.sourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, currentOwner, createInfo.dynamic)
{
if(createInfo.dynamic)
{
dedicatedStagingBuffer = graphics->getStagingManager()->create(createInfo.sourceData.size, owner);
}
if (createInfo.sourceData.data != nullptr)
{
void *data = map();
@@ -303,75 +263,20 @@ UniformBuffer::UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo &
UniformBuffer::~UniformBuffer()
{
if (dedicatedStagingBuffer != nullptr)
{
graphics->getStagingManager()->release(std::move(dedicatedStagingBuffer));
}
}
bool UniformBuffer::updateContents(const DataSource &sourceData)
bool UniformBuffer::updateContents(const DataSource &sourceData)
{
if(!Gfx::UniformBuffer::updateContents(sourceData))
if (!Gfx::UniformBuffer::updateContents(sourceData))
{
// no update was performed, skip
return false;
}
void* data = map();
void *data = map();
std::memcpy(data, sourceData.data, sourceData.size);
unmap();
return true;
}
void* UniformBuffer::map(bool writeOnly)
{
if(dedicatedStagingBuffer != nullptr)
{
return dedicatedStagingBuffer->map();
}
return Vulkan::Buffer::map(writeOnly);
}
void UniformBuffer::unmap()
{
if(dedicatedStagingBuffer != nullptr)
{
dedicatedStagingBuffer->flush();
PCommand command = graphics->getQueueCommands(currentOwner)->getCommands();
VkCommandBuffer cmdHandle = command->getHandle();
VkBufferCopy region;
std::memset(&region, 0, sizeof(VkBufferCopy));
region.size = Vulkan::Buffer::size;
VkBufferMemoryBarrier barrier = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.buffer = buffers[currentBuffer].buffer,
.offset = 0,
.size = size,
};
vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr);
vkCmdCopyBuffer(cmdHandle, dedicatedStagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, &region);
barrier = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.buffer = buffers[currentBuffer].buffer,
.offset = 0,
.size = size,
};
vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr);
}
else
{
Vulkan::Buffer::unmap();
}
}
void UniformBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
{
@@ -383,8 +288,8 @@ void UniformBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
Vulkan::Buffer::executeOwnershipBarrier(newOwner);
}
void UniformBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage)
void UniformBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage)
{
Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
}
@@ -400,14 +305,8 @@ VkAccessFlags UniformBuffer::getDestAccessMask()
}
ShaderBuffer::ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo &sourceData)
: Gfx::ShaderBuffer(graphics->getFamilyMapping(), sourceData.numElements, sourceData.sourceData)
, Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, currentOwner, sourceData.dynamic)
, dedicatedStagingBuffer(nullptr)
: Gfx::ShaderBuffer(graphics->getFamilyMapping(), sourceData.numElements, sourceData.sourceData), Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, currentOwner, sourceData.dynamic)
{
if(sourceData.dynamic)
{
dedicatedStagingBuffer = graphics->getStagingManager()->create(sourceData.sourceData.size, currentOwner);
}
if (sourceData.sourceData.data != nullptr)
{
void *data = map();
@@ -418,76 +317,18 @@ ShaderBuffer::ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo &sou
ShaderBuffer::~ShaderBuffer()
{
if (dedicatedStagingBuffer != nullptr)
{
graphics->getStagingManager()->release(std::move(dedicatedStagingBuffer));
}
}
bool ShaderBuffer::updateContents(const DataSource &sourceData)
bool ShaderBuffer::updateContents(const DataSource &sourceData)
{
assert(sourceData.size <= getSize());
Gfx::ShaderBuffer::updateContents(sourceData);
//We always want to update, as the contents could be different on the GPU
void* data = map();
// We always want to update, as the contents could be different on the GPU
void *data = map();
std::memcpy(data, sourceData.data, sourceData.size);
unmap();
return true;
}
void* ShaderBuffer::map(bool writeOnly)
{
if(dedicatedStagingBuffer != nullptr)
{
return dedicatedStagingBuffer->map();
}
return Vulkan::Buffer::map(writeOnly);
}
void ShaderBuffer::unmap()
{
if(dedicatedStagingBuffer != nullptr)
{
dedicatedStagingBuffer->flush();
PCommand command = graphics->getQueueCommands(currentOwner)->getCommands();
VkCommandBuffer cmdHandle = command->getHandle();
VkBufferCopy region = {
.srcOffset = 0,
.dstOffset = 0,
.size = Vulkan::Buffer::size,
};
VkBufferMemoryBarrier barrier = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.buffer = buffers[currentBuffer].buffer,
.offset = 0,
.size = size,
};
vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr);
vkCmdCopyBuffer(cmdHandle, dedicatedStagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, &region);
barrier = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.buffer = buffers[currentBuffer].buffer,
.offset = 0,
.size = size,
};
vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr);
}
else
{
Vulkan::Buffer::unmap();
}
}
void ShaderBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
{
@@ -499,8 +340,8 @@ void ShaderBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
Vulkan::Buffer::executeOwnershipBarrier(newOwner);
}
void ShaderBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage)
void ShaderBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage)
{
Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
}
@@ -516,8 +357,7 @@ VkAccessFlags ShaderBuffer::getDestAccessMask()
}
VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &sourceData)
: Gfx::VertexBuffer(graphics->getFamilyMapping(), sourceData.numVertices, sourceData.vertexSize, sourceData.sourceData.owner)
, Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, currentOwner)
: Gfx::VertexBuffer(graphics->getFamilyMapping(), sourceData.numVertices, sourceData.vertexSize, sourceData.sourceData.owner), Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, currentOwner)
{
if (sourceData.sourceData.data != nullptr)
{
@@ -533,14 +373,14 @@ VertexBuffer::~VertexBuffer()
void VertexBuffer::updateRegion(DataSource update)
{
void* data = mapRegion(update.offset, update.size);
void *data = mapRegion(update.offset, update.size);
std::memcpy(data, update.data, update.size);
unmap();
}
void VertexBuffer::download(Array<uint8>& buffer)
void VertexBuffer::download(Array<uint8> &buffer)
{
void* data = map(false);
void *data = map(false);
buffer.resize(size);
std::memcpy(buffer.data(), data, size);
unmap();
@@ -556,8 +396,8 @@ void VertexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
Vulkan::Buffer::executeOwnershipBarrier(newOwner);
}
void VertexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage)
void VertexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage)
{
Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
}
@@ -573,8 +413,7 @@ VkAccessFlags VertexBuffer::getDestAccessMask()
}
IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &sourceData)
: Gfx::IndexBuffer(graphics->getFamilyMapping(), sourceData.sourceData.size, sourceData.indexType, sourceData.sourceData.owner)
, Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, currentOwner)
: Gfx::IndexBuffer(graphics->getFamilyMapping(), sourceData.sourceData.size, sourceData.indexType, sourceData.sourceData.owner), Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, currentOwner)
{
if (sourceData.sourceData.data != nullptr)
{
@@ -588,9 +427,9 @@ IndexBuffer::~IndexBuffer()
{
}
void IndexBuffer::download(Array<uint8>& buffer)
void IndexBuffer::download(Array<uint8> &buffer)
{
void* data = map(false);
void *data = map(false);
buffer.resize(size);
std::memcpy(buffer.data(), data, size);
unmap();
@@ -606,8 +445,8 @@ void IndexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
Vulkan::Buffer::executeOwnershipBarrier(newOwner);
}
void IndexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage)
void IndexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage)
{
Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
}
+6 -13
View File
@@ -1,7 +1,6 @@
#pragma once
#include "Graphics/Buffer.h"
#include "Graphics.h"
#include "Allocator.h"
namespace Seele
{
@@ -20,20 +19,21 @@ public:
{
return size;
}
VkDeviceSize getOffset() const;
void advanceBuffer()
{
currentBuffer = (currentBuffer + 1) % numBuffers;
}
virtual void *map(bool writeOnly = true);
virtual void *mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly = true);
virtual void unmap();
void *map(bool writeOnly = true);
void *mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly = true);
void unmap();
protected:
struct BufferAllocation
{
VkBuffer buffer;
OSubAllocation allocation;
VmaAllocation allocation;
VmaAllocationInfo info;
VkMemoryPropertyFlags properties;
};
PGraphics graphics;
uint32 currentBuffer;
@@ -53,7 +53,6 @@ protected:
};
DEFINE_REF(Buffer)
DECLARE_REF(StagingBuffer)
class UniformBuffer : public Gfx::UniformBuffer, public Buffer
{
public:
@@ -61,8 +60,6 @@ public:
virtual ~UniformBuffer();
virtual bool updateContents(const DataSource &sourceData) override;
virtual void* map(bool writeOnly = true) override;
virtual void unmap() override;
protected:
// Inherited via Vulkan::Buffer
virtual VkAccessFlags getSourceAccessMask() override;
@@ -74,7 +71,6 @@ protected:
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) override;
private:
OStagingBuffer dedicatedStagingBuffer;
};
DEFINE_REF(UniformBuffer)
@@ -85,8 +81,6 @@ public:
virtual ~ShaderBuffer();
virtual bool updateContents(const DataSource &sourceData) override;
virtual void* map(bool writeOnly = true) override;
virtual void unmap() override;
protected:
// Inherited via Vulkan::Buffer
virtual VkAccessFlags getSourceAccessMask() override;
@@ -97,7 +91,6 @@ protected:
virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) override;
private:
OStagingBuffer dedicatedStagingBuffer;
};
DEFINE_REF(ShaderBuffer)
+35 -15
View File
@@ -13,6 +13,8 @@
#include <GLFW/glfw3.h>
#include <cstring>
#include <vulkan/vulkan_core.h>
#define VMA_IMPLEMENTATION
#include "vk_mem_alloc.h"
using namespace Seele;
using namespace Seele::Vulkan;
@@ -40,7 +42,6 @@ Graphics::~Graphics()
pipelineCache = nullptr;
allocator = nullptr;
destructionManager = nullptr;
stagingManager = nullptr;
allocatedFramebuffers.clear();
shaderCompiler = nullptr;
vkDestroyDevice(handle, nullptr);
@@ -56,8 +57,19 @@ void Graphics::init(GraphicsInitializer initInfo)
#endif
pickPhysicalDevice();
createDevice(initInfo);
allocator = new Allocator(this);
stagingManager = new StagingManager(this, allocator);
VmaAllocatorCreateInfo createInfo = {
.device = handle,
.instance = instance,
.pAllocationCallbacks = nullptr,
.pDeviceMemoryCallbacks = nullptr,
.pHeapSizeLimit = nullptr,
.physicalDevice = physicalDevice,
.preferredLargeHeapBlockSize = 0,
.pTypeExternalMemoryHandleTypes = nullptr,
.pVulkanFunctions = nullptr,
.vulkanApiVersion = VK_API_VERSION_1_3,
};
vmaCreateAllocator(&createInfo, &allocator);
pipelineCache = new PipelineCache(this, "pipeline.cache");
destructionManager = new DestructionManager(this);
}
@@ -326,16 +338,12 @@ PCommandPool Graphics::getDedicatedTransferCommands()
}
return dedicatedTransferCommands;
}
PAllocator Graphics::getAllocator()
VmaAllocator Graphics::getAllocator()
{
return allocator;
}
PStagingManager Graphics::getStagingManager()
{
return stagingManager;
}
PDestructionManager Graphics::getDestructionManager()
{
return destructionManager;
@@ -374,11 +382,17 @@ void Graphics::initInstance(GraphicsInitializer initInfo)
{
extensions.add(initInfo.instanceExtensions[i]);
}
#ifdef __APPLE__
extensions.add("VK_KHR_portability_enumeration");
#endif
#if ENABLE_VALIDATION
initInfo.layers.add("VK_LAYER_KHRONOS_validation");
#endif
VkInstanceCreateInfo info = {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
#if __APPLE__
.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR,
#endif
.pApplicationInfo = &appInfo,
.enabledLayerCount = (uint32)initInfo.layers.size(),
.ppEnabledLayerNames = initInfo.layers.data(),
@@ -437,7 +451,7 @@ void Graphics::pickPhysicalDevice()
}
}
physicalDevice = bestDevice;
vkGetPhysicalDeviceProperties(physicalDevice, &props);
vkGetPhysicalDeviceFeatures2(physicalDevice, &features);
features.features.robustBufferAccess = 0;
@@ -480,6 +494,13 @@ void Graphics::createDevice(GraphicsInitializer initializer)
auto checkFamilyProperty = [](VkQueueFamilyProperties currProps, uint32 checkBit){
return (currProps.queueFlags & checkBit) == checkBit;
};
auto updateQueueInfo = [&queueProperties](uint32 familyIndex, QueueCreateInfo& info, uint32& numQueues) {
if(info.familyIndex == -1) {
info.familyIndex = familyIndex;
numQueues = std::min(numQueues + 1, queueProperties[familyIndex].queueCount);
info.queueIndex = numQueues - 1;
}
};
for (uint32 familyIndex = 0; familyIndex < queueProperties.size(); ++familyIndex)
{
uint32 numQueuesForFamily = 0;
@@ -487,11 +508,7 @@ void Graphics::createDevice(GraphicsInitializer initializer)
if (checkFamilyProperty(currProps, VK_QUEUE_GRAPHICS_BIT))
{
if (graphicsQueueInfo.familyIndex == -1)
{
graphicsQueueInfo.familyIndex = familyIndex;
numQueuesForFamily++;
}
updateQueueInfo(familyIndex, graphicsQueueInfo, numQueueFamilies);
}
if (currProps.queueFlags & VK_QUEUE_COMPUTE_BIT)
{
@@ -568,6 +585,9 @@ void Graphics::createDevice(GraphicsInitializer initializer)
features12.pNext = &enabledMeshShaderFeatures;
initializer.deviceExtensions.add(VK_EXT_MESH_SHADER_EXTENSION_NAME);
}
#ifdef __APPLE__
initializer.deviceExtensions.add("VK_KHR_portability_subset");
#endif
VkDeviceCreateInfo deviceInfo = {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.pNext = &features11,
+4 -6
View File
@@ -1,13 +1,12 @@
#pragma once
#include "Enums.h"
#include "Graphics/Graphics.h"
#include <vk_mem_alloc.h>
namespace Seele
{
namespace Vulkan
{
DECLARE_REF(Allocator)
DECLARE_REF(StagingManager)
DECLARE_REF(DestructionManager)
DECLARE_REF(CommandPool)
DECLARE_REF(Queue)
@@ -28,8 +27,7 @@ public:
PCommandPool getTransferCommands();
PCommandPool getDedicatedTransferCommands();
PAllocator getAllocator();
PStagingManager getStagingManager();
VmaAllocator getAllocator();
PDestructionManager getDestructionManager();
// Inherited via Graphics
@@ -71,6 +69,7 @@ public:
virtual void resolveTexture(Gfx::PTexture source, Gfx::PTexture destination) override;
void vkCmdDrawMeshTasksEXT(VkCommandBuffer handle, uint32 groupX, uint32 groupY, uint32 groupZ);
protected:
PFN_vkCmdDrawMeshTasksEXT cmdDrawMeshTasks;
Array<const char *> getRequiredExtensions();
@@ -97,9 +96,8 @@ protected:
VkPhysicalDeviceVulkan12Features features12;
VkDebugReportCallbackEXT callback;
Map<uint32, OFramebuffer> allocatedFramebuffers;
OAllocator allocator;
VmaAllocator allocator;
OPipelineCache pipelineCache;
OStagingManager stagingManager;
ODestructionManager destructionManager;
friend class Window;
-6
View File
@@ -129,11 +129,6 @@ void DestructionManager::queueDescriptorPool(PCommand cmd, VkDescriptorPool pool
pools[cmd].add(pool);
}
void DestructionManager::queueAllocation(PCommand cmd, OSubAllocation alloc)
{
allocs[cmd].add(std::move(alloc));
}
void DestructionManager::notifyCmdComplete(PCommand cmd)
{
for(auto buf : buffers[cmd])
@@ -166,5 +161,4 @@ void DestructionManager::notifyCmdComplete(PCommand cmd)
sems[cmd].clear();
pools[cmd].clear();
renderPasses[cmd].clear();
allocs[cmd].clear();
}
-3
View File
@@ -12,7 +12,6 @@ DECLARE_REF(DescriptorPool)
DECLARE_REF(CommandPool)
DECLARE_REF(Command)
DECLARE_REF(Graphics)
DECLARE_REF(SubAllocation)
class Semaphore
{
public:
@@ -63,7 +62,6 @@ public:
void queueSemaphore(PCommand cmd, VkSemaphore sem);
void queueRenderPass(PCommand cmd, VkRenderPass renderPass);
void queueDescriptorPool(PCommand cmd, VkDescriptorPool pool);
void queueAllocation(PCommand cmd, OSubAllocation alloc);
void notifyCmdComplete(PCommand cmdbuffer);
private:
PGraphics graphics;
@@ -73,7 +71,6 @@ private:
Map<PCommand, List<VkSemaphore>> sems;
Map<PCommand, List<VkRenderPass>> renderPasses;
Map<PCommand, List<VkDescriptorPool>> pools;
Map<PCommand, List<OSubAllocation>> allocs;
};
DEFINE_REF(DestructionManager)
+92 -66
View File
@@ -46,7 +46,6 @@ TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType,
if (existingImage == VK_NULL_HANDLE)
{
ownsImage = true;
PAllocator pool = graphics->getAllocator();
VkImageType type = VK_IMAGE_TYPE_MAX_ENUM;
VkImageCreateFlags flags = 0;
switch (viewType)
@@ -97,69 +96,79 @@ TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.initialLayout = cast(layout),
};
VmaAllocationCreateInfo allocInfo = {
.usage = VMA_MEMORY_USAGE_AUTO,
};
VK_CHECK(vmaCreateImage(graphics->getAllocator(), &info, &allocInfo, &image, &allocation, nullptr));
VK_CHECK(vkCreateImage(graphics->getDevice(), &info, nullptr, &image));
const DataSource& sourceData = createInfo.sourceData;
if(sourceData.size > 0)
{
changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
void* data;
VkMemoryPropertyFlags memProps;
VkBuffer stagingBuffer = VK_NULL_HANDLE;
VmaAllocation stagingAlloc = VK_NULL_HANDLE;
vmaGetAllocationMemoryProperties(graphics->getAllocator(), allocation, &memProps);
if(memProps & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
{
vmaMapMemory(graphics->getAllocator(), allocation, &data);
}
else
{
VkBufferCreateInfo stagingInfo = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.size = sourceData.size,
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
};
VmaAllocationCreateInfo alloc = {
.usage = VMA_MEMORY_USAGE_AUTO,
};
VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &stagingInfo, &alloc, &stagingBuffer, &stagingAlloc, nullptr));
vmaMapMemory(graphics->getAllocator(), stagingAlloc, &data);
}
std::memcpy(data, sourceData.data, sourceData.size);
vmaFlushAllocation(graphics->getAllocator(), stagingAlloc, 0, VK_WHOLE_SIZE);
VkMemoryDedicatedRequirements memDedicatedRequirements = {
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
.pNext = nullptr,
};
VkImageMemoryRequirementsInfo2 reqInfo = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
.pNext = nullptr,
.image = image,
};
VkMemoryRequirements2 requirements = {
.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
.pNext = &memDedicatedRequirements,
};
vkGetImageMemoryRequirements2(graphics->getDevice(), &reqInfo, &requirements);
allocation = pool->allocate(requirements, createInfo.memoryProps, image);
vkBindImageMemory(graphics->getDevice(), image, allocation->getHandle(), allocation->getOffset());
PCommandPool commandPool = graphics->getQueueCommands(currentOwner);
VkBufferImageCopy region = {
.bufferOffset = 0,
.bufferRowLength = 0,
.bufferImageHeight = 0,
.imageSubresource = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.mipLevel = 0,
.baseArrayLayer = 0,
.layerCount = arrayCount * layerCount,
},
.imageOffset = {
.x = 0,
.y = 0,
.z = 0,
},
.imageExtent = {
.width = width,
.height = height,
.depth = depth
},
};
vkCmdCopyBufferToImage(commandPool->getCommands()->getHandle(),
stagingBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
// When loading a texture from a file, we will almost always use it as a texture map for fragment shaders
changeLayout(Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
if(stagingBuffer != VK_NULL_HANDLE)
{
vmaDestroyBuffer(graphics->getAllocator(), stagingBuffer, stagingAlloc);
}
}
}
const DataSource& sourceData = createInfo.sourceData;
if(sourceData.size > 0)
{
changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
OStagingBuffer staging = graphics->getStagingManager()->create(sourceData.size, owner);
void* data = staging->map();
std::memcpy(data, sourceData.data, sourceData.size);
staging->flush();
PCommandPool commandPool = graphics->getQueueCommands(currentOwner);
VkBufferImageCopy region = {
.bufferOffset = 0,
.bufferRowLength = 0,
.bufferImageHeight = 0,
.imageSubresource = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.mipLevel = 0,
.baseArrayLayer = 0,
.layerCount = arrayCount * layerCount,
},
.imageOffset = {
.x = 0,
.y = 0,
.z = 0,
},
.imageExtent = {
.width = width,
.height = height,
.depth = depth
},
};
vkCmdCopyBufferToImage(commandPool->getCommands()->getHandle(),
staging->getHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
// When loading a texture from a file, we will almost always use it as a texture map for fragment shaders
changeLayout(Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
graphics->getStagingManager()->release(std::move(staging));
}
else if(usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
if(usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
{
changeLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
}
@@ -231,9 +240,25 @@ void TextureBase::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Arra
{
uint64 imageSize = width * height * depth * Gfx::getFormatInfo(format).blockSize;
OStagingBuffer stagingbuffer = graphics->getStagingManager()->create(imageSize, currentOwner);
auto prevlayout = layout;
auto prevLayout = layout;
changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
void* data;
VkBuffer stagingBuffer = VK_NULL_HANDLE;
VmaAllocation stagingAlloc;
VkBufferCreateInfo stagingInfo = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.size = imageSize,
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
};
VmaAllocationCreateInfo alloc = {
.usage = VMA_MEMORY_USAGE_AUTO,
};
VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &stagingInfo, &alloc, &stagingBuffer, &stagingAlloc, nullptr));
PCommand cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands();
//Gfx::FormatCompatibilityInfo formatInfo = Gfx::getFormatInfo(format);
VkBufferImageCopy region = {
@@ -257,11 +282,12 @@ void TextureBase::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Arra
.depth = depth
},
};
vkCmdCopyImageToBuffer(cmdBuffer->getHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingbuffer->getHandle(), 1, &region);
changeLayout(prevlayout);
buffer.resize(stagingbuffer->getSize());
void* data = stagingbuffer->map();
vkCmdCopyImageToBuffer(cmdBuffer->getHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingBuffer, 1, &region);
changeLayout(prevLayout);
buffer.resize(imageSize);
std::memcpy(buffer.data(), data, buffer.size());
vmaUnmapMemory(graphics->getAllocator(), stagingAlloc);
vmaDestroyBuffer(graphics->getAllocator(), stagingBuffer, stagingAlloc);
}
void TextureBase::executeOwnershipBarrier(Gfx::QueueType newOwner)
+1 -3
View File
@@ -1,13 +1,11 @@
#pragma once
#include "Graphics/Texture.h"
#include "Graphics.h"
#include "Allocator.h"
namespace Seele
{
namespace Vulkan
{
class TextureBase
{
public:
@@ -72,7 +70,7 @@ protected:
//Updates via reference
Gfx::QueueType& currentOwner;
PGraphics graphics;
OSubAllocation allocation;
VmaAllocation allocation;
uint32 width;
uint32 height;
uint32 depth;