diff --git a/include/Nazara/Graphics/Components/GraphicsComponent.hpp b/include/Nazara/Graphics/Components/GraphicsComponent.hpp index f00c668fe..033b755b5 100644 --- a/include/Nazara/Graphics/Components/GraphicsComponent.hpp +++ b/include/Nazara/Graphics/Components/GraphicsComponent.hpp @@ -28,8 +28,7 @@ namespace Nz inline void DetachRenderable(const std::shared_ptr& renderable); inline const std::vector>& GetRenderables() const; - inline WorldInstance& GetWorldInstance(); - inline const WorldInstance& GetWorldInstance() const; + inline const WorldInstancePtr& GetWorldInstance() const; GraphicsComponent& operator=(const GraphicsComponent&) = default; GraphicsComponent& operator=(GraphicsComponent&&) = default; @@ -39,7 +38,7 @@ namespace Nz private: std::vector> m_renderables; - std::unique_ptr m_worldInstance; + WorldInstancePtr m_worldInstance; }; } diff --git a/include/Nazara/Graphics/Components/GraphicsComponent.inl b/include/Nazara/Graphics/Components/GraphicsComponent.inl index 68887d605..31a31cb8b 100644 --- a/include/Nazara/Graphics/Components/GraphicsComponent.inl +++ b/include/Nazara/Graphics/Components/GraphicsComponent.inl @@ -9,7 +9,7 @@ namespace Nz { inline GraphicsComponent::GraphicsComponent() { - m_worldInstance = std::make_unique(); //< FIXME + m_worldInstance = std::make_shared(); //< FIXME: Use pools } inline void GraphicsComponent::AttachRenderable(std::shared_ptr renderable) @@ -35,13 +35,8 @@ namespace Nz return m_renderables; } - inline WorldInstance& GraphicsComponent::GetWorldInstance() + inline const WorldInstancePtr& GraphicsComponent::GetWorldInstance() const { - return *m_worldInstance; - } - - inline const WorldInstance& GraphicsComponent::GetWorldInstance() const - { - return *m_worldInstance; + return m_worldInstance; } } diff --git a/include/Nazara/Graphics/ForwardFramePipeline.hpp b/include/Nazara/Graphics/ForwardFramePipeline.hpp index bf211413d..ce72b1cb6 100644 --- a/include/Nazara/Graphics/ForwardFramePipeline.hpp +++ b/include/Nazara/Graphics/ForwardFramePipeline.hpp @@ -36,12 +36,12 @@ namespace Nz void InvalidateViewer(AbstractViewer* viewerInstance) override; void InvalidateWorldInstance(WorldInstance* worldInstance) override; - void RegisterInstancedDrawable(WorldInstance* worldInstance, const InstancedRenderable* instancedRenderable) override; + void RegisterInstancedDrawable(WorldInstancePtr worldInstance, const InstancedRenderable* instancedRenderable) override; void RegisterViewer(AbstractViewer* viewerInstance) override; void Render(RenderFrame& renderFrame) override; - void UnregisterInstancedDrawable(WorldInstance* worldInstance, const InstancedRenderable* instancedRenderable) override; + void UnregisterInstancedDrawable(const WorldInstancePtr& worldInstance, const InstancedRenderable* instancedRenderable) override; void UnregisterViewer(AbstractViewer* viewerInstance) override; ForwardFramePipeline& operator=(const ForwardFramePipeline&) = delete; @@ -75,10 +75,11 @@ namespace Nz std::unordered_map m_viewers; std::unordered_map m_materials; - std::unordered_map> m_renderables; + std::unordered_map> m_renderables; std::unordered_set m_invalidatedViewerInstances; std::unordered_set m_invalidatedMaterials; std::unordered_set m_invalidatedWorldInstances; + std::unordered_set m_removedWorldInstances; std::vector> m_depthPrepassRenderElements; std::vector> m_forwardRenderElements; std::vector> m_elementRenderers; diff --git a/include/Nazara/Graphics/FramePipeline.hpp b/include/Nazara/Graphics/FramePipeline.hpp index 9272fcd79..da5ae5edf 100644 --- a/include/Nazara/Graphics/FramePipeline.hpp +++ b/include/Nazara/Graphics/FramePipeline.hpp @@ -9,13 +9,13 @@ #include #include +#include namespace Nz { class AbstractViewer; class InstancedRenderable; class RenderFrame; - class WorldInstance; class NAZARA_GRAPHICS_API FramePipeline { @@ -28,12 +28,12 @@ namespace Nz virtual void InvalidateViewer(AbstractViewer* viewerInstance) = 0; virtual void InvalidateWorldInstance(WorldInstance* worldInstance) = 0; - virtual void RegisterInstancedDrawable(WorldInstance* worldInstance, const InstancedRenderable* instancedRenderable) = 0; + virtual void RegisterInstancedDrawable(WorldInstancePtr worldInstance, const InstancedRenderable* instancedRenderable) = 0; virtual void RegisterViewer(AbstractViewer* viewerInstance) = 0; virtual void Render(RenderFrame& renderFrame) = 0; - virtual void UnregisterInstancedDrawable(WorldInstance* worldInstance, const InstancedRenderable* instancedRenderable) = 0; + virtual void UnregisterInstancedDrawable(const WorldInstancePtr& worldInstance, const InstancedRenderable* instancedRenderable) = 0; virtual void UnregisterViewer(AbstractViewer* viewerInstance) = 0; FramePipeline& operator=(const FramePipeline&) = delete; diff --git a/include/Nazara/Graphics/WorldInstance.hpp b/include/Nazara/Graphics/WorldInstance.hpp index 8699eacd3..acae986c5 100644 --- a/include/Nazara/Graphics/WorldInstance.hpp +++ b/include/Nazara/Graphics/WorldInstance.hpp @@ -19,6 +19,9 @@ namespace Nz class CommandBufferBuilder; class MaterialSettings; class UploadPool; + class WorldInstance; + + using WorldInstancePtr = std::shared_ptr; class NAZARA_GRAPHICS_API WorldInstance { diff --git a/src/Nazara/Graphics/ForwardFramePipeline.cpp b/src/Nazara/Graphics/ForwardFramePipeline.cpp index a7ee3a9ad..1c560afe0 100644 --- a/src/Nazara/Graphics/ForwardFramePipeline.cpp +++ b/src/Nazara/Graphics/ForwardFramePipeline.cpp @@ -41,8 +41,10 @@ namespace Nz m_invalidatedWorldInstances.insert(worldInstance); } - void ForwardFramePipeline::RegisterInstancedDrawable(WorldInstance* worldInstance, const InstancedRenderable* instancedRenderable) + void ForwardFramePipeline::RegisterInstancedDrawable(WorldInstancePtr worldInstance, const InstancedRenderable* instancedRenderable) { + m_removedWorldInstances.erase(worldInstance); + auto& renderableMap = m_renderables[worldInstance]; if (auto it = renderableMap.find(instancedRenderable); it == renderableMap.end()) { @@ -99,6 +101,9 @@ namespace Nz { Graphics* graphics = Graphics::Instance(); + renderFrame.PushForRelease(std::move(m_removedWorldInstances)); + m_removedWorldInstances.clear(); + if (m_rebuildFrameGraph) { renderFrame.PushForRelease(std::move(m_bakedFrameGraph)); @@ -252,7 +257,7 @@ namespace Nz } } - void ForwardFramePipeline::UnregisterInstancedDrawable(WorldInstance* worldInstance, const InstancedRenderable* instancedRenderable) + void ForwardFramePipeline::UnregisterInstancedDrawable(const WorldInstancePtr& worldInstance, const InstancedRenderable* instancedRenderable) { auto instanceIt = m_renderables.find(worldInstance); if (instanceIt == m_renderables.end()) @@ -267,7 +272,10 @@ namespace Nz if (instancedRenderables.size() > 1) instancedRenderables.erase(renderableIt); else - m_renderables.erase(worldInstance); + { + m_removedWorldInstances.insert(worldInstance); + m_renderables.erase(instanceIt);; + } std::size_t matCount = instancedRenderable->GetMaterialCount(); for (std::size_t i = 0; i < matCount; ++i) diff --git a/src/Nazara/Graphics/Systems/RenderSystem.cpp b/src/Nazara/Graphics/Systems/RenderSystem.cpp index fffa76ad6..8298d02df 100644 --- a/src/Nazara/Graphics/Systems/RenderSystem.cpp +++ b/src/Nazara/Graphics/Systems/RenderSystem.cpp @@ -60,9 +60,9 @@ namespace Nz GraphicsComponent& entityGfx = registry.get(entity); NodeComponent& entityNode = registry.get(entity); - WorldInstance& worldInstance = entityGfx.GetWorldInstance(); + const WorldInstancePtr& worldInstance = entityGfx.GetWorldInstance(); for (const auto& renderable : entityGfx.GetRenderables()) - m_pipeline->RegisterInstancedDrawable(&worldInstance, renderable.get()); + m_pipeline->RegisterInstancedDrawable(worldInstance, renderable.get()); m_invalidatedWorldNode.insert(entity); @@ -75,14 +75,14 @@ namespace Nz graphicsEntity.onRenderableAttached.Connect(entityGfx.OnRenderableAttached, [this](GraphicsComponent* gfx, const std::shared_ptr& renderable) { - WorldInstance& worldInstance = gfx->GetWorldInstance(); - m_pipeline->RegisterInstancedDrawable(&worldInstance, renderable.get()); + const WorldInstancePtr& worldInstance = gfx->GetWorldInstance(); + m_pipeline->RegisterInstancedDrawable(worldInstance, renderable.get()); }); graphicsEntity.onRenderableDetach.Connect(entityGfx.OnRenderableDetach, [this](GraphicsComponent* gfx, const std::shared_ptr& renderable) { - WorldInstance& worldInstance = gfx->GetWorldInstance(); - m_pipeline->UnregisterInstancedDrawable(&worldInstance, renderable.get()); + const WorldInstancePtr& worldInstance = gfx->GetWorldInstance(); + m_pipeline->UnregisterInstancedDrawable(worldInstance, renderable.get()); }); }); @@ -106,9 +106,9 @@ namespace Nz m_invalidatedWorldNode.erase(entity); GraphicsComponent& entityGfx = registry.get(entity); - WorldInstance& worldInstance = entityGfx.GetWorldInstance(); + const WorldInstancePtr& worldInstance = entityGfx.GetWorldInstance(); for (const auto& renderable : entityGfx.GetRenderables()) - m_pipeline->UnregisterInstancedDrawable(&worldInstance, renderable.get()); + m_pipeline->UnregisterInstancedDrawable(worldInstance, renderable.get()); } void RenderSystem::OnNodeDestroy(entt::registry& registry, entt::entity entity) @@ -139,10 +139,10 @@ namespace Nz const NodeComponent& entityNode = registry.get(entity); GraphicsComponent& entityGraphics = registry.get(entity); - WorldInstance& worldInstance = entityGraphics.GetWorldInstance(); - worldInstance.UpdateWorldMatrix(entityNode.GetTransformMatrix()); + const WorldInstancePtr& worldInstance = entityGraphics.GetWorldInstance(); + worldInstance->UpdateWorldMatrix(entityNode.GetTransformMatrix()); - m_pipeline->InvalidateWorldInstance(&worldInstance); + m_pipeline->InvalidateWorldInstance(worldInstance.get()); } m_invalidatedWorldNode.clear(); } diff --git a/src/Nazara/Graphics/WorldInstance.cpp b/src/Nazara/Graphics/WorldInstance.cpp index a0ace8993..0ef10a809 100644 --- a/src/Nazara/Graphics/WorldInstance.cpp +++ b/src/Nazara/Graphics/WorldInstance.cpp @@ -18,7 +18,7 @@ namespace Nz m_worldMatrix(Nz::Matrix4f::Identity()), m_dataInvalided(true) { - Nz::PredefinedInstanceData instanceUboOffsets = Nz::PredefinedInstanceData::GetOffsets(); + PredefinedInstanceData instanceUboOffsets = PredefinedInstanceData::GetOffsets(); m_instanceDataBuffer = Graphics::Instance()->GetRenderDevice()->InstantiateBuffer(BufferType::Uniform); if (!m_instanceDataBuffer->Initialize(instanceUboOffsets.totalSize, Nz::BufferUsage::DeviceLocal | Nz::BufferUsage::Dynamic)) @@ -39,11 +39,11 @@ namespace Nz { if (m_dataInvalided) { - Nz::PredefinedInstanceData instanceUboOffsets = Nz::PredefinedInstanceData::GetOffsets(); + PredefinedInstanceData instanceUboOffsets = PredefinedInstanceData::GetOffsets(); auto& allocation = uploadPool.Allocate(m_instanceDataBuffer->GetSize()); - Nz::AccessByOffset(allocation.mappedPtr, instanceUboOffsets.worldMatrixOffset) = m_worldMatrix; - Nz::AccessByOffset(allocation.mappedPtr, instanceUboOffsets.invWorldMatrixOffset) = m_invWorldMatrix; + AccessByOffset(allocation.mappedPtr, instanceUboOffsets.worldMatrixOffset) = m_worldMatrix; + AccessByOffset(allocation.mappedPtr, instanceUboOffsets.invWorldMatrixOffset) = m_invWorldMatrix; builder.CopyBuffer(allocation, m_instanceDataBuffer.get());