Adding VMA
This commit is contained in:
Vendored
+1
-1
@@ -28,7 +28,7 @@
|
|||||||
],
|
],
|
||||||
"compilerPath": "/usr/bin/clang",
|
"compilerPath": "/usr/bin/clang",
|
||||||
"cppStandard": "c++20",
|
"cppStandard": "c++20",
|
||||||
"intelliSenseMode": "macos-lang-arm64",
|
"intelliSenseMode": "macos-clang-arm64",
|
||||||
"configurationProvider": "ms-vscode.cmake-tools"
|
"configurationProvider": "ms-vscode.cmake-tools"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ find_package(glm CONFIG REQUIRED)
|
|||||||
find_package(Ktx CONFIG REQUIRED)
|
find_package(Ktx CONFIG REQUIRED)
|
||||||
find_package(nlohmann_json CONFIG REQUIRED)
|
find_package(nlohmann_json CONFIG REQUIRED)
|
||||||
find_package(fmt CONFIG REQUIRED)
|
find_package(fmt CONFIG REQUIRED)
|
||||||
|
find_package(VulkanMemoryAllocator CONFIG REQUIRED)
|
||||||
|
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
@@ -72,6 +73,7 @@ target_link_libraries(Engine PUBLIC nlohmann_json::nlohmann_json)
|
|||||||
target_link_libraries(Engine PUBLIC crcpp)
|
target_link_libraries(Engine PUBLIC crcpp)
|
||||||
target_link_libraries(Engine PUBLIC shader-slang)
|
target_link_libraries(Engine PUBLIC shader-slang)
|
||||||
target_link_libraries(Engine PUBLIC fmt::fmt)
|
target_link_libraries(Engine PUBLIC fmt::fmt)
|
||||||
|
target_link_libraries(Engine PUBLIC GPUOpen::VulkanMemoryAllocator)
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
target_link_libraries(Engine PUBLIC Threads::Threads)
|
target_link_libraries(Engine PUBLIC Threads::Threads)
|
||||||
target_link_libraries(Engine PUBLIC dl)
|
target_link_libraries(Engine PUBLIC dl)
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ int main()
|
|||||||
std::filesystem::path outputPath = "C:/Users/Dynamitos/TrackClearGame";
|
std::filesystem::path outputPath = "C:/Users/Dynamitos/TrackClearGame";
|
||||||
std::filesystem::path sourcePath= "C:/Users/Dynamitos/TrackClear";
|
std::filesystem::path sourcePath= "C:/Users/Dynamitos/TrackClear";
|
||||||
std::filesystem::path binaryPath = sourcePath / "bin" / "TrackClear.dll";
|
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
|
#else
|
||||||
std::filesystem::path outputPath = "/home/dynamitos/TrackClearGame";
|
std::filesystem::path outputPath = "/home/dynamitos/TrackClearGame";
|
||||||
std::filesystem::path sourcePath= "/home/dynamitos/TrackClear";
|
std::filesystem::path sourcePath= "/home/dynamitos/TrackClear";
|
||||||
|
|||||||
@@ -42,6 +42,10 @@ public:
|
|||||||
{
|
{
|
||||||
return p == other.p;
|
return p == other.p;
|
||||||
}
|
}
|
||||||
|
constexpr bool operator!=(const IteratorBase &other) const
|
||||||
|
{
|
||||||
|
return p != other.p;
|
||||||
|
}
|
||||||
constexpr std::strong_ordering operator<=>(const IteratorBase &other) const
|
constexpr std::strong_ordering operator<=>(const IteratorBase &other) const
|
||||||
{
|
{
|
||||||
return p <=> other.p;
|
return p <=> other.p;
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ public:
|
|||||||
}
|
}
|
||||||
constexpr bool operator!=(const IteratorBase& other)
|
constexpr bool operator!=(const IteratorBase& other)
|
||||||
{
|
{
|
||||||
return node == other.node;
|
return node != other.node;
|
||||||
}
|
}
|
||||||
constexpr bool operator==(const IteratorBase& other)
|
constexpr bool operator==(const IteratorBase& other)
|
||||||
{
|
{
|
||||||
@@ -89,7 +89,7 @@ public:
|
|||||||
}
|
}
|
||||||
constexpr std::strong_ordering operator<=>(const IteratorBase& other)
|
constexpr std::strong_ordering operator<=>(const IteratorBase& other)
|
||||||
{
|
{
|
||||||
return node == other.node;
|
return node <=> other.node;
|
||||||
}
|
}
|
||||||
constexpr IteratorBase& operator++()
|
constexpr IteratorBase& operator++()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ struct GraphicsInitializer
|
|||||||
: applicationName("SeeleEngine")
|
: applicationName("SeeleEngine")
|
||||||
, engineName("SeeleEngine")
|
, engineName("SeeleEngine")
|
||||||
, windowLayoutFile(nullptr)
|
, windowLayoutFile(nullptr)
|
||||||
, layers{"VK_LAYER_LUNARG_monitor"}
|
, layers{}
|
||||||
, instanceExtensions{}
|
, instanceExtensions{}
|
||||||
, deviceExtensions{"VK_KHR_swapchain"}
|
, deviceExtensions{"VK_KHR_swapchain"}
|
||||||
, windowHandle(nullptr)
|
, windowHandle(nullptr)
|
||||||
|
|||||||
@@ -1,371 +1,371 @@
|
|||||||
#include "Allocator.h"
|
// #include "Allocator.h"
|
||||||
#include "Graphics.h"
|
// #include "Graphics.h"
|
||||||
#include "Resources.h"
|
// #include "Resources.h"
|
||||||
#include "Enums.h"
|
// #include "Enums.h"
|
||||||
#include "Command.h"
|
// #include "Command.h"
|
||||||
|
|
||||||
using namespace Seele::Vulkan;
|
// using namespace Seele::Vulkan;
|
||||||
|
|
||||||
SubAllocation::SubAllocation(PAllocation owner, VkDeviceSize requestedSize, VkDeviceSize allocatedOffset, VkDeviceSize allocatedSize, VkDeviceSize alignedOffset)
|
// SubAllocation::SubAllocation(PAllocation owner, VkDeviceSize requestedSize, VkDeviceSize allocatedOffset, VkDeviceSize allocatedSize, VkDeviceSize alignedOffset)
|
||||||
: owner(owner)
|
// : owner(owner)
|
||||||
, requestedSize(requestedSize)
|
// , requestedSize(requestedSize)
|
||||||
, allocatedOffset(allocatedOffset)
|
// , allocatedOffset(allocatedOffset)
|
||||||
, allocatedSize(allocatedSize)
|
// , allocatedSize(allocatedSize)
|
||||||
, alignedOffset(alignedOffset)
|
// , alignedOffset(alignedOffset)
|
||||||
{
|
// {
|
||||||
}
|
// }
|
||||||
|
|
||||||
SubAllocation::~SubAllocation()
|
// SubAllocation::~SubAllocation()
|
||||||
{
|
// {
|
||||||
owner->markFree(this);
|
// owner->markFree(this);
|
||||||
}
|
// }
|
||||||
|
|
||||||
VkDeviceMemory SubAllocation::getHandle() const
|
// VkDeviceMemory SubAllocation::getHandle() const
|
||||||
{
|
// {
|
||||||
return owner->getHandle();
|
// return owner->getHandle();
|
||||||
}
|
// }
|
||||||
|
|
||||||
void *SubAllocation::map()
|
// void *SubAllocation::map()
|
||||||
{
|
// {
|
||||||
return (uint8 *)owner->map() + alignedOffset;
|
// return (uint8 *)owner->map() + alignedOffset;
|
||||||
}
|
// }
|
||||||
|
|
||||||
void SubAllocation::flushMemory()
|
// void SubAllocation::flushMemory()
|
||||||
{
|
// {
|
||||||
owner->flushMemory();
|
// owner->flushMemory();
|
||||||
}
|
// }
|
||||||
|
|
||||||
void SubAllocation::invalidate()
|
// void SubAllocation::invalidate()
|
||||||
{
|
// {
|
||||||
owner->invalidate();
|
// owner->invalidate();
|
||||||
}
|
// }
|
||||||
|
|
||||||
Allocation::Allocation(PGraphics graphics, PAllocator pool, VkDeviceSize size, uint8 memoryTypeIndex,
|
// Allocation::Allocation(PGraphics graphics, PAllocator pool, VkDeviceSize size, uint8 memoryTypeIndex,
|
||||||
VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
|
// VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
|
||||||
: device(graphics->getDevice())
|
// : device(graphics->getDevice())
|
||||||
, pool(pool)
|
// , pool(pool)
|
||||||
, bytesAllocated(size)
|
// , bytesAllocated(size)
|
||||||
, bytesUsed(0)
|
// , bytesUsed(0)
|
||||||
, mappedPointer(nullptr)
|
// , mappedPointer(nullptr)
|
||||||
, canMap((properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
|
// , canMap((properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
|
||||||
, isMapped(false)
|
// , isMapped(false)
|
||||||
, properties(properties)
|
// , properties(properties)
|
||||||
, memoryTypeIndex(memoryTypeIndex)
|
// , memoryTypeIndex(memoryTypeIndex)
|
||||||
{
|
// {
|
||||||
VkMemoryAllocateInfo allocInfo = {
|
// VkMemoryAllocateInfo allocInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
// .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||||
.pNext = dedicatedInfo,
|
// .pNext = dedicatedInfo,
|
||||||
.allocationSize = size,
|
// .allocationSize = size,
|
||||||
.memoryTypeIndex = memoryTypeIndex,
|
// .memoryTypeIndex = memoryTypeIndex,
|
||||||
};
|
// };
|
||||||
isDedicated = dedicatedInfo != nullptr;
|
// isDedicated = dedicatedInfo != nullptr;
|
||||||
VK_CHECK(vkAllocateMemory(device, &allocInfo, nullptr, &allocatedMemory));
|
// VK_CHECK(vkAllocateMemory(device, &allocInfo, nullptr, &allocatedMemory));
|
||||||
freeRanges[0] = size;
|
// freeRanges[0] = size;
|
||||||
}
|
// }
|
||||||
|
|
||||||
Allocation::~Allocation()
|
// Allocation::~Allocation()
|
||||||
{
|
// {
|
||||||
vkFreeMemory(device, allocatedMemory, nullptr);
|
// vkFreeMemory(device, allocatedMemory, nullptr);
|
||||||
}
|
// }
|
||||||
|
|
||||||
OSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDeviceSize alignment)
|
// OSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDeviceSize alignment)
|
||||||
{
|
// {
|
||||||
if (isDedicated)
|
// if (isDedicated)
|
||||||
{
|
// {
|
||||||
if (activeAllocations.empty() && requestedSize == bytesAllocated)
|
// if (activeAllocations.empty() && requestedSize == bytesAllocated)
|
||||||
{
|
// {
|
||||||
OSubAllocation suballoc = new SubAllocation(this, requestedSize, 0, requestedSize, 0);
|
// OSubAllocation suballoc = new SubAllocation(this, requestedSize, 0, requestedSize, 0);
|
||||||
activeAllocations.add(suballoc);
|
// activeAllocations.add(suballoc);
|
||||||
freeRanges.clear();
|
// freeRanges.clear();
|
||||||
bytesUsed += requestedSize;
|
// bytesUsed += requestedSize;
|
||||||
return suballoc;
|
// return suballoc;
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
return nullptr;
|
// return nullptr;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
for (const auto& [lower, size] : freeRanges)
|
// for (const auto& [lower, size] : freeRanges)
|
||||||
{
|
// {
|
||||||
VkDeviceSize alignedOffset = lower + alignment - 1;
|
// VkDeviceSize alignedOffset = lower + alignment - 1;
|
||||||
alignedOffset /= alignment;
|
// alignedOffset /= alignment;
|
||||||
alignedOffset *= alignment;
|
// alignedOffset *= alignment;
|
||||||
VkDeviceSize allocatedSize = requestedSize + (alignedOffset - lower);
|
// VkDeviceSize allocatedSize = requestedSize + (alignedOffset - lower);
|
||||||
if (size >= allocatedSize)
|
// if (size >= allocatedSize)
|
||||||
{
|
// {
|
||||||
//std::cout << "Allocating " << lower << "-" << lower + allocatedSize << std::endl;
|
// //std::cout << "Allocating " << lower << "-" << lower + allocatedSize << std::endl;
|
||||||
VkDeviceSize newSize = size - allocatedSize;
|
// VkDeviceSize newSize = size - allocatedSize;
|
||||||
VkDeviceSize newLower = lower + allocatedSize;
|
// VkDeviceSize newLower = lower + allocatedSize;
|
||||||
OSubAllocation alloc = new SubAllocation(this, requestedSize, lower, allocatedSize, alignedOffset);
|
// OSubAllocation alloc = new SubAllocation(this, requestedSize, lower, allocatedSize, alignedOffset);
|
||||||
activeAllocations.add(alloc);
|
// activeAllocations.add(alloc);
|
||||||
freeRanges.erase(lower);
|
// freeRanges.erase(lower);
|
||||||
if (newSize > 0)
|
// if (newSize > 0)
|
||||||
{
|
// {
|
||||||
freeRanges[newLower] = newSize;
|
// freeRanges[newLower] = newSize;
|
||||||
}
|
// }
|
||||||
bytesUsed += allocatedSize;
|
// bytesUsed += allocatedSize;
|
||||||
return alloc;
|
// return alloc;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return nullptr;
|
// return nullptr;
|
||||||
}
|
// }
|
||||||
|
|
||||||
void Allocation::markFree(PSubAllocation allocation)
|
// void Allocation::markFree(PSubAllocation allocation)
|
||||||
{
|
// {
|
||||||
//std::cout << "Freeing " << allocation->allocatedOffset << "-" << allocation->allocatedOffset + allocation->allocatedSize << std::endl;
|
// //std::cout << "Freeing " << allocation->allocatedOffset << "-" << allocation->allocatedOffset + allocation->allocatedSize << std::endl;
|
||||||
assert(activeAllocations.find(allocation) != activeAllocations.end());
|
// assert(activeAllocations.find(allocation) != activeAllocations.end());
|
||||||
VkDeviceSize lowerBound = allocation->allocatedOffset;
|
// VkDeviceSize lowerBound = allocation->allocatedOffset;
|
||||||
VkDeviceSize upperBound = allocation->allocatedOffset + allocation->allocatedSize;
|
// VkDeviceSize upperBound = allocation->allocatedOffset + allocation->allocatedSize;
|
||||||
freeRanges[lowerBound] = allocation->allocatedSize;
|
// freeRanges[lowerBound] = allocation->allocatedSize;
|
||||||
for (const auto& [lower, size] : freeRanges)
|
// for (const auto& [lower, size] : freeRanges)
|
||||||
{
|
// {
|
||||||
if (lower + size == lowerBound)
|
// if (lower + size == lowerBound)
|
||||||
{
|
// {
|
||||||
freeRanges[lower] = size + allocation->allocatedSize;
|
// freeRanges[lower] = size + allocation->allocatedSize;
|
||||||
freeRanges.erase(lowerBound);
|
// freeRanges.erase(lowerBound);
|
||||||
lowerBound = lower;
|
// lowerBound = lower;
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if (freeRanges.find(upperBound) != freeRanges.end())
|
// if (freeRanges.find(upperBound) != freeRanges.end())
|
||||||
{
|
// {
|
||||||
freeRanges[lowerBound] += freeRanges[upperBound];
|
// freeRanges[lowerBound] += freeRanges[upperBound];
|
||||||
freeRanges.erase(upperBound);
|
// freeRanges.erase(upperBound);
|
||||||
}
|
// }
|
||||||
activeAllocations.remove(allocation, false);
|
// activeAllocations.remove(allocation, false);
|
||||||
bytesUsed -= allocation->allocatedSize;
|
// bytesUsed -= allocation->allocatedSize;
|
||||||
//if (activeAllocations.size() == 0)
|
// //if (activeAllocations.size() == 0)
|
||||||
//{
|
// //{
|
||||||
// pool->free(this);
|
// // pool->free(this);
|
||||||
//}
|
// //}
|
||||||
}
|
// }
|
||||||
|
|
||||||
void Allocation::flushMemory()
|
// void Allocation::flushMemory()
|
||||||
{
|
// {
|
||||||
VkMappedMemoryRange range = {
|
// VkMappedMemoryRange range = {
|
||||||
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
|
// .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
|
||||||
.pNext = 0,
|
// .pNext = 0,
|
||||||
.memory = allocatedMemory,
|
// .memory = allocatedMemory,
|
||||||
.offset = 0,
|
// .offset = 0,
|
||||||
.size = bytesAllocated,
|
// .size = bytesAllocated,
|
||||||
};
|
// };
|
||||||
vkFlushMappedMemoryRanges(device, 1, &range);
|
// vkFlushMappedMemoryRanges(device, 1, &range);
|
||||||
}
|
// }
|
||||||
|
|
||||||
void Allocation::invalidate()
|
// void Allocation::invalidate()
|
||||||
{
|
// {
|
||||||
VkMappedMemoryRange range = {
|
// VkMappedMemoryRange range = {
|
||||||
.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
|
// .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
|
||||||
.pNext = 0,
|
// .pNext = 0,
|
||||||
.memory = allocatedMemory,
|
// .memory = allocatedMemory,
|
||||||
.size = bytesAllocated,
|
// .size = bytesAllocated,
|
||||||
};
|
// };
|
||||||
vkInvalidateMappedMemoryRanges(device, 1, &range);
|
// vkInvalidateMappedMemoryRanges(device, 1, &range);
|
||||||
}
|
// }
|
||||||
|
|
||||||
Allocator::Allocator(PGraphics graphics)
|
// Allocator::Allocator(PGraphics graphics)
|
||||||
: graphics(graphics)
|
// : graphics(graphics)
|
||||||
{
|
// {
|
||||||
vkGetPhysicalDeviceMemoryProperties(graphics->getPhysicalDevice(), &memProperties);
|
// vkGetPhysicalDeviceMemoryProperties(graphics->getPhysicalDevice(), &memProperties);
|
||||||
heaps.reserve(memProperties.memoryHeapCount);
|
// heaps.reserve(memProperties.memoryHeapCount);
|
||||||
for (size_t i = 0; i < memProperties.memoryHeapCount; ++i)
|
// for (size_t i = 0; i < memProperties.memoryHeapCount; ++i)
|
||||||
{
|
// {
|
||||||
VkMemoryHeap memoryHeap = memProperties.memoryHeaps[i];
|
// VkMemoryHeap memoryHeap = memProperties.memoryHeaps[i];
|
||||||
HeapInfo heapInfo;
|
// HeapInfo heapInfo;
|
||||||
heapInfo.maxSize = memoryHeap.size;
|
// heapInfo.maxSize = memoryHeap.size;
|
||||||
//std::cout << "Creating heap " << i << " with properties " << memoryHeap.flags << " size " << memoryHeap.size << std::endl;
|
// //std::cout << "Creating heap " << i << " with properties " << memoryHeap.flags << " size " << memoryHeap.size << std::endl;
|
||||||
heaps.add(std::move(heapInfo));
|
// heaps.add(std::move(heapInfo));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
Allocator::~Allocator()
|
// Allocator::~Allocator()
|
||||||
{
|
// {
|
||||||
}
|
// }
|
||||||
|
|
||||||
OSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
|
// OSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
|
||||||
{
|
// {
|
||||||
const VkMemoryRequirements &requirements = memRequirements2.memoryRequirements;
|
// const VkMemoryRequirements &requirements = memRequirements2.memoryRequirements;
|
||||||
uint32 memoryTypeIndex = findMemoryType(requirements.memoryTypeBits, properties);
|
// uint32 memoryTypeIndex = findMemoryType(requirements.memoryTypeBits, properties);
|
||||||
uint32 heapIndex = memProperties.memoryTypes[memoryTypeIndex].heapIndex;
|
// uint32 heapIndex = memProperties.memoryTypes[memoryTypeIndex].heapIndex;
|
||||||
|
|
||||||
if (memRequirements2.pNext != nullptr)
|
// if (memRequirements2.pNext != nullptr)
|
||||||
{
|
// {
|
||||||
VkMemoryDedicatedRequirements *dedicatedReq = (VkMemoryDedicatedRequirements *)memRequirements2.pNext;
|
// VkMemoryDedicatedRequirements *dedicatedReq = (VkMemoryDedicatedRequirements *)memRequirements2.pNext;
|
||||||
if (dedicatedReq->prefersDedicatedAllocation)
|
// if (dedicatedReq->prefersDedicatedAllocation)
|
||||||
{
|
// {
|
||||||
OAllocation newAllocation = new Allocation(graphics, this, requirements.size, memoryTypeIndex, properties, dedicatedInfo);
|
// OAllocation newAllocation = new Allocation(graphics, this, requirements.size, memoryTypeIndex, properties, dedicatedInfo);
|
||||||
heaps[heapIndex].inUse += newAllocation->bytesAllocated;
|
// heaps[heapIndex].inUse += newAllocation->bytesAllocated;
|
||||||
std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << std::endl;
|
// std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << std::endl;
|
||||||
heaps[heapIndex].allocations.add(std::move(newAllocation));
|
// heaps[heapIndex].allocations.add(std::move(newAllocation));
|
||||||
return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment);
|
// return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
for (auto& alloc : heaps[heapIndex].allocations)
|
// for (auto& alloc : heaps[heapIndex].allocations)
|
||||||
{
|
// {
|
||||||
if(alloc->memoryTypeIndex == memoryTypeIndex)
|
// if(alloc->memoryTypeIndex == memoryTypeIndex)
|
||||||
{
|
// {
|
||||||
OSubAllocation suballoc = alloc->getSuballocation(requirements.size, requirements.alignment);
|
// OSubAllocation suballoc = alloc->getSuballocation(requirements.size, requirements.alignment);
|
||||||
if (suballoc != nullptr)
|
// if (suballoc != nullptr)
|
||||||
{
|
// {
|
||||||
return suballoc;
|
// return suballoc;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// no suitable allocations found, allocate new block
|
// // no suitable allocations found, allocate new block
|
||||||
OAllocation newAllocation = new Allocation(graphics, this, (requirements.size > DEFAULT_ALLOCATION) ? requirements.size : DEFAULT_ALLOCATION, memoryTypeIndex, properties, nullptr);
|
// OAllocation newAllocation = new Allocation(graphics, this, (requirements.size > DEFAULT_ALLOCATION) ? requirements.size : DEFAULT_ALLOCATION, memoryTypeIndex, properties, nullptr);
|
||||||
heaps[heapIndex].inUse += newAllocation->bytesAllocated;
|
// heaps[heapIndex].inUse += newAllocation->bytesAllocated;
|
||||||
std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << std::endl;
|
// std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << std::endl;
|
||||||
heaps[heapIndex].allocations.add(std::move(newAllocation));
|
// heaps[heapIndex].allocations.add(std::move(newAllocation));
|
||||||
return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment);
|
// return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment);
|
||||||
}
|
// }
|
||||||
|
|
||||||
void Allocator::free(PAllocation allocation)
|
// void Allocator::free(PAllocation allocation)
|
||||||
{
|
// {
|
||||||
for (uint32 heapIndex = 0; heapIndex < heaps.size(); ++heapIndex)
|
// for (uint32 heapIndex = 0; heapIndex < heaps.size(); ++heapIndex)
|
||||||
{
|
// {
|
||||||
for (uint32 alloc = 0; alloc < heaps[heapIndex].allocations.size(); ++alloc)
|
// for (uint32 alloc = 0; alloc < heaps[heapIndex].allocations.size(); ++alloc)
|
||||||
{
|
// {
|
||||||
if (heaps[heapIndex].allocations[alloc] == allocation)
|
// if (heaps[heapIndex].allocations[alloc] == allocation)
|
||||||
{
|
// {
|
||||||
heaps[heapIndex].allocations.removeAt(alloc, false);
|
// heaps[heapIndex].allocations.removeAt(alloc, false);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
void Allocator::print()
|
// void Allocator::print()
|
||||||
{
|
// {
|
||||||
for (uint32 heapIndex = 0; heapIndex < heaps.size(); ++heapIndex)
|
// for (uint32 heapIndex = 0; heapIndex < heaps.size(); ++heapIndex)
|
||||||
{
|
// {
|
||||||
std::cout << "Heap " << heapIndex << std::endl;
|
// std::cout << "Heap " << heapIndex << std::endl;
|
||||||
for (uint32 alloc = 0; alloc < heaps[heapIndex].allocations.size(); ++alloc)
|
// 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;
|
// std::cout << "[" << alloc << "]: " << (float)heaps[heapIndex].allocations[alloc]->bytesUsed / heaps[heapIndex].allocations[alloc]->bytesAllocated << std::endl;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
uint32 Allocator::findMemoryType(uint32 typeFilter, VkMemoryPropertyFlags properties)
|
// uint32 Allocator::findMemoryType(uint32 typeFilter, VkMemoryPropertyFlags properties)
|
||||||
{
|
// {
|
||||||
for (uint32 i = 0; i < memProperties.memoryTypeCount; i++)
|
// for (uint32 i = 0; i < memProperties.memoryTypeCount; i++)
|
||||||
{
|
// {
|
||||||
if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties)
|
// if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties)
|
||||||
{
|
// {
|
||||||
return i;
|
// 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)
|
// StagingBuffer::StagingBuffer(PGraphics graphics, OSubAllocation allocation, VkBuffer buffer, VkDeviceSize size, Gfx::QueueType owner)
|
||||||
: owner(owner)
|
// : owner(owner)
|
||||||
, allocation(std::move(allocation))
|
// , allocation(std::move(allocation))
|
||||||
, graphics(graphics)
|
// , graphics(graphics)
|
||||||
, buffer(buffer)
|
// , buffer(buffer)
|
||||||
, size(size)
|
// , size(size)
|
||||||
{
|
// {
|
||||||
}
|
// }
|
||||||
|
|
||||||
StagingBuffer::~StagingBuffer()
|
// StagingBuffer::~StagingBuffer()
|
||||||
{
|
// {
|
||||||
graphics->getDestructionManager()->queueBuffer(
|
// graphics->getDestructionManager()->queueBuffer(
|
||||||
graphics->getQueueCommands(owner)->getCommands(), buffer);
|
// graphics->getQueueCommands(owner)->getCommands(), buffer);
|
||||||
graphics->getDestructionManager()->queueAllocation(
|
// graphics->getDestructionManager()->queueAllocation(
|
||||||
graphics->getQueueCommands(owner)->getCommands(), std::move(allocation));
|
// graphics->getQueueCommands(owner)->getCommands(), std::move(allocation));
|
||||||
}
|
// }
|
||||||
|
|
||||||
void* StagingBuffer::map()
|
// void* StagingBuffer::map()
|
||||||
{
|
// {
|
||||||
return allocation->map();
|
// return allocation->map();
|
||||||
}
|
// }
|
||||||
|
|
||||||
void StagingBuffer::flush()
|
// void StagingBuffer::flush()
|
||||||
{
|
// {
|
||||||
allocation->flushMemory();
|
// allocation->flushMemory();
|
||||||
}
|
// }
|
||||||
|
|
||||||
void StagingBuffer::invalidate()
|
// void StagingBuffer::invalidate()
|
||||||
{
|
// {
|
||||||
allocation->invalidate();
|
// allocation->invalidate();
|
||||||
}
|
// }
|
||||||
|
|
||||||
VkDeviceMemory StagingBuffer::getMemory() const
|
// VkDeviceMemory StagingBuffer::getMemory() const
|
||||||
{
|
// {
|
||||||
return allocation->getHandle();
|
// return allocation->getHandle();
|
||||||
}
|
// }
|
||||||
|
|
||||||
VkDeviceSize StagingBuffer::getOffset() const
|
// VkDeviceSize StagingBuffer::getOffset() const
|
||||||
{
|
// {
|
||||||
return allocation->getOffset();
|
// return allocation->getOffset();
|
||||||
}
|
// }
|
||||||
|
|
||||||
StagingManager::StagingManager(PGraphics graphics, PAllocator pool)
|
// StagingManager::StagingManager(PGraphics graphics, PAllocator pool)
|
||||||
: graphics(graphics), pool(pool)
|
// : graphics(graphics), pool(pool)
|
||||||
{
|
// {
|
||||||
}
|
// }
|
||||||
|
|
||||||
StagingManager::~StagingManager()
|
// StagingManager::~StagingManager()
|
||||||
{
|
// {
|
||||||
}
|
// }
|
||||||
|
|
||||||
OStagingBuffer StagingManager::create(uint64 size, Gfx::QueueType owner)
|
// OStagingBuffer StagingManager::create(uint64 size, Gfx::QueueType owner)
|
||||||
{
|
// {
|
||||||
//vkDeviceWaitIdle(graphics->getDevice());
|
// //vkDeviceWaitIdle(graphics->getDevice());
|
||||||
//std::cout << "Creating new stagingbuffer" << std::endl;
|
// //std::cout << "Creating new stagingbuffer" << std::endl;
|
||||||
for (uint32 i = 0; i < freeBuffers.size(); ++i)
|
// for (uint32 i = 0; i < freeBuffers.size(); ++i)
|
||||||
{
|
// {
|
||||||
if (size <= freeBuffers[i]->getSize() && owner == freeBuffers[i]->getOwner())
|
// if (size <= freeBuffers[i]->getSize() && owner == freeBuffers[i]->getOwner())
|
||||||
{
|
// {
|
||||||
OStagingBuffer result = std::move(freeBuffers[i]);
|
// OStagingBuffer result = std::move(freeBuffers[i]);
|
||||||
freeBuffers.removeAt(i);
|
// freeBuffers.removeAt(i);
|
||||||
return result;
|
// return result;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
uint32 queueIndex = graphics->getFamilyMapping().getQueueTypeFamilyIndex(owner);
|
// uint32 queueIndex = graphics->getFamilyMapping().getQueueTypeFamilyIndex(owner);
|
||||||
VkBufferCreateInfo stagingBufferCreateInfo = {
|
// VkBufferCreateInfo stagingBufferCreateInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
// .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
// .pNext = nullptr,
|
||||||
.flags = 0,
|
// .flags = 0,
|
||||||
.size = size,
|
// .size = size,
|
||||||
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
// .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
// .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||||
.queueFamilyIndexCount = 1,
|
// .queueFamilyIndexCount = 1,
|
||||||
.pQueueFamilyIndices = &queueIndex,
|
// .pQueueFamilyIndices = &queueIndex,
|
||||||
};
|
// };
|
||||||
|
|
||||||
VkBuffer buffer;
|
// VkBuffer buffer;
|
||||||
VK_CHECK(vkCreateBuffer(graphics->getDevice(), &stagingBufferCreateInfo, nullptr, &buffer));
|
// VK_CHECK(vkCreateBuffer(graphics->getDevice(), &stagingBufferCreateInfo, nullptr, &buffer));
|
||||||
|
|
||||||
VkMemoryDedicatedRequirements dedicatedReqs = {
|
// VkMemoryDedicatedRequirements dedicatedReqs = {
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
|
// .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
|
||||||
.pNext = nullptr,
|
// .pNext = nullptr,
|
||||||
};
|
// };
|
||||||
VkMemoryRequirements2 memReqs = {
|
// VkMemoryRequirements2 memReqs = {
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
|
// .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
|
||||||
.pNext = &dedicatedReqs,
|
// .pNext = &dedicatedReqs,
|
||||||
};
|
// };
|
||||||
VkBufferMemoryRequirementsInfo2 bufferQuery = {
|
// VkBufferMemoryRequirementsInfo2 bufferQuery = {
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
|
// .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
|
||||||
.pNext = nullptr,
|
// .pNext = nullptr,
|
||||||
.buffer = buffer,
|
// .buffer = buffer,
|
||||||
};
|
// };
|
||||||
vkGetBufferMemoryRequirements2(graphics->getDevice(), &bufferQuery, &memReqs);
|
// vkGetBufferMemoryRequirements2(graphics->getDevice(), &bufferQuery, &memReqs);
|
||||||
|
|
||||||
OStagingBuffer stagingBuffer = new StagingBuffer(
|
// OStagingBuffer stagingBuffer = new StagingBuffer(
|
||||||
graphics,
|
// graphics,
|
||||||
pool->allocate(memReqs, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT, buffer),
|
// pool->allocate(memReqs, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT, buffer),
|
||||||
buffer,
|
// buffer,
|
||||||
size,
|
// size,
|
||||||
owner
|
// owner
|
||||||
);
|
// );
|
||||||
vkBindBufferMemory(graphics->getDevice(), buffer, stagingBuffer->getMemory(), stagingBuffer->getOffset());
|
// vkBindBufferMemory(graphics->getDevice(), buffer, stagingBuffer->getMemory(), stagingBuffer->getOffset());
|
||||||
|
|
||||||
return stagingBuffer;
|
// return stagingBuffer;
|
||||||
}
|
// }
|
||||||
|
|
||||||
void StagingManager::release(OStagingBuffer)
|
// void StagingManager::release(OStagingBuffer)
|
||||||
{
|
// {
|
||||||
//freeBuffers.add(std::move(buffer));
|
// //freeBuffers.add(std::move(buffer));
|
||||||
}
|
// }
|
||||||
|
|||||||
@@ -1,196 +1,196 @@
|
|||||||
#pragma once
|
// #pragma once
|
||||||
#include "MinimalEngine.h"
|
// #include "MinimalEngine.h"
|
||||||
#include "Enums.h"
|
// #include "Enums.h"
|
||||||
#include "Containers/Map.h"
|
// #include "Containers/Map.h"
|
||||||
#include "Containers/Array.h"
|
// #include "Containers/Array.h"
|
||||||
#include "Graphics/Resources.h"
|
// #include "Graphics/Resources.h"
|
||||||
#include <mutex>
|
// #include <mutex>
|
||||||
|
|
||||||
namespace Seele
|
// namespace Seele
|
||||||
{
|
// {
|
||||||
namespace Vulkan
|
// namespace Vulkan
|
||||||
{
|
// {
|
||||||
DECLARE_REF(Graphics)
|
// DECLARE_REF(Graphics)
|
||||||
DECLARE_REF(Allocator)
|
// DECLARE_REF(Allocator)
|
||||||
DECLARE_REF(Allocation)
|
// DECLARE_REF(Allocation)
|
||||||
class SubAllocation
|
// class SubAllocation
|
||||||
{
|
// {
|
||||||
public:
|
// public:
|
||||||
SubAllocation(PAllocation owner, VkDeviceSize requestedSize, VkDeviceSize allocatedOffset, VkDeviceSize allocatedSize, VkDeviceSize alignedOffset);
|
// SubAllocation(PAllocation owner, VkDeviceSize requestedSize, VkDeviceSize allocatedOffset, VkDeviceSize allocatedSize, VkDeviceSize alignedOffset);
|
||||||
~SubAllocation();
|
// ~SubAllocation();
|
||||||
VkDeviceMemory getHandle() const;
|
// VkDeviceMemory getHandle() const;
|
||||||
|
|
||||||
constexpr VkDeviceSize getSize() const
|
// constexpr VkDeviceSize getSize() const
|
||||||
{
|
// {
|
||||||
return requestedSize;
|
// return requestedSize;
|
||||||
}
|
// }
|
||||||
|
|
||||||
constexpr VkDeviceSize getOffset() const
|
// constexpr VkDeviceSize getOffset() const
|
||||||
{
|
// {
|
||||||
return alignedOffset;
|
// return alignedOffset;
|
||||||
}
|
// }
|
||||||
|
|
||||||
void *map();
|
// void *map();
|
||||||
void flushMemory();
|
// void flushMemory();
|
||||||
void invalidate();
|
// void invalidate();
|
||||||
|
|
||||||
private:
|
// private:
|
||||||
PAllocation owner;
|
// PAllocation owner;
|
||||||
VkDeviceSize requestedSize;
|
// VkDeviceSize requestedSize;
|
||||||
VkDeviceSize allocatedOffset;
|
// VkDeviceSize allocatedOffset;
|
||||||
VkDeviceSize allocatedSize;
|
// VkDeviceSize allocatedSize;
|
||||||
VkDeviceSize alignedOffset;
|
// VkDeviceSize alignedOffset;
|
||||||
friend class Allocation;
|
// friend class Allocation;
|
||||||
friend class Allocator;
|
// friend class Allocator;
|
||||||
};
|
// };
|
||||||
DEFINE_REF(SubAllocation)
|
// DEFINE_REF(SubAllocation)
|
||||||
class Allocation
|
// class Allocation
|
||||||
{
|
// {
|
||||||
public:
|
// public:
|
||||||
Allocation(PGraphics graphics, PAllocator pool, VkDeviceSize size, uint8 memoryTypeIndex,
|
// Allocation(PGraphics graphics, PAllocator pool, VkDeviceSize size, uint8 memoryTypeIndex,
|
||||||
VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo = nullptr);
|
// VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo = nullptr);
|
||||||
Allocation(const Allocation& other) = delete;
|
// Allocation(const Allocation& other) = delete;
|
||||||
Allocation& operator=(const Allocation& other) = delete;
|
// Allocation& operator=(const Allocation& other) = delete;
|
||||||
~Allocation();
|
// ~Allocation();
|
||||||
OSubAllocation getSuballocation(VkDeviceSize size, VkDeviceSize alignment);
|
// OSubAllocation getSuballocation(VkDeviceSize size, VkDeviceSize alignment);
|
||||||
void markFree(PSubAllocation alloc);
|
// void markFree(PSubAllocation alloc);
|
||||||
constexpr VkDeviceMemory getHandle() const
|
// constexpr VkDeviceMemory getHandle() const
|
||||||
{
|
// {
|
||||||
return allocatedMemory;
|
// return allocatedMemory;
|
||||||
}
|
// }
|
||||||
constexpr VkMemoryPropertyFlags getProperties() const
|
// constexpr VkMemoryPropertyFlags getProperties() const
|
||||||
{
|
// {
|
||||||
return properties;
|
// return properties;
|
||||||
}
|
// }
|
||||||
constexpr void* map()
|
// constexpr void* map()
|
||||||
{
|
// {
|
||||||
if (!canMap)
|
// if (!canMap)
|
||||||
{
|
// {
|
||||||
return nullptr;
|
// return nullptr;
|
||||||
}
|
// }
|
||||||
if (!isMapped)
|
// if (!isMapped)
|
||||||
{
|
// {
|
||||||
vkMapMemory(device, allocatedMemory, 0, bytesAllocated, 0, &mappedPointer);
|
// vkMapMemory(device, allocatedMemory, 0, bytesAllocated, 0, &mappedPointer);
|
||||||
isMapped = true;
|
// isMapped = true;
|
||||||
}
|
// }
|
||||||
return mappedPointer;
|
// return mappedPointer;
|
||||||
}
|
// }
|
||||||
|
|
||||||
void flushMemory();
|
// void flushMemory();
|
||||||
void invalidate();
|
// void invalidate();
|
||||||
|
|
||||||
private:
|
// private:
|
||||||
VkDevice device;
|
// VkDevice device;
|
||||||
PAllocator pool;
|
// PAllocator pool;
|
||||||
VkDeviceSize bytesAllocated;
|
// VkDeviceSize bytesAllocated;
|
||||||
VkDeviceSize bytesUsed;
|
// VkDeviceSize bytesUsed;
|
||||||
VkDeviceMemory allocatedMemory;
|
// VkDeviceMemory allocatedMemory;
|
||||||
Array<PSubAllocation> activeAllocations;
|
// Array<PSubAllocation> activeAllocations;
|
||||||
Map<VkDeviceSize, VkDeviceSize> freeRanges;
|
// Map<VkDeviceSize, VkDeviceSize> freeRanges;
|
||||||
void *mappedPointer;
|
// void *mappedPointer;
|
||||||
uint8 canMap : 1;
|
// uint8 canMap : 1;
|
||||||
uint8 isMapped : 1;
|
// uint8 isMapped : 1;
|
||||||
uint8 isDedicated : 1;
|
// uint8 isDedicated : 1;
|
||||||
VkMemoryPropertyFlags properties;
|
// VkMemoryPropertyFlags properties;
|
||||||
uint8 memoryTypeIndex;
|
// uint8 memoryTypeIndex;
|
||||||
friend class Allocator;
|
// friend class Allocator;
|
||||||
};
|
// };
|
||||||
DEFINE_REF(Allocation)
|
// DEFINE_REF(Allocation)
|
||||||
|
|
||||||
class Allocator
|
// class Allocator
|
||||||
{
|
// {
|
||||||
public:
|
// public:
|
||||||
Allocator(PGraphics graphics);
|
// Allocator(PGraphics graphics);
|
||||||
~Allocator();
|
// ~Allocator();
|
||||||
OSubAllocation allocate(const VkMemoryRequirements2 &requirements, VkMemoryPropertyFlags props,
|
// OSubAllocation allocate(const VkMemoryRequirements2 &requirements, VkMemoryPropertyFlags props,
|
||||||
VkMemoryDedicatedAllocateInfo *dedicatedInfo = nullptr);
|
// VkMemoryDedicatedAllocateInfo *dedicatedInfo = nullptr);
|
||||||
OSubAllocation allocate(const VkMemoryRequirements2 &requirements, VkMemoryPropertyFlags props,
|
// OSubAllocation allocate(const VkMemoryRequirements2 &requirements, VkMemoryPropertyFlags props,
|
||||||
VkBuffer buffer)
|
// VkBuffer buffer)
|
||||||
{
|
// {
|
||||||
VkMemoryDedicatedAllocateInfo allocInfo = {
|
// VkMemoryDedicatedAllocateInfo allocInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
|
// .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
|
||||||
.pNext = nullptr,
|
// .pNext = nullptr,
|
||||||
.image = VK_NULL_HANDLE,
|
// .image = VK_NULL_HANDLE,
|
||||||
.buffer = buffer,
|
// .buffer = buffer,
|
||||||
};
|
// };
|
||||||
return allocate(requirements, props, &allocInfo);
|
// return allocate(requirements, props, &allocInfo);
|
||||||
}
|
// }
|
||||||
OSubAllocation allocate(const VkMemoryRequirements2 &requirements, VkMemoryPropertyFlags props,
|
// OSubAllocation allocate(const VkMemoryRequirements2 &requirements, VkMemoryPropertyFlags props,
|
||||||
VkImage image)
|
// VkImage image)
|
||||||
{
|
// {
|
||||||
VkMemoryDedicatedAllocateInfo allocInfo = {
|
// VkMemoryDedicatedAllocateInfo allocInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
|
// .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
|
||||||
.pNext = nullptr,
|
// .pNext = nullptr,
|
||||||
.image = image,
|
// .image = image,
|
||||||
.buffer = VK_NULL_HANDLE,
|
// .buffer = VK_NULL_HANDLE,
|
||||||
};
|
// };
|
||||||
return allocate(requirements, props, &allocInfo);
|
// return allocate(requirements, props, &allocInfo);
|
||||||
}
|
// }
|
||||||
|
|
||||||
void free(PAllocation allocation);
|
// void free(PAllocation allocation);
|
||||||
void print();
|
// void print();
|
||||||
private:
|
// private:
|
||||||
static constexpr VkDeviceSize DEFAULT_ALLOCATION = 16 * 1024 * 1024; // 16MB
|
// static constexpr VkDeviceSize DEFAULT_ALLOCATION = 16 * 1024 * 1024; // 16MB
|
||||||
struct HeapInfo
|
// struct HeapInfo
|
||||||
{
|
// {
|
||||||
VkDeviceSize maxSize = 0;
|
// VkDeviceSize maxSize = 0;
|
||||||
VkDeviceSize inUse = 0;
|
// VkDeviceSize inUse = 0;
|
||||||
Array<OAllocation> allocations;
|
// Array<OAllocation> allocations;
|
||||||
HeapInfo() = default;
|
// HeapInfo() = default;
|
||||||
HeapInfo(const HeapInfo& other) = delete;
|
// HeapInfo(const HeapInfo& other) = delete;
|
||||||
HeapInfo(HeapInfo&& other) = default;
|
// HeapInfo(HeapInfo&& other) = default;
|
||||||
HeapInfo& operator=(const HeapInfo& other) = delete;
|
// HeapInfo& operator=(const HeapInfo& other) = delete;
|
||||||
HeapInfo& operator=(HeapInfo&& other) = default;
|
// HeapInfo& operator=(HeapInfo&& other) = default;
|
||||||
};
|
// };
|
||||||
Array<HeapInfo> heaps;
|
// Array<HeapInfo> heaps;
|
||||||
uint32 findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties);
|
// uint32 findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties);
|
||||||
PGraphics graphics;
|
// PGraphics graphics;
|
||||||
VkPhysicalDeviceMemoryProperties memProperties;
|
// VkPhysicalDeviceMemoryProperties memProperties;
|
||||||
};
|
// };
|
||||||
DEFINE_REF(Allocator)
|
// DEFINE_REF(Allocator)
|
||||||
class StagingBuffer
|
// class StagingBuffer
|
||||||
{
|
// {
|
||||||
public:
|
// public:
|
||||||
StagingBuffer(PGraphics graphics, OSubAllocation allocation, VkBuffer buffer, VkDeviceSize size, Gfx::QueueType owner);
|
// StagingBuffer(PGraphics graphics, OSubAllocation allocation, VkBuffer buffer, VkDeviceSize size, Gfx::QueueType owner);
|
||||||
~StagingBuffer();
|
// ~StagingBuffer();
|
||||||
void* map();
|
// void* map();
|
||||||
void flush();
|
// void flush();
|
||||||
void invalidate();
|
// void invalidate();
|
||||||
constexpr VkBuffer getHandle() const
|
// constexpr VkBuffer getHandle() const
|
||||||
{
|
// {
|
||||||
return buffer;
|
// return buffer;
|
||||||
}
|
// }
|
||||||
VkDeviceMemory getMemory() const;
|
// VkDeviceMemory getMemory() const;
|
||||||
VkDeviceSize getOffset() const;
|
// VkDeviceSize getOffset() const;
|
||||||
constexpr uint64 getSize() const
|
// constexpr uint64 getSize() const
|
||||||
{
|
// {
|
||||||
return size;
|
// return size;
|
||||||
}
|
// }
|
||||||
constexpr Gfx::QueueType getOwner() const
|
// constexpr Gfx::QueueType getOwner() const
|
||||||
{
|
// {
|
||||||
return owner;
|
// return owner;
|
||||||
}
|
// }
|
||||||
private:
|
// private:
|
||||||
Gfx::QueueType owner;
|
// Gfx::QueueType owner;
|
||||||
OSubAllocation allocation;
|
// OSubAllocation allocation;
|
||||||
PGraphics graphics;
|
// PGraphics graphics;
|
||||||
VkBuffer buffer;
|
// VkBuffer buffer;
|
||||||
VkDeviceSize size;
|
// VkDeviceSize size;
|
||||||
};
|
// };
|
||||||
DEFINE_REF(StagingBuffer)
|
// DEFINE_REF(StagingBuffer)
|
||||||
|
|
||||||
class StagingManager
|
// class StagingManager
|
||||||
{
|
// {
|
||||||
public:
|
// public:
|
||||||
StagingManager(PGraphics graphics, PAllocator pool);
|
// StagingManager(PGraphics graphics, PAllocator pool);
|
||||||
~StagingManager();
|
// ~StagingManager();
|
||||||
OStagingBuffer create(uint64 size, Gfx::QueueType owner);
|
// OStagingBuffer create(uint64 size, Gfx::QueueType owner);
|
||||||
void release(OStagingBuffer buffer);
|
// void release(OStagingBuffer buffer);
|
||||||
private:
|
// private:
|
||||||
PGraphics graphics;
|
// PGraphics graphics;
|
||||||
PAllocator pool;
|
// PAllocator pool;
|
||||||
Array<OStagingBuffer> freeBuffers;
|
// Array<OStagingBuffer> freeBuffers;
|
||||||
};
|
// };
|
||||||
DEFINE_REF(StagingManager)
|
// DEFINE_REF(StagingManager)
|
||||||
} // namespace Vulkan
|
// } // namespace Vulkan
|
||||||
} // namespace Seele
|
// } // namespace Seele
|
||||||
@@ -8,20 +8,19 @@ struct PendingBuffer
|
|||||||
{
|
{
|
||||||
uint64 offset;
|
uint64 offset;
|
||||||
uint64 size;
|
uint64 size;
|
||||||
OStagingBuffer stagingBuffer;
|
VkBuffer stagingBuffer;
|
||||||
|
VmaAllocation allocation;
|
||||||
|
void *mappedMemory;
|
||||||
Gfx::QueueType prevQueue;
|
Gfx::QueueType prevQueue;
|
||||||
bool writeOnly;
|
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)
|
Buffer::Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType &queueType, bool dynamic)
|
||||||
: graphics(graphics)
|
: graphics(graphics), currentBuffer(0), size(size), owner(queueType)
|
||||||
, currentBuffer(0)
|
|
||||||
, size(size)
|
|
||||||
, owner(queueType)
|
|
||||||
{
|
{
|
||||||
if(dynamic)
|
if (dynamic)
|
||||||
{
|
{
|
||||||
numBuffers = Gfx::numFramesBuffered;
|
numBuffers = Gfx::numFramesBuffered;
|
||||||
}
|
}
|
||||||
@@ -29,53 +28,32 @@ Buffer::Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::Q
|
|||||||
{
|
{
|
||||||
numBuffers = 1;
|
numBuffers = 1;
|
||||||
}
|
}
|
||||||
usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
|
||||||
usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
|
||||||
uint32 queueFamilyIndex = graphics->getFamilyMapping().getQueueTypeFamilyIndex(queueType);
|
|
||||||
VkBufferCreateInfo info = {
|
VkBufferCreateInfo info = {
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.size = size,
|
.size = size,
|
||||||
.usage = usage,
|
.usage = usage,
|
||||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||||
.queueFamilyIndexCount = 1,
|
|
||||||
.pQueueFamilyIndices = &queueFamilyIndex,
|
|
||||||
};
|
};
|
||||||
VkBufferMemoryRequirementsInfo2 bufferReqInfo = {
|
VmaAllocationCreateInfo allocInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
|
.usage = VMA_MEMORY_USAGE_AUTO,
|
||||||
.pNext = nullptr,
|
.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
|
||||||
};
|
|
||||||
VkMemoryDedicatedRequirements dedicatedRequirements = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
|
|
||||||
.pNext = nullptr,
|
|
||||||
};
|
|
||||||
VkMemoryRequirements2 memRequirements = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
|
|
||||||
.pNext = &dedicatedRequirements,
|
|
||||||
};
|
};
|
||||||
for (uint32 i = 0; i < numBuffers; ++i)
|
for (uint32 i = 0; i < numBuffers; ++i)
|
||||||
{
|
{
|
||||||
VK_CHECK(vkCreateBuffer(graphics->getDevice(), &info, nullptr, &buffers[i].buffer));
|
vmaCreateBuffer(graphics->getAllocator(), &info, &allocInfo, &buffers[i].buffer, &buffers[i].allocation, &buffers[i].info);
|
||||||
bufferReqInfo.buffer = buffers[i].buffer;
|
vmaGetAllocationMemoryProperties(graphics->getAllocator(), buffers[i].allocation, &buffers[i].properties);
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer::~Buffer()
|
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);
|
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)
|
void Buffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||||
{
|
{
|
||||||
Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping();
|
Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping();
|
||||||
@@ -145,7 +123,7 @@ void Buffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Buffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
|
void Buffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
|
||||||
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage)
|
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage)
|
||||||
{
|
{
|
||||||
PCommand commandBuffer = graphics->getQueueCommands(owner)->getCommands();
|
PCommand commandBuffer = graphics->getQueueCommands(owner)->getCommands();
|
||||||
VkBufferMemoryBarrier barrier = {
|
VkBufferMemoryBarrier barrier = {
|
||||||
@@ -159,7 +137,7 @@ void Buffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlag
|
|||||||
.size = size,
|
.size = size,
|
||||||
};
|
};
|
||||||
VkBufferMemoryBarrier dynamicBarriers[Gfx::numFramesBuffered];
|
VkBufferMemoryBarrier dynamicBarriers[Gfx::numFramesBuffered];
|
||||||
for(uint32 i = 0; i < numBuffers; ++i)
|
for (uint32 i = 0; i < numBuffers; ++i)
|
||||||
{
|
{
|
||||||
dynamicBarriers[i] = barrier;
|
dynamicBarriers[i] = barrier;
|
||||||
dynamicBarriers[i].buffer = buffers[i].buffer;
|
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);
|
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);
|
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;
|
void *data = nullptr;
|
||||||
|
|
||||||
@@ -183,50 +161,30 @@ void * Buffer::mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly)
|
|||||||
pending.size = regionSize;
|
pending.size = regionSize;
|
||||||
if (writeOnly)
|
if (writeOnly)
|
||||||
{
|
{
|
||||||
//requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER);
|
if (buffers[currentBuffer].properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
|
||||||
OStagingBuffer stagingBuffer = graphics->getStagingManager()->create(regionSize, owner);
|
{
|
||||||
data = stagingBuffer->map();
|
VK_CHECK(vmaMapMemory(graphics->getAllocator(), buffers[currentBuffer].allocation, &pending.mappedMemory));
|
||||||
pending.stagingBuffer = std::move(stagingBuffer);
|
}
|
||||||
|
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
|
else
|
||||||
{
|
{
|
||||||
PCommand current = graphics->getQueueCommands(owner)->getCommands();
|
assert(false);
|
||||||
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);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
pendingBuffers[this] = std::move(pending);
|
pendingBuffers[this] = std::move(pending);
|
||||||
|
|
||||||
@@ -239,60 +197,62 @@ void Buffer::unmap()
|
|||||||
auto found = pendingBuffers.find(this);
|
auto found = pendingBuffers.find(this);
|
||||||
if (found != pendingBuffers.end())
|
if (found != pendingBuffers.end())
|
||||||
{
|
{
|
||||||
PendingBuffer& pending = found->value;
|
PendingBuffer &pending = found->value;
|
||||||
pending.stagingBuffer->flush();
|
vmaFlushAllocation(graphics->getAllocator(), pending.allocation, 0, VK_WHOLE_SIZE);
|
||||||
if (pending.writeOnly)
|
if (pending.writeOnly)
|
||||||
{
|
{
|
||||||
PStagingBuffer stagingBuffer = pending.stagingBuffer;
|
if (buffers[currentBuffer].properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
|
||||||
PCommand command = graphics->getQueueCommands(owner)->getCommands();
|
{
|
||||||
VkCommandBuffer cmdHandle = command->getHandle();
|
vmaUnmapMemory(graphics->getAllocator(), buffers[currentBuffer].allocation);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vmaUnmapMemory(graphics->getAllocator(), pending.allocation);
|
||||||
|
PCommand command = graphics->getQueueCommands(owner)->getCommands();
|
||||||
|
VkCommandBuffer cmdHandle = command->getHandle();
|
||||||
|
|
||||||
VkBufferCopy region = {
|
VkBufferCopy region = {
|
||||||
.srcOffset = 0,
|
.srcOffset = 0,
|
||||||
.dstOffset = pending.offset,
|
.dstOffset = pending.offset,
|
||||||
.size = pending.size,
|
.size = pending.size,
|
||||||
};
|
};
|
||||||
VkBufferMemoryBarrier barrier = {
|
VkBufferMemoryBarrier barrier = {
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
|
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT,
|
.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT,
|
||||||
.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
|
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.buffer = buffers[currentBuffer].buffer,
|
.buffer = buffers[currentBuffer].buffer,
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.size = size,
|
.size = size,
|
||||||
};
|
};
|
||||||
vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr);
|
vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr);
|
||||||
vkCmdCopyBuffer(cmdHandle, stagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, ®ion);
|
vkCmdCopyBuffer(cmdHandle, pending.stagingBuffer, buffers[currentBuffer].buffer, 1, ®ion);
|
||||||
barrier = {
|
barrier = {
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
|
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
|
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
|
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
|
||||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.buffer = buffers[currentBuffer].buffer,
|
.buffer = buffers[currentBuffer].buffer,
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.size = size,
|
.size = size,
|
||||||
};
|
};
|
||||||
vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr);
|
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);
|
// requestOwnershipTransfer(pending.prevQueue);
|
||||||
graphics->getStagingManager()->release(std::move(pending.stagingBuffer));
|
|
||||||
pendingBuffers.erase(this);
|
pendingBuffers.erase(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UniformBuffer::UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo &createInfo)
|
UniformBuffer::UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo &createInfo)
|
||||||
: Gfx::UniformBuffer(graphics->getFamilyMapping(), createInfo.sourceData)
|
: Gfx::UniformBuffer(graphics->getFamilyMapping(), createInfo.sourceData), Vulkan::Buffer(graphics, createInfo.sourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, currentOwner, createInfo.dynamic)
|
||||||
, Vulkan::Buffer(graphics, createInfo.sourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, currentOwner, createInfo.dynamic)
|
|
||||||
, dedicatedStagingBuffer(nullptr)
|
|
||||||
{
|
{
|
||||||
if(createInfo.dynamic)
|
|
||||||
{
|
|
||||||
dedicatedStagingBuffer = graphics->getStagingManager()->create(createInfo.sourceData.size, owner);
|
|
||||||
}
|
|
||||||
if (createInfo.sourceData.data != nullptr)
|
if (createInfo.sourceData.data != nullptr)
|
||||||
{
|
{
|
||||||
void *data = map();
|
void *data = map();
|
||||||
@@ -303,75 +263,20 @@ UniformBuffer::UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo &
|
|||||||
|
|
||||||
UniformBuffer::~UniformBuffer()
|
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
|
// no update was performed, skip
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
void* data = map();
|
void *data = map();
|
||||||
std::memcpy(data, sourceData.data, sourceData.size);
|
std::memcpy(data, sourceData.data, sourceData.size);
|
||||||
unmap();
|
unmap();
|
||||||
return true;
|
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)
|
void UniformBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
|
||||||
{
|
{
|
||||||
@@ -384,7 +289,7 @@ void UniformBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void UniformBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
|
void UniformBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
|
||||||
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage)
|
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage)
|
||||||
{
|
{
|
||||||
Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
|
Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
|
||||||
}
|
}
|
||||||
@@ -400,14 +305,8 @@ VkAccessFlags UniformBuffer::getDestAccessMask()
|
|||||||
}
|
}
|
||||||
|
|
||||||
ShaderBuffer::ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo &sourceData)
|
ShaderBuffer::ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo &sourceData)
|
||||||
: Gfx::ShaderBuffer(graphics->getFamilyMapping(), sourceData.numElements, sourceData.sourceData)
|
: Gfx::ShaderBuffer(graphics->getFamilyMapping(), sourceData.numElements, sourceData.sourceData), Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, currentOwner, sourceData.dynamic)
|
||||||
, Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, currentOwner, sourceData.dynamic)
|
|
||||||
, dedicatedStagingBuffer(nullptr)
|
|
||||||
{
|
{
|
||||||
if(sourceData.dynamic)
|
|
||||||
{
|
|
||||||
dedicatedStagingBuffer = graphics->getStagingManager()->create(sourceData.sourceData.size, currentOwner);
|
|
||||||
}
|
|
||||||
if (sourceData.sourceData.data != nullptr)
|
if (sourceData.sourceData.data != nullptr)
|
||||||
{
|
{
|
||||||
void *data = map();
|
void *data = map();
|
||||||
@@ -418,76 +317,18 @@ ShaderBuffer::ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo &sou
|
|||||||
|
|
||||||
ShaderBuffer::~ShaderBuffer()
|
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());
|
assert(sourceData.size <= getSize());
|
||||||
Gfx::ShaderBuffer::updateContents(sourceData);
|
Gfx::ShaderBuffer::updateContents(sourceData);
|
||||||
//We always want to update, as the contents could be different on the GPU
|
// We always want to update, as the contents could be different on the GPU
|
||||||
void* data = map();
|
void *data = map();
|
||||||
std::memcpy(data, sourceData.data, sourceData.size);
|
std::memcpy(data, sourceData.data, sourceData.size);
|
||||||
unmap();
|
unmap();
|
||||||
return true;
|
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)
|
void ShaderBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
|
||||||
{
|
{
|
||||||
@@ -500,7 +341,7 @@ void ShaderBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ShaderBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
|
void ShaderBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
|
||||||
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage)
|
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage)
|
||||||
{
|
{
|
||||||
Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
|
Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
|
||||||
}
|
}
|
||||||
@@ -516,8 +357,7 @@ VkAccessFlags ShaderBuffer::getDestAccessMask()
|
|||||||
}
|
}
|
||||||
|
|
||||||
VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &sourceData)
|
VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &sourceData)
|
||||||
: Gfx::VertexBuffer(graphics->getFamilyMapping(), sourceData.numVertices, sourceData.vertexSize, sourceData.sourceData.owner)
|
: Gfx::VertexBuffer(graphics->getFamilyMapping(), sourceData.numVertices, sourceData.vertexSize, sourceData.sourceData.owner), Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, currentOwner)
|
||||||
, Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, currentOwner)
|
|
||||||
{
|
{
|
||||||
if (sourceData.sourceData.data != nullptr)
|
if (sourceData.sourceData.data != nullptr)
|
||||||
{
|
{
|
||||||
@@ -533,14 +373,14 @@ VertexBuffer::~VertexBuffer()
|
|||||||
|
|
||||||
void VertexBuffer::updateRegion(DataSource update)
|
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);
|
std::memcpy(data, update.data, update.size);
|
||||||
unmap();
|
unmap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertexBuffer::download(Array<uint8>& buffer)
|
void VertexBuffer::download(Array<uint8> &buffer)
|
||||||
{
|
{
|
||||||
void* data = map(false);
|
void *data = map(false);
|
||||||
buffer.resize(size);
|
buffer.resize(size);
|
||||||
std::memcpy(buffer.data(), data, size);
|
std::memcpy(buffer.data(), data, size);
|
||||||
unmap();
|
unmap();
|
||||||
@@ -557,7 +397,7 @@ void VertexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VertexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
|
void VertexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
|
||||||
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage)
|
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage)
|
||||||
{
|
{
|
||||||
Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
|
Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
|
||||||
}
|
}
|
||||||
@@ -573,8 +413,7 @@ VkAccessFlags VertexBuffer::getDestAccessMask()
|
|||||||
}
|
}
|
||||||
|
|
||||||
IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &sourceData)
|
IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &sourceData)
|
||||||
: Gfx::IndexBuffer(graphics->getFamilyMapping(), sourceData.sourceData.size, sourceData.indexType, sourceData.sourceData.owner)
|
: 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)
|
||||||
, Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, currentOwner)
|
|
||||||
{
|
{
|
||||||
if (sourceData.sourceData.data != nullptr)
|
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);
|
buffer.resize(size);
|
||||||
std::memcpy(buffer.data(), data, size);
|
std::memcpy(buffer.data(), data, size);
|
||||||
unmap();
|
unmap();
|
||||||
@@ -607,7 +446,7 @@ void IndexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IndexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
|
void IndexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
|
||||||
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage)
|
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage)
|
||||||
{
|
{
|
||||||
Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
|
Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Graphics/Buffer.h"
|
#include "Graphics/Buffer.h"
|
||||||
#include "Graphics.h"
|
#include "Graphics.h"
|
||||||
#include "Allocator.h"
|
|
||||||
|
|
||||||
namespace Seele
|
namespace Seele
|
||||||
{
|
{
|
||||||
@@ -20,20 +19,21 @@ public:
|
|||||||
{
|
{
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
VkDeviceSize getOffset() const;
|
|
||||||
void advanceBuffer()
|
void advanceBuffer()
|
||||||
{
|
{
|
||||||
currentBuffer = (currentBuffer + 1) % numBuffers;
|
currentBuffer = (currentBuffer + 1) % numBuffers;
|
||||||
}
|
}
|
||||||
virtual void *map(bool writeOnly = true);
|
void *map(bool writeOnly = true);
|
||||||
virtual void *mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly = true);
|
void *mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly = true);
|
||||||
virtual void unmap();
|
void unmap();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct BufferAllocation
|
struct BufferAllocation
|
||||||
{
|
{
|
||||||
VkBuffer buffer;
|
VkBuffer buffer;
|
||||||
OSubAllocation allocation;
|
VmaAllocation allocation;
|
||||||
|
VmaAllocationInfo info;
|
||||||
|
VkMemoryPropertyFlags properties;
|
||||||
};
|
};
|
||||||
PGraphics graphics;
|
PGraphics graphics;
|
||||||
uint32 currentBuffer;
|
uint32 currentBuffer;
|
||||||
@@ -53,7 +53,6 @@ protected:
|
|||||||
};
|
};
|
||||||
DEFINE_REF(Buffer)
|
DEFINE_REF(Buffer)
|
||||||
|
|
||||||
DECLARE_REF(StagingBuffer)
|
|
||||||
class UniformBuffer : public Gfx::UniformBuffer, public Buffer
|
class UniformBuffer : public Gfx::UniformBuffer, public Buffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -61,8 +60,6 @@ public:
|
|||||||
virtual ~UniformBuffer();
|
virtual ~UniformBuffer();
|
||||||
virtual bool updateContents(const DataSource &sourceData) override;
|
virtual bool updateContents(const DataSource &sourceData) override;
|
||||||
|
|
||||||
virtual void* map(bool writeOnly = true) override;
|
|
||||||
virtual void unmap() override;
|
|
||||||
protected:
|
protected:
|
||||||
// Inherited via Vulkan::Buffer
|
// Inherited via Vulkan::Buffer
|
||||||
virtual VkAccessFlags getSourceAccessMask() override;
|
virtual VkAccessFlags getSourceAccessMask() override;
|
||||||
@@ -74,7 +71,6 @@ protected:
|
|||||||
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) override;
|
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OStagingBuffer dedicatedStagingBuffer;
|
|
||||||
};
|
};
|
||||||
DEFINE_REF(UniformBuffer)
|
DEFINE_REF(UniformBuffer)
|
||||||
|
|
||||||
@@ -85,8 +81,6 @@ public:
|
|||||||
virtual ~ShaderBuffer();
|
virtual ~ShaderBuffer();
|
||||||
virtual bool updateContents(const DataSource &sourceData) override;
|
virtual bool updateContents(const DataSource &sourceData) override;
|
||||||
|
|
||||||
virtual void* map(bool writeOnly = true) override;
|
|
||||||
virtual void unmap() override;
|
|
||||||
protected:
|
protected:
|
||||||
// Inherited via Vulkan::Buffer
|
// Inherited via Vulkan::Buffer
|
||||||
virtual VkAccessFlags getSourceAccessMask() override;
|
virtual VkAccessFlags getSourceAccessMask() override;
|
||||||
@@ -97,7 +91,6 @@ protected:
|
|||||||
virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
|
virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
|
||||||
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) override;
|
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) override;
|
||||||
private:
|
private:
|
||||||
OStagingBuffer dedicatedStagingBuffer;
|
|
||||||
};
|
};
|
||||||
DEFINE_REF(ShaderBuffer)
|
DEFINE_REF(ShaderBuffer)
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vulkan/vulkan_core.h>
|
#include <vulkan/vulkan_core.h>
|
||||||
|
#define VMA_IMPLEMENTATION
|
||||||
|
#include "vk_mem_alloc.h"
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
using namespace Seele::Vulkan;
|
using namespace Seele::Vulkan;
|
||||||
@@ -40,7 +42,6 @@ Graphics::~Graphics()
|
|||||||
pipelineCache = nullptr;
|
pipelineCache = nullptr;
|
||||||
allocator = nullptr;
|
allocator = nullptr;
|
||||||
destructionManager = nullptr;
|
destructionManager = nullptr;
|
||||||
stagingManager = nullptr;
|
|
||||||
allocatedFramebuffers.clear();
|
allocatedFramebuffers.clear();
|
||||||
shaderCompiler = nullptr;
|
shaderCompiler = nullptr;
|
||||||
vkDestroyDevice(handle, nullptr);
|
vkDestroyDevice(handle, nullptr);
|
||||||
@@ -56,8 +57,19 @@ void Graphics::init(GraphicsInitializer initInfo)
|
|||||||
#endif
|
#endif
|
||||||
pickPhysicalDevice();
|
pickPhysicalDevice();
|
||||||
createDevice(initInfo);
|
createDevice(initInfo);
|
||||||
allocator = new Allocator(this);
|
VmaAllocatorCreateInfo createInfo = {
|
||||||
stagingManager = new StagingManager(this, allocator);
|
.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");
|
pipelineCache = new PipelineCache(this, "pipeline.cache");
|
||||||
destructionManager = new DestructionManager(this);
|
destructionManager = new DestructionManager(this);
|
||||||
}
|
}
|
||||||
@@ -326,16 +338,12 @@ PCommandPool Graphics::getDedicatedTransferCommands()
|
|||||||
}
|
}
|
||||||
return dedicatedTransferCommands;
|
return dedicatedTransferCommands;
|
||||||
}
|
}
|
||||||
PAllocator Graphics::getAllocator()
|
|
||||||
|
VmaAllocator Graphics::getAllocator()
|
||||||
{
|
{
|
||||||
return allocator;
|
return allocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
PStagingManager Graphics::getStagingManager()
|
|
||||||
{
|
|
||||||
return stagingManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
PDestructionManager Graphics::getDestructionManager()
|
PDestructionManager Graphics::getDestructionManager()
|
||||||
{
|
{
|
||||||
return destructionManager;
|
return destructionManager;
|
||||||
@@ -374,11 +382,17 @@ void Graphics::initInstance(GraphicsInitializer initInfo)
|
|||||||
{
|
{
|
||||||
extensions.add(initInfo.instanceExtensions[i]);
|
extensions.add(initInfo.instanceExtensions[i]);
|
||||||
}
|
}
|
||||||
|
#ifdef __APPLE__
|
||||||
|
extensions.add("VK_KHR_portability_enumeration");
|
||||||
|
#endif
|
||||||
#if ENABLE_VALIDATION
|
#if ENABLE_VALIDATION
|
||||||
initInfo.layers.add("VK_LAYER_KHRONOS_validation");
|
initInfo.layers.add("VK_LAYER_KHRONOS_validation");
|
||||||
#endif
|
#endif
|
||||||
VkInstanceCreateInfo info = {
|
VkInstanceCreateInfo info = {
|
||||||
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||||
|
#if __APPLE__
|
||||||
|
.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR,
|
||||||
|
#endif
|
||||||
.pApplicationInfo = &appInfo,
|
.pApplicationInfo = &appInfo,
|
||||||
.enabledLayerCount = (uint32)initInfo.layers.size(),
|
.enabledLayerCount = (uint32)initInfo.layers.size(),
|
||||||
.ppEnabledLayerNames = initInfo.layers.data(),
|
.ppEnabledLayerNames = initInfo.layers.data(),
|
||||||
@@ -480,6 +494,13 @@ void Graphics::createDevice(GraphicsInitializer initializer)
|
|||||||
auto checkFamilyProperty = [](VkQueueFamilyProperties currProps, uint32 checkBit){
|
auto checkFamilyProperty = [](VkQueueFamilyProperties currProps, uint32 checkBit){
|
||||||
return (currProps.queueFlags & checkBit) == 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)
|
for (uint32 familyIndex = 0; familyIndex < queueProperties.size(); ++familyIndex)
|
||||||
{
|
{
|
||||||
uint32 numQueuesForFamily = 0;
|
uint32 numQueuesForFamily = 0;
|
||||||
@@ -487,11 +508,7 @@ void Graphics::createDevice(GraphicsInitializer initializer)
|
|||||||
|
|
||||||
if (checkFamilyProperty(currProps, VK_QUEUE_GRAPHICS_BIT))
|
if (checkFamilyProperty(currProps, VK_QUEUE_GRAPHICS_BIT))
|
||||||
{
|
{
|
||||||
if (graphicsQueueInfo.familyIndex == -1)
|
updateQueueInfo(familyIndex, graphicsQueueInfo, numQueueFamilies);
|
||||||
{
|
|
||||||
graphicsQueueInfo.familyIndex = familyIndex;
|
|
||||||
numQueuesForFamily++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (currProps.queueFlags & VK_QUEUE_COMPUTE_BIT)
|
if (currProps.queueFlags & VK_QUEUE_COMPUTE_BIT)
|
||||||
{
|
{
|
||||||
@@ -568,6 +585,9 @@ void Graphics::createDevice(GraphicsInitializer initializer)
|
|||||||
features12.pNext = &enabledMeshShaderFeatures;
|
features12.pNext = &enabledMeshShaderFeatures;
|
||||||
initializer.deviceExtensions.add(VK_EXT_MESH_SHADER_EXTENSION_NAME);
|
initializer.deviceExtensions.add(VK_EXT_MESH_SHADER_EXTENSION_NAME);
|
||||||
}
|
}
|
||||||
|
#ifdef __APPLE__
|
||||||
|
initializer.deviceExtensions.add("VK_KHR_portability_subset");
|
||||||
|
#endif
|
||||||
VkDeviceCreateInfo deviceInfo = {
|
VkDeviceCreateInfo deviceInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||||
.pNext = &features11,
|
.pNext = &features11,
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Enums.h"
|
#include "Enums.h"
|
||||||
#include "Graphics/Graphics.h"
|
#include "Graphics/Graphics.h"
|
||||||
|
#include <vk_mem_alloc.h>
|
||||||
|
|
||||||
namespace Seele
|
namespace Seele
|
||||||
{
|
{
|
||||||
namespace Vulkan
|
namespace Vulkan
|
||||||
{
|
{
|
||||||
DECLARE_REF(Allocator)
|
|
||||||
DECLARE_REF(StagingManager)
|
|
||||||
DECLARE_REF(DestructionManager)
|
DECLARE_REF(DestructionManager)
|
||||||
DECLARE_REF(CommandPool)
|
DECLARE_REF(CommandPool)
|
||||||
DECLARE_REF(Queue)
|
DECLARE_REF(Queue)
|
||||||
@@ -28,8 +27,7 @@ public:
|
|||||||
PCommandPool getTransferCommands();
|
PCommandPool getTransferCommands();
|
||||||
PCommandPool getDedicatedTransferCommands();
|
PCommandPool getDedicatedTransferCommands();
|
||||||
|
|
||||||
PAllocator getAllocator();
|
VmaAllocator getAllocator();
|
||||||
PStagingManager getStagingManager();
|
|
||||||
PDestructionManager getDestructionManager();
|
PDestructionManager getDestructionManager();
|
||||||
|
|
||||||
// Inherited via Graphics
|
// Inherited via Graphics
|
||||||
@@ -71,6 +69,7 @@ public:
|
|||||||
virtual void resolveTexture(Gfx::PTexture source, Gfx::PTexture destination) override;
|
virtual void resolveTexture(Gfx::PTexture source, Gfx::PTexture destination) override;
|
||||||
|
|
||||||
void vkCmdDrawMeshTasksEXT(VkCommandBuffer handle, uint32 groupX, uint32 groupY, uint32 groupZ);
|
void vkCmdDrawMeshTasksEXT(VkCommandBuffer handle, uint32 groupX, uint32 groupY, uint32 groupZ);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PFN_vkCmdDrawMeshTasksEXT cmdDrawMeshTasks;
|
PFN_vkCmdDrawMeshTasksEXT cmdDrawMeshTasks;
|
||||||
Array<const char *> getRequiredExtensions();
|
Array<const char *> getRequiredExtensions();
|
||||||
@@ -97,9 +96,8 @@ protected:
|
|||||||
VkPhysicalDeviceVulkan12Features features12;
|
VkPhysicalDeviceVulkan12Features features12;
|
||||||
VkDebugReportCallbackEXT callback;
|
VkDebugReportCallbackEXT callback;
|
||||||
Map<uint32, OFramebuffer> allocatedFramebuffers;
|
Map<uint32, OFramebuffer> allocatedFramebuffers;
|
||||||
OAllocator allocator;
|
VmaAllocator allocator;
|
||||||
OPipelineCache pipelineCache;
|
OPipelineCache pipelineCache;
|
||||||
OStagingManager stagingManager;
|
|
||||||
ODestructionManager destructionManager;
|
ODestructionManager destructionManager;
|
||||||
|
|
||||||
friend class Window;
|
friend class Window;
|
||||||
|
|||||||
@@ -129,11 +129,6 @@ void DestructionManager::queueDescriptorPool(PCommand cmd, VkDescriptorPool pool
|
|||||||
pools[cmd].add(pool);
|
pools[cmd].add(pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DestructionManager::queueAllocation(PCommand cmd, OSubAllocation alloc)
|
|
||||||
{
|
|
||||||
allocs[cmd].add(std::move(alloc));
|
|
||||||
}
|
|
||||||
|
|
||||||
void DestructionManager::notifyCmdComplete(PCommand cmd)
|
void DestructionManager::notifyCmdComplete(PCommand cmd)
|
||||||
{
|
{
|
||||||
for(auto buf : buffers[cmd])
|
for(auto buf : buffers[cmd])
|
||||||
@@ -166,5 +161,4 @@ void DestructionManager::notifyCmdComplete(PCommand cmd)
|
|||||||
sems[cmd].clear();
|
sems[cmd].clear();
|
||||||
pools[cmd].clear();
|
pools[cmd].clear();
|
||||||
renderPasses[cmd].clear();
|
renderPasses[cmd].clear();
|
||||||
allocs[cmd].clear();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ DECLARE_REF(DescriptorPool)
|
|||||||
DECLARE_REF(CommandPool)
|
DECLARE_REF(CommandPool)
|
||||||
DECLARE_REF(Command)
|
DECLARE_REF(Command)
|
||||||
DECLARE_REF(Graphics)
|
DECLARE_REF(Graphics)
|
||||||
DECLARE_REF(SubAllocation)
|
|
||||||
class Semaphore
|
class Semaphore
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -63,7 +62,6 @@ public:
|
|||||||
void queueSemaphore(PCommand cmd, VkSemaphore sem);
|
void queueSemaphore(PCommand cmd, VkSemaphore sem);
|
||||||
void queueRenderPass(PCommand cmd, VkRenderPass renderPass);
|
void queueRenderPass(PCommand cmd, VkRenderPass renderPass);
|
||||||
void queueDescriptorPool(PCommand cmd, VkDescriptorPool pool);
|
void queueDescriptorPool(PCommand cmd, VkDescriptorPool pool);
|
||||||
void queueAllocation(PCommand cmd, OSubAllocation alloc);
|
|
||||||
void notifyCmdComplete(PCommand cmdbuffer);
|
void notifyCmdComplete(PCommand cmdbuffer);
|
||||||
private:
|
private:
|
||||||
PGraphics graphics;
|
PGraphics graphics;
|
||||||
@@ -73,7 +71,6 @@ private:
|
|||||||
Map<PCommand, List<VkSemaphore>> sems;
|
Map<PCommand, List<VkSemaphore>> sems;
|
||||||
Map<PCommand, List<VkRenderPass>> renderPasses;
|
Map<PCommand, List<VkRenderPass>> renderPasses;
|
||||||
Map<PCommand, List<VkDescriptorPool>> pools;
|
Map<PCommand, List<VkDescriptorPool>> pools;
|
||||||
Map<PCommand, List<OSubAllocation>> allocs;
|
|
||||||
};
|
};
|
||||||
DEFINE_REF(DestructionManager)
|
DEFINE_REF(DestructionManager)
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType,
|
|||||||
if (existingImage == VK_NULL_HANDLE)
|
if (existingImage == VK_NULL_HANDLE)
|
||||||
{
|
{
|
||||||
ownsImage = true;
|
ownsImage = true;
|
||||||
PAllocator pool = graphics->getAllocator();
|
|
||||||
VkImageType type = VK_IMAGE_TYPE_MAX_ENUM;
|
VkImageType type = VK_IMAGE_TYPE_MAX_ENUM;
|
||||||
VkImageCreateFlags flags = 0;
|
VkImageCreateFlags flags = 0;
|
||||||
switch (viewType)
|
switch (viewType)
|
||||||
@@ -97,69 +96,79 @@ TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType,
|
|||||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||||
.initialLayout = cast(layout),
|
.initialLayout = cast(layout),
|
||||||
};
|
};
|
||||||
|
VmaAllocationCreateInfo allocInfo = {
|
||||||
|
.usage = VMA_MEMORY_USAGE_AUTO,
|
||||||
VK_CHECK(vkCreateImage(graphics->getDevice(), &info, nullptr, &image));
|
|
||||||
|
|
||||||
VkMemoryDedicatedRequirements memDedicatedRequirements = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
|
|
||||||
.pNext = nullptr,
|
|
||||||
};
|
};
|
||||||
VkImageMemoryRequirementsInfo2 reqInfo = {
|
VK_CHECK(vmaCreateImage(graphics->getAllocator(), &info, &allocInfo, &image, &allocation, nullptr));
|
||||||
.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);
|
const DataSource& sourceData = createInfo.sourceData;
|
||||||
vkBindImageMemory(graphics->getDevice(), image, allocation->getHandle(), allocation->getOffset());
|
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);
|
||||||
|
|
||||||
|
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(usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
changeLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
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;
|
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);
|
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();
|
PCommand cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands();
|
||||||
//Gfx::FormatCompatibilityInfo formatInfo = Gfx::getFormatInfo(format);
|
//Gfx::FormatCompatibilityInfo formatInfo = Gfx::getFormatInfo(format);
|
||||||
VkBufferImageCopy region = {
|
VkBufferImageCopy region = {
|
||||||
@@ -257,11 +282,12 @@ void TextureBase::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Arra
|
|||||||
.depth = depth
|
.depth = depth
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
vkCmdCopyImageToBuffer(cmdBuffer->getHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingbuffer->getHandle(), 1, ®ion);
|
vkCmdCopyImageToBuffer(cmdBuffer->getHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingBuffer, 1, ®ion);
|
||||||
changeLayout(prevlayout);
|
changeLayout(prevLayout);
|
||||||
buffer.resize(stagingbuffer->getSize());
|
buffer.resize(imageSize);
|
||||||
void* data = stagingbuffer->map();
|
|
||||||
std::memcpy(buffer.data(), data, buffer.size());
|
std::memcpy(buffer.data(), data, buffer.size());
|
||||||
|
vmaUnmapMemory(graphics->getAllocator(), stagingAlloc);
|
||||||
|
vmaDestroyBuffer(graphics->getAllocator(), stagingBuffer, stagingAlloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureBase::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
void TextureBase::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Graphics/Texture.h"
|
#include "Graphics/Texture.h"
|
||||||
#include "Graphics.h"
|
#include "Graphics.h"
|
||||||
#include "Allocator.h"
|
|
||||||
|
|
||||||
namespace Seele
|
namespace Seele
|
||||||
{
|
{
|
||||||
namespace Vulkan
|
namespace Vulkan
|
||||||
{
|
{
|
||||||
|
|
||||||
class TextureBase
|
class TextureBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -72,7 +70,7 @@ protected:
|
|||||||
//Updates via reference
|
//Updates via reference
|
||||||
Gfx::QueueType& currentOwner;
|
Gfx::QueueType& currentOwner;
|
||||||
PGraphics graphics;
|
PGraphics graphics;
|
||||||
OSubAllocation allocation;
|
VmaAllocation allocation;
|
||||||
uint32 width;
|
uint32 width;
|
||||||
uint32 height;
|
uint32 height;
|
||||||
uint32 depth;
|
uint32 depth;
|
||||||
|
|||||||
@@ -95,10 +95,6 @@ void GameView::reloadGame()
|
|||||||
|
|
||||||
void GameView::keyCallback(KeyCode code, InputAction action, KeyModifier modifier)
|
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);
|
keyboardSystem->keyCallback(code, action, modifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -11,6 +11,7 @@
|
|||||||
"nlohmann-json",
|
"nlohmann-json",
|
||||||
"fmt",
|
"fmt",
|
||||||
"shader-slang",
|
"shader-slang",
|
||||||
"gtest"
|
"gtest",
|
||||||
|
"vulkan-memory-allocator"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user