From b3c9af384b0409e4576754c05499ef354e6fcc3a Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Sun, 12 Nov 2023 16:11:27 +0100 Subject: [PATCH] Adding delayed destruction for resources --- src/Engine/Graphics/Vulkan/Allocator.cpp | 10 ++--- src/Engine/Graphics/Vulkan/Allocator.h | 2 +- src/Engine/Graphics/Vulkan/Buffer.cpp | 4 ++ src/Engine/Graphics/Vulkan/CommandBuffer.cpp | 1 + src/Engine/Graphics/Vulkan/Graphics.cpp | 20 ++++++--- src/Engine/Graphics/Vulkan/Graphics.h | 3 ++ src/Engine/Graphics/Vulkan/Resources.cpp | 43 ++++++++++++++++++++ src/Engine/Graphics/Vulkan/Resources.h | 22 ++++++++-- src/Engine/Graphics/Vulkan/Shader.cpp | 1 + src/Engine/Graphics/Vulkan/Texture.cpp | 9 +--- 10 files changed, 92 insertions(+), 23 deletions(-) diff --git a/src/Engine/Graphics/Vulkan/Allocator.cpp b/src/Engine/Graphics/Vulkan/Allocator.cpp index 92e72fe..4d9fceb 100644 --- a/src/Engine/Graphics/Vulkan/Allocator.cpp +++ b/src/Engine/Graphics/Vulkan/Allocator.cpp @@ -101,7 +101,7 @@ OSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice activeAllocations.add(alloc); freeRanges.erase(lower); bytesUsed += allocatedSize; - return std::move(alloc); + return alloc; } else if (allocatedSize < size) { @@ -112,7 +112,7 @@ OSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice freeRanges.erase(lower); freeRanges[newLower] = newSize; bytesUsed += allocatedSize; - return std::move(subAlloc); + return subAlloc; } } return nullptr; @@ -212,7 +212,7 @@ OSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2 { OAllocation newAllocation = new Allocation(graphics, this, requirements.size, memoryTypeIndex, properties, dedicatedInfo); heaps[heapIndex].inUse += newAllocation->bytesAllocated; - std::cout << "Heap " << heapIndex << " +" <bytesAllocated << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize << "%" << std::endl; + std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize << "%" << std::endl; heaps[heapIndex].allocations.add(std::move(newAllocation)); return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment); } @@ -232,7 +232,7 @@ OSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2 // no suitable allocations found, allocate new block OAllocation newAllocation = new Allocation(graphics, this, (requirements.size > MemoryBlockSize) ? requirements.size : (VkDeviceSize)MemoryBlockSize, memoryTypeIndex, properties, nullptr); heaps[heapIndex].inUse += newAllocation->bytesAllocated; - std::cout << "Heap " << heapIndex << " +" <bytesAllocated << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize << "%" << std::endl; heaps[heapIndex].allocations.add(std::move(newAllocation)); + std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize << "%" << std::endl; heaps[heapIndex].allocations.add(std::move(newAllocation)); return heaps[heapIndex].allocations.back()->getSuballocation(requirements.size, requirements.alignment); } @@ -245,7 +245,7 @@ void Allocator::free(PAllocation allocation) if (heaps[heapIndex].allocations[alloc] == allocation) { heaps[heapIndex].inUse -= allocation->bytesAllocated; - std::cout << "Heap " << heapIndex << " -" <bytesAllocated << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize << "%" << std::endl; + std::cout << "Heap " << heapIndex << ": " << (float)heaps[heapIndex].inUse / heaps[heapIndex].maxSize << "%" << std::endl; heaps[heapIndex].allocations.removeAt(alloc, false); return; } diff --git a/src/Engine/Graphics/Vulkan/Allocator.h b/src/Engine/Graphics/Vulkan/Allocator.h index dc24d1e..80b65d5 100644 --- a/src/Engine/Graphics/Vulkan/Allocator.h +++ b/src/Engine/Graphics/Vulkan/Allocator.h @@ -39,8 +39,8 @@ private: PAllocation owner; VkDeviceSize requestedSize; VkDeviceSize allocatedOffset; - VkDeviceSize alignedOffset; VkDeviceSize allocatedSize; + VkDeviceSize alignedOffset; friend class Allocation; friend class Allocator; }; diff --git a/src/Engine/Graphics/Vulkan/Buffer.cpp b/src/Engine/Graphics/Vulkan/Buffer.cpp index ae0c54a..a0d95f3 100644 --- a/src/Engine/Graphics/Vulkan/Buffer.cpp +++ b/src/Engine/Graphics/Vulkan/Buffer.cpp @@ -61,6 +61,10 @@ Buffer::Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::Q Buffer::~Buffer() { + for(uint32 i = 0; i < numBuffers; ++i) + { + graphics->getDestructionManager()->queueBuffer(graphics->getQueueCommands(owner)->getCommands(), buffers[i].buffer); + } } VkDeviceSize Buffer::getOffset() const diff --git a/src/Engine/Graphics/Vulkan/CommandBuffer.cpp b/src/Engine/Graphics/Vulkan/CommandBuffer.cpp index f7ba17e..51646ad 100644 --- a/src/Engine/Graphics/Vulkan/CommandBuffer.cpp +++ b/src/Engine/Graphics/Vulkan/CommandBuffer.cpp @@ -156,6 +156,7 @@ void CmdBuffer::refreshFence() descriptor->unbind(); } boundDescriptors.clear(); + graphics->getDestructionManager()->notifyCmdComplete(this); state = State::ReadyBegin; } } diff --git a/src/Engine/Graphics/Vulkan/Graphics.cpp b/src/Engine/Graphics/Vulkan/Graphics.cpp index 4fd3391..e20420a 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.cpp +++ b/src/Engine/Graphics/Vulkan/Graphics.cpp @@ -49,6 +49,7 @@ void Graphics::init(GraphicsInitializer initInfo) allocator = new Allocator(this); stagingManager = new StagingManager(this, allocator); pipelineCache = new PipelineCache(this, "pipeline.cache"); + destructionManager = new DestructionManager(this); } Gfx::OWindow Graphics::createWindow(const WindowCreateInfo &createInfo) @@ -164,31 +165,31 @@ Gfx::OVertexShader Graphics::createVertexShader(const ShaderCreateInfo& createIn { OVertexShader shader = new VertexShader(this); shader->create(createInfo); - return std::move(shader); + return shader; } Gfx::OFragmentShader Graphics::createFragmentShader(const ShaderCreateInfo& createInfo) { OFragmentShader shader = new FragmentShader(this); shader->create(createInfo); - return std::move(shader); + return shader; } Gfx::OComputeShader Graphics::createComputeShader(const ShaderCreateInfo& createInfo) { OComputeShader shader = new ComputeShader(this); shader->create(createInfo); - return std::move(shader); + return shader; } Gfx::OTaskShader Graphics::createTaskShader(const ShaderCreateInfo& createInfo) { OTaskShader shader = new TaskShader(this); shader->create(createInfo); - return std::move(shader); + return shader; } Gfx::OMeshShader Graphics::createMeshShader(const ShaderCreateInfo& createInfo) { OMeshShader shader = new MeshShader(this); shader->create(createInfo); - return std::move(shader); + return shader; } Gfx::PGraphicsPipeline Graphics::createGraphicsPipeline(Gfx::LegacyPipelineCreateInfo createInfo) @@ -227,12 +228,14 @@ Gfx::OSamplerState Graphics::createSamplerState(const SamplerCreateInfo& createI vkInfo.mipmapMode = cast(createInfo.mipmapMode); vkInfo.unnormalizedCoordinates = createInfo.unnormalizedCoordinates; VK_CHECK(vkCreateSampler(handle, &vkInfo, nullptr, &sampler->sampler)); - return std::move(sampler); + return sampler; } + Gfx::ODescriptorLayout Graphics::createDescriptorLayout(const std::string& name) { return new DescriptorLayout(this, name); } + Gfx::OPipelineLayout Graphics::createPipelineLayout(Gfx::PPipelineLayout baseLayout) { return new PipelineLayout(this, baseLayout); @@ -367,6 +370,11 @@ PStagingManager Graphics::getStagingManager() return stagingManager; } +PDestructionManager Graphics::getDestructionManager() +{ + return destructionManager; +} + Array Graphics::getRequiredExtensions() { Array extensions; diff --git a/src/Engine/Graphics/Vulkan/Graphics.h b/src/Engine/Graphics/Vulkan/Graphics.h index 653e87a..ce925ae 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.h +++ b/src/Engine/Graphics/Vulkan/Graphics.h @@ -8,6 +8,7 @@ namespace Vulkan { DECLARE_REF(Allocator) DECLARE_REF(StagingManager) +DECLARE_REF(DestructionManager) DECLARE_REF(CommandBufferManager) DECLARE_REF(Queue) DECLARE_REF(RenderPass) @@ -34,6 +35,7 @@ public: PAllocator getAllocator(); PStagingManager getStagingManager(); + PDestructionManager getDestructionManager(); // Inherited via Graphics virtual void init(GraphicsInitializer initializer) override; @@ -107,6 +109,7 @@ protected: Map allocatedFramebuffers; OAllocator allocator; OStagingManager stagingManager; + ODestructionManager destructionManager; friend class Window; }; diff --git a/src/Engine/Graphics/Vulkan/Resources.cpp b/src/Engine/Graphics/Vulkan/Resources.cpp index 4c96b1a..fc34a6c 100644 --- a/src/Engine/Graphics/Vulkan/Resources.cpp +++ b/src/Engine/Graphics/Vulkan/Resources.cpp @@ -80,6 +80,49 @@ void Fence::wait(uint32 timeout) } } +DestructionManager::DestructionManager(PGraphics graphics) + : graphics(graphics) +{ +} + +DestructionManager::~DestructionManager() +{ +} + +void DestructionManager::queueBuffer(PCmdBuffer cmd, VkBuffer buffer) +{ + buffers[cmd].add(buffer); +} + +void DestructionManager::queueImage(PCmdBuffer cmd, VkImage image) +{ + images[cmd].add(image); +} + +void DestructionManager::queueImageView(PCmdBuffer cmd, VkImageView image) +{ + views[cmd].add(image); +} + +void DestructionManager::notifyCmdComplete(PCmdBuffer cmdbuffer) +{ + for(auto buf : buffers[cmdbuffer]) + { + vkDestroyBuffer(graphics->getDevice(), buf, nullptr); + } + for(auto view : views[cmdbuffer]) + { + vkDestroyImageView(graphics->getDevice(), view, nullptr); + } + for(auto img : images[cmdbuffer]) + { + vkDestroyImage(graphics->getDevice(), img, nullptr); + } + buffers[cmdbuffer].clear(); + images[cmdbuffer].clear(); + views[cmdbuffer].clear(); +} + VertexDeclaration::VertexDeclaration(const Array& elementList) : elementList(elementList) { diff --git a/src/Engine/Graphics/Vulkan/Resources.h b/src/Engine/Graphics/Vulkan/Resources.h index 401155f..8a5bcef 100644 --- a/src/Engine/Graphics/Vulkan/Resources.h +++ b/src/Engine/Graphics/Vulkan/Resources.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include "Containers/List.h" #include "Graphics/Resources.h" #include "Allocator.h" @@ -42,10 +43,6 @@ public: return fence; } void wait(uint32 timeout); - /*Event& operator co_await() - { - return signaled; - }*/ bool operator<(const Fence &other) const { return fence < other.fence; @@ -58,6 +55,23 @@ private: }; DEFINE_REF(Fence) +class DestructionManager +{ +public: + DestructionManager(PGraphics graphics); + ~DestructionManager(); + void queueBuffer(PCmdBuffer cmd, VkBuffer buffer); + void queueImage(PCmdBuffer cmd, VkImage image); + void queueImageView(PCmdBuffer cmd, VkImageView view); + void notifyCmdComplete(PCmdBuffer cmdbuffer); +private: + PGraphics graphics; + Map> buffers; + Map> images; + Map> views; +}; +DEFINE_REF(DestructionManager) + class VertexDeclaration : public Gfx::VertexDeclaration { public: diff --git a/src/Engine/Graphics/Vulkan/Shader.cpp b/src/Engine/Graphics/Vulkan/Shader.cpp index bbfe3dd..83fa0f1 100644 --- a/src/Engine/Graphics/Vulkan/Shader.cpp +++ b/src/Engine/Graphics/Vulkan/Shader.cpp @@ -3,6 +3,7 @@ #include "slang.h" #include "slang-com-ptr.h" #include "stdlib.h" +#include using namespace Seele; using namespace Seele::Vulkan; diff --git a/src/Engine/Graphics/Vulkan/Texture.cpp b/src/Engine/Graphics/Vulkan/Texture.cpp index e07d49e..5548a23 100644 --- a/src/Engine/Graphics/Vulkan/Texture.cpp +++ b/src/Engine/Graphics/Vulkan/Texture.cpp @@ -159,13 +159,8 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, TextureHandle::~TextureHandle() { - //auto cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands(); - //VkDevice device = graphics->getDevice(); - //VkImageView view = defaultView; - //VkImage img = image; - //vkDestroyImageView(device, view, nullptr); - //vkDestroyImage(device, img, nullptr); - //co_return; + graphics->getDestructionManager()->queueImage(graphics->getQueueCommands(currentOwner)->getCommands(), image); + graphics->getDestructionManager()->queueImageView(graphics->getQueueCommands(currentOwner)->getCommands(), defaultView); } TextureHandle* TextureBase::cast(Gfx::PTexture texture)