Adding VMA
This commit is contained in:
@@ -26,6 +26,10 @@ int main()
|
||||
std::filesystem::path outputPath = "C:/Users/Dynamitos/TrackClearGame";
|
||||
std::filesystem::path sourcePath= "C:/Users/Dynamitos/TrackClear";
|
||||
std::filesystem::path binaryPath = sourcePath / "bin" / "TrackClear.dll";
|
||||
#elif __APPLE__
|
||||
std::filesystem::path outputPath = "/dynamitos/TrackClearGame";
|
||||
std::filesystem::path sourcePath= "/dynamitos/TrackClear";
|
||||
std::filesystem::path binaryPath = sourcePath / "cmake" / "libTrackClear.dynlib";
|
||||
#else
|
||||
std::filesystem::path outputPath = "/home/dynamitos/TrackClearGame";
|
||||
std::filesystem::path sourcePath= "/home/dynamitos/TrackClear";
|
||||
|
||||
@@ -42,6 +42,10 @@ public:
|
||||
{
|
||||
return p == other.p;
|
||||
}
|
||||
constexpr bool operator!=(const IteratorBase &other) const
|
||||
{
|
||||
return p != other.p;
|
||||
}
|
||||
constexpr std::strong_ordering operator<=>(const IteratorBase &other) const
|
||||
{
|
||||
return p <=> other.p;
|
||||
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
}
|
||||
constexpr bool operator!=(const IteratorBase& other)
|
||||
{
|
||||
return node == other.node;
|
||||
return node != other.node;
|
||||
}
|
||||
constexpr bool operator==(const IteratorBase& other)
|
||||
{
|
||||
@@ -89,7 +89,7 @@ public:
|
||||
}
|
||||
constexpr std::strong_ordering operator<=>(const IteratorBase& other)
|
||||
{
|
||||
return node == other.node;
|
||||
return node <=> other.node;
|
||||
}
|
||||
constexpr IteratorBase& operator++()
|
||||
{
|
||||
|
||||
@@ -24,7 +24,7 @@ struct GraphicsInitializer
|
||||
: applicationName("SeeleEngine")
|
||||
, engineName("SeeleEngine")
|
||||
, windowLayoutFile(nullptr)
|
||||
, layers{"VK_LAYER_LUNARG_monitor"}
|
||||
, layers{}
|
||||
, instanceExtensions{}
|
||||
, deviceExtensions{"VK_KHR_swapchain"}
|
||||
, windowHandle(nullptr)
|
||||
|
||||
@@ -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));
|
||||
// }
|
||||
|
||||
@@ -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
|
||||
@@ -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, ®ions);
|
||||
|
||||
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, ®ion);
|
||||
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, ®ion);
|
||||
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(®ion, 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, ®ion);
|
||||
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, ®ion);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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, ®ion);
|
||||
|
||||
// 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, ®ion);
|
||||
|
||||
// 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, ®ion);
|
||||
changeLayout(prevlayout);
|
||||
buffer.resize(stagingbuffer->getSize());
|
||||
void* data = stagingbuffer->map();
|
||||
vkCmdCopyImageToBuffer(cmdBuffer->getHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingBuffer, 1, ®ion);
|
||||
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,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;
|
||||
|
||||
@@ -95,10 +95,6 @@ void GameView::reloadGame()
|
||||
|
||||
void GameView::keyCallback(KeyCode code, InputAction action, KeyModifier modifier)
|
||||
{
|
||||
if (code == KeyCode::KEY_P && action == InputAction::PRESS)
|
||||
{
|
||||
((Vulkan::Graphics*)graphics.getHandle())->getAllocator()->print();
|
||||
}
|
||||
keyboardSystem->keyCallback(code, action, modifier);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user