From ba7f0e6d62207ca0a49cda59cde462102e265948 Mon Sep 17 00:00:00 2001 From: Georg Hagen Date: Wed, 10 Jul 2024 16:11:36 +0200 Subject: [PATCH 01/10] Restructure some files regarding resource management --- .../Vulkan/Resources/IShaderOwner.hpp | 2 +- ...{ManagedResource.hpp => ManagedBuffer.hpp} | 87 +---------------- ...nagedResource.cpp => MemoryAllocation.cpp} | 2 +- .../Vulkan/Resources/MemoryAllocation.hpp | 97 +++++++++++++++++++ .../Vulkan/Resources/ResourceManager.cpp | 5 +- .../Vulkan/Resources/ResourceManager.hpp | 12 ++- .../Vulkan/Resources/UniformBuffer.cpp | 2 +- .../Vulkan/Scene/VulkanGeometry.hpp | 2 +- openVulkanoCpp/Vulkan/Scene/VulkanShader.hpp | 3 +- 9 files changed, 114 insertions(+), 98 deletions(-) rename openVulkanoCpp/Vulkan/Resources/{ManagedResource.hpp => ManagedBuffer.hpp} (61%) rename openVulkanoCpp/Vulkan/Resources/{ManagedResource.cpp => MemoryAllocation.cpp} (95%) create mode 100644 openVulkanoCpp/Vulkan/Resources/MemoryAllocation.hpp diff --git a/openVulkanoCpp/Vulkan/Resources/IShaderOwner.hpp b/openVulkanoCpp/Vulkan/Resources/IShaderOwner.hpp index 01824f0..782e001 100644 --- a/openVulkanoCpp/Vulkan/Resources/IShaderOwner.hpp +++ b/openVulkanoCpp/Vulkan/Resources/IShaderOwner.hpp @@ -8,7 +8,7 @@ namespace OpenVulkano::Vulkan { - struct VulkanShader; + class VulkanShader; class IShaderOwner { diff --git a/openVulkanoCpp/Vulkan/Resources/ManagedResource.hpp b/openVulkanoCpp/Vulkan/Resources/ManagedBuffer.hpp similarity index 61% rename from openVulkanoCpp/Vulkan/Resources/ManagedResource.hpp rename to openVulkanoCpp/Vulkan/Resources/ManagedBuffer.hpp index 1142614..fa0f9a6 100644 --- a/openVulkanoCpp/Vulkan/Resources/ManagedResource.hpp +++ b/openVulkanoCpp/Vulkan/Resources/ManagedBuffer.hpp @@ -8,97 +8,12 @@ #define CRASH_ON_MULTIPLE_MAPPINGS_TO_SAME_ALLOCATION +#include "MemoryAllocation.hpp" #include -#include #include -#include "Base/Utils.hpp" namespace OpenVulkano::Vulkan { - struct MemoryAllocation - { - vk::DeviceMemory memory; - size_t used; - const size_t size; - const uint32_t type; - const vk::Device device; - void* mapped; - - private: - uint32_t mappedCount; - static constexpr uint32_t CHILD_MAPPED_FLAG = 1u << 31; - - public: - MemoryAllocation(size_t size, uint32_t type, vk::Device device): - memory(nullptr), used(0), size(size), type(type), device(device), mapped(nullptr), mappedCount(0) - { - } - - ~MemoryAllocation() - { - if (device && memory) - device.free(memory); - } - - [[nodiscard]] size_t FreeSpace() const - { - return size - used; - } - - [[nodiscard]] size_t FreeSpace(size_t alignment) const - { - return size - Utils::Align(used, alignment); - } - - void HandleChildMappingValidation() const; - - void* Map() - { - HandleChildMappingValidation(); - if (!mapped) - { - mapped = device.mapMemory(memory, 0, size, vk::MemoryMapFlags()); - } - mappedCount++; - return mapped; - } - - void UnMap() - { - if (mappedCount > 0) - { - mappedCount--; - if (mappedCount == 0) - { - device.unmapMemory(memory); - } - } - } - - [[nodiscard]] bool IsChildMapped() const - { - return mappedCount & CHILD_MAPPED_FLAG; - } - - void* MapChild(size_t offset, vk::DeviceSize size) - { - HandleChildMappingValidation(); - mappedCount |= CHILD_MAPPED_FLAG; - mappedCount++; - return device.mapMemory(memory, offset, size, vk::MemoryMapFlags()); - } - - void UnMapChild() - { - mappedCount &= ~CHILD_MAPPED_FLAG; - mappedCount--; - if (mappedCount == 0) - { - device.unmapMemory(memory); - } - } - }; - struct ManagedBuffer { using Ptr = std::unique_ptr>; diff --git a/openVulkanoCpp/Vulkan/Resources/ManagedResource.cpp b/openVulkanoCpp/Vulkan/Resources/MemoryAllocation.cpp similarity index 95% rename from openVulkanoCpp/Vulkan/Resources/ManagedResource.cpp rename to openVulkanoCpp/Vulkan/Resources/MemoryAllocation.cpp index 871f266..0930694 100644 --- a/openVulkanoCpp/Vulkan/Resources/ManagedResource.cpp +++ b/openVulkanoCpp/Vulkan/Resources/MemoryAllocation.cpp @@ -4,7 +4,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -#include "ManagedResource.hpp" +#include "ManagedBuffer.hpp" #include "Base/Logger.hpp" namespace OpenVulkano::Vulkan diff --git a/openVulkanoCpp/Vulkan/Resources/MemoryAllocation.hpp b/openVulkanoCpp/Vulkan/Resources/MemoryAllocation.hpp new file mode 100644 index 0000000..428766d --- /dev/null +++ b/openVulkanoCpp/Vulkan/Resources/MemoryAllocation.hpp @@ -0,0 +1,97 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "Base/Utils.hpp" +#include + +namespace OpenVulkano::Vulkan +{ + struct MemoryAllocation + { + vk::DeviceMemory memory; + size_t used; + const size_t size; + const uint32_t type; + const vk::Device device; + void* mapped; + + private: + uint32_t mappedCount; + static constexpr uint32_t CHILD_MAPPED_FLAG = 1u << 31; + + public: + MemoryAllocation(size_t size, uint32_t type, vk::Device device): + memory(nullptr), used(0), size(size), type(type), device(device), mapped(nullptr), mappedCount(0) + { + } + + ~MemoryAllocation() + { + if (device && memory) + device.free(memory); + } + + [[nodiscard]] size_t FreeSpace() const + { + return size - used; + } + + [[nodiscard]] size_t FreeSpace(size_t alignment) const + { + return size - Utils::Align(used, alignment); + } + + void HandleChildMappingValidation() const; + + void* Map() + { + HandleChildMappingValidation(); + if (!mapped) + { + mapped = device.mapMemory(memory, 0, size, vk::MemoryMapFlags()); + } + mappedCount++; + return mapped; + } + + void UnMap() + { + if (mappedCount > 0) + { + mappedCount--; + if (mappedCount == 0) + { + device.unmapMemory(memory); + } + } + } + + [[nodiscard]] bool IsChildMapped() const + { + return mappedCount & CHILD_MAPPED_FLAG; + } + + void* MapChild(size_t offset, vk::DeviceSize size) + { + HandleChildMappingValidation(); + mappedCount |= CHILD_MAPPED_FLAG; + mappedCount++; + return device.mapMemory(memory, offset, size, vk::MemoryMapFlags()); + } + + void UnMapChild() + { + mappedCount &= ~CHILD_MAPPED_FLAG; + mappedCount--; + if (mappedCount == 0) + { + device.unmapMemory(memory); + } + } + }; +} \ No newline at end of file diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp index 326d2aa..8fbb8cb 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp @@ -5,10 +5,13 @@ */ #include "ResourceManager.hpp" +#include "ManagedBuffer.hpp" +#include "MemoryAllocation.hpp" #include "Scene/Vertex.hpp" #include "Scene/Geometry.hpp" #include "Scene/Material.hpp" #include "Scene/UniformBuffer.hpp" +#include "Scene/Camera.hpp" #include "Math/ByteSize.hpp" #include "Vulkan/Context.hpp" #include "Vulkan/Image.hpp" @@ -91,7 +94,6 @@ namespace OpenVulkano::Vulkan nodes.clear(); device.destroyDescriptorPool(descriptorPool); allocations.clear(); - lastAllocation = nullptr; toFree.clear(); recycleBuffers.clear(); descriptorSetLayoutCache.clear(); @@ -372,7 +374,6 @@ namespace OpenVulkano::Vulkan } } if(!alloc && createIfAllFull) alloc = CreateMemoryAllocation(64_MiB, type, true); - if(alloc) lastAllocation = alloc; return alloc; } diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp index 0286d57..0aa985b 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp @@ -9,16 +9,15 @@ // Workaround for libc++ #define __cpp_lib_three_way_comparison 201907 -#include "vulkan/vulkan.hpp" #include "Base/ICloseable.hpp" #include "IShaderOwner.hpp" -#include "ManagedResource.hpp" #include "Vulkan/Image.hpp" #include "Scene/Shader/DescriptorInputDescription.hpp" -#include "Scene/Camera.hpp" -#include +#include #include #include +#include +#include namespace OpenVulkano { @@ -29,6 +28,7 @@ namespace OpenVulkano class Material; class Texture; class Shader; + class Camera; class UniformBuffer; } @@ -39,8 +39,11 @@ namespace OpenVulkano class VulkanTexture; class VulkanCamera; class VulkanNode; + class VulkanShader; class VulkanUniformBuffer; class UniformBuffer; + class ManagedBuffer; + class MemoryAllocation; class ResourceManager : public ICloseable, public IShaderOwner { @@ -57,7 +60,6 @@ namespace OpenVulkano std::vector> shaders; std::vector> geometries; std::vector> nodes; - MemoryAllocation* lastAllocation = nullptr; std::mutex mutex; vk::DeviceSize uniformBufferAlignment; std::vector> toFree; diff --git a/openVulkanoCpp/Vulkan/Resources/UniformBuffer.cpp b/openVulkanoCpp/Vulkan/Resources/UniformBuffer.cpp index 4255f96..cbfbd1f 100644 --- a/openVulkanoCpp/Vulkan/Resources/UniformBuffer.cpp +++ b/openVulkanoCpp/Vulkan/Resources/UniformBuffer.cpp @@ -5,7 +5,7 @@ */ #include "UniformBuffer.hpp" -#include "ManagedResource.hpp" +#include "ManagedBuffer.hpp" #include "ResourceManager.hpp" #include "Vulkan/VulkanDrawContext.hpp" #include "Vulkan/Scene/VulkanShader.hpp" diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanGeometry.hpp b/openVulkanoCpp/Vulkan/Scene/VulkanGeometry.hpp index a2f2363..db34fab 100644 --- a/openVulkanoCpp/Vulkan/Scene/VulkanGeometry.hpp +++ b/openVulkanoCpp/Vulkan/Scene/VulkanGeometry.hpp @@ -9,7 +9,7 @@ #include "IRecordable.hpp" #include "Scene/Scene.hpp" #include "Scene/Geometry.hpp" -#include "Vulkan/Resources/ManagedResource.hpp" +#include "Vulkan/Resources/ManagedBuffer.hpp" namespace OpenVulkano::Vulkan { diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanShader.hpp b/openVulkanoCpp/Vulkan/Scene/VulkanShader.hpp index 02cb77a..af41830 100644 --- a/openVulkanoCpp/Vulkan/Scene/VulkanShader.hpp +++ b/openVulkanoCpp/Vulkan/Scene/VulkanShader.hpp @@ -23,8 +23,9 @@ namespace OpenVulkano class Context; class IShaderOwner; - struct VulkanShader final : public ICloseable, public IRecordable + class VulkanShader final : public ICloseable, public IRecordable { + public: Scene::Shader* shader = nullptr; vk::Device device; std::vector shaderModules; // TODO manage live time somewhere else to allow sharing of shader programs From a54e1b10edb5feaab8788a964b9f678578bc5c8d Mon Sep 17 00:00:00 2001 From: Georg Hagen Date: Wed, 10 Jul 2024 16:23:35 +0200 Subject: [PATCH 02/10] Make ResourceManager no longer extend IClosable --- openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp index 0aa985b..27f27c1 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp @@ -9,7 +9,6 @@ // Workaround for libc++ #define __cpp_lib_three_way_comparison 201907 -#include "Base/ICloseable.hpp" #include "IShaderOwner.hpp" #include "Vulkan/Image.hpp" #include "Scene/Shader/DescriptorInputDescription.hpp" @@ -45,7 +44,7 @@ namespace OpenVulkano class ManagedBuffer; class MemoryAllocation; - class ResourceManager : public ICloseable, public IShaderOwner + class ResourceManager : public IShaderOwner { friend UniformBuffer; friend VulkanTexture; @@ -80,7 +79,7 @@ namespace OpenVulkano void Init(Context* context, int buffers = 2); - void Close() override; + void Close(); void StartFrame(uint64_t frameId); From b1081bd26cbcc1d999bbc91baa7ef43827492d75 Mon Sep 17 00:00:00 2001 From: Georg Hagen Date: Wed, 10 Jul 2024 17:03:45 +0200 Subject: [PATCH 03/10] Cleanup ResourceManager --- openVulkanoCpp/Data/Containers/Array.hpp | 9 ++ .../Vulkan/Resources/ResourceManager.cpp | 85 +++++++++---------- .../Vulkan/Resources/ResourceManager.hpp | 14 +-- 3 files changed, 57 insertions(+), 51 deletions(-) diff --git a/openVulkanoCpp/Data/Containers/Array.hpp b/openVulkanoCpp/Data/Containers/Array.hpp index 4df03ec..2c7057e 100644 --- a/openVulkanoCpp/Data/Containers/Array.hpp +++ b/openVulkanoCpp/Data/Containers/Array.hpp @@ -98,6 +98,15 @@ namespace OpenVulkano Fill(defaultValue); } + template + Array(size_t size, ARGS... args) : size(size), data(MakeBuffer(size)) + { + for(size_t i = 0; i < size; i++) + { + new (&data[i]) T(args...); + } + } + ~Array() noexcept { ClearData(); diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp index 8fbb8cb..6e3075c 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp @@ -26,6 +26,30 @@ namespace OpenVulkano::Vulkan { ResourceManager* ResourceManager::INSTANCE; + struct ResourceManager::FrameResources + { + vk::Device device; + vk::CommandPool cmdPool; + vk::CommandBuffer cmdBuffer; + vk::Semaphore semaphore; + + FrameResources(Device* device) + { + this->device = device->device; + cmdPool = this->device.createCommandPool({ {}, device->queueIndices.transfer }); + cmdBuffer = this->device.allocateCommandBuffers({ cmdPool, vk::CommandBufferLevel::ePrimary, 1 })[0]; + semaphore = this->device.createSemaphore({}); + } + + ~FrameResources() + { + device.freeCommandBuffers(cmdPool, 1, &cmdBuffer); + device.destroyCommandPool(cmdPool); + device.destroy(semaphore); + } + }; + + ResourceManager::ResourceManager() { static_assert(sizeof(DescriptorSetLayoutBinding) == sizeof(vk::DescriptorSetLayoutBinding)); @@ -40,20 +64,12 @@ namespace OpenVulkano::Vulkan void ResourceManager::Init(Context* context, int buffers) { this->context = context; - this->device = context->device->device; - this->buffers = buffers; + device = context->device->device; uniformBufferAlignment = context->device->properties.limits.minUniformBufferOffsetAlignment; + + frameResources = Array(static_cast(buffers), context->device.get()); - cmdPools = new vk::CommandPool[buffers]; - cmdBuffers = new vk::CommandBuffer[buffers]; - semaphores = new vk::Semaphore[buffers]; - for (int i = 0; i < buffers; i++) - { - cmdPools[i] = this->device.createCommandPool({ {}, context->device->queueIndices.transfer }); - cmdBuffers[i] = this->device.allocateCommandBuffers({ cmdPools[i], vk::CommandBufferLevel::ePrimary, 1 })[0]; - semaphores[i] = this->device.createSemaphore({}); - } toFree.resize(buffers); transferQueue = this->device.getQueue(context->device->queueIndices.transfer, 0); @@ -81,15 +97,7 @@ namespace OpenVulkano::Vulkan void ResourceManager::Close() { transferQueue.waitIdle(); - for (int i = 0; i < buffers; i++) - { - device.freeCommandBuffers(cmdPools[i], 1, &cmdBuffers[i]); - device.destroyCommandPool(cmdPools[i]); - device.destroy(semaphores[i]); - } - cmdPools = nullptr; - cmdBuffers = nullptr; - semaphores = nullptr; + transferQueue = nullptr; geometries.clear(); nodes.clear(); device.destroyDescriptorPool(descriptorPool); @@ -103,26 +111,25 @@ namespace OpenVulkano::Vulkan } samplerCache.clear(); shaders.clear(); - cmdBuffers = nullptr; - cmdPools = nullptr; - transferQueue = nullptr; device = nullptr; } + vk::CommandBuffer& ResourceManager::GetCmdBuffer() { return frameResources[currentBuffer].cmdBuffer; } + void ResourceManager::StartFrame(uint64_t frameId) { currentBuffer = frameId; FreeBuffers(); - device.resetCommandPool(cmdPools[currentBuffer], {}); - cmdBuffers[currentBuffer].begin({ vk::CommandBufferUsageFlagBits::eOneTimeSubmit }); + device.resetCommandPool(frameResources[currentBuffer].cmdPool, {}); + GetCmdBuffer().begin({ vk::CommandBufferUsageFlagBits::eOneTimeSubmit }); } vk::Semaphore ResourceManager::EndFrame() { - cmdBuffers[currentBuffer].end(); - vk::SubmitInfo si = { 0, nullptr, nullptr, 1, &cmdBuffers[currentBuffer], 1, &semaphores[currentBuffer] }; + GetCmdBuffer().end(); + vk::SubmitInfo si = { 0, nullptr, nullptr, 1, &frameResources[currentBuffer].cmdBuffer, 1, &frameResources[currentBuffer].semaphore }; transferQueue.submit(1, &si, vk::Fence()); - return semaphores[currentBuffer]; + return frameResources[currentBuffer].semaphore; } void ResourceManager::Resize() @@ -254,7 +261,7 @@ namespace OpenVulkano::Vulkan void ResourceManager::RemoveShader(VulkanShader* shader) { - if (!cmdPools) return; + if (!transferQueue) return; const std::unique_lock lock(mutex); std::vector>::iterator object = find_if(shaders.begin(), shaders.end(), @@ -296,27 +303,15 @@ namespace OpenVulkano::Vulkan ManagedBuffer* uploadBuffer = CreateBuffer(size, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible); uploadBuffer->Copy(data, size, 0); - image->SetLayout(cmdBuffers[currentBuffer], vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eTransferDstOptimal); + image->SetLayout(GetCmdBuffer(), vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eTransferDstOptimal); vk::BufferImageCopy region(0, 0, 0, { vk::ImageAspectFlagBits::eColor, 0, 0, 1 }, { 0, 0, 0 }, image->extent); - cmdBuffers[currentBuffer].copyBufferToImage(uploadBuffer->buffer, image->image, vk::ImageLayout::eTransferDstOptimal, 1, ®ion); + GetCmdBuffer().copyBufferToImage(uploadBuffer->buffer, image->image, vk::ImageLayout::eTransferDstOptimal, 1, ®ion); - /*vk::ImageMemoryBarrier barrier {}; - barrier.oldLayout = vk::ImageLayout::eUndefined; - barrier.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal; - barrier.image = image->image; - barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor; - barrier.subresourceRange.baseMipLevel = 0; - barrier.subresourceRange.levelCount = 1; - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = 1; - barrier.setSrcAccessMask({}); - barrier.setDstAccessMask(vk::AccessFlagBits::eTransferWrite);*/ - - image->SetLayout(cmdBuffers[currentBuffer], vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eShaderReadOnlyOptimal, vk::ImageLayout::eTransferDstOptimal); + image->SetLayout(GetCmdBuffer(), vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eShaderReadOnlyOptimal, vk::ImageLayout::eTransferDstOptimal); // TODO set access masks for mip and array layers - //cmdBuffers[currentBuffer].pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, 0, nullptr, 0, nullptr, 1, &barrier ); + //GetCmdBuffer().pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, 0, nullptr, 0, nullptr, 1, &barrier ); FreeBuffer(uploadBuffer); } diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp index 27f27c1..a3716df 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp @@ -49,12 +49,12 @@ namespace OpenVulkano friend UniformBuffer; friend VulkanTexture; + struct FrameResources; + Context* context; vk::Device device = nullptr; vk::Queue transferQueue = nullptr; - vk::CommandPool* cmdPools = nullptr; - vk::CommandBuffer* cmdBuffers = nullptr; - vk::Semaphore* semaphores = nullptr; + Array frameResources; std::vector> allocations; std::vector> shaders; std::vector> geometries; @@ -68,7 +68,9 @@ namespace OpenVulkano std::map descriptorSetLayoutCache; std::map samplerCache; - int buffers = -1, currentBuffer = -1; + int currentBuffer = -1; + + vk::CommandBuffer& GetCmdBuffer(); public: static ResourceManager* INSTANCE; @@ -122,10 +124,10 @@ namespace OpenVulkano ManagedBuffer* CreateDeviceOnlyBufferWithData(vk::DeviceSize size, vk::BufferUsageFlagBits usage, const void* data); - inline void RecordCopy(vk::Buffer src, vk::Buffer dest, vk::DeviceSize size) const + inline void RecordCopy(vk::Buffer src, vk::Buffer dest, vk::DeviceSize size) { vk::BufferCopy copyRegion = { 0, 0, size }; - cmdBuffers[currentBuffer].copyBuffer(src, dest, 1, ©Region); + GetCmdBuffer().copyBuffer(src, dest, 1, ©Region); } ManagedBuffer* CreateBuffer(vk::DeviceSize size, const vk::BufferUsageFlags& usage, const vk::MemoryPropertyFlags& properties); From 22cb48be89edab597a59aab79b3d871a8e37d8e2 Mon Sep 17 00:00:00 2001 From: Georg Hagen Date: Thu, 11 Jul 2024 00:10:48 +0200 Subject: [PATCH 04/10] Update logging --- openVulkanoCpp/Host/GLFW/WindowGLFW.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/openVulkanoCpp/Host/GLFW/WindowGLFW.cpp b/openVulkanoCpp/Host/GLFW/WindowGLFW.cpp index 03f15e1..6525988 100644 --- a/openVulkanoCpp/Host/GLFW/WindowGLFW.cpp +++ b/openVulkanoCpp/Host/GLFW/WindowGLFW.cpp @@ -253,7 +253,11 @@ namespace OpenVulkano::GLFW vk::SurfaceKHR WindowGLFW::CreateSurface(const vk::Instance& instance, const vk::AllocationCallbacks* pAllocator) { VkSurfaceKHR rawSurface; - const auto result = static_cast(glfwCreateWindowSurface(static_cast(instance), window, reinterpret_cast(pAllocator), &rawSurface)); + const vk::Result result = static_cast(glfwCreateWindowSurface(static_cast(instance), window, reinterpret_cast(pAllocator), &rawSurface)); + if (result != vk::Result::eSuccess) [[unlikely]] + { + Logger::WINDOW->error("Failed to create vulkan surface. Result: {}", vk::to_string(result)); + } return rawSurface;//createResultValue(result, rawSurface, "vk::CommandBuffer::begin"); } @@ -282,19 +286,19 @@ namespace OpenVulkano::GLFW void WindowGLFW::OnFocusLost() { - Logger::WINDOW->debug("Window (id: {0}) focus lost", GetWindowId()); + Logger::WINDOW->trace("Window (id: {0}) focus lost", GetWindowId()); handler->OnWindowFocusLost(this); } void WindowGLFW::OnFocusGained() { - Logger::WINDOW->debug("Window (id: {0}) focus gained", GetWindowId()); + Logger::WINDOW->trace("Window (id: {0}) focus gained", GetWindowId()); handler->OnWindowFocusGained(this); } void WindowGLFW::OnMove(const int posX, const int posY) { - Logger::WINDOW->debug("Window (id: {0}) moved (x: {1}, y: {2})", GetWindowId(), posX, posY); + Logger::WINDOW->trace("Window (id: {0}) moved (x: {1}, y: {2})", GetWindowId(), posX, posY); if (windowConfig.windowMode == WINDOWED || windowConfig.windowMode == BORDERLESS) { // Don't save window position for fullscreen windowConfig.position.x = posX; From 313b01db1b81326467cc0e20609e1c8d6a233f33 Mon Sep 17 00:00:00 2001 From: Georg Hagen Date: Thu, 11 Jul 2024 13:22:01 +0200 Subject: [PATCH 05/10] Fix issue with freeing resources --- openVulkanoCpp/Vulkan/Context.cpp | 2 + openVulkanoCpp/Vulkan/Device.cpp | 2 + openVulkanoCpp/Vulkan/Device.hpp | 2 + openVulkanoCpp/Vulkan/DeviceManager.hpp | 5 +- openVulkanoCpp/Vulkan/Renderer.cpp | 8 +- .../Vulkan/Resources/ManagedBuffer.hpp | 6 +- .../Vulkan/Resources/MemoryPool.cpp | 140 ++++++++++++++++ .../Vulkan/Resources/MemoryPool.hpp | 64 ++++++++ .../Vulkan/Resources/ResourceManager.cpp | 152 ++++-------------- .../Vulkan/Resources/ResourceManager.hpp | 35 ++-- .../Vulkan/Resources/UniformBuffer.cpp | 10 +- .../Vulkan/Resources/UniformBuffer.hpp | 7 +- openVulkanoCpp/Vulkan/Scene/VulkanCamera.hpp | 5 + .../Vulkan/Scene/VulkanGeometry.hpp | 4 +- openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp | 5 + openVulkanoCpp/Vulkan/SwapChain.cpp | 9 +- 16 files changed, 300 insertions(+), 156 deletions(-) create mode 100644 openVulkanoCpp/Vulkan/Resources/MemoryPool.cpp create mode 100644 openVulkanoCpp/Vulkan/Resources/MemoryPool.hpp diff --git a/openVulkanoCpp/Vulkan/Context.cpp b/openVulkanoCpp/Vulkan/Context.cpp index b430379..308256a 100644 --- a/openVulkanoCpp/Vulkan/Context.cpp +++ b/openVulkanoCpp/Vulkan/Context.cpp @@ -50,6 +50,8 @@ namespace OpenVulkano::Vulkan //TODO if (enableValidationLayer) Debug::CloseValidationLayers(instance); + + instance.destroy(); initialized = false; } diff --git a/openVulkanoCpp/Vulkan/Device.cpp b/openVulkanoCpp/Vulkan/Device.cpp index 6080108..deb58a1 100644 --- a/openVulkanoCpp/Vulkan/Device.cpp +++ b/openVulkanoCpp/Vulkan/Device.cpp @@ -230,6 +230,8 @@ namespace OpenVulkano::Vulkan void Device::Close() { device.destroyCommandPool(graphicsCommandPool); + device.destroyPipelineCache(pipelineCache); + device.destroy(); //TODO fill } } diff --git a/openVulkanoCpp/Vulkan/Device.hpp b/openVulkanoCpp/Vulkan/Device.hpp index a951c1e..6a26226 100644 --- a/openVulkanoCpp/Vulkan/Device.hpp +++ b/openVulkanoCpp/Vulkan/Device.hpp @@ -45,6 +45,8 @@ namespace OpenVulkano public: Device(vk::PhysicalDevice& physicalDevice); + ~Device() { if (device) Close(); } + [[nodiscard]] std::string GetDeviceName() const { return properties.deviceName.data(); diff --git a/openVulkanoCpp/Vulkan/DeviceManager.hpp b/openVulkanoCpp/Vulkan/DeviceManager.hpp index a19bf46..93fa321 100644 --- a/openVulkanoCpp/Vulkan/DeviceManager.hpp +++ b/openVulkanoCpp/Vulkan/DeviceManager.hpp @@ -26,7 +26,10 @@ namespace OpenVulkano::Vulkan Init(instance); } - ~DeviceManager() = default; + ~DeviceManager() + { + if (!devices.empty()) Close(); + } void Init(const vk::Instance& instance); diff --git a/openVulkanoCpp/Vulkan/Renderer.cpp b/openVulkanoCpp/Vulkan/Renderer.cpp index 1514fc4..bdc3189 100644 --- a/openVulkanoCpp/Vulkan/Renderer.cpp +++ b/openVulkanoCpp/Vulkan/Renderer.cpp @@ -72,9 +72,15 @@ namespace OpenVulkano::Vulkan void Renderer::Close() { + context.device->WaitIdle(); + for (int i = 0; i < context.swapChain.GetImageCount(); i++) + { + //context.device->device.destroySemaphore(waitSemaphores[i]); + } + uiRenderer.Close(); resourceManager.Close(); context.Close(); - uiRenderer.Close(); + scene = nullptr; } std::string Renderer::GetMainRenderDeviceName() diff --git a/openVulkanoCpp/Vulkan/Resources/ManagedBuffer.hpp b/openVulkanoCpp/Vulkan/Resources/ManagedBuffer.hpp index fa0f9a6..86c1629 100644 --- a/openVulkanoCpp/Vulkan/Resources/ManagedBuffer.hpp +++ b/openVulkanoCpp/Vulkan/Resources/ManagedBuffer.hpp @@ -9,14 +9,16 @@ #define CRASH_ON_MULTIPLE_MAPPINGS_TO_SAME_ALLOCATION #include "MemoryAllocation.hpp" +#include "MemoryPool.hpp" #include #include namespace OpenVulkano::Vulkan { - struct ManagedBuffer + class ManagedBuffer { - using Ptr = std::unique_ptr>; + public: + using Ptr = std::unique_ptr; MemoryAllocation* allocation; vk::DeviceSize offset, size; diff --git a/openVulkanoCpp/Vulkan/Resources/MemoryPool.cpp b/openVulkanoCpp/Vulkan/Resources/MemoryPool.cpp new file mode 100644 index 0000000..3194984 --- /dev/null +++ b/openVulkanoCpp/Vulkan/Resources/MemoryPool.cpp @@ -0,0 +1,140 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include "MemoryPool.hpp" +#include "ManagedBuffer.hpp" +#include "Vulkan/Device.hpp" +#include "Base/Logger.hpp" +#include "Math/ByteSize.hpp" + +namespace OpenVulkano::Vulkan +{ + namespace + { + std::vector MEM_POOLS; + } + + void MemoryPool::ReleaseBuffer(OpenVulkano::Vulkan::ManagedBuffer* buffer) + { + for (MemoryPool* memPool : MEM_POOLS) + { + if (memPool->FreeBuffer(buffer)) return; + } + delete buffer; + } + + MemoryPool::MemoryPool() + { + freeFunction = [this](ManagedBuffer* buffer) { this->FreeBuffer(buffer); }; + MEM_POOLS.push_back(this); + Logger::RENDER->info("Created gpu memory pool"); + } + + MemoryPool::~MemoryPool() + { + Utils::Remove(MEM_POOLS, this); + Logger::RENDER->info("Destroyed gpu memory pool"); + } + + void MemoryPool::Init(Device* dev, int bufferCount) + { + device = dev; + toFree = decltype(toFree)(bufferCount); + } + + void MemoryPool::StartFrame(uint64_t bufferId) + { + currentBuffer = bufferId; + for (ManagedBuffer* i : toFree[currentBuffer]) + { + DoFree(i); + } + toFree[currentBuffer].clear(); + } + + void MemoryPool::DoFree(ManagedBuffer* buffer) + { + if (buffer->IsLast()) + { + device->device.destroyBuffer(buffer->buffer); + buffer->allocation->used -= buffer->size; + } + else + { + recycleBuffers.push_back(buffer); + } + } + + bool MemoryPool::FreeBuffer(ManagedBuffer* buffer) + { + if (buffer) toFree[currentBuffer].push_back(buffer); + + return true; + } + + MemoryAllocation* MemoryPool::CreateMemoryAllocation(size_t size, uint32_t type, bool addToCache) + { + MemoryAllocation* alloc = new MemoryAllocation(size, type, device->device); + const vk::MemoryAllocateInfo allocInfo = { size, type }; + alloc->memory = device->device.allocateMemory(allocInfo); + if (addToCache) allocations.emplace_back(alloc); + return alloc; + } + + MemoryAllocation* MemoryPool::GetFreeMemoryAllocation(size_t size, vk::DeviceSize alignment, uint32_t type, bool createIfAllFull) + { + MemoryAllocation* alloc = nullptr; + for (auto& allocation : allocations) + { + if (allocation->type == type && allocation->FreeSpace(alignment) >= size) + { + alloc = allocation.get(); + break; + } + } + if(!alloc && createIfAllFull) alloc = CreateMemoryAllocation(64_MiB, type, true); + return alloc; + } + + MemoryPool::ManagedBufferPtr MemoryPool::CreateBuffer(vk::DeviceSize size, const vk::BufferUsageFlags& usage, const vk::MemoryPropertyFlags& properties) + { + size = Utils::Align(size, 16); + vk::BufferCreateInfo bufferCreateInfo = { {}, size, usage, vk::SharingMode::eExclusive }; + vk::Buffer buffer = device->device.createBuffer(bufferCreateInfo); + const vk::MemoryRequirements memoryRequirements = device->device.getBufferMemoryRequirements(buffer); + uint32_t memtype = device->GetMemoryType(memoryRequirements.memoryTypeBits, properties); + if (memoryRequirements.size != size) + { + Logger::DATA->debug("Memory Requirement Size ({0}) != Size ({1})", memoryRequirements.size, size); + size = memoryRequirements.size; + device->device.destroy(buffer); + bufferCreateInfo.size = size; + buffer = device->device.createBuffer(bufferCreateInfo); + } + MemoryAllocation* allocation = GetFreeMemoryAllocation(size, memoryRequirements.alignment, memtype); + uint32_t offset = Utils::Align(allocation->used, memoryRequirements.alignment); + device->device.bindBufferMemory(buffer, allocation->memory, offset); + allocation->used += size + (offset - allocation->used); + return ManagedBufferPtr{ new ManagedBuffer({allocation, offset, size, buffer, usage, properties, nullptr}) }; + } + + MemoryPool::ManagedBufferPtr MemoryPool::CreateSharedMemoryBuffer(size_t size) + { + if (!recycleBuffers.empty()) + { + for(auto buff : recycleBuffers) + { + if (buff->size == size) + { + Logger::DATA->info("Recycle Buffer"); + Utils::Remove(recycleBuffers, buff); + return ManagedBufferPtr{ buff }; + } + } + } + return CreateBuffer(size, vk::BufferUsageFlagBits::eVertexBuffer, vk::MemoryPropertyFlagBits::eHostCoherent/* | vk::MemoryPropertyFlagBits::eDeviceLocal*/); + } +} diff --git a/openVulkanoCpp/Vulkan/Resources/MemoryPool.hpp b/openVulkanoCpp/Vulkan/Resources/MemoryPool.hpp new file mode 100644 index 0000000..26530f4 --- /dev/null +++ b/openVulkanoCpp/Vulkan/Resources/MemoryPool.hpp @@ -0,0 +1,64 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "Data/Containers/Array.hpp" +#include +#include +#include +#include + +namespace OpenVulkano::Vulkan +{ + class Device; + class MemoryAllocation; + class ManagedBuffer; + struct ManagedBufferDeleter; + + class MemoryPool + { + Device* device; + std::vector> allocations; + Array> toFree; + std::vector recycleBuffers; + std::function freeFunction; + + uint64_t currentBuffer = 0; + + void DoFree(ManagedBuffer* buffer); + + bool FreeBuffer(ManagedBuffer* buffer); + public: + using ManagedBufferPtr = std::unique_ptr; + + MemoryPool(); + + ~MemoryPool(); + + void Init(Device* dev, int bufferCount); + + void StartFrame(uint64_t bufferId); + + MemoryAllocation* CreateMemoryAllocation(size_t size, uint32_t type, bool addToCache = true); + + MemoryAllocation* GetFreeMemoryAllocation(size_t size, vk::DeviceSize alignment, uint32_t type, bool createIfAllFull = true); + + ManagedBufferPtr CreateBuffer(vk::DeviceSize size, const vk::BufferUsageFlags& usage, const vk::MemoryPropertyFlags& properties); + + ManagedBufferPtr CreateSharedMemoryBuffer(size_t size); + + static void ReleaseBuffer(ManagedBuffer* buffer); + }; + + struct ManagedBufferDeleter + { + void operator()(ManagedBuffer* buffer) + { + MemoryPool::ReleaseBuffer(buffer); + } + }; +} \ No newline at end of file diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp index 6e3075c..5e03db3 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp @@ -53,7 +53,6 @@ namespace OpenVulkano::Vulkan ResourceManager::ResourceManager() { static_assert(sizeof(DescriptorSetLayoutBinding) == sizeof(vk::DescriptorSetLayoutBinding)); - freeFunction = [this](ManagedBuffer* buffer) { this->FreeBuffer(buffer); }; } ResourceManager::~ResourceManager() noexcept @@ -70,7 +69,7 @@ namespace OpenVulkano::Vulkan frameResources = Array(static_cast(buffers), context->device.get()); - toFree.resize(buffers); + memPool.Init(context->device.get(), buffers); transferQueue = this->device.getQueue(context->device->queueIndices.transfer, 0); @@ -100,16 +99,20 @@ namespace OpenVulkano::Vulkan transferQueue = nullptr; geometries.clear(); nodes.clear(); + textures.clear(); + cameras.clear(); + uniforms.clear(); device.destroyDescriptorPool(descriptorPool); - allocations.clear(); - toFree.clear(); - recycleBuffers.clear(); - descriptorSetLayoutCache.clear(); for (auto& sampler : samplerCache) { device.destroy(sampler.second); } samplerCache.clear(); + for(auto& layout : descriptorSetLayoutCache) + { + device.destroy(layout.second); + } + descriptorSetLayoutCache.clear(); shaders.clear(); device = nullptr; } @@ -119,7 +122,7 @@ namespace OpenVulkano::Vulkan void ResourceManager::StartFrame(uint64_t frameId) { currentBuffer = frameId; - FreeBuffers(); + memPool.StartFrame(frameId); device.resetCommandPool(frameResources[currentBuffer].cmdPool, {}); GetCmdBuffer().begin({ vk::CommandBufferUsageFlagBits::eOneTimeSubmit }); } @@ -145,12 +148,10 @@ namespace OpenVulkano::Vulkan const std::unique_lock lock(mutex); if(!geometry->renderGeo) { - ManagedBuffer::Ptr vertexBuffer( - CreateDeviceOnlyBufferWithData(sizeof(Vertex) * geometry->GetVertexCount(), vk::BufferUsageFlagBits::eVertexBuffer, geometry->GetVertices()), - freeFunction); - ManagedBuffer::Ptr indexBuffer( - CreateDeviceOnlyBufferWithData(Utils::EnumAsInt(geometry->indexType) * geometry->GetIndexCount(), vk::BufferUsageFlagBits::eIndexBuffer, geometry->GetIndices()), - freeFunction); + ManagedBuffer::Ptr vertexBuffer = + CreateDeviceOnlyBufferWithData(sizeof(Vertex) * geometry->GetVertexCount(), vk::BufferUsageFlagBits::eVertexBuffer, geometry->GetVertices()); + ManagedBuffer::Ptr indexBuffer = + CreateDeviceOnlyBufferWithData(Utils::EnumAsInt(geometry->indexType) * geometry->GetIndexCount(), vk::BufferUsageFlagBits::eIndexBuffer, geometry->GetIndices()); VulkanGeometry* vkGeo = new VulkanGeometry(geometry, vertexBuffer, indexBuffer); geometries.emplace_back(vkGeo); geometry->renderGeo = vkGeo; @@ -173,7 +174,7 @@ namespace OpenVulkano::Vulkan if (!node->renderNode) { UniformBuffer* uBuffer = new UniformBuffer(); - ManagedBuffer* buffer; + ManagedBuffer::Ptr buffer; VulkanNode* vkNode; const vk::DeviceSize allocSize = Utils::Align(sizeof(Math::Matrix4f), uniformBufferAlignment); vk::DeviceSize frameSize = 0; @@ -182,7 +183,7 @@ namespace OpenVulkano::Vulkan frameSize = allocSize; vkNode = new VulkanNodeDynamic(); const uint32_t imgs = context->swapChain.GetImageCount(); - buffer = CreateBuffer(imgs * allocSize, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible); + buffer = memPool.CreateBuffer(imgs * allocSize, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible); buffer->Map(); } else @@ -191,7 +192,7 @@ namespace OpenVulkano::Vulkan buffer = CreateDeviceOnlyBufferWithData(Scene::Node::SIZE, vk::BufferUsageFlagBits::eUniformBuffer, &node->worldMat); } - uBuffer->Init(buffer, frameSize, allocSize, GetDescriptorLayoutSet(Scene::Node::DESCRIPTOR_SET_LAYOUT_BINDING), Scene::Node::DESCRIPTOR_SET_LAYOUT_BINDING, 0); + uBuffer->Init(std::move(buffer), frameSize, allocSize, GetDescriptorLayoutSet(Scene::Node::DESCRIPTOR_SET_LAYOUT_BINDING), Scene::Node::DESCRIPTOR_SET_LAYOUT_BINDING, 0); vkNode->Init(node, uBuffer); node->renderNode = vkNode; nodes.emplace_back(vkNode); @@ -206,12 +207,13 @@ namespace OpenVulkano::Vulkan { const vk::DeviceSize allocSize = Utils::Align(Scene::Camera::SIZE, uniformBufferAlignment); const uint32_t imgs = context->swapChain.GetImageCount(); - ManagedBuffer* buffer = CreateBuffer(imgs * allocSize, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible); + ManagedBuffer::Ptr buffer = memPool.CreateBuffer(imgs * allocSize, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible); buffer->Map(); UniformBuffer* uBuffer = new UniformBuffer(); - uBuffer->Init(buffer, allocSize, allocSize, GetDescriptorLayoutSet(Scene::Camera::DESCRIPTOR_SET_LAYOUT_BINDING), Scene::Camera::DESCRIPTOR_SET_LAYOUT_BINDING, 1); + uBuffer->Init(std::move(buffer), allocSize, allocSize, GetDescriptorLayoutSet(Scene::Camera::DESCRIPTOR_SET_LAYOUT_BINDING), Scene::Camera::DESCRIPTOR_SET_LAYOUT_BINDING, 1); VulkanCamera* vkCam = new VulkanCamera(); vkCam->Init(camera, uBuffer); + cameras.emplace_back(vkCam); camera->renderCamera = vkCam; } return static_cast(camera->renderCamera); @@ -225,7 +227,7 @@ namespace OpenVulkano::Vulkan auto buffer = CreateDeviceOnlyBufferWithData(allocSize, vk::BufferUsageFlagBits::eUniformBuffer, data); UniformBuffer* uBuffer = new UniformBuffer(); - uBuffer->Init(buffer, 0, allocSize, GetDescriptorLayoutSet(binding), binding, setId); + uBuffer->Init(std::move(buffer), 0, allocSize, GetDescriptorLayoutSet(binding), binding, setId); return uBuffer; } @@ -240,23 +242,10 @@ namespace OpenVulkano::Vulkan return &layout; } - ManagedBuffer* ResourceManager::CreateSharedMemoryBuffer(const size_t size) + MemoryPool::ManagedBufferPtr ResourceManager::CreateSharedMemoryBuffer(const size_t size) { const std::unique_lock lock(mutex); - if (!recycleBuffers.empty()) - { - for(auto buff : recycleBuffers) - { - if (buff->size == size) - { - Logger::DATA->info("Recycle Buffer"); - Utils::Remove(recycleBuffers, buff); - return buff; - } - } - } - ManagedBuffer* buffer = CreateBuffer(size, vk::BufferUsageFlagBits::eVertexBuffer, vk::MemoryPropertyFlagBits::eHostCoherent/* | vk::MemoryPropertyFlagBits::eDeviceLocal*/); - return buffer; + return memPool.CreateSharedMemoryBuffer(size); } void ResourceManager::RemoveShader(VulkanShader* shader) @@ -270,37 +259,9 @@ namespace OpenVulkano::Vulkan shaders.erase(object); } - void ResourceManager::FreeBuffer(ManagedBuffer* buffer) - { - if (buffer) - toFree[currentBuffer].push_back(buffer); - } - - void ResourceManager::DoFreeBuffer(ManagedBuffer* buffer) - { - if (buffer->IsLast()) - { - device.destroyBuffer(buffer->buffer); - buffer->allocation->used -= buffer->size; - } - else - { - recycleBuffers.push_back(buffer); - } - } - - void ResourceManager::FreeBuffers() - { - for (auto& i : toFree[currentBuffer]) - { - DoFreeBuffer(i); - } - toFree[currentBuffer].clear(); - } - void ResourceManager::CopyDataToImage(vk::DeviceSize size, void* data, Image* image) { - ManagedBuffer* uploadBuffer = CreateBuffer(size, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible); + ManagedBuffer::Ptr uploadBuffer = memPool.CreateBuffer(size, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible); uploadBuffer->Copy(data, size, 0); image->SetLayout(GetCmdBuffer(), vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eTransferDstOptimal); @@ -312,66 +273,17 @@ namespace OpenVulkano::Vulkan // TODO set access masks for mip and array layers //GetCmdBuffer().pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, 0, nullptr, 0, nullptr, 1, &barrier ); - - FreeBuffer(uploadBuffer); } - ManagedBuffer* ResourceManager::CreateDeviceOnlyBufferWithData(vk::DeviceSize size, vk::BufferUsageFlagBits usage, const void* data) + ManagedBuffer::Ptr ResourceManager::CreateDeviceOnlyBufferWithData(vk::DeviceSize size, vk::BufferUsageFlagBits usage, const void* data) { - ManagedBuffer* target = CreateBuffer(size, usage | vk::BufferUsageFlagBits::eTransferDst, vk::MemoryPropertyFlagBits::eDeviceLocal); - ManagedBuffer* uploadBuffer = CreateBuffer(size, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible); + ManagedBuffer::Ptr target = memPool.CreateBuffer(size, usage | vk::BufferUsageFlagBits::eTransferDst, vk::MemoryPropertyFlagBits::eDeviceLocal); + ManagedBuffer::Ptr uploadBuffer = memPool.CreateBuffer(size, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible); uploadBuffer->Copy(data, size, 0); RecordCopy(uploadBuffer->buffer, target->buffer, size); - FreeBuffer(uploadBuffer); return target; } - ManagedBuffer* ResourceManager::CreateBuffer(vk::DeviceSize size, const vk::BufferUsageFlags& usage, const vk::MemoryPropertyFlags& properties) - { - size = Utils::Align(size, 16); - vk::BufferCreateInfo bufferCreateInfo = { {}, size, usage, vk::SharingMode::eExclusive }; - vk::Buffer buffer = device.createBuffer(bufferCreateInfo); - const vk::MemoryRequirements memoryRequirements = device.getBufferMemoryRequirements(buffer); - uint32_t memtype = context->device->GetMemoryType(memoryRequirements.memoryTypeBits, properties); - if (memoryRequirements.size != size) - { - Logger::DATA->debug("Memory Requirement Size ({0}) != Size ({1})", memoryRequirements.size, size); - size = memoryRequirements.size; - device.destroy(buffer); - bufferCreateInfo.size = size; - buffer = device.createBuffer(bufferCreateInfo); - } - MemoryAllocation* allocation = GetFreeMemoryAllocation(size, memoryRequirements.alignment, memtype); - uint32_t offset = Utils::Align(allocation->used, memoryRequirements.alignment); - device.bindBufferMemory(buffer, allocation->memory, offset); - allocation->used += size + (offset - allocation->used); - return new ManagedBuffer{ allocation, offset, size, buffer, usage, properties, nullptr }; - } - - MemoryAllocation* ResourceManager::CreateMemoryAllocation(size_t size, uint32_t type, bool addToCache) - { - MemoryAllocation* alloc = new MemoryAllocation(size, type, device); - const vk::MemoryAllocateInfo allocInfo = { size, type }; - alloc->memory = device.allocateMemory(allocInfo); - if (addToCache) allocations.emplace_back(alloc); - return alloc; - } - - MemoryAllocation* ResourceManager::GetFreeMemoryAllocation(size_t size, vk::DeviceSize alignment, uint32_t type, bool createIfAllFull) - { - MemoryAllocation* alloc = nullptr; - for (auto& allocation : allocations) - { - if (allocation->type == type && allocation->FreeSpace(alignment) >= size) - { - alloc = allocation.get(); - break; - } - } - if(!alloc && createIfAllFull) alloc = CreateMemoryAllocation(64_MiB, type, true); - return alloc; - } - VulkanShader* ResourceManager::CreateShader(Scene::Shader* shader) { const std::unique_lock lock(mutex); @@ -394,6 +306,8 @@ namespace OpenVulkano::Vulkan vkTexture->Init(this, texture, GetDescriptorLayoutSet(Scene::Texture::DESCRIPTOR_SET_LAYOUT_BINDING), Scene::Texture::DESCRIPTOR_SET_LAYOUT_BINDING); + textures.emplace_back(vkTexture); + return vkTexture; } @@ -403,7 +317,7 @@ namespace OpenVulkano::Vulkan if (buffer->renderBuffer) return static_cast(buffer->renderBuffer); VulkanUniformBuffer* vkBuffer; - ManagedBuffer* mBuffer; + ManagedBuffer::Ptr mBuffer; const vk::DeviceSize allocSize = Utils::Align(buffer->size, uniformBufferAlignment); vk::DeviceSize frameSize = 0; if (buffer->GetUpdateFrequency() != Scene::UpdateFrequency::Never) @@ -411,7 +325,7 @@ namespace OpenVulkano::Vulkan frameSize = allocSize; vkBuffer = new VulkanUniformBufferDynamic(); const uint32_t imgs = context->swapChain.GetImageCount(); - mBuffer = CreateBuffer(imgs * allocSize, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible); + mBuffer = memPool.CreateBuffer(imgs * allocSize, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible); mBuffer->Map(); } else @@ -423,9 +337,11 @@ namespace OpenVulkano::Vulkan UniformBuffer* uBuffer = new UniformBuffer(); - uBuffer->Init(mBuffer, 0, mBuffer->size, GetDescriptorLayoutSet(buffer->binding), buffer->binding, buffer->setId); + const uint64_t s = mBuffer->size; + uBuffer->Init(std::move(mBuffer), 0, s, GetDescriptorLayoutSet(buffer->binding), buffer->binding, buffer->setId); vkBuffer->Init(buffer, uBuffer); + uniforms.emplace_back(vkBuffer); return vkBuffer; } diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp index a3716df..fe75424 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp @@ -7,13 +7,16 @@ #pragma once // Workaround for libc++ +#ifndef __cpp_lib_three_way_comparison #define __cpp_lib_three_way_comparison 201907 +#endif #include "IShaderOwner.hpp" +#include "MemoryPool.hpp" +#include "Base/Wrapper.hpp" #include "Vulkan/Image.hpp" #include "Scene/Shader/DescriptorInputDescription.hpp" #include -#include #include #include #include @@ -55,15 +58,15 @@ namespace OpenVulkano vk::Device device = nullptr; vk::Queue transferQueue = nullptr; Array frameResources; - std::vector> allocations; - std::vector> shaders; - std::vector> geometries; - std::vector> nodes; + MemoryPool memPool; + std::vector> shaders; + std::vector> geometries; + std::vector> nodes; + std::vector> textures; + std::vector> cameras; + std::vector> uniforms; std::mutex mutex; vk::DeviceSize uniformBufferAlignment; - std::vector> toFree; - std::vector recycleBuffers; - std::function freeFunction; vk::DescriptorPool descriptorPool; std::map descriptorSetLayoutCache; std::map samplerCache; @@ -105,9 +108,7 @@ namespace OpenVulkano void CopyDataToImage(vk::DeviceSize size, void* data, OpenVulkano::Vulkan::Image* image); - ManagedBuffer* CreateSharedMemoryBuffer(size_t size); - - void FreeBuffer(ManagedBuffer* buffer); + MemoryPool::ManagedBufferPtr CreateSharedMemoryBuffer(size_t size); [[nodiscard]] Context* GetContext() const { return context; } @@ -118,23 +119,13 @@ namespace OpenVulkano vk::Sampler CreateSampler(const vk::SamplerCreateInfo& samplerConfig); protected: // Allocation management - void DoFreeBuffer(ManagedBuffer* buffer); - - void FreeBuffers(); - - ManagedBuffer* CreateDeviceOnlyBufferWithData(vk::DeviceSize size, vk::BufferUsageFlagBits usage, const void* data); + MemoryPool::ManagedBufferPtr CreateDeviceOnlyBufferWithData(vk::DeviceSize size, vk::BufferUsageFlagBits usage, const void* data); inline void RecordCopy(vk::Buffer src, vk::Buffer dest, vk::DeviceSize size) { vk::BufferCopy copyRegion = { 0, 0, size }; GetCmdBuffer().copyBuffer(src, dest, 1, ©Region); } - - ManagedBuffer* CreateBuffer(vk::DeviceSize size, const vk::BufferUsageFlags& usage, const vk::MemoryPropertyFlags& properties); - - MemoryAllocation* CreateMemoryAllocation(size_t size, uint32_t type, bool addToCache = true); - - MemoryAllocation* GetFreeMemoryAllocation(size_t size, vk::DeviceSize alignment, uint32_t type, bool createIfAllFull = true); public: vk::DescriptorSetLayout* GetDescriptorLayoutSet(const DescriptorSetLayoutBinding& descriptorSetLayoutBinding); diff --git a/openVulkanoCpp/Vulkan/Resources/UniformBuffer.cpp b/openVulkanoCpp/Vulkan/Resources/UniformBuffer.cpp index cbfbd1f..dae0aa0 100644 --- a/openVulkanoCpp/Vulkan/Resources/UniformBuffer.cpp +++ b/openVulkanoCpp/Vulkan/Resources/UniformBuffer.cpp @@ -12,18 +12,18 @@ namespace OpenVulkano::Vulkan { - void UniformBuffer::Init(ManagedBuffer* buffer, uint32_t frameOffset, uint32_t frameSize, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding, uint32_t setId) + void UniformBuffer::Init(ManagedBuffer::Ptr buffer, uint32_t frameOffset, uint32_t frameSize, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding, uint32_t setId) { - m_buffer = buffer; + m_buffer = std::move(buffer); m_frameOffset = frameOffset; const vk::DescriptorSetAllocateInfo descSetAllocInfo = { ResourceManager::INSTANCE->descriptorPool, 1, descriptorSetLayout }; - m_descriptorSet = buffer->allocation->device.allocateDescriptorSets(descSetAllocInfo)[0]; - vk::DescriptorBufferInfo bufferInfo = { buffer->buffer, 0, frameSize }; + m_descriptorSet = m_buffer->allocation->device.allocateDescriptorSets(descSetAllocInfo)[0]; + vk::DescriptorBufferInfo bufferInfo = { m_buffer->buffer, 0, frameSize }; vk::WriteDescriptorSet writeDescriptorSet = { m_descriptorSet, binding.bindingId, 0, 1 }; writeDescriptorSet.descriptorType = static_cast(binding.descriptorType); writeDescriptorSet.pBufferInfo = &bufferInfo; - buffer->allocation->device.updateDescriptorSets(1, &writeDescriptorSet, 0, nullptr); + m_buffer->allocation->device.updateDescriptorSets(1, &writeDescriptorSet, 0, nullptr); m_setOffset = setId; m_dynamic = binding.descriptorType == DescriptorSetLayoutBinding::TYPE_UNIFORM_BUFFER_DYNAMIC || binding.descriptorType == DescriptorSetLayoutBinding::TYPE_STORAGE_BUFFER_DYNAMIC; } diff --git a/openVulkanoCpp/Vulkan/Resources/UniformBuffer.hpp b/openVulkanoCpp/Vulkan/Resources/UniformBuffer.hpp index 37528c0..656ae61 100644 --- a/openVulkanoCpp/Vulkan/Resources/UniformBuffer.hpp +++ b/openVulkanoCpp/Vulkan/Resources/UniformBuffer.hpp @@ -7,15 +7,16 @@ #pragma once #include "Base/ICloseable.hpp" +#include "Vulkan/Resources/ManagedBuffer.hpp" #include "Vulkan/Scene/IRecordable.hpp" namespace OpenVulkano::Vulkan { - struct ManagedBuffer; + class ManagedBuffer; class UniformBuffer final : public IRecordable, public ICloseable { - ManagedBuffer* m_buffer = nullptr; + ManagedBuffer::Ptr m_buffer = nullptr; vk::DescriptorSet m_descriptorSet; uint32_t m_frameOffset; uint32_t m_setOffset, m_setCount = 1; @@ -27,7 +28,7 @@ namespace OpenVulkano::Vulkan if (m_buffer) Close(); } - void Init(ManagedBuffer* buffer, uint32_t frameOffset, uint32_t frameSize, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding, uint32_t setId); + void Init(ManagedBuffer::Ptr buffer, uint32_t frameOffset, uint32_t frameSize, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding, uint32_t setId); void Close() override; diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanCamera.hpp b/openVulkanoCpp/Vulkan/Scene/VulkanCamera.hpp index 9c0a835..7996b4a 100644 --- a/openVulkanoCpp/Vulkan/Scene/VulkanCamera.hpp +++ b/openVulkanoCpp/Vulkan/Scene/VulkanCamera.hpp @@ -18,6 +18,8 @@ namespace OpenVulkano::Vulkan UniformBuffer* m_buffer = nullptr; public: + ~VulkanCamera() override { if (m_camera) VulkanCamera::Close(); } + void Init(Scene::Camera* camera, UniformBuffer* uniformBuffer) { m_camera = camera; @@ -32,7 +34,10 @@ namespace OpenVulkano::Vulkan void Close() override { + m_camera->renderCamera = nullptr; m_buffer->Close(); + m_camera = nullptr; + delete m_buffer; } }; } \ No newline at end of file diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanGeometry.hpp b/openVulkanoCpp/Vulkan/Scene/VulkanGeometry.hpp index db34fab..c96932b 100644 --- a/openVulkanoCpp/Vulkan/Scene/VulkanGeometry.hpp +++ b/openVulkanoCpp/Vulkan/Scene/VulkanGeometry.hpp @@ -22,8 +22,8 @@ namespace OpenVulkano::Vulkan vk::DeviceSize m_offsets = 0; public: - VulkanGeometry() : m_geometry(nullptr), m_vertexBuffer(nullptr, nullptr) - , m_indexBuffer(nullptr, nullptr), m_indexType(vk::IndexType::eUint32) + VulkanGeometry() : m_geometry(nullptr), m_vertexBuffer(nullptr) + , m_indexBuffer(nullptr), m_indexType(vk::IndexType::eUint32) {} VulkanGeometry(Scene::Geometry* geo, ManagedBuffer::Ptr& vertexBuffer, ManagedBuffer::Ptr& indexBuffer) diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp b/openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp index c41c2dc..1442434 100644 --- a/openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp +++ b/openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp @@ -37,6 +37,11 @@ namespace OpenVulkano::Vulkan texture->renderTexture = this; } + virtual ~VulkanTexture() override + { + if (m_texture) Close(); + } + void Close() override { Image::Close(); diff --git a/openVulkanoCpp/Vulkan/SwapChain.cpp b/openVulkanoCpp/Vulkan/SwapChain.cpp index a86ba33..eca6a43 100644 --- a/openVulkanoCpp/Vulkan/SwapChain.cpp +++ b/openVulkanoCpp/Vulkan/SwapChain.cpp @@ -10,7 +10,6 @@ #include "Base/UI/IVulkanWindow.hpp" #include "Base/EngineConfiguration.hpp" #include "Scene/DataFormat.hpp" -#include namespace OpenVulkano::Vulkan { @@ -25,13 +24,17 @@ namespace OpenVulkano::Vulkan CreateSwapChain({window->GetWidth(), window->GetHeight() }); FrameBuffer::Init(device, vk::Extent3D(size, 1)); + + Logger::RENDER->trace("Initialized swapchain"); } void SwapChain::Close() { + FrameBuffer::Close(); DestroySwapChain(); device = nullptr; - FrameBuffer::Close(); + window = nullptr; + Logger::RENDER->trace("Closed swapchain"); } void SwapChain::Resize(const uint32_t newWidth, const uint32_t newHeight) @@ -40,6 +43,7 @@ namespace OpenVulkano::Vulkan CreateSwapChain({ newWidth, newHeight }); FrameBuffer::Resize(vk::Extent3D(size, 1)); + Logger::RENDER->trace("Resized swapchain"); } uint32_t SwapChain::AcquireNextImage(const vk::Fence& fence) @@ -141,6 +145,7 @@ namespace OpenVulkano::Vulkan for (auto& semaphore : imageAvailableSemaphores) device->device.destroySemaphore(semaphore); imageAvailableSemaphores.clear(); + Logger::RENDER->trace("Destroyed swapchain"); } vk::PresentModeKHR SwapChain::ChosePresentMode() From 0fda5a02413150fa5ee9e669ec21d774204da5f1 Mon Sep 17 00:00:00 2001 From: Georg Hagen Date: Thu, 11 Jul 2024 16:54:37 +0200 Subject: [PATCH 06/10] Fix memory leak with events --- .../Host/iOS/NamedEventProcessor.mm | 44 ++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/openVulkanoCpp/Host/iOS/NamedEventProcessor.mm b/openVulkanoCpp/Host/iOS/NamedEventProcessor.mm index 1b12f3a..6e6227f 100644 --- a/openVulkanoCpp/Host/iOS/NamedEventProcessor.mm +++ b/openVulkanoCpp/Host/iOS/NamedEventProcessor.mm @@ -132,36 +132,40 @@ namespace OpenVulkano void NamedEventProcessor::Notify(const std::string& eventName, const std::vector& parameters) const { - if (Class eventClass = FindGenericEventClass(m_classNamePrefixes, m_classNameSuffixes, eventName)) + @autoreleasepool { - if (SEL init = GetInitForClass(eventClass, BuildTypeName(parameters))) + if (Class eventClass = FindGenericEventClass(m_classNamePrefixes, m_classNameSuffixes, eventName)) { - NSObject* event = [eventClass alloc]; - auto inv = [NSInvocation invocationWithMethodSignature:[event methodSignatureForSelector:init]]; - [inv setTarget:event]; - [inv setSelector:init]; - for (int i = 0; i < parameters.size(); i++) + if (SEL init = GetInitForClass(eventClass, BuildTypeName(parameters))) { - auto arg = std::visit([](auto&& arg) { return CreateValue(arg); }, parameters[i]); - [inv setArgument:&arg atIndex:(i + 2)]; + NSObject* event = [eventClass alloc]; + auto inv = [NSInvocation invocationWithMethodSignature:[event methodSignatureForSelector:init]]; + [inv setTarget:event]; + [inv setSelector:init]; + for (int i = 0; i < parameters.size(); i++) + { + auto arg = std::visit([](auto&& arg) { return CreateValue(arg); }, parameters[i]); + [inv setArgument:&arg atIndex:(i + 2)]; + } + [inv invoke]; + for (Class clazz = eventClass; clazz && clazz != NSObject.class; clazz = class_getSuperclass(clazz)) + { + NSString* notificationName; + if (m_useClassNameAsEventName) notificationName = NSStringFromClass(clazz); + else notificationName = [NSString stringWithUTF8String:eventName.c_str()]; + [[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:event userInfo:nil]; + } + [event release]; } - [inv invoke]; - for (Class clazz = eventClass; clazz && clazz != NSObject.class; clazz = class_getSuperclass(clazz)) + else { - NSString* notificationName; - if (m_useClassNameAsEventName) notificationName = NSStringFromClass(clazz); - else notificationName = [NSString stringWithUTF8String:eventName.c_str()]; - [[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:event userInfo:nil]; + Logger::MANAGER->error("Cannot find constructor for named event %s", eventName); } } else { - Logger::MANAGER->error("Cannot find constructor for named event %s", eventName); + Logger::MANAGER->debug("Cannot find implementation for named event %s", eventName); } } - else - { - Logger::MANAGER->debug("Cannot find implementation for named event %s", eventName); - } } } From 888e30193b392c08ae384f62eca4b867dc2522e7 Mon Sep 17 00:00:00 2001 From: Georg Hagen Date: Thu, 11 Jul 2024 16:56:26 +0200 Subject: [PATCH 07/10] Cleanup memory pool data on close --- .../Vulkan/Resources/MemoryPool.cpp | 27 ++++++++++++++----- .../Vulkan/Resources/MemoryPool.hpp | 4 ++- .../Vulkan/Resources/ResourceManager.cpp | 1 + 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/openVulkanoCpp/Vulkan/Resources/MemoryPool.cpp b/openVulkanoCpp/Vulkan/Resources/MemoryPool.cpp index 3194984..6fe32c5 100644 --- a/openVulkanoCpp/Vulkan/Resources/MemoryPool.cpp +++ b/openVulkanoCpp/Vulkan/Resources/MemoryPool.cpp @@ -26,16 +26,28 @@ namespace OpenVulkano::Vulkan delete buffer; } - MemoryPool::MemoryPool() - { - freeFunction = [this](ManagedBuffer* buffer) { this->FreeBuffer(buffer); }; - MEM_POOLS.push_back(this); - Logger::RENDER->info("Created gpu memory pool"); - } - MemoryPool::~MemoryPool() + { + if (!allocations.empty()) Close(); + } + + void MemoryPool::Close() { Utils::Remove(MEM_POOLS, this); + for(ManagedBuffer* buffer : recycleBuffers) + { + delete buffer; + } + recycleBuffers.clear(); + for(auto& fF : toFree) + { + for(ManagedBuffer* buffer : fF) + { + delete buffer; + } + fF.clear(); + } + allocations.clear(); Logger::RENDER->info("Destroyed gpu memory pool"); } @@ -43,6 +55,7 @@ namespace OpenVulkano::Vulkan { device = dev; toFree = decltype(toFree)(bufferCount); + MEM_POOLS.push_back(this); } void MemoryPool::StartFrame(uint64_t bufferId) diff --git a/openVulkanoCpp/Vulkan/Resources/MemoryPool.hpp b/openVulkanoCpp/Vulkan/Resources/MemoryPool.hpp index 26530f4..abd75df 100644 --- a/openVulkanoCpp/Vulkan/Resources/MemoryPool.hpp +++ b/openVulkanoCpp/Vulkan/Resources/MemoryPool.hpp @@ -35,12 +35,14 @@ namespace OpenVulkano::Vulkan public: using ManagedBufferPtr = std::unique_ptr; - MemoryPool(); + MemoryPool() = default; ~MemoryPool(); void Init(Device* dev, int bufferCount); + void Close(); + void StartFrame(uint64_t bufferId); MemoryAllocation* CreateMemoryAllocation(size_t size, uint32_t type, bool addToCache = true); diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp index 5e03db3..7aad414 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp @@ -114,6 +114,7 @@ namespace OpenVulkano::Vulkan } descriptorSetLayoutCache.clear(); shaders.clear(); + memPool.Close(); device = nullptr; } From 1d06e56c9e7ee396b331c5364305554dab8d1c95 Mon Sep 17 00:00:00 2001 From: Georg Hagen Date: Thu, 11 Jul 2024 16:56:52 +0200 Subject: [PATCH 08/10] Delete created semaphores on close --- openVulkanoCpp/Vulkan/Renderer.cpp | 8 +++++--- openVulkanoCpp/Vulkan/Renderer.hpp | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/openVulkanoCpp/Vulkan/Renderer.cpp b/openVulkanoCpp/Vulkan/Renderer.cpp index bdc3189..92b57a0 100644 --- a/openVulkanoCpp/Vulkan/Renderer.cpp +++ b/openVulkanoCpp/Vulkan/Renderer.cpp @@ -32,7 +32,9 @@ namespace OpenVulkano::Vulkan for (int i = 0; i < context.swapChain.GetImageCount(); i++) { waitSemaphores.emplace_back(); - waitSemaphores[i].renderComplete.push_back(context.device->device.createSemaphore({})); + vk::Semaphore sema = context.device->device.createSemaphore({}); + semaphores.push_back(sema); + waitSemaphores[i].renderComplete.push_back(sema); waitSemaphores[i].renderReady.resize(2); } resourceManager.Init(&context, context.swapChain.GetImageCount()); @@ -73,9 +75,9 @@ namespace OpenVulkano::Vulkan void Renderer::Close() { context.device->WaitIdle(); - for (int i = 0; i < context.swapChain.GetImageCount(); i++) + for (auto& sema : semaphores) { - //context.device->device.destroySemaphore(waitSemaphores[i]); + context.device->device.destroySemaphore(sema); } uiRenderer.Close(); resourceManager.Close(); diff --git a/openVulkanoCpp/Vulkan/Renderer.hpp b/openVulkanoCpp/Vulkan/Renderer.hpp index f981bae..39e1d2d 100644 --- a/openVulkanoCpp/Vulkan/Renderer.hpp +++ b/openVulkanoCpp/Vulkan/Renderer.hpp @@ -30,6 +30,7 @@ namespace OpenVulkano::Vulkan { Context context; std::shared_ptr logger; + std::vector semaphores; std::vector waitSemaphores; Scene::Scene* scene = nullptr; ResourceManager resourceManager; From a80c9b639e227867b5fef30ac2bbf93ab11da55e Mon Sep 17 00:00:00 2001 From: Georg Hagen Date: Thu, 11 Jul 2024 16:59:34 +0200 Subject: [PATCH 09/10] Log on destruction of OpenVulkanoView --- openVulkanoCpp/Host/iOS/OpenVulkanoView.mm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openVulkanoCpp/Host/iOS/OpenVulkanoView.mm b/openVulkanoCpp/Host/iOS/OpenVulkanoView.mm index c5f99e9..cd47b8a 100644 --- a/openVulkanoCpp/Host/iOS/OpenVulkanoView.mm +++ b/openVulkanoCpp/Host/iOS/OpenVulkanoView.mm @@ -6,6 +6,7 @@ #import "OpenVulkanoView.h" +#include "Base/Logger.hpp" #include "Input/Touch/InputDeviceTouch.hpp" #include "Input/InputManager.hpp" #include "MetalViewWindow.h" @@ -113,6 +114,7 @@ using namespace OpenVulkano; m_touchDevice.Close(); [m_displayLink release]; [m_mtdelegate release]; + OpenVulkano::Logger::WINDOW->info("Destroyed OpenVulkanoView"); [super dealloc]; } From ca052ef7f1cd7db022201a9df9cffda31855cd4d Mon Sep 17 00:00:00 2001 From: Georg Hagen Date: Thu, 11 Jul 2024 17:03:49 +0200 Subject: [PATCH 10/10] Fix memory leak on closing view --- openVulkanoCpp/Host/iOS/OpenVulkanoViewController.mm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/openVulkanoCpp/Host/iOS/OpenVulkanoViewController.mm b/openVulkanoCpp/Host/iOS/OpenVulkanoViewController.mm index 186b493..8fb242f 100644 --- a/openVulkanoCpp/Host/iOS/OpenVulkanoViewController.mm +++ b/openVulkanoCpp/Host/iOS/OpenVulkanoViewController.mm @@ -36,6 +36,12 @@ using namespace OpenVulkano; -(void) dealloc { manager->ShutDown(); + delete manager; + app = nullptr; + //TODO figure out where these two references are held + [_openVulkanoView release]; + [_openVulkanoView release]; + _openVulkanoView = nil; [super dealloc]; }