From 524f26d92163e8fb315d5a6e18bc7495f85981a5 Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Wed, 17 Jan 2024 17:57:59 +0100 Subject: [PATCH] Adding VMA --- .vscode/c_cpp_properties.json | 2 +- CMakeLists.txt | 2 + src/Editor/main.cpp | 4 + src/Engine/Containers/Array.h | 4 + src/Engine/Containers/Tree.h | 4 +- src/Engine/Graphics/Initializer.h | 2 +- src/Engine/Graphics/Vulkan/Allocator.cpp | 668 +++++++++++------------ src/Engine/Graphics/Vulkan/Allocator.h | 372 ++++++------- src/Engine/Graphics/Vulkan/Buffer.cpp | 379 ++++--------- src/Engine/Graphics/Vulkan/Buffer.h | 19 +- src/Engine/Graphics/Vulkan/Graphics.cpp | 50 +- src/Engine/Graphics/Vulkan/Graphics.h | 10 +- src/Engine/Graphics/Vulkan/Resources.cpp | 6 - src/Engine/Graphics/Vulkan/Resources.h | 3 - src/Engine/Graphics/Vulkan/Texture.cpp | 158 +++--- src/Engine/Graphics/Vulkan/Texture.h | 4 +- src/Engine/Window/GameView.cpp | 4 - vcpkg.json | 3 +- 18 files changed, 783 insertions(+), 911 deletions(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 5ee5de9..1eeb684 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -28,7 +28,7 @@ ], "compilerPath": "/usr/bin/clang", "cppStandard": "c++20", - "intelliSenseMode": "macos-lang-arm64", + "intelliSenseMode": "macos-clang-arm64", "configurationProvider": "ms-vscode.cmake-tools" } ], diff --git a/CMakeLists.txt b/CMakeLists.txt index bf5270c..3a3214c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,7 @@ find_package(glm CONFIG REQUIRED) find_package(Ktx CONFIG REQUIRED) find_package(nlohmann_json CONFIG REQUIRED) find_package(fmt CONFIG REQUIRED) +find_package(VulkanMemoryAllocator CONFIG REQUIRED) if(UNIX) 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 shader-slang) target_link_libraries(Engine PUBLIC fmt::fmt) +target_link_libraries(Engine PUBLIC GPUOpen::VulkanMemoryAllocator) if(UNIX) target_link_libraries(Engine PUBLIC Threads::Threads) target_link_libraries(Engine PUBLIC dl) diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp index 5693722..b13b68c 100644 --- a/src/Editor/main.cpp +++ b/src/Editor/main.cpp @@ -26,6 +26,10 @@ int main() std::filesystem::path outputPath = "C:/Users/Dynamitos/TrackClearGame"; std::filesystem::path sourcePath= "C:/Users/Dynamitos/TrackClear"; std::filesystem::path binaryPath = sourcePath / "bin" / "TrackClear.dll"; +#elif __APPLE__ + std::filesystem::path outputPath = "/dynamitos/TrackClearGame"; + std::filesystem::path sourcePath= "/dynamitos/TrackClear"; + std::filesystem::path binaryPath = sourcePath / "cmake" / "libTrackClear.dynlib"; #else std::filesystem::path outputPath = "/home/dynamitos/TrackClearGame"; std::filesystem::path sourcePath= "/home/dynamitos/TrackClear"; diff --git a/src/Engine/Containers/Array.h b/src/Engine/Containers/Array.h index 644d9ba..d37c354 100644 --- a/src/Engine/Containers/Array.h +++ b/src/Engine/Containers/Array.h @@ -42,6 +42,10 @@ public: { return p == other.p; } + constexpr bool operator!=(const IteratorBase &other) const + { + return p != other.p; + } constexpr std::strong_ordering operator<=>(const IteratorBase &other) const { return p <=> other.p; diff --git a/src/Engine/Containers/Tree.h b/src/Engine/Containers/Tree.h index 280dc74..703c198 100644 --- a/src/Engine/Containers/Tree.h +++ b/src/Engine/Containers/Tree.h @@ -81,7 +81,7 @@ public: } constexpr bool operator!=(const IteratorBase& other) { - return node == other.node; + return node != other.node; } constexpr bool operator==(const IteratorBase& other) { @@ -89,7 +89,7 @@ public: } constexpr std::strong_ordering operator<=>(const IteratorBase& other) { - return node == other.node; + return node <=> other.node; } constexpr IteratorBase& operator++() { diff --git a/src/Engine/Graphics/Initializer.h b/src/Engine/Graphics/Initializer.h index 493aea6..f69edeb 100644 --- a/src/Engine/Graphics/Initializer.h +++ b/src/Engine/Graphics/Initializer.h @@ -24,7 +24,7 @@ struct GraphicsInitializer : applicationName("SeeleEngine") , engineName("SeeleEngine") , windowLayoutFile(nullptr) - , layers{"VK_LAYER_LUNARG_monitor"} + , layers{} , instanceExtensions{} , deviceExtensions{"VK_KHR_swapchain"} , windowHandle(nullptr) diff --git a/src/Engine/Graphics/Vulkan/Allocator.cpp b/src/Engine/Graphics/Vulkan/Allocator.cpp index 8125226..3adade3 100644 --- a/src/Engine/Graphics/Vulkan/Allocator.cpp +++ b/src/Engine/Graphics/Vulkan/Allocator.cpp @@ -1,371 +1,371 @@ -#include "Allocator.h" -#include "Graphics.h" -#include "Resources.h" -#include "Enums.h" -#include "Command.h" +// #include "Allocator.h" +// #include "Graphics.h" +// #include "Resources.h" +// #include "Enums.h" +// #include "Command.h" -using namespace Seele::Vulkan; +// using namespace Seele::Vulkan; -SubAllocation::SubAllocation(PAllocation owner, VkDeviceSize requestedSize, VkDeviceSize allocatedOffset, VkDeviceSize allocatedSize, VkDeviceSize alignedOffset) - : owner(owner) - , requestedSize(requestedSize) - , allocatedOffset(allocatedOffset) - , allocatedSize(allocatedSize) - , alignedOffset(alignedOffset) -{ -} +// SubAllocation::SubAllocation(PAllocation owner, VkDeviceSize requestedSize, VkDeviceSize allocatedOffset, VkDeviceSize allocatedSize, VkDeviceSize alignedOffset) +// : owner(owner) +// , requestedSize(requestedSize) +// , allocatedOffset(allocatedOffset) +// , allocatedSize(allocatedSize) +// , alignedOffset(alignedOffset) +// { +// } -SubAllocation::~SubAllocation() -{ - owner->markFree(this); -} +// SubAllocation::~SubAllocation() +// { +// owner->markFree(this); +// } -VkDeviceMemory SubAllocation::getHandle() const -{ - return owner->getHandle(); -} +// VkDeviceMemory SubAllocation::getHandle() const +// { +// return owner->getHandle(); +// } -void *SubAllocation::map() -{ - return (uint8 *)owner->map() + alignedOffset; -} +// void *SubAllocation::map() +// { +// return (uint8 *)owner->map() + alignedOffset; +// } -void SubAllocation::flushMemory() -{ - owner->flushMemory(); -} +// void SubAllocation::flushMemory() +// { +// owner->flushMemory(); +// } -void SubAllocation::invalidate() -{ - owner->invalidate(); -} +// void SubAllocation::invalidate() +// { +// owner->invalidate(); +// } -Allocation::Allocation(PGraphics graphics, PAllocator pool, VkDeviceSize size, uint8 memoryTypeIndex, - VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo) - : device(graphics->getDevice()) - , pool(pool) - , bytesAllocated(size) - , bytesUsed(0) - , mappedPointer(nullptr) - , canMap((properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) - , isMapped(false) - , properties(properties) - , memoryTypeIndex(memoryTypeIndex) -{ - VkMemoryAllocateInfo allocInfo = { - .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - .pNext = dedicatedInfo, - .allocationSize = size, - .memoryTypeIndex = memoryTypeIndex, - }; - isDedicated = dedicatedInfo != nullptr; - VK_CHECK(vkAllocateMemory(device, &allocInfo, nullptr, &allocatedMemory)); - freeRanges[0] = size; -} +// Allocation::Allocation(PGraphics graphics, PAllocator pool, VkDeviceSize size, uint8 memoryTypeIndex, +// VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo) +// : device(graphics->getDevice()) +// , pool(pool) +// , bytesAllocated(size) +// , bytesUsed(0) +// , mappedPointer(nullptr) +// , canMap((properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) +// , isMapped(false) +// , properties(properties) +// , memoryTypeIndex(memoryTypeIndex) +// { +// VkMemoryAllocateInfo allocInfo = { +// .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, +// .pNext = dedicatedInfo, +// .allocationSize = size, +// .memoryTypeIndex = memoryTypeIndex, +// }; +// isDedicated = dedicatedInfo != nullptr; +// VK_CHECK(vkAllocateMemory(device, &allocInfo, nullptr, &allocatedMemory)); +// freeRanges[0] = size; +// } -Allocation::~Allocation() -{ - vkFreeMemory(device, allocatedMemory, nullptr); -} +// Allocation::~Allocation() +// { +// vkFreeMemory(device, allocatedMemory, nullptr); +// } -OSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDeviceSize alignment) -{ - if (isDedicated) - { - if (activeAllocations.empty() && requestedSize == bytesAllocated) - { - OSubAllocation suballoc = new SubAllocation(this, requestedSize, 0, requestedSize, 0); - activeAllocations.add(suballoc); - freeRanges.clear(); - bytesUsed += requestedSize; - return suballoc; - } - else - { - return nullptr; - } - } - for (const auto& [lower, size] : freeRanges) - { - VkDeviceSize alignedOffset = lower + alignment - 1; - alignedOffset /= alignment; - alignedOffset *= alignment; - VkDeviceSize allocatedSize = requestedSize + (alignedOffset - lower); - if (size >= allocatedSize) - { - //std::cout << "Allocating " << lower << "-" << lower + allocatedSize << std::endl; - VkDeviceSize newSize = size - allocatedSize; - VkDeviceSize newLower = lower + allocatedSize; - OSubAllocation alloc = new SubAllocation(this, requestedSize, lower, allocatedSize, alignedOffset); - activeAllocations.add(alloc); - freeRanges.erase(lower); - if (newSize > 0) - { - freeRanges[newLower] = newSize; - } - bytesUsed += allocatedSize; - return alloc; - } - } - return nullptr; -} +// OSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDeviceSize alignment) +// { +// if (isDedicated) +// { +// if (activeAllocations.empty() && requestedSize == bytesAllocated) +// { +// OSubAllocation suballoc = new SubAllocation(this, requestedSize, 0, requestedSize, 0); +// activeAllocations.add(suballoc); +// freeRanges.clear(); +// bytesUsed += requestedSize; +// return suballoc; +// } +// else +// { +// return nullptr; +// } +// } +// for (const auto& [lower, size] : freeRanges) +// { +// VkDeviceSize alignedOffset = lower + alignment - 1; +// alignedOffset /= alignment; +// alignedOffset *= alignment; +// VkDeviceSize allocatedSize = requestedSize + (alignedOffset - lower); +// if (size >= allocatedSize) +// { +// //std::cout << "Allocating " << lower << "-" << lower + allocatedSize << std::endl; +// VkDeviceSize newSize = size - allocatedSize; +// VkDeviceSize newLower = lower + allocatedSize; +// OSubAllocation alloc = new SubAllocation(this, requestedSize, lower, allocatedSize, alignedOffset); +// activeAllocations.add(alloc); +// freeRanges.erase(lower); +// if (newSize > 0) +// { +// freeRanges[newLower] = newSize; +// } +// bytesUsed += allocatedSize; +// return alloc; +// } +// } +// return nullptr; +// } -void Allocation::markFree(PSubAllocation allocation) -{ - //std::cout << "Freeing " << allocation->allocatedOffset << "-" << allocation->allocatedOffset + allocation->allocatedSize << std::endl; - assert(activeAllocations.find(allocation) != activeAllocations.end()); - VkDeviceSize lowerBound = allocation->allocatedOffset; - VkDeviceSize upperBound = allocation->allocatedOffset + allocation->allocatedSize; - freeRanges[lowerBound] = allocation->allocatedSize; - for (const auto& [lower, size] : freeRanges) - { - if (lower + size == lowerBound) - { - freeRanges[lower] = size + allocation->allocatedSize; - freeRanges.erase(lowerBound); - lowerBound = lower; - break; - } - } - if (freeRanges.find(upperBound) != freeRanges.end()) - { - freeRanges[lowerBound] += freeRanges[upperBound]; - freeRanges.erase(upperBound); - } - activeAllocations.remove(allocation, false); - bytesUsed -= allocation->allocatedSize; - //if (activeAllocations.size() == 0) - //{ - // pool->free(this); - //} -} +// void Allocation::markFree(PSubAllocation allocation) +// { +// //std::cout << "Freeing " << allocation->allocatedOffset << "-" << allocation->allocatedOffset + allocation->allocatedSize << std::endl; +// assert(activeAllocations.find(allocation) != activeAllocations.end()); +// VkDeviceSize lowerBound = allocation->allocatedOffset; +// VkDeviceSize upperBound = allocation->allocatedOffset + allocation->allocatedSize; +// freeRanges[lowerBound] = allocation->allocatedSize; +// for (const auto& [lower, size] : freeRanges) +// { +// if (lower + size == lowerBound) +// { +// freeRanges[lower] = size + allocation->allocatedSize; +// freeRanges.erase(lowerBound); +// lowerBound = lower; +// break; +// } +// } +// if (freeRanges.find(upperBound) != freeRanges.end()) +// { +// freeRanges[lowerBound] += freeRanges[upperBound]; +// freeRanges.erase(upperBound); +// } +// activeAllocations.remove(allocation, false); +// bytesUsed -= allocation->allocatedSize; +// //if (activeAllocations.size() == 0) +// //{ +// // pool->free(this); +// //} +// } -void Allocation::flushMemory() -{ - VkMappedMemoryRange range = { - .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, - .pNext = 0, - .memory = allocatedMemory, - .offset = 0, - .size = bytesAllocated, - }; - vkFlushMappedMemoryRanges(device, 1, &range); -} +// void Allocation::flushMemory() +// { +// VkMappedMemoryRange range = { +// .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, +// .pNext = 0, +// .memory = allocatedMemory, +// .offset = 0, +// .size = bytesAllocated, +// }; +// vkFlushMappedMemoryRanges(device, 1, &range); +// } -void Allocation::invalidate() -{ - VkMappedMemoryRange range = { - .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, - .pNext = 0, - .memory = allocatedMemory, - .size = bytesAllocated, - }; - vkInvalidateMappedMemoryRanges(device, 1, &range); -} +// void Allocation::invalidate() +// { +// VkMappedMemoryRange range = { +// .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, +// .pNext = 0, +// .memory = allocatedMemory, +// .size = bytesAllocated, +// }; +// vkInvalidateMappedMemoryRanges(device, 1, &range); +// } -Allocator::Allocator(PGraphics graphics) - : graphics(graphics) -{ - vkGetPhysicalDeviceMemoryProperties(graphics->getPhysicalDevice(), &memProperties); - heaps.reserve(memProperties.memoryHeapCount); - for (size_t i = 0; i < memProperties.memoryHeapCount; ++i) - { - VkMemoryHeap memoryHeap = memProperties.memoryHeaps[i]; - HeapInfo heapInfo; - heapInfo.maxSize = memoryHeap.size; - //std::cout << "Creating heap " << i << " with properties " << memoryHeap.flags << " size " << memoryHeap.size << std::endl; - heaps.add(std::move(heapInfo)); - } -} +// Allocator::Allocator(PGraphics graphics) +// : graphics(graphics) +// { +// vkGetPhysicalDeviceMemoryProperties(graphics->getPhysicalDevice(), &memProperties); +// heaps.reserve(memProperties.memoryHeapCount); +// for (size_t i = 0; i < memProperties.memoryHeapCount; ++i) +// { +// VkMemoryHeap memoryHeap = memProperties.memoryHeaps[i]; +// HeapInfo heapInfo; +// heapInfo.maxSize = memoryHeap.size; +// //std::cout << "Creating heap " << i << " with properties " << memoryHeap.flags << " size " << memoryHeap.size << std::endl; +// heaps.add(std::move(heapInfo)); +// } +// } -Allocator::~Allocator() -{ -} +// Allocator::~Allocator() +// { +// } -OSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo) -{ - const VkMemoryRequirements &requirements = memRequirements2.memoryRequirements; - uint32 memoryTypeIndex = findMemoryType(requirements.memoryTypeBits, properties); - uint32 heapIndex = memProperties.memoryTypes[memoryTypeIndex].heapIndex; +// OSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo) +// { +// const VkMemoryRequirements &requirements = memRequirements2.memoryRequirements; +// uint32 memoryTypeIndex = findMemoryType(requirements.memoryTypeBits, properties); +// uint32 heapIndex = memProperties.memoryTypes[memoryTypeIndex].heapIndex; - if (memRequirements2.pNext != nullptr) - { - VkMemoryDedicatedRequirements *dedicatedReq = (VkMemoryDedicatedRequirements *)memRequirements2.pNext; - if (dedicatedReq->prefersDedicatedAllocation) - { - OAllocation newAllocation = new Allocation(graphics, this, requirements.size, memoryTypeIndex, properties, dedicatedInfo); - heaps[heapIndex].inUse += newAllocation->bytesAllocated; - std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << std::endl; - heaps[heapIndex].allocations.add(std::move(newAllocation)); - return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment); - } - } - for (auto& alloc : heaps[heapIndex].allocations) - { - if(alloc->memoryTypeIndex == memoryTypeIndex) - { - OSubAllocation suballoc = alloc->getSuballocation(requirements.size, requirements.alignment); - if (suballoc != nullptr) - { - return suballoc; - } - } - } +// if (memRequirements2.pNext != nullptr) +// { +// VkMemoryDedicatedRequirements *dedicatedReq = (VkMemoryDedicatedRequirements *)memRequirements2.pNext; +// if (dedicatedReq->prefersDedicatedAllocation) +// { +// OAllocation newAllocation = new Allocation(graphics, this, requirements.size, memoryTypeIndex, properties, dedicatedInfo); +// heaps[heapIndex].inUse += newAllocation->bytesAllocated; +// std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << std::endl; +// heaps[heapIndex].allocations.add(std::move(newAllocation)); +// return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment); +// } +// } +// for (auto& alloc : heaps[heapIndex].allocations) +// { +// if(alloc->memoryTypeIndex == memoryTypeIndex) +// { +// OSubAllocation suballoc = alloc->getSuballocation(requirements.size, requirements.alignment); +// if (suballoc != nullptr) +// { +// return suballoc; +// } +// } +// } - // no suitable allocations found, allocate new block - OAllocation newAllocation = new Allocation(graphics, this, (requirements.size > DEFAULT_ALLOCATION) ? requirements.size : DEFAULT_ALLOCATION, memoryTypeIndex, properties, nullptr); - heaps[heapIndex].inUse += newAllocation->bytesAllocated; - std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << std::endl; - heaps[heapIndex].allocations.add(std::move(newAllocation)); - return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment); -} +// // no suitable allocations found, allocate new block +// OAllocation newAllocation = new Allocation(graphics, this, (requirements.size > DEFAULT_ALLOCATION) ? requirements.size : DEFAULT_ALLOCATION, memoryTypeIndex, properties, nullptr); +// heaps[heapIndex].inUse += newAllocation->bytesAllocated; +// std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize * 100 << "%" << std::endl; +// heaps[heapIndex].allocations.add(std::move(newAllocation)); +// return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment); +// } -void Allocator::free(PAllocation allocation) -{ - for (uint32 heapIndex = 0; heapIndex < heaps.size(); ++heapIndex) - { - for (uint32 alloc = 0; alloc < heaps[heapIndex].allocations.size(); ++alloc) - { - if (heaps[heapIndex].allocations[alloc] == allocation) - { - heaps[heapIndex].allocations.removeAt(alloc, false); - } - } - } -} +// void Allocator::free(PAllocation allocation) +// { +// for (uint32 heapIndex = 0; heapIndex < heaps.size(); ++heapIndex) +// { +// for (uint32 alloc = 0; alloc < heaps[heapIndex].allocations.size(); ++alloc) +// { +// if (heaps[heapIndex].allocations[alloc] == allocation) +// { +// heaps[heapIndex].allocations.removeAt(alloc, false); +// } +// } +// } +// } -void Allocator::print() -{ - for (uint32 heapIndex = 0; heapIndex < heaps.size(); ++heapIndex) - { - std::cout << "Heap " << heapIndex << std::endl; - for (uint32 alloc = 0; alloc < heaps[heapIndex].allocations.size(); ++alloc) - { - std::cout << "[" << alloc << "]: " << (float)heaps[heapIndex].allocations[alloc]->bytesUsed / heaps[heapIndex].allocations[alloc]->bytesAllocated << std::endl; - } - } -} +// void Allocator::print() +// { +// for (uint32 heapIndex = 0; heapIndex < heaps.size(); ++heapIndex) +// { +// std::cout << "Heap " << heapIndex << std::endl; +// for (uint32 alloc = 0; alloc < heaps[heapIndex].allocations.size(); ++alloc) +// { +// std::cout << "[" << alloc << "]: " << (float)heaps[heapIndex].allocations[alloc]->bytesUsed / heaps[heapIndex].allocations[alloc]->bytesAllocated << std::endl; +// } +// } +// } -uint32 Allocator::findMemoryType(uint32 typeFilter, VkMemoryPropertyFlags properties) -{ - for (uint32 i = 0; i < memProperties.memoryTypeCount; i++) - { - if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) - { - return i; - } - } +// uint32 Allocator::findMemoryType(uint32 typeFilter, VkMemoryPropertyFlags properties) +// { +// for (uint32 i = 0; i < memProperties.memoryTypeCount; i++) +// { +// if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) +// { +// return i; +// } +// } - throw std::runtime_error("error finding memory"); -} +// throw std::runtime_error("error finding memory"); +// } -StagingBuffer::StagingBuffer(PGraphics graphics, OSubAllocation allocation, VkBuffer buffer, VkDeviceSize size, Gfx::QueueType owner) - : owner(owner) - , allocation(std::move(allocation)) - , graphics(graphics) - , buffer(buffer) - , size(size) -{ -} +// StagingBuffer::StagingBuffer(PGraphics graphics, OSubAllocation allocation, VkBuffer buffer, VkDeviceSize size, Gfx::QueueType owner) +// : owner(owner) +// , allocation(std::move(allocation)) +// , graphics(graphics) +// , buffer(buffer) +// , size(size) +// { +// } -StagingBuffer::~StagingBuffer() -{ - graphics->getDestructionManager()->queueBuffer( - graphics->getQueueCommands(owner)->getCommands(), buffer); - graphics->getDestructionManager()->queueAllocation( - graphics->getQueueCommands(owner)->getCommands(), std::move(allocation)); -} +// StagingBuffer::~StagingBuffer() +// { +// graphics->getDestructionManager()->queueBuffer( +// graphics->getQueueCommands(owner)->getCommands(), buffer); +// graphics->getDestructionManager()->queueAllocation( +// graphics->getQueueCommands(owner)->getCommands(), std::move(allocation)); +// } -void* StagingBuffer::map() -{ - return allocation->map(); -} +// void* StagingBuffer::map() +// { +// return allocation->map(); +// } -void StagingBuffer::flush() -{ - allocation->flushMemory(); -} +// void StagingBuffer::flush() +// { +// allocation->flushMemory(); +// } -void StagingBuffer::invalidate() -{ - allocation->invalidate(); -} +// void StagingBuffer::invalidate() +// { +// allocation->invalidate(); +// } -VkDeviceMemory StagingBuffer::getMemory() const -{ - return allocation->getHandle(); -} +// VkDeviceMemory StagingBuffer::getMemory() const +// { +// return allocation->getHandle(); +// } -VkDeviceSize StagingBuffer::getOffset() const -{ - return allocation->getOffset(); -} +// VkDeviceSize StagingBuffer::getOffset() const +// { +// return allocation->getOffset(); +// } -StagingManager::StagingManager(PGraphics graphics, PAllocator pool) - : graphics(graphics), pool(pool) -{ -} +// StagingManager::StagingManager(PGraphics graphics, PAllocator pool) +// : graphics(graphics), pool(pool) +// { +// } -StagingManager::~StagingManager() -{ -} +// StagingManager::~StagingManager() +// { +// } -OStagingBuffer StagingManager::create(uint64 size, Gfx::QueueType owner) -{ - //vkDeviceWaitIdle(graphics->getDevice()); - //std::cout << "Creating new stagingbuffer" << std::endl; - for (uint32 i = 0; i < freeBuffers.size(); ++i) - { - if (size <= freeBuffers[i]->getSize() && owner == freeBuffers[i]->getOwner()) - { - OStagingBuffer result = std::move(freeBuffers[i]); - freeBuffers.removeAt(i); - return result; - } - } - uint32 queueIndex = graphics->getFamilyMapping().getQueueTypeFamilyIndex(owner); - VkBufferCreateInfo stagingBufferCreateInfo = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .size = size, - .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - .queueFamilyIndexCount = 1, - .pQueueFamilyIndices = &queueIndex, - }; +// OStagingBuffer StagingManager::create(uint64 size, Gfx::QueueType owner) +// { +// //vkDeviceWaitIdle(graphics->getDevice()); +// //std::cout << "Creating new stagingbuffer" << std::endl; +// for (uint32 i = 0; i < freeBuffers.size(); ++i) +// { +// if (size <= freeBuffers[i]->getSize() && owner == freeBuffers[i]->getOwner()) +// { +// OStagingBuffer result = std::move(freeBuffers[i]); +// freeBuffers.removeAt(i); +// return result; +// } +// } +// uint32 queueIndex = graphics->getFamilyMapping().getQueueTypeFamilyIndex(owner); +// VkBufferCreateInfo stagingBufferCreateInfo = { +// .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, +// .pNext = nullptr, +// .flags = 0, +// .size = size, +// .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, +// .sharingMode = VK_SHARING_MODE_EXCLUSIVE, +// .queueFamilyIndexCount = 1, +// .pQueueFamilyIndices = &queueIndex, +// }; - VkBuffer buffer; - VK_CHECK(vkCreateBuffer(graphics->getDevice(), &stagingBufferCreateInfo, nullptr, &buffer)); +// VkBuffer buffer; +// VK_CHECK(vkCreateBuffer(graphics->getDevice(), &stagingBufferCreateInfo, nullptr, &buffer)); - VkMemoryDedicatedRequirements dedicatedReqs = { - .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, - .pNext = nullptr, - }; - VkMemoryRequirements2 memReqs = { - .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, - .pNext = &dedicatedReqs, - }; - VkBufferMemoryRequirementsInfo2 bufferQuery = { - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, - .pNext = nullptr, - .buffer = buffer, - }; - vkGetBufferMemoryRequirements2(graphics->getDevice(), &bufferQuery, &memReqs); +// VkMemoryDedicatedRequirements dedicatedReqs = { +// .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, +// .pNext = nullptr, +// }; +// VkMemoryRequirements2 memReqs = { +// .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, +// .pNext = &dedicatedReqs, +// }; +// VkBufferMemoryRequirementsInfo2 bufferQuery = { +// .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, +// .pNext = nullptr, +// .buffer = buffer, +// }; +// vkGetBufferMemoryRequirements2(graphics->getDevice(), &bufferQuery, &memReqs); - OStagingBuffer stagingBuffer = new StagingBuffer( - graphics, - pool->allocate(memReqs, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT, buffer), - buffer, - size, - owner - ); - vkBindBufferMemory(graphics->getDevice(), buffer, stagingBuffer->getMemory(), stagingBuffer->getOffset()); +// OStagingBuffer stagingBuffer = new StagingBuffer( +// graphics, +// pool->allocate(memReqs, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT, buffer), +// buffer, +// size, +// owner +// ); +// vkBindBufferMemory(graphics->getDevice(), buffer, stagingBuffer->getMemory(), stagingBuffer->getOffset()); - return stagingBuffer; -} +// return stagingBuffer; +// } -void StagingManager::release(OStagingBuffer) -{ - //freeBuffers.add(std::move(buffer)); -} +// void StagingManager::release(OStagingBuffer) +// { +// //freeBuffers.add(std::move(buffer)); +// } diff --git a/src/Engine/Graphics/Vulkan/Allocator.h b/src/Engine/Graphics/Vulkan/Allocator.h index 947bbf6..3ca9bda 100644 --- a/src/Engine/Graphics/Vulkan/Allocator.h +++ b/src/Engine/Graphics/Vulkan/Allocator.h @@ -1,196 +1,196 @@ -#pragma once -#include "MinimalEngine.h" -#include "Enums.h" -#include "Containers/Map.h" -#include "Containers/Array.h" -#include "Graphics/Resources.h" -#include +// #pragma once +// #include "MinimalEngine.h" +// #include "Enums.h" +// #include "Containers/Map.h" +// #include "Containers/Array.h" +// #include "Graphics/Resources.h" +// #include -namespace Seele -{ -namespace Vulkan -{ -DECLARE_REF(Graphics) -DECLARE_REF(Allocator) -DECLARE_REF(Allocation) -class SubAllocation -{ -public: - SubAllocation(PAllocation owner, VkDeviceSize requestedSize, VkDeviceSize allocatedOffset, VkDeviceSize allocatedSize, VkDeviceSize alignedOffset); - ~SubAllocation(); - VkDeviceMemory getHandle() const; +// namespace Seele +// { +// namespace Vulkan +// { +// DECLARE_REF(Graphics) +// DECLARE_REF(Allocator) +// DECLARE_REF(Allocation) +// class SubAllocation +// { +// public: +// SubAllocation(PAllocation owner, VkDeviceSize requestedSize, VkDeviceSize allocatedOffset, VkDeviceSize allocatedSize, VkDeviceSize alignedOffset); +// ~SubAllocation(); +// VkDeviceMemory getHandle() const; - constexpr VkDeviceSize getSize() const - { - return requestedSize; - } +// constexpr VkDeviceSize getSize() const +// { +// return requestedSize; +// } - constexpr VkDeviceSize getOffset() const - { - return alignedOffset; - } +// constexpr VkDeviceSize getOffset() const +// { +// return alignedOffset; +// } - void *map(); - void flushMemory(); - void invalidate(); +// void *map(); +// void flushMemory(); +// void invalidate(); -private: - PAllocation owner; - VkDeviceSize requestedSize; - VkDeviceSize allocatedOffset; - VkDeviceSize allocatedSize; - VkDeviceSize alignedOffset; - friend class Allocation; - friend class Allocator; -}; -DEFINE_REF(SubAllocation) -class Allocation -{ -public: - Allocation(PGraphics graphics, PAllocator pool, VkDeviceSize size, uint8 memoryTypeIndex, - VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo = nullptr); - Allocation(const Allocation& other) = delete; - Allocation& operator=(const Allocation& other) = delete; - ~Allocation(); - OSubAllocation getSuballocation(VkDeviceSize size, VkDeviceSize alignment); - void markFree(PSubAllocation alloc); - constexpr VkDeviceMemory getHandle() const - { - return allocatedMemory; - } - constexpr VkMemoryPropertyFlags getProperties() const - { - return properties; - } - constexpr void* map() - { - if (!canMap) - { - return nullptr; - } - if (!isMapped) - { - vkMapMemory(device, allocatedMemory, 0, bytesAllocated, 0, &mappedPointer); - isMapped = true; - } - return mappedPointer; - } +// private: +// PAllocation owner; +// VkDeviceSize requestedSize; +// VkDeviceSize allocatedOffset; +// VkDeviceSize allocatedSize; +// VkDeviceSize alignedOffset; +// friend class Allocation; +// friend class Allocator; +// }; +// DEFINE_REF(SubAllocation) +// class Allocation +// { +// public: +// Allocation(PGraphics graphics, PAllocator pool, VkDeviceSize size, uint8 memoryTypeIndex, +// VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo = nullptr); +// Allocation(const Allocation& other) = delete; +// Allocation& operator=(const Allocation& other) = delete; +// ~Allocation(); +// OSubAllocation getSuballocation(VkDeviceSize size, VkDeviceSize alignment); +// void markFree(PSubAllocation alloc); +// constexpr VkDeviceMemory getHandle() const +// { +// return allocatedMemory; +// } +// constexpr VkMemoryPropertyFlags getProperties() const +// { +// return properties; +// } +// constexpr void* map() +// { +// if (!canMap) +// { +// return nullptr; +// } +// if (!isMapped) +// { +// vkMapMemory(device, allocatedMemory, 0, bytesAllocated, 0, &mappedPointer); +// isMapped = true; +// } +// return mappedPointer; +// } - void flushMemory(); - void invalidate(); +// void flushMemory(); +// void invalidate(); -private: - VkDevice device; - PAllocator pool; - VkDeviceSize bytesAllocated; - VkDeviceSize bytesUsed; - VkDeviceMemory allocatedMemory; - Array activeAllocations; - Map freeRanges; - void *mappedPointer; - uint8 canMap : 1; - uint8 isMapped : 1; - uint8 isDedicated : 1; - VkMemoryPropertyFlags properties; - uint8 memoryTypeIndex; - friend class Allocator; -}; -DEFINE_REF(Allocation) +// private: +// VkDevice device; +// PAllocator pool; +// VkDeviceSize bytesAllocated; +// VkDeviceSize bytesUsed; +// VkDeviceMemory allocatedMemory; +// Array activeAllocations; +// Map freeRanges; +// void *mappedPointer; +// uint8 canMap : 1; +// uint8 isMapped : 1; +// uint8 isDedicated : 1; +// VkMemoryPropertyFlags properties; +// uint8 memoryTypeIndex; +// friend class Allocator; +// }; +// DEFINE_REF(Allocation) -class Allocator -{ -public: - Allocator(PGraphics graphics); - ~Allocator(); - OSubAllocation allocate(const VkMemoryRequirements2 &requirements, VkMemoryPropertyFlags props, - VkMemoryDedicatedAllocateInfo *dedicatedInfo = nullptr); - OSubAllocation allocate(const VkMemoryRequirements2 &requirements, VkMemoryPropertyFlags props, - VkBuffer buffer) - { - VkMemoryDedicatedAllocateInfo allocInfo = { - .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, - .pNext = nullptr, - .image = VK_NULL_HANDLE, - .buffer = buffer, - }; - return allocate(requirements, props, &allocInfo); - } - OSubAllocation allocate(const VkMemoryRequirements2 &requirements, VkMemoryPropertyFlags props, - VkImage image) - { - VkMemoryDedicatedAllocateInfo allocInfo = { - .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, - .pNext = nullptr, - .image = image, - .buffer = VK_NULL_HANDLE, - }; - return allocate(requirements, props, &allocInfo); - } +// class Allocator +// { +// public: +// Allocator(PGraphics graphics); +// ~Allocator(); +// OSubAllocation allocate(const VkMemoryRequirements2 &requirements, VkMemoryPropertyFlags props, +// VkMemoryDedicatedAllocateInfo *dedicatedInfo = nullptr); +// OSubAllocation allocate(const VkMemoryRequirements2 &requirements, VkMemoryPropertyFlags props, +// VkBuffer buffer) +// { +// VkMemoryDedicatedAllocateInfo allocInfo = { +// .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, +// .pNext = nullptr, +// .image = VK_NULL_HANDLE, +// .buffer = buffer, +// }; +// return allocate(requirements, props, &allocInfo); +// } +// OSubAllocation allocate(const VkMemoryRequirements2 &requirements, VkMemoryPropertyFlags props, +// VkImage image) +// { +// VkMemoryDedicatedAllocateInfo allocInfo = { +// .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, +// .pNext = nullptr, +// .image = image, +// .buffer = VK_NULL_HANDLE, +// }; +// return allocate(requirements, props, &allocInfo); +// } - void free(PAllocation allocation); - void print(); -private: - static constexpr VkDeviceSize DEFAULT_ALLOCATION = 16 * 1024 * 1024; // 16MB - struct HeapInfo - { - VkDeviceSize maxSize = 0; - VkDeviceSize inUse = 0; - Array allocations; - HeapInfo() = default; - HeapInfo(const HeapInfo& other) = delete; - HeapInfo(HeapInfo&& other) = default; - HeapInfo& operator=(const HeapInfo& other) = delete; - HeapInfo& operator=(HeapInfo&& other) = default; - }; - Array heaps; - uint32 findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties); - PGraphics graphics; - VkPhysicalDeviceMemoryProperties memProperties; -}; -DEFINE_REF(Allocator) -class StagingBuffer -{ -public: - StagingBuffer(PGraphics graphics, OSubAllocation allocation, VkBuffer buffer, VkDeviceSize size, Gfx::QueueType owner); - ~StagingBuffer(); - void* map(); - void flush(); - void invalidate(); - constexpr VkBuffer getHandle() const - { - return buffer; - } - VkDeviceMemory getMemory() const; - VkDeviceSize getOffset() const; - constexpr uint64 getSize() const - { - return size; - } - constexpr Gfx::QueueType getOwner() const - { - return owner; - } -private: - Gfx::QueueType owner; - OSubAllocation allocation; - PGraphics graphics; - VkBuffer buffer; - VkDeviceSize size; -}; -DEFINE_REF(StagingBuffer) +// void free(PAllocation allocation); +// void print(); +// private: +// static constexpr VkDeviceSize DEFAULT_ALLOCATION = 16 * 1024 * 1024; // 16MB +// struct HeapInfo +// { +// VkDeviceSize maxSize = 0; +// VkDeviceSize inUse = 0; +// Array allocations; +// HeapInfo() = default; +// HeapInfo(const HeapInfo& other) = delete; +// HeapInfo(HeapInfo&& other) = default; +// HeapInfo& operator=(const HeapInfo& other) = delete; +// HeapInfo& operator=(HeapInfo&& other) = default; +// }; +// Array heaps; +// uint32 findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties); +// PGraphics graphics; +// VkPhysicalDeviceMemoryProperties memProperties; +// }; +// DEFINE_REF(Allocator) +// class StagingBuffer +// { +// public: +// StagingBuffer(PGraphics graphics, OSubAllocation allocation, VkBuffer buffer, VkDeviceSize size, Gfx::QueueType owner); +// ~StagingBuffer(); +// void* map(); +// void flush(); +// void invalidate(); +// constexpr VkBuffer getHandle() const +// { +// return buffer; +// } +// VkDeviceMemory getMemory() const; +// VkDeviceSize getOffset() const; +// constexpr uint64 getSize() const +// { +// return size; +// } +// constexpr Gfx::QueueType getOwner() const +// { +// return owner; +// } +// private: +// Gfx::QueueType owner; +// OSubAllocation allocation; +// PGraphics graphics; +// VkBuffer buffer; +// VkDeviceSize size; +// }; +// DEFINE_REF(StagingBuffer) -class StagingManager -{ -public: - StagingManager(PGraphics graphics, PAllocator pool); - ~StagingManager(); - OStagingBuffer create(uint64 size, Gfx::QueueType owner); - void release(OStagingBuffer buffer); -private: - PGraphics graphics; - PAllocator pool; - Array freeBuffers; -}; -DEFINE_REF(StagingManager) -} // namespace Vulkan -} // namespace Seele \ No newline at end of file +// class StagingManager +// { +// public: +// StagingManager(PGraphics graphics, PAllocator pool); +// ~StagingManager(); +// OStagingBuffer create(uint64 size, Gfx::QueueType owner); +// void release(OStagingBuffer buffer); +// private: +// PGraphics graphics; +// PAllocator pool; +// Array freeBuffers; +// }; +// DEFINE_REF(StagingManager) +// } // namespace Vulkan +// } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/Buffer.cpp b/src/Engine/Graphics/Vulkan/Buffer.cpp index b499b7b..0b5a625 100644 --- a/src/Engine/Graphics/Vulkan/Buffer.cpp +++ b/src/Engine/Graphics/Vulkan/Buffer.cpp @@ -8,74 +8,52 @@ struct PendingBuffer { uint64 offset; uint64 size; - OStagingBuffer stagingBuffer; + VkBuffer stagingBuffer; + VmaAllocation allocation; + void *mappedMemory; Gfx::QueueType prevQueue; bool writeOnly; }; -static Map pendingBuffers; +static Map pendingBuffers; -Buffer::Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool dynamic) - : graphics(graphics) - , currentBuffer(0) - , size(size) - , owner(queueType) +Buffer::Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType &queueType, bool dynamic) + : graphics(graphics), currentBuffer(0), size(size), owner(queueType) { - if(dynamic) + if (dynamic) { numBuffers = Gfx::numFramesBuffered; - } + } else { numBuffers = 1; } - usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; - usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - uint32 queueFamilyIndex = graphics->getFamilyMapping().getQueueTypeFamilyIndex(queueType); VkBufferCreateInfo info = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = nullptr, .size = size, .usage = usage, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - .queueFamilyIndexCount = 1, - .pQueueFamilyIndices = &queueFamilyIndex, }; - VkBufferMemoryRequirementsInfo2 bufferReqInfo = { - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, - .pNext = nullptr, - }; - VkMemoryDedicatedRequirements dedicatedRequirements = { - .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, - .pNext = nullptr, - }; - VkMemoryRequirements2 memRequirements = { - .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, - .pNext = &dedicatedRequirements, + VmaAllocationCreateInfo allocInfo = { + .usage = VMA_MEMORY_USAGE_AUTO, + .flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, }; for (uint32 i = 0; i < numBuffers; ++i) { - VK_CHECK(vkCreateBuffer(graphics->getDevice(), &info, nullptr, &buffers[i].buffer)); - bufferReqInfo.buffer = buffers[i].buffer; - vkGetBufferMemoryRequirements2(graphics->getDevice(), &bufferReqInfo, &memRequirements); - buffers[i].allocation = graphics->getAllocator()->allocate(memRequirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, buffers[i].buffer); - vkBindBufferMemory(graphics->getDevice(), buffers[i].buffer, buffers[i].allocation->getHandle(), buffers[i].allocation->getOffset()); + vmaCreateBuffer(graphics->getAllocator(), &info, &allocInfo, &buffers[i].buffer, &buffers[i].allocation, &buffers[i].info); + vmaGetAllocationMemoryProperties(graphics->getAllocator(), buffers[i].allocation, &buffers[i].properties); } } Buffer::~Buffer() { - for(uint32 i = 0; i < numBuffers; ++i) - { + for (uint32 i = 0; i < numBuffers; ++i) + { graphics->getDestructionManager()->queueBuffer(graphics->getQueueCommands(owner)->getCommands(), buffers[i].buffer); } } -VkDeviceSize Buffer::getOffset() const -{ - return buffers[currentBuffer].allocation->getOffset(); -} - void Buffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping(); @@ -145,12 +123,12 @@ void Buffer::executeOwnershipBarrier(Gfx::QueueType newOwner) } void Buffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, - VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) { PCommand commandBuffer = graphics->getQueueCommands(owner)->getCommands(); VkBufferMemoryBarrier barrier = { .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - .pNext = nullptr, + .pNext = nullptr, .srcAccessMask = srcAccess, .dstAccessMask = dstAccess, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, @@ -159,7 +137,7 @@ void Buffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlag .size = size, }; VkBufferMemoryBarrier dynamicBarriers[Gfx::numFramesBuffered]; - for(uint32 i = 0; i < numBuffers; ++i) + for (uint32 i = 0; i < numBuffers; ++i) { dynamicBarriers[i] = barrier; dynamicBarriers[i].buffer = buffers[i].buffer; @@ -167,12 +145,12 @@ void Buffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlag vkCmdPipelineBarrier(commandBuffer->getHandle(), srcStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr); } -void * Buffer::map(bool writeOnly) +void *Buffer::map(bool writeOnly) { return mapRegion(0, size, writeOnly); } -void * Buffer::mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly) +void *Buffer::mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly) { void *data = nullptr; @@ -183,50 +161,30 @@ void * Buffer::mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly) pending.size = regionSize; if (writeOnly) { - //requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER); - OStagingBuffer stagingBuffer = graphics->getStagingManager()->create(regionSize, owner); - data = stagingBuffer->map(); - pending.stagingBuffer = std::move(stagingBuffer); + if (buffers[currentBuffer].properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) + { + VK_CHECK(vmaMapMemory(graphics->getAllocator(), buffers[currentBuffer].allocation, &pending.mappedMemory)); + } + else + { + VkBufferCreateInfo stagingInfo = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + .size = regionSize, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + }; + VmaAllocationCreateInfo allocInfo = { + .usage = VMA_MEMORY_USAGE_AUTO, + }; + VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &stagingInfo, &allocInfo, &pending.stagingBuffer, &pending.allocation, nullptr)); + vmaMapMemory(graphics->getAllocator(), pending.allocation, &pending.mappedMemory); + } } else { - PCommand current = graphics->getQueueCommands(owner)->getCommands(); - current->waitForCommand(); - - requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER); - VkCommandBuffer handle = graphics->getQueueCommands(owner)->getCommands()->getHandle(); - - VkBufferMemoryBarrier barrier = { - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - .pNext = nullptr, - .srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, - .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .buffer = buffers[currentBuffer].buffer, - .offset = 0, - .size = size, - }; - vkCmdPipelineBarrier(handle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr); - - OStagingBuffer stagingBuffer = graphics->getStagingManager()->create(size, owner); - - VkBufferCopy regions = { - .srcOffset = 0, - .dstOffset = 0, - .size = size, - }; - - vkCmdCopyBuffer(handle, buffers[currentBuffer].buffer, stagingBuffer->getHandle(), 1, ®ions); - - graphics->getQueueCommands(owner)->submitCommands(); - vkQueueWaitIdle(graphics->getQueueCommands(owner)->getQueue()->getHandle()); - stagingBuffer->map(); // this maps the memory if not mapped already - stagingBuffer->flush(); - data = stagingBuffer->map(); - - pending.stagingBuffer = std::move(stagingBuffer); - + assert(false); } pendingBuffers[this] = std::move(pending); @@ -239,60 +197,62 @@ void Buffer::unmap() auto found = pendingBuffers.find(this); if (found != pendingBuffers.end()) { - PendingBuffer& pending = found->value; - pending.stagingBuffer->flush(); + PendingBuffer &pending = found->value; + vmaFlushAllocation(graphics->getAllocator(), pending.allocation, 0, VK_WHOLE_SIZE); if (pending.writeOnly) { - PStagingBuffer stagingBuffer = pending.stagingBuffer; - PCommand command = graphics->getQueueCommands(owner)->getCommands(); - VkCommandBuffer cmdHandle = command->getHandle(); + if (buffers[currentBuffer].properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) + { + vmaUnmapMemory(graphics->getAllocator(), buffers[currentBuffer].allocation); + } + else + { + vmaUnmapMemory(graphics->getAllocator(), pending.allocation); + PCommand command = graphics->getQueueCommands(owner)->getCommands(); + VkCommandBuffer cmdHandle = command->getHandle(); - VkBufferCopy region = { - .srcOffset = 0, - .dstOffset = pending.offset, - .size = pending.size, - }; - VkBufferMemoryBarrier barrier = { - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - .pNext = nullptr, - .srcAccessMask = VK_ACCESS_MEMORY_READ_BIT, - .dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .buffer = buffers[currentBuffer].buffer, - .offset = 0, - .size = size, - }; - vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr); - vkCmdCopyBuffer(cmdHandle, stagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, ®ion); - barrier = { - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - .pNext = nullptr, - .srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, - .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .buffer = buffers[currentBuffer].buffer, - .offset = 0, - .size = size, - }; - vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr); + VkBufferCopy region = { + .srcOffset = 0, + .dstOffset = pending.offset, + .size = pending.size, + }; + VkBufferMemoryBarrier barrier = { + .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, + .pNext = nullptr, + .srcAccessMask = VK_ACCESS_MEMORY_READ_BIT, + .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .buffer = buffers[currentBuffer].buffer, + .offset = 0, + .size = size, + }; + vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr); + vkCmdCopyBuffer(cmdHandle, pending.stagingBuffer, buffers[currentBuffer].buffer, 1, ®ion); + barrier = { + .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, + .pNext = nullptr, + .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, + .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .buffer = buffers[currentBuffer].buffer, + .offset = 0, + .size = size, + }; + vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr); + vmaDestroyBuffer(graphics->getAllocator(), pending.stagingBuffer, pending.allocation); + } } - //requestOwnershipTransfer(pending.prevQueue); - graphics->getStagingManager()->release(std::move(pending.stagingBuffer)); + // requestOwnershipTransfer(pending.prevQueue); + pendingBuffers.erase(this); } } UniformBuffer::UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo &createInfo) - : Gfx::UniformBuffer(graphics->getFamilyMapping(), createInfo.sourceData) - , Vulkan::Buffer(graphics, createInfo.sourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, currentOwner, createInfo.dynamic) - , dedicatedStagingBuffer(nullptr) + : Gfx::UniformBuffer(graphics->getFamilyMapping(), createInfo.sourceData), Vulkan::Buffer(graphics, createInfo.sourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, currentOwner, createInfo.dynamic) { - if(createInfo.dynamic) - { - dedicatedStagingBuffer = graphics->getStagingManager()->create(createInfo.sourceData.size, owner); - } if (createInfo.sourceData.data != nullptr) { void *data = map(); @@ -303,75 +263,20 @@ UniformBuffer::UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo & UniformBuffer::~UniformBuffer() { - if (dedicatedStagingBuffer != nullptr) - { - graphics->getStagingManager()->release(std::move(dedicatedStagingBuffer)); - } } -bool UniformBuffer::updateContents(const DataSource &sourceData) +bool UniformBuffer::updateContents(const DataSource &sourceData) { - if(!Gfx::UniformBuffer::updateContents(sourceData)) + if (!Gfx::UniformBuffer::updateContents(sourceData)) { // no update was performed, skip return false; } - void* data = map(); + void *data = map(); std::memcpy(data, sourceData.data, sourceData.size); unmap(); return true; } -void* UniformBuffer::map(bool writeOnly) -{ - if(dedicatedStagingBuffer != nullptr) - { - return dedicatedStagingBuffer->map(); - } - return Vulkan::Buffer::map(writeOnly); -} - -void UniformBuffer::unmap() -{ - if(dedicatedStagingBuffer != nullptr) - { - dedicatedStagingBuffer->flush(); - PCommand command = graphics->getQueueCommands(currentOwner)->getCommands(); - VkCommandBuffer cmdHandle = command->getHandle(); - - VkBufferCopy region; - std::memset(®ion, 0, sizeof(VkBufferCopy)); - region.size = Vulkan::Buffer::size; - VkBufferMemoryBarrier barrier = { - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - .pNext = nullptr, - .srcAccessMask = VK_ACCESS_MEMORY_READ_BIT, - .dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .buffer = buffers[currentBuffer].buffer, - .offset = 0, - .size = size, - }; - vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr); - vkCmdCopyBuffer(cmdHandle, dedicatedStagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, ®ion); - barrier = { - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - .pNext = nullptr, - .srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, - .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .buffer = buffers[currentBuffer].buffer, - .offset = 0, - .size = size, - }; - vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr); - } - else - { - Vulkan::Buffer::unmap(); - } -} void UniformBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) { @@ -383,8 +288,8 @@ void UniformBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) Vulkan::Buffer::executeOwnershipBarrier(newOwner); } -void UniformBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, - VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) +void UniformBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) { Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); } @@ -400,14 +305,8 @@ VkAccessFlags UniformBuffer::getDestAccessMask() } ShaderBuffer::ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo &sourceData) - : Gfx::ShaderBuffer(graphics->getFamilyMapping(), sourceData.numElements, sourceData.sourceData) - , Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, currentOwner, sourceData.dynamic) - , dedicatedStagingBuffer(nullptr) + : Gfx::ShaderBuffer(graphics->getFamilyMapping(), sourceData.numElements, sourceData.sourceData), Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, currentOwner, sourceData.dynamic) { - if(sourceData.dynamic) - { - dedicatedStagingBuffer = graphics->getStagingManager()->create(sourceData.sourceData.size, currentOwner); - } if (sourceData.sourceData.data != nullptr) { void *data = map(); @@ -418,76 +317,18 @@ ShaderBuffer::ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo &sou ShaderBuffer::~ShaderBuffer() { - if (dedicatedStagingBuffer != nullptr) - { - graphics->getStagingManager()->release(std::move(dedicatedStagingBuffer)); - } } -bool ShaderBuffer::updateContents(const DataSource &sourceData) +bool ShaderBuffer::updateContents(const DataSource &sourceData) { assert(sourceData.size <= getSize()); Gfx::ShaderBuffer::updateContents(sourceData); - //We always want to update, as the contents could be different on the GPU - void* data = map(); + // We always want to update, as the contents could be different on the GPU + void *data = map(); std::memcpy(data, sourceData.data, sourceData.size); unmap(); return true; } -void* ShaderBuffer::map(bool writeOnly) -{ - if(dedicatedStagingBuffer != nullptr) - { - return dedicatedStagingBuffer->map(); - } - return Vulkan::Buffer::map(writeOnly); -} - -void ShaderBuffer::unmap() -{ - if(dedicatedStagingBuffer != nullptr) - { - dedicatedStagingBuffer->flush(); - PCommand command = graphics->getQueueCommands(currentOwner)->getCommands(); - VkCommandBuffer cmdHandle = command->getHandle(); - - VkBufferCopy region = { - .srcOffset = 0, - .dstOffset = 0, - .size = Vulkan::Buffer::size, - }; - - VkBufferMemoryBarrier barrier = { - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - .pNext = nullptr, - .srcAccessMask = VK_ACCESS_MEMORY_READ_BIT, - .dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .buffer = buffers[currentBuffer].buffer, - .offset = 0, - .size = size, - }; - vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr); - vkCmdCopyBuffer(cmdHandle, dedicatedStagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, ®ion); - barrier = { - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, - .pNext = nullptr, - .srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT, - .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .buffer = buffers[currentBuffer].buffer, - .offset = 0, - .size = size, - }; - vkCmdPipelineBarrier(cmdHandle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr); - } - else - { - Vulkan::Buffer::unmap(); - } -} void ShaderBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) { @@ -499,8 +340,8 @@ void ShaderBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) Vulkan::Buffer::executeOwnershipBarrier(newOwner); } -void ShaderBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, - VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) +void ShaderBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) { Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); } @@ -516,8 +357,7 @@ VkAccessFlags ShaderBuffer::getDestAccessMask() } VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &sourceData) - : Gfx::VertexBuffer(graphics->getFamilyMapping(), sourceData.numVertices, sourceData.vertexSize, sourceData.sourceData.owner) - , Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, currentOwner) + : Gfx::VertexBuffer(graphics->getFamilyMapping(), sourceData.numVertices, sourceData.vertexSize, sourceData.sourceData.owner), Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, currentOwner) { if (sourceData.sourceData.data != nullptr) { @@ -533,14 +373,14 @@ VertexBuffer::~VertexBuffer() void VertexBuffer::updateRegion(DataSource update) { - void* data = mapRegion(update.offset, update.size); + void *data = mapRegion(update.offset, update.size); std::memcpy(data, update.data, update.size); unmap(); } -void VertexBuffer::download(Array& buffer) +void VertexBuffer::download(Array &buffer) { - void* data = map(false); + void *data = map(false); buffer.resize(size); std::memcpy(buffer.data(), data, size); unmap(); @@ -556,8 +396,8 @@ void VertexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) Vulkan::Buffer::executeOwnershipBarrier(newOwner); } -void VertexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, - VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) +void VertexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) { Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); } @@ -573,8 +413,7 @@ VkAccessFlags VertexBuffer::getDestAccessMask() } IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &sourceData) - : Gfx::IndexBuffer(graphics->getFamilyMapping(), sourceData.sourceData.size, sourceData.indexType, sourceData.sourceData.owner) - , Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, currentOwner) + : Gfx::IndexBuffer(graphics->getFamilyMapping(), sourceData.sourceData.size, sourceData.indexType, sourceData.sourceData.owner), Vulkan::Buffer(graphics, sourceData.sourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, currentOwner) { if (sourceData.sourceData.data != nullptr) { @@ -588,9 +427,9 @@ IndexBuffer::~IndexBuffer() { } -void IndexBuffer::download(Array& buffer) +void IndexBuffer::download(Array &buffer) { - void* data = map(false); + void *data = map(false); buffer.resize(size); std::memcpy(buffer.data(), data, size); unmap(); @@ -606,8 +445,8 @@ void IndexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) Vulkan::Buffer::executeOwnershipBarrier(newOwner); } -void IndexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, - VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) +void IndexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, + VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) { Vulkan::Buffer::executePipelineBarrier(srcAccess, srcStage, dstAccess, dstStage); } diff --git a/src/Engine/Graphics/Vulkan/Buffer.h b/src/Engine/Graphics/Vulkan/Buffer.h index e5e5796..c8e0b68 100644 --- a/src/Engine/Graphics/Vulkan/Buffer.h +++ b/src/Engine/Graphics/Vulkan/Buffer.h @@ -1,7 +1,6 @@ #pragma once #include "Graphics/Buffer.h" #include "Graphics.h" -#include "Allocator.h" namespace Seele { @@ -20,20 +19,21 @@ public: { return size; } - VkDeviceSize getOffset() const; void advanceBuffer() { currentBuffer = (currentBuffer + 1) % numBuffers; } - virtual void *map(bool writeOnly = true); - virtual void *mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly = true); - virtual void unmap(); + void *map(bool writeOnly = true); + void *mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly = true); + void unmap(); protected: struct BufferAllocation { VkBuffer buffer; - OSubAllocation allocation; + VmaAllocation allocation; + VmaAllocationInfo info; + VkMemoryPropertyFlags properties; }; PGraphics graphics; uint32 currentBuffer; @@ -53,7 +53,6 @@ protected: }; DEFINE_REF(Buffer) -DECLARE_REF(StagingBuffer) class UniformBuffer : public Gfx::UniformBuffer, public Buffer { public: @@ -61,8 +60,6 @@ public: virtual ~UniformBuffer(); virtual bool updateContents(const DataSource &sourceData) override; - virtual void* map(bool writeOnly = true) override; - virtual void unmap() override; protected: // Inherited via Vulkan::Buffer virtual VkAccessFlags getSourceAccessMask() override; @@ -74,7 +71,6 @@ protected: VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) override; private: - OStagingBuffer dedicatedStagingBuffer; }; DEFINE_REF(UniformBuffer) @@ -85,8 +81,6 @@ public: virtual ~ShaderBuffer(); virtual bool updateContents(const DataSource &sourceData) override; - virtual void* map(bool writeOnly = true) override; - virtual void unmap() override; protected: // Inherited via Vulkan::Buffer virtual VkAccessFlags getSourceAccessMask() override; @@ -97,7 +91,6 @@ protected: virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) override; private: - OStagingBuffer dedicatedStagingBuffer; }; DEFINE_REF(ShaderBuffer) diff --git a/src/Engine/Graphics/Vulkan/Graphics.cpp b/src/Engine/Graphics/Vulkan/Graphics.cpp index ebd4a58..d8325f4 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.cpp +++ b/src/Engine/Graphics/Vulkan/Graphics.cpp @@ -13,6 +13,8 @@ #include #include #include +#define VMA_IMPLEMENTATION +#include "vk_mem_alloc.h" using namespace Seele; using namespace Seele::Vulkan; @@ -40,7 +42,6 @@ Graphics::~Graphics() pipelineCache = nullptr; allocator = nullptr; destructionManager = nullptr; - stagingManager = nullptr; allocatedFramebuffers.clear(); shaderCompiler = nullptr; vkDestroyDevice(handle, nullptr); @@ -56,8 +57,19 @@ void Graphics::init(GraphicsInitializer initInfo) #endif pickPhysicalDevice(); createDevice(initInfo); - allocator = new Allocator(this); - stagingManager = new StagingManager(this, allocator); + VmaAllocatorCreateInfo createInfo = { + .device = handle, + .instance = instance, + .pAllocationCallbacks = nullptr, + .pDeviceMemoryCallbacks = nullptr, + .pHeapSizeLimit = nullptr, + .physicalDevice = physicalDevice, + .preferredLargeHeapBlockSize = 0, + .pTypeExternalMemoryHandleTypes = nullptr, + .pVulkanFunctions = nullptr, + .vulkanApiVersion = VK_API_VERSION_1_3, + }; + vmaCreateAllocator(&createInfo, &allocator); pipelineCache = new PipelineCache(this, "pipeline.cache"); destructionManager = new DestructionManager(this); } @@ -326,16 +338,12 @@ PCommandPool Graphics::getDedicatedTransferCommands() } return dedicatedTransferCommands; } -PAllocator Graphics::getAllocator() + +VmaAllocator Graphics::getAllocator() { return allocator; } -PStagingManager Graphics::getStagingManager() -{ - return stagingManager; -} - PDestructionManager Graphics::getDestructionManager() { return destructionManager; @@ -374,11 +382,17 @@ void Graphics::initInstance(GraphicsInitializer initInfo) { extensions.add(initInfo.instanceExtensions[i]); } +#ifdef __APPLE__ + extensions.add("VK_KHR_portability_enumeration"); +#endif #if ENABLE_VALIDATION initInfo.layers.add("VK_LAYER_KHRONOS_validation"); #endif VkInstanceCreateInfo info = { .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, +#if __APPLE__ + .flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR, +#endif .pApplicationInfo = &appInfo, .enabledLayerCount = (uint32)initInfo.layers.size(), .ppEnabledLayerNames = initInfo.layers.data(), @@ -437,7 +451,7 @@ void Graphics::pickPhysicalDevice() } } physicalDevice = bestDevice; - + vkGetPhysicalDeviceProperties(physicalDevice, &props); vkGetPhysicalDeviceFeatures2(physicalDevice, &features); features.features.robustBufferAccess = 0; @@ -480,6 +494,13 @@ void Graphics::createDevice(GraphicsInitializer initializer) auto checkFamilyProperty = [](VkQueueFamilyProperties currProps, uint32 checkBit){ return (currProps.queueFlags & checkBit) == checkBit; }; + auto updateQueueInfo = [&queueProperties](uint32 familyIndex, QueueCreateInfo& info, uint32& numQueues) { + if(info.familyIndex == -1) { + info.familyIndex = familyIndex; + numQueues = std::min(numQueues + 1, queueProperties[familyIndex].queueCount); + info.queueIndex = numQueues - 1; + } + }; for (uint32 familyIndex = 0; familyIndex < queueProperties.size(); ++familyIndex) { uint32 numQueuesForFamily = 0; @@ -487,11 +508,7 @@ void Graphics::createDevice(GraphicsInitializer initializer) if (checkFamilyProperty(currProps, VK_QUEUE_GRAPHICS_BIT)) { - if (graphicsQueueInfo.familyIndex == -1) - { - graphicsQueueInfo.familyIndex = familyIndex; - numQueuesForFamily++; - } + updateQueueInfo(familyIndex, graphicsQueueInfo, numQueueFamilies); } if (currProps.queueFlags & VK_QUEUE_COMPUTE_BIT) { @@ -568,6 +585,9 @@ void Graphics::createDevice(GraphicsInitializer initializer) features12.pNext = &enabledMeshShaderFeatures; initializer.deviceExtensions.add(VK_EXT_MESH_SHADER_EXTENSION_NAME); } +#ifdef __APPLE__ + initializer.deviceExtensions.add("VK_KHR_portability_subset"); +#endif VkDeviceCreateInfo deviceInfo = { .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .pNext = &features11, diff --git a/src/Engine/Graphics/Vulkan/Graphics.h b/src/Engine/Graphics/Vulkan/Graphics.h index dbe8195..73abcb7 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.h +++ b/src/Engine/Graphics/Vulkan/Graphics.h @@ -1,13 +1,12 @@ #pragma once #include "Enums.h" #include "Graphics/Graphics.h" +#include namespace Seele { namespace Vulkan { -DECLARE_REF(Allocator) -DECLARE_REF(StagingManager) DECLARE_REF(DestructionManager) DECLARE_REF(CommandPool) DECLARE_REF(Queue) @@ -28,8 +27,7 @@ public: PCommandPool getTransferCommands(); PCommandPool getDedicatedTransferCommands(); - PAllocator getAllocator(); - PStagingManager getStagingManager(); + VmaAllocator getAllocator(); PDestructionManager getDestructionManager(); // Inherited via Graphics @@ -71,6 +69,7 @@ public: virtual void resolveTexture(Gfx::PTexture source, Gfx::PTexture destination) override; void vkCmdDrawMeshTasksEXT(VkCommandBuffer handle, uint32 groupX, uint32 groupY, uint32 groupZ); + protected: PFN_vkCmdDrawMeshTasksEXT cmdDrawMeshTasks; Array getRequiredExtensions(); @@ -97,9 +96,8 @@ protected: VkPhysicalDeviceVulkan12Features features12; VkDebugReportCallbackEXT callback; Map allocatedFramebuffers; - OAllocator allocator; + VmaAllocator allocator; OPipelineCache pipelineCache; - OStagingManager stagingManager; ODestructionManager destructionManager; friend class Window; diff --git a/src/Engine/Graphics/Vulkan/Resources.cpp b/src/Engine/Graphics/Vulkan/Resources.cpp index d0afbe4..8e2aa14 100644 --- a/src/Engine/Graphics/Vulkan/Resources.cpp +++ b/src/Engine/Graphics/Vulkan/Resources.cpp @@ -129,11 +129,6 @@ void DestructionManager::queueDescriptorPool(PCommand cmd, VkDescriptorPool pool pools[cmd].add(pool); } -void DestructionManager::queueAllocation(PCommand cmd, OSubAllocation alloc) -{ - allocs[cmd].add(std::move(alloc)); -} - void DestructionManager::notifyCmdComplete(PCommand cmd) { for(auto buf : buffers[cmd]) @@ -166,5 +161,4 @@ void DestructionManager::notifyCmdComplete(PCommand cmd) sems[cmd].clear(); pools[cmd].clear(); renderPasses[cmd].clear(); - allocs[cmd].clear(); } diff --git a/src/Engine/Graphics/Vulkan/Resources.h b/src/Engine/Graphics/Vulkan/Resources.h index b034689..3207765 100644 --- a/src/Engine/Graphics/Vulkan/Resources.h +++ b/src/Engine/Graphics/Vulkan/Resources.h @@ -12,7 +12,6 @@ DECLARE_REF(DescriptorPool) DECLARE_REF(CommandPool) DECLARE_REF(Command) DECLARE_REF(Graphics) -DECLARE_REF(SubAllocation) class Semaphore { public: @@ -63,7 +62,6 @@ public: void queueSemaphore(PCommand cmd, VkSemaphore sem); void queueRenderPass(PCommand cmd, VkRenderPass renderPass); void queueDescriptorPool(PCommand cmd, VkDescriptorPool pool); - void queueAllocation(PCommand cmd, OSubAllocation alloc); void notifyCmdComplete(PCommand cmdbuffer); private: PGraphics graphics; @@ -73,7 +71,6 @@ private: Map> sems; Map> renderPasses; Map> pools; - Map> allocs; }; DEFINE_REF(DestructionManager) diff --git a/src/Engine/Graphics/Vulkan/Texture.cpp b/src/Engine/Graphics/Vulkan/Texture.cpp index ca31e6a..1e067c4 100644 --- a/src/Engine/Graphics/Vulkan/Texture.cpp +++ b/src/Engine/Graphics/Vulkan/Texture.cpp @@ -46,7 +46,6 @@ TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType, if (existingImage == VK_NULL_HANDLE) { ownsImage = true; - PAllocator pool = graphics->getAllocator(); VkImageType type = VK_IMAGE_TYPE_MAX_ENUM; VkImageCreateFlags flags = 0; switch (viewType) @@ -97,69 +96,79 @@ TextureBase::TextureBase(PGraphics graphics, VkImageViewType viewType, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, .initialLayout = cast(layout), }; - + VmaAllocationCreateInfo allocInfo = { + .usage = VMA_MEMORY_USAGE_AUTO, + }; + VK_CHECK(vmaCreateImage(graphics->getAllocator(), &info, &allocInfo, &image, &allocation, nullptr)); - VK_CHECK(vkCreateImage(graphics->getDevice(), &info, nullptr, &image)); + const DataSource& sourceData = createInfo.sourceData; + if(sourceData.size > 0) + { + changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + void* data; + VkMemoryPropertyFlags memProps; + VkBuffer stagingBuffer = VK_NULL_HANDLE; + VmaAllocation stagingAlloc = VK_NULL_HANDLE; + vmaGetAllocationMemoryProperties(graphics->getAllocator(), allocation, &memProps); + if(memProps & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) + { + vmaMapMemory(graphics->getAllocator(), allocation, &data); + } + else + { + VkBufferCreateInfo stagingInfo = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .size = sourceData.size, + .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + }; + VmaAllocationCreateInfo alloc = { + .usage = VMA_MEMORY_USAGE_AUTO, + }; + VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &stagingInfo, &alloc, &stagingBuffer, &stagingAlloc, nullptr)); + vmaMapMemory(graphics->getAllocator(), stagingAlloc, &data); + } + std::memcpy(data, sourceData.data, sourceData.size); + vmaFlushAllocation(graphics->getAllocator(), stagingAlloc, 0, VK_WHOLE_SIZE); - VkMemoryDedicatedRequirements memDedicatedRequirements = { - .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, - .pNext = nullptr, - }; - VkImageMemoryRequirementsInfo2 reqInfo = { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2, - .pNext = nullptr, - .image = image, - }; - VkMemoryRequirements2 requirements = { - .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, - .pNext = &memDedicatedRequirements, - }; - vkGetImageMemoryRequirements2(graphics->getDevice(), &reqInfo, &requirements); - - allocation = pool->allocate(requirements, createInfo.memoryProps, image); - vkBindImageMemory(graphics->getDevice(), image, allocation->getHandle(), allocation->getOffset()); + PCommandPool commandPool = graphics->getQueueCommands(currentOwner); + VkBufferImageCopy region = { + .bufferOffset = 0, + .bufferRowLength = 0, + .bufferImageHeight = 0, + .imageSubresource = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = arrayCount * layerCount, + }, + .imageOffset = { + .x = 0, + .y = 0, + .z = 0, + }, + .imageExtent = { + .width = width, + .height = height, + .depth = depth + }, + }; + + vkCmdCopyBufferToImage(commandPool->getCommands()->getHandle(), + stagingBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + + // When loading a texture from a file, we will almost always use it as a texture map for fragment shaders + changeLayout(Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + if(stagingBuffer != VK_NULL_HANDLE) + { + vmaDestroyBuffer(graphics->getAllocator(), stagingBuffer, stagingAlloc); + } + } } - const DataSource& sourceData = createInfo.sourceData; - if(sourceData.size > 0) - { - changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - OStagingBuffer staging = graphics->getStagingManager()->create(sourceData.size, owner); - void* data = staging->map(); - std::memcpy(data, sourceData.data, sourceData.size); - staging->flush(); - - PCommandPool commandPool = graphics->getQueueCommands(currentOwner); - VkBufferImageCopy region = { - .bufferOffset = 0, - .bufferRowLength = 0, - .bufferImageHeight = 0, - .imageSubresource = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .mipLevel = 0, - .baseArrayLayer = 0, - .layerCount = arrayCount * layerCount, - }, - .imageOffset = { - .x = 0, - .y = 0, - .z = 0, - }, - .imageExtent = { - .width = width, - .height = height, - .depth = depth - }, - }; - - vkCmdCopyBufferToImage(commandPool->getCommands()->getHandle(), - staging->getHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); - - // When loading a texture from a file, we will almost always use it as a texture map for fragment shaders - changeLayout(Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - graphics->getStagingManager()->release(std::move(staging)); - } - else if(usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) + if(usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { changeLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); } @@ -231,9 +240,25 @@ void TextureBase::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Arra { uint64 imageSize = width * height * depth * Gfx::getFormatInfo(format).blockSize; - OStagingBuffer stagingbuffer = graphics->getStagingManager()->create(imageSize, currentOwner); - auto prevlayout = layout; + auto prevLayout = layout; changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + void* data; + VkBuffer stagingBuffer = VK_NULL_HANDLE; + VmaAllocation stagingAlloc; + + VkBufferCreateInfo stagingInfo = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .size = imageSize, + .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + }; + VmaAllocationCreateInfo alloc = { + .usage = VMA_MEMORY_USAGE_AUTO, + }; + VK_CHECK(vmaCreateBuffer(graphics->getAllocator(), &stagingInfo, &alloc, &stagingBuffer, &stagingAlloc, nullptr)); + PCommand cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands(); //Gfx::FormatCompatibilityInfo formatInfo = Gfx::getFormatInfo(format); VkBufferImageCopy region = { @@ -257,11 +282,12 @@ void TextureBase::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Arra .depth = depth }, }; - vkCmdCopyImageToBuffer(cmdBuffer->getHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingbuffer->getHandle(), 1, ®ion); - changeLayout(prevlayout); - buffer.resize(stagingbuffer->getSize()); - void* data = stagingbuffer->map(); + vkCmdCopyImageToBuffer(cmdBuffer->getHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingBuffer, 1, ®ion); + changeLayout(prevLayout); + buffer.resize(imageSize); std::memcpy(buffer.data(), data, buffer.size()); + vmaUnmapMemory(graphics->getAllocator(), stagingAlloc); + vmaDestroyBuffer(graphics->getAllocator(), stagingBuffer, stagingAlloc); } void TextureBase::executeOwnershipBarrier(Gfx::QueueType newOwner) diff --git a/src/Engine/Graphics/Vulkan/Texture.h b/src/Engine/Graphics/Vulkan/Texture.h index 04e59b6..08a3c5d 100644 --- a/src/Engine/Graphics/Vulkan/Texture.h +++ b/src/Engine/Graphics/Vulkan/Texture.h @@ -1,13 +1,11 @@ #pragma once #include "Graphics/Texture.h" #include "Graphics.h" -#include "Allocator.h" namespace Seele { namespace Vulkan { - class TextureBase { public: @@ -72,7 +70,7 @@ protected: //Updates via reference Gfx::QueueType& currentOwner; PGraphics graphics; - OSubAllocation allocation; + VmaAllocation allocation; uint32 width; uint32 height; uint32 depth; diff --git a/src/Engine/Window/GameView.cpp b/src/Engine/Window/GameView.cpp index 94c187a..a6834d3 100644 --- a/src/Engine/Window/GameView.cpp +++ b/src/Engine/Window/GameView.cpp @@ -95,10 +95,6 @@ void GameView::reloadGame() void GameView::keyCallback(KeyCode code, InputAction action, KeyModifier modifier) { - if (code == KeyCode::KEY_P && action == InputAction::PRESS) - { - ((Vulkan::Graphics*)graphics.getHandle())->getAllocator()->print(); - } keyboardSystem->keyCallback(code, action, modifier); } diff --git a/vcpkg.json b/vcpkg.json index 39093c9..d8fb830 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -11,6 +11,7 @@ "nlohmann-json", "fmt", "shader-slang", - "gtest" + "gtest", + "vulkan-memory-allocator" ] } \ No newline at end of file