From 25a0978a5716f7928d39d47bb12e1034c3c3a5ac Mon Sep 17 00:00:00 2001 From: Georg Hagen Date: Tue, 20 Aug 2024 23:44:17 +0200 Subject: [PATCH 1/8] Add render resouce --- openVulkanoCpp/Base/Render/RenderResource.hpp | 143 ++++++++++++++++++ openVulkanoCpp/Scene/Node.cpp | 2 +- openVulkanoCpp/Scene/Node.hpp | 4 +- .../Vulkan/Resources/ResourceManager.cpp | 11 +- openVulkanoCpp/Vulkan/Scene/VulkanNode.hpp | 34 ++--- openVulkanoCpp/Vulkan/VulkanDrawContext.cpp | 2 +- 6 files changed, 164 insertions(+), 32 deletions(-) create mode 100644 openVulkanoCpp/Base/Render/RenderResource.hpp diff --git a/openVulkanoCpp/Base/Render/RenderResource.hpp b/openVulkanoCpp/Base/Render/RenderResource.hpp new file mode 100644 index 0000000..13503e9 --- /dev/null +++ b/openVulkanoCpp/Base/Render/RenderResource.hpp @@ -0,0 +1,143 @@ +/* + * 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 +#include +#include + +namespace OpenVulkano +{ + class RenderResource; + + class IRenderResourceHelper + { + friend class RenderResource; + + protected: + void UpdateRenderResource(RenderResource& resource); + + void ResetRenderResource(RenderResource& resource); + + virtual void Release() = 0; + }; + + template + concept Renderable = std::is_convertible_v; + + class RenderResource final + { + friend class IRenderResourceHelper; + + IRenderResourceHelper* renderObject = nullptr; + + public: + RenderResource() = default; + RenderResource(const RenderResource& ignored) { /* Do not copy, copy will be created by renderer */ } + RenderResource(RenderResource&& move) : renderObject(move.renderObject) { move.renderObject = nullptr; } + + ~RenderResource() + { + Release(); + } + + void Release() + { + if (!renderObject) return; + renderObject->Release(); + renderObject = nullptr; + } + + template + T* As() { return static_cast(renderObject); } + + template + operator T() { return static_cast(renderObject); } + + operator bool() const { return renderObject; } + }; + + inline void IRenderResourceHelper::UpdateRenderResource(RenderResource& resource) + { + resource.renderObject = this; + } + + inline void IRenderResourceHelper::ResetRenderResource(RenderResource& resource) + { + resource.renderObject = nullptr; + } + + template + class IRenderResource : public IRenderResourceHelper + { + API_INDEPENDENT_CLASS* m_owner; + + protected: + IRenderResource(API_INDEPENDENT_CLASS* owner) : m_owner(owner) + { + if (m_owner) UpdateRenderResource(GetOwnerResource()); + } + + IRenderResource(const IRenderResource& copy) = delete; + + IRenderResource(IRenderResource&& move) + : m_owner(move.m_owner) + { + if (m_owner) UpdateRenderResource(GetOwnerResource()); + move.m_owner = nullptr; + } + + RenderResource& GetOwnerResource() { return static_cast(*m_owner); } + + public: + virtual ~IRenderResource() + { + if (m_owner) ResetRenderResource(GetOwnerResource()); + } + + void UpdateAddress(API_INDEPENDENT_CLASS* owner) + { + m_owner = owner; + } + + operator API_INDEPENDENT_CLASS*() const { return m_owner; } + + API_INDEPENDENT_CLASS* GetOwner() const { return m_owner; } + }; + + /** + * This is a convenience class to create a Renderable class. + * You can also just create a RenderResource instance a conversion operator inside your own class to make it Renderable; and you probably want to delete your move constructor in that case. + */ + template + class RenderResourceHolder + { + RenderResource renderResource; + + protected: + RenderResourceHolder() = default; + RenderResourceHolder(const RenderResourceHolder& ignored) {} + RenderResourceHolder(RenderResourceHolder&& move) + : renderResource(std::move(move.renderResource)) + { + if (IRenderResource* renderRes = renderResource) + renderRes->UpdateAddress(static_cast(this)); + } + + ~RenderResourceHolder() = default; + + public: + operator RenderResource&() { return renderResource; } + + RenderResource& GetRenderResource() { return renderResource; } + + template + operator RT() const { return renderResource; } + + bool HasRenderResource() const { return renderResource; } + }; +} diff --git a/openVulkanoCpp/Scene/Node.cpp b/openVulkanoCpp/Scene/Node.cpp index 604cc45..c362f43 100644 --- a/openVulkanoCpp/Scene/Node.cpp +++ b/openVulkanoCpp/Scene/Node.cpp @@ -37,7 +37,7 @@ namespace OpenVulkano::Scene void Node::Close() { children.clear(); - if (renderNode) renderNode->Close(); + GetRenderResource().Release(); parent = nullptr; scene = nullptr; enabled = false; diff --git a/openVulkanoCpp/Scene/Node.hpp b/openVulkanoCpp/Scene/Node.hpp index 89be67c..70bb07f 100644 --- a/openVulkanoCpp/Scene/Node.hpp +++ b/openVulkanoCpp/Scene/Node.hpp @@ -7,6 +7,7 @@ #pragma once #include "Base/ICloseable.hpp" +#include "Base/Render/RenderResource.hpp" #include "Math/Math.hpp" #include "Math/Pose.hpp" #include "Drawable.hpp" @@ -19,7 +20,7 @@ namespace OpenVulkano::Scene { class Scene; - class Node : public ICloseable + class Node : public RenderResourceHolder, public ICloseable { friend Scene; @@ -33,7 +34,6 @@ namespace OpenVulkano::Scene std::vector children; std::vector drawables; UpdateFrequency matrixUpdateFrequency = UpdateFrequency::Never; - ICloseable* renderNode = nullptr; bool enabled = true; public: diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp index 69e29f5..fa4f719 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp @@ -183,7 +183,7 @@ namespace OpenVulkano::Vulkan VulkanNode* ResourceManager::PrepareNode(Scene::Node* node) { const std::unique_lock lock(mutex); - if (!node->renderNode) + if (!node->HasRenderResource()) { UniformBuffer* uBuffer = new UniformBuffer(); ManagedBuffer::Ptr buffer; @@ -193,23 +193,22 @@ namespace OpenVulkano::Vulkan if (node->GetUpdateFrequency() != Scene::UpdateFrequency::Never) { frameSize = allocSize; - vkNode = new VulkanNodeDynamic(); + vkNode = new VulkanNodeDynamic(node, uBuffer); const uint32_t imgs = context->swapChain.GetImageCount(); buffer = memPool.CreateBuffer(imgs * allocSize, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible); buffer->Map(); } else { - vkNode = new VulkanNode(); buffer = CreateDeviceOnlyBufferWithData(Scene::Node::SIZE, vk::BufferUsageFlagBits::eUniformBuffer, &node->worldMat); + vkNode = new VulkanNode(node, uBuffer); } 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); + return vkNode; } - return static_cast(node->renderNode); + return node->GetRenderResource(); } VulkanCamera* ResourceManager::PrepareCamera(Scene::Camera* camera) diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanNode.hpp b/openVulkanoCpp/Vulkan/Scene/VulkanNode.hpp index 020c304..1e5aeab 100644 --- a/openVulkanoCpp/Vulkan/Scene/VulkanNode.hpp +++ b/openVulkanoCpp/Vulkan/Scene/VulkanNode.hpp @@ -6,28 +6,23 @@ #pragma once -#include "Base/ICloseable.hpp" +#include "Base/Render/RenderResource.hpp" #include "IRecordable.hpp" #include "Scene/Camera.hpp" #include "Vulkan/Resources/UniformBuffer.hpp" namespace OpenVulkano::Vulkan { - class VulkanNode : public IRecordable, public ICloseable + class VulkanNode : public IRenderResource, public IRecordable { public: - Scene::Node* node = nullptr; - UniformBuffer* buffer = nullptr; + Unique buffer = nullptr; - ~VulkanNode() override - { - if (node) VulkanNode::Close(); - } + ~VulkanNode() override = default; - virtual void Init(Scene::Node* node, UniformBuffer* uniformBuffer) + VulkanNode(Scene::Node* node, UniformBuffer* uniformBuffer) + : IRenderResource(node), buffer(uniformBuffer) { - this->node = node; - this->buffer = uniformBuffer; } void Record(VulkanDrawContext* context) override @@ -35,12 +30,9 @@ namespace OpenVulkano::Vulkan buffer->Record(context); } - void Close() override + void Release() override { - if (node) node->renderNode = nullptr; - delete buffer; - node = nullptr; - buffer = nullptr; + //TODO } }; @@ -48,18 +40,16 @@ namespace OpenVulkano::Vulkan { //uint32_t lastUpdate = -1; - void Init(Scene::Node* node, UniformBuffer* uniformBuffer) override - { - VulkanNode::Init(node, uniformBuffer); - //lastUpdate = -1; - } + VulkanNodeDynamic(Scene::Node* node, UniformBuffer* uniformBuffer) + : VulkanNode(node, uniformBuffer) + {} void Record(VulkanDrawContext* context) override { //if(context->currentImageId != lastUpdate) //TODO fix { //lastUpdate = bufferId; - buffer->Update(&node->worldMat, sizeof(Math::Matrix4f), context->currentImageId); + buffer->Update(&GetOwner()->worldMat, sizeof(Math::Matrix4f), context->currentImageId); } buffer->Record(context); } diff --git a/openVulkanoCpp/Vulkan/VulkanDrawContext.cpp b/openVulkanoCpp/Vulkan/VulkanDrawContext.cpp index fca2246..bc02e80 100644 --- a/openVulkanoCpp/Vulkan/VulkanDrawContext.cpp +++ b/openVulkanoCpp/Vulkan/VulkanDrawContext.cpp @@ -34,7 +34,7 @@ namespace OpenVulkano::Vulkan void VulkanDrawContext::EncodeNode(Scene::Node* node) { - VulkanNode* vkNode = static_cast(node->renderNode); + VulkanNode* vkNode = node->GetRenderResource(); if (!vkNode) { vkNode = renderer->GetResourceManager().PrepareNode(node); From 4ebaa622b4ace3263408ac6a61e50f547f29409e Mon Sep 17 00:00:00 2001 From: Georg Hagen Date: Wed, 21 Aug 2024 10:17:09 +0200 Subject: [PATCH 2/8] Small refactor --- openVulkanoCpp/Base/Render/RenderResource.hpp | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/openVulkanoCpp/Base/Render/RenderResource.hpp b/openVulkanoCpp/Base/Render/RenderResource.hpp index 13503e9..78141e6 100644 --- a/openVulkanoCpp/Base/Render/RenderResource.hpp +++ b/openVulkanoCpp/Base/Render/RenderResource.hpp @@ -12,35 +12,35 @@ namespace OpenVulkano { - class RenderResource; + class RenderResourcePtr; class IRenderResourceHelper { - friend class RenderResource; + friend class RenderResourcePtr; protected: - void UpdateRenderResource(RenderResource& resource); + void UpdateRenderResource(RenderResourcePtr& resource); - void ResetRenderResource(RenderResource& resource); + void ResetRenderResource(RenderResourcePtr& resource); virtual void Release() = 0; }; template - concept Renderable = std::is_convertible_v; + concept Renderable = std::is_convertible_v; - class RenderResource final + class RenderResourcePtr final { friend class IRenderResourceHelper; IRenderResourceHelper* renderObject = nullptr; public: - RenderResource() = default; - RenderResource(const RenderResource& ignored) { /* Do not copy, copy will be created by renderer */ } - RenderResource(RenderResource&& move) : renderObject(move.renderObject) { move.renderObject = nullptr; } + RenderResourcePtr() = default; + RenderResourcePtr(const RenderResourcePtr& ignored) { /* Do not copy, copy will be created by renderer */ } + RenderResourcePtr(RenderResourcePtr&& move) : renderObject(move.renderObject) { move.renderObject = nullptr; } - ~RenderResource() + ~RenderResourcePtr() { Release(); } @@ -61,12 +61,12 @@ namespace OpenVulkano operator bool() const { return renderObject; } }; - inline void IRenderResourceHelper::UpdateRenderResource(RenderResource& resource) + inline void IRenderResourceHelper::UpdateRenderResource(RenderResourcePtr& resource) { resource.renderObject = this; } - inline void IRenderResourceHelper::ResetRenderResource(RenderResource& resource) + inline void IRenderResourceHelper::ResetRenderResource(RenderResourcePtr& resource) { resource.renderObject = nullptr; } @@ -87,11 +87,14 @@ namespace OpenVulkano IRenderResource(IRenderResource&& move) : m_owner(move.m_owner) { - if (m_owner) UpdateRenderResource(GetOwnerResource()); + if (m_owner) + { + UpdateRenderResource(GetOwnerResource()); + } move.m_owner = nullptr; } - RenderResource& GetOwnerResource() { return static_cast(*m_owner); } + RenderResourcePtr& GetOwnerResource() { return static_cast(*m_owner); } public: virtual ~IRenderResource() @@ -116,7 +119,7 @@ namespace OpenVulkano template class RenderResourceHolder { - RenderResource renderResource; + RenderResourcePtr renderResource; protected: RenderResourceHolder() = default; @@ -131,9 +134,9 @@ namespace OpenVulkano ~RenderResourceHolder() = default; public: - operator RenderResource&() { return renderResource; } + operator RenderResourcePtr&() { return renderResource; } - RenderResource& GetRenderResource() { return renderResource; } + RenderResourcePtr& GetRenderResource() { return renderResource; } template operator RT() const { return renderResource; } From 33c8b743420850c072cfa5c2b95607e4f0634e5e Mon Sep 17 00:00:00 2001 From: Georg Hagen Date: Wed, 21 Aug 2024 10:17:45 +0200 Subject: [PATCH 3/8] Use RenderResource for uniform buffers --- openVulkanoCpp/Scene/UniformBuffer.hpp | 5 +-- .../Vulkan/Resources/ResourceManager.cpp | 10 ++--- .../ArBackgroundDrawableVulkanEncoder.cpp | 2 +- .../Scene/SimpleDrawableVulkanEncoder.cpp | 3 +- .../Vulkan/Scene/VulkanUniformBuffer.hpp | 41 +++++++------------ 5 files changed, 22 insertions(+), 39 deletions(-) diff --git a/openVulkanoCpp/Scene/UniformBuffer.hpp b/openVulkanoCpp/Scene/UniformBuffer.hpp index f198c3e..ec6370a 100644 --- a/openVulkanoCpp/Scene/UniformBuffer.hpp +++ b/openVulkanoCpp/Scene/UniformBuffer.hpp @@ -6,20 +6,19 @@ #pragma once -#include "Base/ICloseable.hpp" +#include "Base/Render/RenderResource.hpp" #include "Scene/Shader/DescriptorInputDescription.hpp" #include "Scene/UpdateFrequency.hpp" namespace OpenVulkano::Scene { - class UniformBuffer + class UniformBuffer : public RenderResourceHolder { public: static constexpr inline DescriptorSetLayoutBinding DESCRIPTOR_SET_LAYOUT_BINDING = { 0, DescriptorSetLayoutBinding::Type::TYPE_UNIFORM_BUFFER, 1, ShaderProgramType::ALL_GRAPHICS }; DescriptorSetLayoutBinding binding; uint32_t setId; - ICloseable* renderBuffer = nullptr; size_t size = 0; const void* data = nullptr; UpdateFrequency updateFrequency = UpdateFrequency::Never; diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp index fa4f719..7f40247 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp @@ -335,31 +335,29 @@ namespace OpenVulkano::Vulkan VulkanUniformBuffer* ResourceManager::PrepareUniformBuffer(Scene::UniformBuffer* buffer) { const std::unique_lock lock(mutex); - if (buffer->renderBuffer) return static_cast(buffer->renderBuffer); + if (buffer->HasRenderResource()) return static_cast(buffer->GetRenderResource()); VulkanUniformBuffer* vkBuffer; ManagedBuffer::Ptr mBuffer; const vk::DeviceSize allocSize = Utils::Align(buffer->size, uniformBufferAlignment); + UniformBuffer* uBuffer = new UniformBuffer(); if (buffer->GetUpdateFrequency() != Scene::UpdateFrequency::Never) { - vkBuffer = new VulkanUniformBufferDynamic(); const uint32_t imgs = context->swapChain.GetImageCount(); mBuffer = memPool.CreateBuffer(imgs * allocSize, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible); mBuffer->Map(); + vkBuffer = new VulkanUniformBufferDynamic(buffer, uBuffer); } else { - vkBuffer = new VulkanUniformBuffer(); mBuffer = CreateDeviceOnlyBufferWithData(Scene::Node::SIZE, vk::BufferUsageFlagBits::eUniformBuffer, buffer->data); buffer->updated = false; + vkBuffer = new VulkanUniformBuffer(buffer, uBuffer); } - - UniformBuffer* uBuffer = new UniformBuffer(); 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/Scene/ArBackgroundDrawableVulkanEncoder.cpp b/openVulkanoCpp/Vulkan/Scene/ArBackgroundDrawableVulkanEncoder.cpp index eec522c..dcdb1b1 100644 --- a/openVulkanoCpp/Vulkan/Scene/ArBackgroundDrawableVulkanEncoder.cpp +++ b/openVulkanoCpp/Vulkan/Scene/ArBackgroundDrawableVulkanEncoder.cpp @@ -24,7 +24,7 @@ namespace OpenVulkano::Vulkan { vkTexture = drawContext->renderer->GetResourceManager().PrepareTexture(const_cast(texture)); } - VulkanUniformBuffer* vkBuffer = static_cast(bgDrawable->GetBuffer().renderBuffer); + VulkanUniformBuffer* vkBuffer = bgDrawable->GetBuffer().GetRenderResource(); if (!vkBuffer) { vkBuffer = drawContext->renderer->GetResourceManager().PrepareUniformBuffer(&bgDrawable->GetBuffer()); diff --git a/openVulkanoCpp/Vulkan/Scene/SimpleDrawableVulkanEncoder.cpp b/openVulkanoCpp/Vulkan/Scene/SimpleDrawableVulkanEncoder.cpp index 54ba990..c943b89 100644 --- a/openVulkanoCpp/Vulkan/Scene/SimpleDrawableVulkanEncoder.cpp +++ b/openVulkanoCpp/Vulkan/Scene/SimpleDrawableVulkanEncoder.cpp @@ -6,7 +6,6 @@ #include "Scene/SimpleDrawable.hpp" #include "Scene/Material.hpp" -#include "Scene/UniformBuffer.hpp" #include "VulkanGeometry.hpp" #include "VulkanNode.hpp" #include "Vulkan/VulkanDrawContext.hpp" @@ -28,7 +27,7 @@ namespace OpenVulkano::Vulkan if (drawable->GetBuffer()) { - VulkanUniformBuffer* vkBuffer = static_cast(drawable->GetBuffer()->renderBuffer); + VulkanUniformBuffer* vkBuffer = drawable->GetBuffer()->GetRenderResource(); if (!vkBuffer) { vkBuffer = drawContext->renderer->GetResourceManager().PrepareUniformBuffer(drawable->GetBuffer()); diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanUniformBuffer.hpp b/openVulkanoCpp/Vulkan/Scene/VulkanUniformBuffer.hpp index 2d50c9a..412ffd5 100644 --- a/openVulkanoCpp/Vulkan/Scene/VulkanUniformBuffer.hpp +++ b/openVulkanoCpp/Vulkan/Scene/VulkanUniformBuffer.hpp @@ -6,42 +6,31 @@ #pragma once -#include "Base/ICloseable.hpp" #include "IRecordable.hpp" #include "Scene/UniformBuffer.hpp" #include "Vulkan/Resources/UniformBuffer.hpp" namespace OpenVulkano::Vulkan { - class VulkanUniformBuffer : public IRecordable, public ICloseable + class VulkanUniformBuffer : public IRenderResource, public IRecordable { public: - Scene::UniformBuffer* uBuffer = nullptr; - UniformBuffer* buffer = nullptr; + Unique buffer = nullptr; - ~VulkanUniformBuffer() override - { - if (uBuffer) VulkanUniformBuffer::Close(); - } + ~VulkanUniformBuffer() override = default; - virtual void Init(Scene::UniformBuffer* uBuffer, UniformBuffer* uniformBuffer) - { - this->uBuffer = uBuffer; - this->buffer = uniformBuffer; - uBuffer->renderBuffer = this; - } + VulkanUniformBuffer(Scene::UniformBuffer* sceneBuffer, UniformBuffer* uniformBuffer) + : IRenderResource(sceneBuffer), buffer(uniformBuffer) + {} void Record(VulkanDrawContext* context) override { buffer->Record(context); } - void Close() override + void Release() override { - if (uBuffer) uBuffer->renderBuffer = nullptr; - delete buffer; - uBuffer = nullptr; - buffer = nullptr; + //TODO } }; @@ -49,18 +38,16 @@ namespace OpenVulkano::Vulkan { uint32_t lastUpdate = 0; - void Init(Scene::UniformBuffer* buffer, UniformBuffer* uniformBuffer) override - { - VulkanUniformBuffer::Init(buffer, uniformBuffer); - lastUpdate = -1; - } + VulkanUniformBufferDynamic(Scene::UniformBuffer* sceneBuffer, UniformBuffer* uniformBuffer) + : VulkanUniformBuffer(sceneBuffer, uniformBuffer) + {} void Record(VulkanDrawContext* context) override { - if(uBuffer->updated) //TODO fix + if(GetOwner()->updated) //TODO fix { - uBuffer->updated = false; - buffer->Update(uBuffer->data, uBuffer->size, context->currentImageId); + GetOwner()->updated = false; + buffer->Update(GetOwner()->data, GetOwner()->size, context->currentImageId); } buffer->Record(context); } From 3940a720848dc0987790bbb1c7f7f2851f266ed5 Mon Sep 17 00:00:00 2001 From: Georg Hagen Date: Wed, 21 Aug 2024 13:13:43 +0200 Subject: [PATCH 4/8] Render resource handling for textures --- openVulkanoCpp/Base/Render/RenderResource.hpp | 34 ++++++++++++++----- openVulkanoCpp/Scene/Texture.hpp | 20 ++--------- .../Vulkan/Metal/MetalBackedTexture.mm | 6 ++-- .../Vulkan/Resources/ResourceManager.cpp | 4 +-- .../ArBackgroundDrawableVulkanEncoder.cpp | 2 +- .../Scene/SimpleDrawableVulkanEncoder.cpp | 4 +-- openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp | 34 +++++++++++-------- 7 files changed, 57 insertions(+), 47 deletions(-) diff --git a/openVulkanoCpp/Base/Render/RenderResource.hpp b/openVulkanoCpp/Base/Render/RenderResource.hpp index 78141e6..9aa7edb 100644 --- a/openVulkanoCpp/Base/Render/RenderResource.hpp +++ b/openVulkanoCpp/Base/Render/RenderResource.hpp @@ -12,6 +12,11 @@ namespace OpenVulkano { + namespace Vulkan + { + class MetalBackedTexture; + } + class RenderResourcePtr; class IRenderResourceHelper @@ -19,9 +24,11 @@ namespace OpenVulkano friend class RenderResourcePtr; protected: - void UpdateRenderResource(RenderResourcePtr& resource); + void UpdateRenderResource(RenderResourcePtr* resource); - void ResetRenderResource(RenderResourcePtr& resource); + void ResetRenderResource(RenderResourcePtr* resource); + + virtual void DoRelease() = 0; virtual void Release() = 0; }; @@ -32,6 +39,7 @@ namespace OpenVulkano class RenderResourcePtr final { friend class IRenderResourceHelper; + friend class Vulkan::MetalBackedTexture; IRenderResourceHelper* renderObject = nullptr; @@ -48,7 +56,7 @@ namespace OpenVulkano void Release() { if (!renderObject) return; - renderObject->Release(); + renderObject->DoRelease(); renderObject = nullptr; } @@ -61,14 +69,16 @@ namespace OpenVulkano operator bool() const { return renderObject; } }; - inline void IRenderResourceHelper::UpdateRenderResource(RenderResourcePtr& resource) + inline void IRenderResourceHelper::UpdateRenderResource(RenderResourcePtr* resource) { - resource.renderObject = this; + if (resource) + resource->renderObject = this; } - inline void IRenderResourceHelper::ResetRenderResource(RenderResourcePtr& resource) + inline void IRenderResourceHelper::ResetRenderResource(RenderResourcePtr* resource) { - resource.renderObject = nullptr; + if (resource) + resource->renderObject = nullptr; } template @@ -94,7 +104,13 @@ namespace OpenVulkano move.m_owner = nullptr; } - RenderResourcePtr& GetOwnerResource() { return static_cast(*m_owner); } + RenderResourcePtr* GetOwnerResource() { if (!m_owner) return nullptr; else return &static_cast(*m_owner); } + + void DoRelease() final override + { + m_owner = nullptr; + Release(); + } public: virtual ~IRenderResource() @@ -136,7 +152,7 @@ namespace OpenVulkano public: operator RenderResourcePtr&() { return renderResource; } - RenderResourcePtr& GetRenderResource() { return renderResource; } + RenderResourcePtr& GetRenderResource() const { return const_cast(this)->renderResource; } template operator RT() const { return renderResource; } diff --git a/openVulkanoCpp/Scene/Texture.hpp b/openVulkanoCpp/Scene/Texture.hpp index e65a1ce..3565105 100644 --- a/openVulkanoCpp/Scene/Texture.hpp +++ b/openVulkanoCpp/Scene/Texture.hpp @@ -8,27 +8,19 @@ #include "UpdateFrequency.hpp" #include "SamplerConfig.hpp" -#include "Base/ICloseable.hpp" +#include "Base/Render/RenderResource.hpp" #include "Math/Math.hpp" #include "DataFormat.hpp" #include "Scene/Shader/DescriptorInputDescription.hpp" namespace OpenVulkano::Scene { - class Texture; - - struct RenderTexture - { - Texture* m_texture = nullptr; - }; - - class Texture + class Texture : public RenderResourceHolder { public: static Texture PLACEHOLDER; static constexpr inline DescriptorSetLayoutBinding DESCRIPTOR_SET_LAYOUT_BINDING = { 0, DescriptorSetLayoutBinding::Type::TYPE_COMBINED_IMAGE_SAMPLER, 1, ShaderProgramType::ALL_GRAPHICS }; - RenderTexture* renderTexture = nullptr; void* textureBuffer = nullptr; size_t size = 0; Math::Vector3ui resolution = {0,0,0}; @@ -41,13 +33,7 @@ namespace OpenVulkano::Scene : m_samplerConfig(samplerConfig) { if (placeholder) MakePlaceholder(); } - ~Texture() - { - if (renderTexture) - { - renderTexture->m_texture = nullptr; - } - } + ~Texture() = default; void MakePlaceholder(uint32_t width = 32, uint32_t height = 32, Math::Vector4uc color1 = {248, 123, 255, 255}, Math::Vector4uc color2 = {250, 19, 255, 255}); diff --git a/openVulkanoCpp/Vulkan/Metal/MetalBackedTexture.mm b/openVulkanoCpp/Vulkan/Metal/MetalBackedTexture.mm index f3ffc79..10f23d3 100644 --- a/openVulkanoCpp/Vulkan/Metal/MetalBackedTexture.mm +++ b/openVulkanoCpp/Vulkan/Metal/MetalBackedTexture.mm @@ -19,7 +19,6 @@ namespace OpenVulkano::Vulkan resolution = { static_cast(mtlTexture.width), static_cast(mtlTexture.height), static_cast(mtlTexture.depth) }; format = DataFormat::GetFromMetalPixelFormat(static_cast(mtlTexture.pixelFormat)); - m_vulkanTexture.m_texture = this; m_vulkanTexture.device = resManager->GetDevice(); m_vulkanTexture.format = format; m_vulkanTexture.extent = reinterpret_cast(resolution); @@ -57,7 +56,10 @@ namespace OpenVulkano::Vulkan m_vulkanTexture.m_sampler = resManager->CreateSampler(reinterpret_cast(Scene::SamplerConfig::DEFAULT)); m_vulkanTexture.SetDescriptorSet(resManager, resManager->GetDescriptorLayoutSet(binding), binding); - renderTexture = &m_vulkanTexture; + //m_vulkanTexture.UpdateAddress(this); + //UpdateRenderResource(GetOwnerResource()); + GetRenderResource().renderObject = &m_vulkanTexture; + m_vulkanTexture.UpdateAddress(this); if (!ownsTexture) m_metalTexture = nullptr; } diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp index 7f40247..e370336 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp @@ -174,7 +174,7 @@ namespace OpenVulkano::Vulkan void ResourceManager::PrepareMaterial(Scene::Material* material) { - if (material->texture && !material->texture->renderTexture) + if (material->texture && !material->texture->HasRenderResource()) { PrepareTexture(material->texture); } @@ -318,7 +318,7 @@ namespace OpenVulkano::Vulkan VulkanTexture* ResourceManager::PrepareTexture(Scene::Texture* texture) { const std::unique_lock lock(mutex); - if (texture->renderTexture) return static_cast(texture->renderTexture); + if (texture->HasRenderResource()) return static_cast(texture->GetRenderResource()); VulkanTexture* vkTexture; if (texture->updateFrequency == Scene::UpdateFrequency::Never) vkTexture = new VulkanTexture(); diff --git a/openVulkanoCpp/Vulkan/Scene/ArBackgroundDrawableVulkanEncoder.cpp b/openVulkanoCpp/Vulkan/Scene/ArBackgroundDrawableVulkanEncoder.cpp index dcdb1b1..229319f 100644 --- a/openVulkanoCpp/Vulkan/Scene/ArBackgroundDrawableVulkanEncoder.cpp +++ b/openVulkanoCpp/Vulkan/Scene/ArBackgroundDrawableVulkanEncoder.cpp @@ -19,7 +19,7 @@ namespace OpenVulkano::Vulkan ArBackgroundDrawable* bgDrawable = static_cast(instance); bgDrawable->Tick(); const Texture* texture = bgDrawable->GetTexture(); - VulkanTexture* vkTexture = static_cast(texture->renderTexture); + VulkanTexture* vkTexture = texture->GetRenderResource(); if (!vkTexture) { vkTexture = drawContext->renderer->GetResourceManager().PrepareTexture(const_cast(texture)); diff --git a/openVulkanoCpp/Vulkan/Scene/SimpleDrawableVulkanEncoder.cpp b/openVulkanoCpp/Vulkan/Scene/SimpleDrawableVulkanEncoder.cpp index c943b89..45f89ea 100644 --- a/openVulkanoCpp/Vulkan/Scene/SimpleDrawableVulkanEncoder.cpp +++ b/openVulkanoCpp/Vulkan/Scene/SimpleDrawableVulkanEncoder.cpp @@ -39,11 +39,11 @@ namespace OpenVulkano::Vulkan { if (Texture* texture = material->texture) { - VulkanTexture* renderTexture = static_cast(texture->renderTexture); + VulkanTexture* renderTexture = texture->GetRenderResource(); if (!renderTexture) { drawContext->renderer->GetResourceManager().PrepareMaterial(drawable->GetMaterial()); - renderTexture = static_cast(texture->renderTexture); + renderTexture = texture->GetRenderResource(); } renderTexture->Record(drawContext); } diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp b/openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp index 5a079d4..84e3530 100644 --- a/openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp +++ b/openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp @@ -16,28 +16,29 @@ namespace OpenVulkano::Vulkan { - class VulkanTexture : public Scene::RenderTexture, public IRecordable, public Image + class VulkanTexture : public IRenderResource, public IRecordable, public Image { public: vk::Sampler m_sampler; vk::DescriptorSet m_descriptorSet; + VulkanTexture() : IRenderResource(nullptr) {} + virtual void Init(ResourceManager* resManager, Scene::Texture* texture, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding) { - m_texture = texture; Image::Init(resManager->GetContext()->device.get(), texture->format, { texture->resolution.x, texture->resolution.y, texture->resolution.z }); - resManager->CopyDataToImage(m_texture->size, m_texture->textureBuffer, this); + resManager->CopyDataToImage(texture->size, texture->textureBuffer, this); texture->updated = false; m_sampler = resManager->CreateSampler(reinterpret_cast(*texture->m_samplerConfig)); SetDescriptorSet(resManager, descriptorSetLayout, binding); - texture->renderTexture = this; + UpdateAddress(texture); + UpdateRenderResource(GetOwnerResource()); } void InitSharedMem(ResourceManager* resManager, Scene::Texture* texture, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding) { - m_texture = texture; Image::Init(resManager->GetContext()->device.get(), texture->format, { texture->resolution.x, texture->resolution.y, texture->resolution.z }, vk::MemoryPropertyFlagBits::eDeviceLocal | vk::MemoryPropertyFlagBits::eHostVisible); texture->updated = false; texture->textureBuffer = Map(); @@ -45,7 +46,8 @@ namespace OpenVulkano::Vulkan m_sampler = resManager->CreateSampler(reinterpret_cast(*texture->m_samplerConfig)); SetDescriptorSet(resManager, descriptorSetLayout, binding); - texture->renderTexture = this; + UpdateAddress(texture); + UpdateRenderResource(GetOwnerResource()); } virtual ~VulkanTexture() override @@ -55,9 +57,8 @@ namespace OpenVulkano::Vulkan void Close() override { + ResetRenderResource(GetOwnerResource()); Image::Close(); - if (m_texture) m_texture->renderTexture = nullptr; - m_texture = nullptr; } void SetDescriptorSet(ResourceManager* resManager, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding) @@ -106,6 +107,11 @@ namespace OpenVulkano::Vulkan { context->commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, context->GetShader()->pipelineLayout, setId, 1, &m_descriptorSet, 0, nullptr); } + + void Release() override + { + //TODO + } }; class VulkanTextureDynamic : public VulkanTexture @@ -118,20 +124,20 @@ namespace OpenVulkano::Vulkan void Record(VulkanDrawContext* context) override { - if(m_texture->updated) + if(GetOwner()->updated) { - context->renderer->GetResourceManager().CopyDataToImage(m_texture->size, m_texture->textureBuffer, this); - m_texture->updated = false; + context->renderer->GetResourceManager().CopyDataToImage(GetOwner()->size, GetOwner()->textureBuffer, this); + GetOwner()->updated = false; } VulkanTexture::Record(context); } void Record(VulkanDrawContext* context, int setId) override { - if(m_texture->updated) + if(GetOwner()->updated) { - context->renderer->GetResourceManager().CopyDataToImage(m_texture->size, m_texture->textureBuffer, this); - m_texture->updated = false; + context->renderer->GetResourceManager().CopyDataToImage(GetOwner()->size, GetOwner()->textureBuffer, this); + GetOwner()->updated = false; } VulkanTexture::Record(context, setId); } From b13c1c54aecc3b1f28748bb3e1423d59d4ce60a5 Mon Sep 17 00:00:00 2001 From: Georg Hagen Date: Wed, 21 Aug 2024 13:33:15 +0200 Subject: [PATCH 5/8] Update shader to use new render resource system --- openVulkanoCpp/Scene/Shader/Shader.hpp | 12 ++++----- .../Vulkan/Resources/ResourceManager.cpp | 6 ++--- openVulkanoCpp/Vulkan/Scene/VulkanShader.cpp | 26 ++++++++----------- openVulkanoCpp/Vulkan/Scene/VulkanShader.hpp | 16 +++--------- openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp | 2 +- openVulkanoCpp/Vulkan/VulkanDrawContext.cpp | 2 +- 6 files changed, 26 insertions(+), 38 deletions(-) diff --git a/openVulkanoCpp/Scene/Shader/Shader.hpp b/openVulkanoCpp/Scene/Shader/Shader.hpp index ed1da7d..e89cb9a 100644 --- a/openVulkanoCpp/Scene/Shader/Shader.hpp +++ b/openVulkanoCpp/Scene/Shader/Shader.hpp @@ -8,6 +8,7 @@ #include "Base/ICloseable.hpp" #include "Base/Utils.hpp" +#include "Base/Render/RenderResource.hpp" #include "VertexInputDescription.hpp" #include "ShaderProgramType.hpp" #include "DescriptorInputDescription.hpp" @@ -79,7 +80,7 @@ namespace OpenVulkano::Scene - class Shader final : public ICloseable + class Shader final : public RenderResourceHolder, public ICloseable { public: std::vector shaderPrograms{}; @@ -88,7 +89,6 @@ namespace OpenVulkano::Scene std::vector pushConstantRanges; Topology topology = Topology::TRIANGLE_LIST; CullMode cullMode = CullMode::BACK; - ICloseable* renderShader = nullptr; CompareOp depthCompareOp = CompareOp::LESS; bool alphaBlend = false; // TODO allow fine control over blending bool depthTest = true; @@ -96,7 +96,7 @@ namespace OpenVulkano::Scene bool dynamicViewport = true; // If disabled the swapchains fullscreen viewport will always be used, regardless of framebuffer or viewport Shader() = default; - ~Shader() override { if (renderShader) Shader::Close(); } + ~Shader() override { Shader::Close(); } Shader& AddShaderProgram(const ShaderProgram& shaderProgram) { @@ -163,14 +163,14 @@ namespace OpenVulkano::Scene void Close() override { - renderShader->Close(); - renderShader = nullptr; + if (HasRenderResource()) + GetRenderResource().Release(); } private: void CheckShaderInitState() const { - if (renderShader) throw std::runtime_error("Shader already initialized!"); + if (HasRenderResource()) throw std::runtime_error("Shader already initialized!"); } }; } diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp index e370336..1d9042a 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp @@ -277,6 +277,7 @@ namespace OpenVulkano::Vulkan find_if(shaders.begin(), shaders.end(), [&](auto& obj){ return obj.get() == shader; } ); + object->get()->owner = nullptr; shaders.erase(object); } @@ -308,9 +309,8 @@ namespace OpenVulkano::Vulkan VulkanShader* ResourceManager::CreateShader(Scene::Shader* shader) { const std::unique_lock lock(mutex); - if (shader->renderShader) return static_cast(shader->renderShader); - VulkanShader* vkShader = new VulkanShader(); - vkShader->Init(context, shader, this); + if (shader->HasRenderResource()) return static_cast(shader->GetRenderResource()); + VulkanShader* vkShader = new VulkanShader(context, shader, this); shaders.emplace_back(vkShader); return vkShader; } diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanShader.cpp b/openVulkanoCpp/Vulkan/Scene/VulkanShader.cpp index fc851aa..e7bc334 100644 --- a/openVulkanoCpp/Vulkan/Scene/VulkanShader.cpp +++ b/openVulkanoCpp/Vulkan/Scene/VulkanShader.cpp @@ -17,7 +17,8 @@ namespace OpenVulkano::Vulkan VulkanShader::~VulkanShader() { - if (shader) Close(); + if (owner) owner->RemoveShader(this); + owner = nullptr; device.destroyPipeline(pipeline); for(auto& shaderModule : shaderModules) { @@ -28,12 +29,9 @@ namespace OpenVulkano::Vulkan device.destroyDescriptorSetLayout(descriptorSetLayout); } - void VulkanShader::Init(Context* context, Scene::Shader* shader, IShaderOwner* owner) + VulkanShader::VulkanShader(Context* context, Scene::Shader* shader, IShaderOwner* owner) + : IRenderResource(shader), device(context->device->device), owner(owner), context(context) { - this->device = context->device->device; - this->shader = shader; - this->owner = owner; - this->context = context; shaderModules.reserve(shader->shaderPrograms.size()); shaderStageCreateInfo.resize(shader->shaderPrograms.size()); int i = 0; @@ -45,11 +43,11 @@ namespace OpenVulkano::Vulkan i++; } BuildPipeline(); - shader->renderShader = this; } void VulkanShader::BuildPipeline() { + Scene::Shader* shader = GetOwner(); std::vector vertexBindDesc; std::vector attributeDescriptions; vertexBindDesc.reserve(shader->vertexInputDescriptions.size()); @@ -129,14 +127,6 @@ namespace OpenVulkano::Vulkan context->commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline); } - void VulkanShader::Close() - { - shader->renderShader = nullptr; - shader = nullptr; - if (owner) owner->RemoveShader(this); - owner = nullptr; - } - void VulkanShader::CreatePipelineLayout() { if (!descriptorSetLayouts.empty()) @@ -150,6 +140,7 @@ namespace OpenVulkano::Vulkan descriptorSetLayouts.push_back(device.createDescriptorSetLayout({ {}, layoutBindings1.size(), layoutBindings1.data() })); descriptorSetLayouts.push_back(device.createDescriptorSetLayout({ {}, layoutBindings2.size(), layoutBindings2.data() })); + Scene::Shader* shader = GetOwner(); for(const auto& set : shader->descriptorSets) { vk::DescriptorSetLayoutCreateInfo createInfo { {}, static_cast(set.size()), reinterpret_cast(set.data()) }; @@ -159,4 +150,9 @@ namespace OpenVulkano::Vulkan vk::PipelineLayoutCreateInfo plci = {{}, static_cast(descriptorSetLayouts.size()), descriptorSetLayouts.data(), static_cast(shader->pushConstantRanges.size()), pcRanges }; pipelineLayout = this->device.createPipelineLayout(plci); } + + void VulkanShader::Release() + { + if (owner) owner->RemoveShader(this); + } } diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanShader.hpp b/openVulkanoCpp/Vulkan/Scene/VulkanShader.hpp index af41830..738e0c2 100644 --- a/openVulkanoCpp/Vulkan/Scene/VulkanShader.hpp +++ b/openVulkanoCpp/Vulkan/Scene/VulkanShader.hpp @@ -7,26 +7,20 @@ #pragma once #include "IRecordable.hpp" -#include "Base/ICloseable.hpp" +#include "Scene/Shader/Shader.hpp" #include #include namespace OpenVulkano { - namespace Scene - { - class Shader; - } - namespace Vulkan { class Context; class IShaderOwner; - class VulkanShader final : public ICloseable, public IRecordable + class VulkanShader final : public IRenderResource, 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 std::vector shaderStageCreateInfo; @@ -36,17 +30,15 @@ namespace OpenVulkano IShaderOwner* owner = nullptr; Context* context = nullptr; - VulkanShader() = default; + VulkanShader(Context* context, Scene::Shader* shader, IShaderOwner* owner); ~VulkanShader() override; - void Init(Context* context, Scene::Shader* shader, IShaderOwner* owner); - void Resize(); void Record(VulkanDrawContext* context) override; - void Close() override; + void Release() override; private: void BuildPipeline(); diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp b/openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp index 84e3530..c57aa81 100644 --- a/openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp +++ b/openVulkanoCpp/Vulkan/Scene/VulkanTexture.hpp @@ -76,7 +76,7 @@ namespace OpenVulkano::Vulkan void Record(VulkanDrawContext* context) override { int setId = -1, i = 0; - for (const auto& descriptorSet : context->GetShader()->shader->descriptorSets) + for (const auto& descriptorSet : context->GetShader()->GetOwner()->descriptorSets) { for (const auto& descriptor : descriptorSet) { diff --git a/openVulkanoCpp/Vulkan/VulkanDrawContext.cpp b/openVulkanoCpp/Vulkan/VulkanDrawContext.cpp index bc02e80..935bdd5 100644 --- a/openVulkanoCpp/Vulkan/VulkanDrawContext.cpp +++ b/openVulkanoCpp/Vulkan/VulkanDrawContext.cpp @@ -14,7 +14,7 @@ namespace OpenVulkano::Vulkan { void VulkanDrawContext::EncodeShader(Scene::Shader* shader) { - VulkanShader* vkShader = static_cast(shader->renderShader); + VulkanShader* vkShader = shader->GetRenderResource(); if (!vkShader) { vkShader = renderer->GetResourceManager().CreateShader(shader); From 2d08b3ab91651598bb0645c4705e7698116fdd17 Mon Sep 17 00:00:00 2001 From: Georg Hagen Date: Wed, 21 Aug 2024 14:33:45 +0200 Subject: [PATCH 6/8] Add render resource handling for geometry --- openVulkanoCpp/Base/Render/RenderResource.hpp | 33 +++++++++++-- openVulkanoCpp/Scene/Geometry.cpp | 49 +++++++------------ openVulkanoCpp/Scene/Geometry.hpp | 4 +- .../Vulkan/Resources/ResourceManager.cpp | 5 +- .../Scene/SimpleDrawableVulkanEncoder.cpp | 3 +- .../Vulkan/Scene/VulkanGeometry.hpp | 33 +++---------- 6 files changed, 59 insertions(+), 68 deletions(-) diff --git a/openVulkanoCpp/Base/Render/RenderResource.hpp b/openVulkanoCpp/Base/Render/RenderResource.hpp index 9aa7edb..93e62a6 100644 --- a/openVulkanoCpp/Base/Render/RenderResource.hpp +++ b/openVulkanoCpp/Base/Render/RenderResource.hpp @@ -45,8 +45,8 @@ namespace OpenVulkano public: RenderResourcePtr() = default; - RenderResourcePtr(const RenderResourcePtr& ignored) { /* Do not copy, copy will be created by renderer */ } - RenderResourcePtr(RenderResourcePtr&& move) : renderObject(move.renderObject) { move.renderObject = nullptr; } + RenderResourcePtr(const RenderResourcePtr& ignored) noexcept { /* Do not copy, copy will be created by renderer */ } + RenderResourcePtr(RenderResourcePtr&& move) noexcept : renderObject(move.renderObject) { move.renderObject = nullptr; } ~RenderResourcePtr() { @@ -67,6 +67,14 @@ namespace OpenVulkano operator T() { return static_cast(renderObject); } operator bool() const { return renderObject; } + + RenderResourcePtr& operator =(RenderResourcePtr&& move) noexcept + { + if (renderObject) renderObject->Release(); + renderObject = move.renderObject; + move.renderObject = nullptr; + return *this; + } }; inline void IRenderResourceHelper::UpdateRenderResource(RenderResourcePtr* resource) @@ -94,7 +102,7 @@ namespace OpenVulkano IRenderResource(const IRenderResource& copy) = delete; - IRenderResource(IRenderResource&& move) + IRenderResource(IRenderResource&& move) noexcept : m_owner(move.m_owner) { if (m_owner) @@ -139,8 +147,8 @@ namespace OpenVulkano protected: RenderResourceHolder() = default; - RenderResourceHolder(const RenderResourceHolder& ignored) {} - RenderResourceHolder(RenderResourceHolder&& move) + RenderResourceHolder(const RenderResourceHolder& ignored) noexcept {} + RenderResourceHolder(RenderResourceHolder&& move) noexcept : renderResource(std::move(move.renderResource)) { if (IRenderResource* renderRes = renderResource) @@ -158,5 +166,20 @@ namespace OpenVulkano operator RT() const { return renderResource; } bool HasRenderResource() const { return renderResource; } + + RenderResourceHolder& operator =(RenderResourceHolder&& move) noexcept + { + renderResource = std::move(move.renderResource); + if (IRenderResource* renderRes = renderResource) + renderRes->UpdateAddress(static_cast(this)); + return *this; + } + + void Swap(RenderResourceHolder& other) noexcept + { + RenderResourceHolder tmp(std::move(*this)); + *this = std::move(other); + other = std::move(tmp); + } }; } diff --git a/openVulkanoCpp/Scene/Geometry.cpp b/openVulkanoCpp/Scene/Geometry.cpp index c2b28db..a5b897c 100644 --- a/openVulkanoCpp/Scene/Geometry.cpp +++ b/openVulkanoCpp/Scene/Geometry.cpp @@ -19,21 +19,18 @@ namespace OpenVulkano::Scene { - Geometry::Geometry(const Geometry& other) - { - this->vertexCount = other.vertexCount; - this->indexCount = other.indexCount; - this->indexType = other.indexType; - this->aabb = other.aabb; - this->ownsMemory = other.ownsMemory; - this->freeAfterUpload = other.freeAfterUpload; - this->renderGeo = nullptr; - this->vertices = new Vertex[vertexCount]; + Geometry::Geometry(const Geometry& other) + : vertexCount(other.vertexCount), indexCount(other.indexCount) + , vertices(other.vertices ? new Vertex[other.vertexCount] : nullptr) + , indices(other.indices ? malloc(static_cast(Utils::EnumAsInt(other.indexType)) * other.indexCount) : nullptr) + , indexType(other.indexType) + , ownsMemory(other.ownsMemory), freeAfterUpload(other.freeAfterUpload) + , aabb(other.aabb) + { if (other.vertices) { std::copy(other.vertices, other.vertices + other.vertexCount, this->vertices); } - this->indices = malloc(static_cast(Utils::EnumAsInt(other.indexType)) * other.indexCount); if (other.indices) { if (other.indexType == VertexIndexType::UINT16) @@ -58,21 +55,14 @@ namespace OpenVulkano::Scene return *this; } - Geometry::Geometry(Geometry&& other) noexcept + Geometry::Geometry(Geometry&& other) noexcept + : RenderResourceHolder(std::move(other)), vertexCount(other.vertexCount), indexCount(other.indexCount) + , vertices(other.vertices), indices(other.indices), indexType(other.indexType) + , ownsMemory(other.ownsMemory), freeAfterUpload(other.freeAfterUpload), aabb(other.aabb) { - this->vertexCount = other.vertexCount; - this->indexCount = other.indexCount; - this->indexType = other.indexType; - this->ownsMemory = other.ownsMemory; - this->freeAfterUpload = other.freeAfterUpload; - this->aabb = std::move(other.aabb); - this->vertices = other.vertices; - this->indices = other.indices; - this->renderGeo = other.renderGeo; other.vertexCount = other.indexCount = 0; other.vertices = nullptr; other.indices = nullptr; - other.renderGeo = nullptr; } Geometry& Geometry::operator=(Geometry&& other) noexcept @@ -88,11 +78,10 @@ namespace OpenVulkano::Scene this->aabb = std::move(other.aabb); this->vertices = other.vertices; this->indices = other.indices; - this->renderGeo = other.renderGeo; + RenderResourceHolder::operator=(std::move(other)); other.vertexCount = other.indexCount = 0; other.vertices = nullptr; other.indices = nullptr; - other.renderGeo = nullptr; } return *this; } @@ -103,27 +92,26 @@ namespace OpenVulkano::Scene } void Geometry::Swap(Geometry& other) noexcept - { + { + RenderResourceHolder::Swap(other); std::swap(this->vertexCount, other.vertexCount); std::swap(this->indexCount, other.indexCount); std::swap(this->aabb, other.aabb); std::swap(this->indexType, other.indexType); std::swap(this->vertices, other.vertices); std::swap(this->indices, other.indices); - std::swap(this->renderGeo, other.renderGeo); std::swap(this->ownsMemory, other.ownsMemory); std::swap(this->freeAfterUpload, other.freeAfterUpload); } void Geometry::Init(uint32_t vertexCount, uint32_t indexCount) { - if (this->vertexCount || this->indexCount) throw std::runtime_error("Geometry is already initialized."); + if (HasRenderResource() || this->vertexCount || this->indexCount) throw std::runtime_error("Geometry is already initialized."); this->vertexCount = vertexCount; this->indexCount = indexCount; indexType = (vertexCount > UINT16_MAX) ? VertexIndexType::UINT32 : VertexIndexType::UINT16; vertices = new Vertex[vertexCount]; indices = malloc(static_cast(Utils::EnumAsInt(indexType)) * indexCount); - renderGeo = nullptr; } void Geometry::InitFromFile(const std::string& file) @@ -212,10 +200,9 @@ namespace OpenVulkano::Scene indexCount = 0; Free(); } - if (renderGeo) + if (HasRenderResource()) { - renderGeo->Close(); - renderGeo = nullptr; + GetRenderResource().Release(); } } diff --git a/openVulkanoCpp/Scene/Geometry.hpp b/openVulkanoCpp/Scene/Geometry.hpp index c38b9cb..4ef3dcc 100644 --- a/openVulkanoCpp/Scene/Geometry.hpp +++ b/openVulkanoCpp/Scene/Geometry.hpp @@ -7,6 +7,7 @@ #pragma once #include "Base/ICloseable.hpp" +#include "Base/Render/RenderResource.hpp" #include "Math/AABB.hpp" #include "Base/Utils.hpp" #include @@ -24,7 +25,7 @@ namespace OpenVulkano UINT16 = sizeof(uint16_t), UINT32 = sizeof(uint32_t) }; - class Geometry : public ICloseable + class Geometry : public RenderResourceHolder, public ICloseable { public: uint32_t vertexCount = 0, indexCount = 0; @@ -33,7 +34,6 @@ namespace OpenVulkano VertexIndexType indexType = VertexIndexType::UINT16; bool ownsMemory = true, freeAfterUpload = true; Math::AABB aabb; - ICloseable* renderGeo = nullptr; public: Geometry() = default; Geometry(const Geometry& other); diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp index 1d9042a..16e9c4b 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp @@ -153,7 +153,7 @@ namespace OpenVulkano::Vulkan VulkanGeometry* ResourceManager::PrepareGeometry(Scene::Geometry* geometry) { const std::unique_lock lock(mutex); - if(!geometry->renderGeo) + if(!geometry->HasRenderResource()) { ManagedBuffer::Ptr vertexBuffer = CreateDeviceOnlyBufferWithData(sizeof(Vertex) * geometry->GetVertexCount(), vk::BufferUsageFlagBits::eVertexBuffer, geometry->GetVertices()); @@ -162,14 +162,13 @@ namespace OpenVulkano::Vulkan 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; if (geometry->ownsMemory && geometry->freeAfterUpload) { geometry->Free(); } return vkGeo; } - return dynamic_cast(geometry->renderGeo); + return geometry->GetRenderResource(); } void ResourceManager::PrepareMaterial(Scene::Material* material) diff --git a/openVulkanoCpp/Vulkan/Scene/SimpleDrawableVulkanEncoder.cpp b/openVulkanoCpp/Vulkan/Scene/SimpleDrawableVulkanEncoder.cpp index 45f89ea..a6b40c8 100644 --- a/openVulkanoCpp/Vulkan/Scene/SimpleDrawableVulkanEncoder.cpp +++ b/openVulkanoCpp/Vulkan/Scene/SimpleDrawableVulkanEncoder.cpp @@ -20,13 +20,12 @@ namespace OpenVulkano::Vulkan { SimpleDrawable* drawable = static_cast(instance); Geometry* mesh = drawable->GetMesh(); - VulkanGeometry* renderGeo = static_cast(mesh->renderGeo); + VulkanGeometry* renderGeo = mesh->GetRenderResource(); if (!renderGeo) renderGeo = drawContext->renderer->GetResourceManager().PrepareGeometry(mesh); renderGeo->RecordBind(drawContext->commandBuffer); if (drawable->GetBuffer()) { - VulkanUniformBuffer* vkBuffer = drawable->GetBuffer()->GetRenderResource(); if (!vkBuffer) { diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanGeometry.hpp b/openVulkanoCpp/Vulkan/Scene/VulkanGeometry.hpp index eb5459f..10c5c6b 100644 --- a/openVulkanoCpp/Vulkan/Scene/VulkanGeometry.hpp +++ b/openVulkanoCpp/Vulkan/Scene/VulkanGeometry.hpp @@ -13,36 +13,21 @@ namespace OpenVulkano::Vulkan { - class VulkanGeometry final : public ICloseable + class VulkanGeometry final : public IRenderResource { - Scene::Geometry* m_geometry; ManagedBuffer::Ptr m_vertexBuffer; ManagedBuffer::Ptr m_indexBuffer; vk::IndexType m_indexType; vk::DeviceSize m_offsets = 0; public: - 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) - : m_geometry(geo), m_vertexBuffer(std::move(vertexBuffer)), m_indexBuffer(std::move(indexBuffer)) + : IRenderResource(geo) + , m_vertexBuffer(std::move(vertexBuffer)), m_indexBuffer(std::move(indexBuffer)) , m_indexType((geo->indexType == Scene::VertexIndexType::UINT16) ? vk::IndexType::eUint16 : vk::IndexType::eUint32) {} - ~VulkanGeometry() override - { - if (m_vertexBuffer) VulkanGeometry::Close(); - } - - void Init(Scene::Geometry* geo, ManagedBuffer::Ptr& vertexBuffer, ManagedBuffer::Ptr& indexBuffer) - { - m_geometry = geo; - m_vertexBuffer = std::move(vertexBuffer); - m_indexBuffer = std::move(indexBuffer); - m_indexType = (geo->indexType == Scene::VertexIndexType::UINT16) ? vk::IndexType::eUint16 : vk::IndexType::eUint32; - } + ~VulkanGeometry() override = default; void RecordBind(vk::CommandBuffer& cmdBuffer) { @@ -52,15 +37,13 @@ namespace OpenVulkano::Vulkan void RecordDraw(vk::CommandBuffer& cmdBuffer) { - if (m_geometry->GetIndexCount()) { cmdBuffer.drawIndexed(m_geometry->GetIndexCount(), 1, 0, 0, 0); } - else { cmdBuffer.draw(m_geometry->GetVertexCount(), 1, 0, 0); } + if (GetOwner()->GetIndexCount()) { cmdBuffer.drawIndexed(GetOwner()->GetIndexCount(), 1, 0, 0, 0); } + else { cmdBuffer.draw(GetOwner()->GetVertexCount(), 1, 0, 0); } } - void Close() override + void Release() override { - m_geometry->renderGeo = nullptr; - m_vertexBuffer.reset(); - m_indexBuffer.reset(); + //TODO } }; } From 6f19758bebec5191d575ff6df924e8f583e9e744 Mon Sep 17 00:00:00 2001 From: Georg Hagen Date: Wed, 21 Aug 2024 15:09:49 +0200 Subject: [PATCH 7/8] Render resource handling for camera --- openVulkanoCpp/Scene/Camera.hpp | 12 +++---- .../Vulkan/Resources/ResourceManager.cpp | 8 ++--- openVulkanoCpp/Vulkan/Scene/VulkanCamera.hpp | 33 ++++++++----------- openVulkanoCpp/Vulkan/VulkanDrawContext.cpp | 4 +-- 4 files changed, 24 insertions(+), 33 deletions(-) diff --git a/openVulkanoCpp/Scene/Camera.hpp b/openVulkanoCpp/Scene/Camera.hpp index 08dfac3..f755ded 100644 --- a/openVulkanoCpp/Scene/Camera.hpp +++ b/openVulkanoCpp/Scene/Camera.hpp @@ -13,10 +13,9 @@ namespace OpenVulkano::Scene { - class Camera : public Node + class Camera : public RenderResourceHolder, public Node { public: - ICloseable* renderCamera = nullptr; static constexpr inline size_t SIZE = sizeof(Math::Matrix4f) * 3 + sizeof(Math::Vector4f) + sizeof(float) * 12; static constexpr inline DescriptorSetLayoutBinding DESCRIPTOR_SET_LAYOUT_BINDING = { 0, DescriptorSetLayoutBinding::Type::TYPE_UNIFORM_BUFFER_DYNAMIC, 1, ShaderProgramType::ALL_GRAPHICS }; @@ -36,10 +35,7 @@ namespace OpenVulkano::Scene { } - ~Camera() override - { - //if (renderCamera) renderCamera->Close(); - } + ~Camera() override = default; void Init(float width, float height, float nearPlane, float farPlane) { @@ -152,6 +148,10 @@ namespace OpenVulkano::Scene float GetWidth() const { return m_width; } float GetHeight() const { return m_height; } Math::Vector2f GetSize() const { return { m_width, m_height }; } + + using RenderResourceHolder::GetRenderResource; + using RenderResourceHolder::HasRenderResource; + using RenderResourceHolder::operator RenderResourcePtr&; }; class PerspectiveCamera : public Camera diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp index 16e9c4b..ff946c0 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp @@ -213,7 +213,7 @@ namespace OpenVulkano::Vulkan VulkanCamera* ResourceManager::PrepareCamera(Scene::Camera* camera) { const std::unique_lock lock(mutex); - if (!camera->renderCamera) + if (!camera->HasRenderResource()) { const vk::DeviceSize allocSize = Utils::Align(Scene::Camera::SIZE, uniformBufferAlignment); const uint32_t imgs = context->swapChain.GetImageCount(); @@ -221,12 +221,10 @@ namespace OpenVulkano::Vulkan buffer->Map(); UniformBuffer* uBuffer = new UniformBuffer(); 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); + VulkanCamera* vkCam = new VulkanCamera(camera, uBuffer); cameras.emplace_back(vkCam); - camera->renderCamera = vkCam; } - return static_cast(camera->renderCamera); + return static_cast(camera->GetRenderResource()); } UniformBuffer* ResourceManager::CreateUniformBuffer(const DescriptorSetLayoutBinding& binding, size_t size, void* data, uint32_t setId, bool hostVis) diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanCamera.hpp b/openVulkanoCpp/Vulkan/Scene/VulkanCamera.hpp index 1832fec..5ba6dce 100644 --- a/openVulkanoCpp/Vulkan/Scene/VulkanCamera.hpp +++ b/openVulkanoCpp/Vulkan/Scene/VulkanCamera.hpp @@ -6,41 +6,34 @@ #pragma once -#include "Base/ICloseable.hpp" #include "Scene/Camera.hpp" #include "IRecordable.hpp" #include "Vulkan/Resources/UniformBuffer.hpp" namespace OpenVulkano::Vulkan { - class VulkanCamera : public ICloseable, public IRecordable +class VulkanCamera : public IRenderResource, public IRecordable { - Scene::Camera* m_camera = nullptr; - UniformBuffer* m_buffer = nullptr; + const Unique m_buffer; public: - ~VulkanCamera() override { if (m_camera) VulkanCamera::Close(); } + VulkanCamera(Scene::Camera* camera, UniformBuffer* uniformBuffer) + : IRenderResource(camera), m_buffer(uniformBuffer) + {} - void Init(Scene::Camera* camera, UniformBuffer* uniformBuffer) - { - m_camera = camera; - m_buffer = uniformBuffer; - } + ~VulkanCamera() override = default; void Record(VulkanDrawContext* context) override { - m_buffer->Update(m_camera->GetData(), Scene::Camera::SIZE, context->currentImageId); + m_buffer->Update(GetCamera()->GetData(), Scene::Camera::SIZE, context->currentImageId); m_buffer->Record(context); } - - void Close() override - { - m_camera->renderCamera = nullptr; - m_buffer->Close(); - m_camera = nullptr; - delete m_buffer; - } - [[nodiscard]] Scene::Camera* GetCamera() const { return m_camera; } + [[nodiscard]] Scene::Camera* GetCamera() const { return GetOwner(); } + + void Release() override + { + /* TODO */ + } }; } diff --git a/openVulkanoCpp/Vulkan/VulkanDrawContext.cpp b/openVulkanoCpp/Vulkan/VulkanDrawContext.cpp index 935bdd5..740aac6 100644 --- a/openVulkanoCpp/Vulkan/VulkanDrawContext.cpp +++ b/openVulkanoCpp/Vulkan/VulkanDrawContext.cpp @@ -44,8 +44,8 @@ namespace OpenVulkano::Vulkan void VulkanDrawContext::SetCamera(Scene::Camera* camera) { - if (!camera->renderCamera) m_lastCamera = ResourceManager::INSTANCE->PrepareCamera(camera); - else m_lastCamera = static_cast(camera->renderCamera); + if (!camera->HasRenderResource()) m_lastCamera = ResourceManager::INSTANCE->PrepareCamera(camera); + else m_lastCamera = camera->GetRenderResource(); if (m_lastShader) m_lastCamera->Record(this); } } \ No newline at end of file From 35515c79020743a6e9fd328fddf3478ebf843a96 Mon Sep 17 00:00:00 2001 From: Georg Hagen Date: Wed, 21 Aug 2024 15:45:46 +0200 Subject: [PATCH 8/8] Prevent crash when trying to release buffer from already destroyed memory pool --- openVulkanoCpp/Vulkan/Metal/MetalBackedTexture.mm | 2 -- openVulkanoCpp/Vulkan/Resources/ManagedBuffer.hpp | 2 +- openVulkanoCpp/Vulkan/Resources/MemoryPool.cpp | 2 ++ openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp | 1 + openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp | 3 +++ 5 files changed, 7 insertions(+), 3 deletions(-) diff --git a/openVulkanoCpp/Vulkan/Metal/MetalBackedTexture.mm b/openVulkanoCpp/Vulkan/Metal/MetalBackedTexture.mm index 10f23d3..db65281 100644 --- a/openVulkanoCpp/Vulkan/Metal/MetalBackedTexture.mm +++ b/openVulkanoCpp/Vulkan/Metal/MetalBackedTexture.mm @@ -56,8 +56,6 @@ namespace OpenVulkano::Vulkan m_vulkanTexture.m_sampler = resManager->CreateSampler(reinterpret_cast(Scene::SamplerConfig::DEFAULT)); m_vulkanTexture.SetDescriptorSet(resManager, resManager->GetDescriptorLayoutSet(binding), binding); - //m_vulkanTexture.UpdateAddress(this); - //UpdateRenderResource(GetOwnerResource()); GetRenderResource().renderObject = &m_vulkanTexture; m_vulkanTexture.UpdateAddress(this); diff --git a/openVulkanoCpp/Vulkan/Resources/ManagedBuffer.hpp b/openVulkanoCpp/Vulkan/Resources/ManagedBuffer.hpp index 7689741..4dedc18 100644 --- a/openVulkanoCpp/Vulkan/Resources/ManagedBuffer.hpp +++ b/openVulkanoCpp/Vulkan/Resources/ManagedBuffer.hpp @@ -33,7 +33,7 @@ namespace OpenVulkano::Vulkan ~ManagedBuffer() { - allocation->device.destroy(buffer); + if (allocation) [[likely]] allocation->device.destroy(buffer); } [[nodiscard]] bool IsLast() const diff --git a/openVulkanoCpp/Vulkan/Resources/MemoryPool.cpp b/openVulkanoCpp/Vulkan/Resources/MemoryPool.cpp index 4292dc3..2b9ac70 100644 --- a/openVulkanoCpp/Vulkan/Resources/MemoryPool.cpp +++ b/openVulkanoCpp/Vulkan/Resources/MemoryPool.cpp @@ -23,6 +23,8 @@ namespace OpenVulkano::Vulkan { if (memPool->FreeBuffer(buffer)) return; } + Logger::RENDER->error("Attempted to released buffer to pool, but owning pool no longer exists!"); + buffer->allocation = nullptr; // Allocation is no longer valid since owning pool is gone already delete buffer; } diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp index ff946c0..435542a 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp @@ -98,6 +98,7 @@ namespace OpenVulkano::Vulkan { transferQueue.waitIdle(); transferQueue = nullptr; + OnShutdown(this); // Notify all custom resources that it's time to die geometries.clear(); nodes.clear(); textures.clear(); diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp index b347f73..9274a32 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp @@ -14,6 +14,7 @@ #include "IShaderOwner.hpp" #include "MemoryPool.hpp" #include "Base/Wrapper.hpp" +#include "Base/Event.hpp" #include "Base/Render/IResourceManager.hpp" #include "Vulkan/Image.hpp" #include "Scene/Shader/DescriptorInputDescription.hpp" @@ -134,6 +135,8 @@ namespace OpenVulkano vk::DescriptorSetLayout* GetDescriptorLayoutSet(const DescriptorSetLayoutBinding& descriptorSetLayoutBinding); VulkanShader* CreateShader(Scene::Shader* shader); + + Event OnShutdown; }; } }