Graphics: Fix WorldInstance removal while being in use

This commit is contained in:
Jérôme Leclercq 2021-07-28 13:31:13 +02:00
parent 03236b70c1
commit 5b1123b971
8 changed files with 41 additions and 35 deletions

View File

@ -28,8 +28,7 @@ namespace Nz
inline void DetachRenderable(const std::shared_ptr<InstancedRenderable>& renderable); inline void DetachRenderable(const std::shared_ptr<InstancedRenderable>& renderable);
inline const std::vector<std::shared_ptr<InstancedRenderable>>& GetRenderables() const; inline const std::vector<std::shared_ptr<InstancedRenderable>>& GetRenderables() const;
inline WorldInstance& GetWorldInstance(); inline const WorldInstancePtr& GetWorldInstance() const;
inline const WorldInstance& GetWorldInstance() const;
GraphicsComponent& operator=(const GraphicsComponent&) = default; GraphicsComponent& operator=(const GraphicsComponent&) = default;
GraphicsComponent& operator=(GraphicsComponent&&) = default; GraphicsComponent& operator=(GraphicsComponent&&) = default;
@ -39,7 +38,7 @@ namespace Nz
private: private:
std::vector<std::shared_ptr<InstancedRenderable>> m_renderables; std::vector<std::shared_ptr<InstancedRenderable>> m_renderables;
std::unique_ptr<WorldInstance> m_worldInstance; WorldInstancePtr m_worldInstance;
}; };
} }

View File

@ -9,7 +9,7 @@ namespace Nz
{ {
inline GraphicsComponent::GraphicsComponent() inline GraphicsComponent::GraphicsComponent()
{ {
m_worldInstance = std::make_unique<WorldInstance>(); //< FIXME m_worldInstance = std::make_shared<WorldInstance>(); //< FIXME: Use pools
} }
inline void GraphicsComponent::AttachRenderable(std::shared_ptr<InstancedRenderable> renderable) inline void GraphicsComponent::AttachRenderable(std::shared_ptr<InstancedRenderable> renderable)
@ -35,13 +35,8 @@ namespace Nz
return m_renderables; return m_renderables;
} }
inline WorldInstance& GraphicsComponent::GetWorldInstance() inline const WorldInstancePtr& GraphicsComponent::GetWorldInstance() const
{ {
return *m_worldInstance; return m_worldInstance;
}
inline const WorldInstance& GraphicsComponent::GetWorldInstance() const
{
return *m_worldInstance;
} }
} }

View File

@ -36,12 +36,12 @@ namespace Nz
void InvalidateViewer(AbstractViewer* viewerInstance) override; void InvalidateViewer(AbstractViewer* viewerInstance) override;
void InvalidateWorldInstance(WorldInstance* worldInstance) 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 RegisterViewer(AbstractViewer* viewerInstance) override;
void Render(RenderFrame& renderFrame) 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; void UnregisterViewer(AbstractViewer* viewerInstance) override;
ForwardFramePipeline& operator=(const ForwardFramePipeline&) = delete; ForwardFramePipeline& operator=(const ForwardFramePipeline&) = delete;
@ -75,10 +75,11 @@ namespace Nz
std::unordered_map<AbstractViewer*, ViewerData> m_viewers; std::unordered_map<AbstractViewer*, ViewerData> m_viewers;
std::unordered_map<MaterialPass*, MaterialData> m_materials; std::unordered_map<MaterialPass*, MaterialData> m_materials;
std::unordered_map<WorldInstance*, std::unordered_map<const InstancedRenderable*, RenderableData>> m_renderables; std::unordered_map<WorldInstancePtr, std::unordered_map<const InstancedRenderable*, RenderableData>> m_renderables;
std::unordered_set<AbstractViewer*> m_invalidatedViewerInstances; std::unordered_set<AbstractViewer*> m_invalidatedViewerInstances;
std::unordered_set<MaterialPass*> m_invalidatedMaterials; std::unordered_set<MaterialPass*> m_invalidatedMaterials;
std::unordered_set<WorldInstance*> m_invalidatedWorldInstances; std::unordered_set<WorldInstance*> m_invalidatedWorldInstances;
std::unordered_set<WorldInstancePtr> m_removedWorldInstances;
std::vector<std::unique_ptr<RenderElement>> m_depthPrepassRenderElements; std::vector<std::unique_ptr<RenderElement>> m_depthPrepassRenderElements;
std::vector<std::unique_ptr<RenderElement>> m_forwardRenderElements; std::vector<std::unique_ptr<RenderElement>> m_forwardRenderElements;
std::vector<std::unique_ptr<ElementRenderer>> m_elementRenderers; std::vector<std::unique_ptr<ElementRenderer>> m_elementRenderers;

View File

@ -9,13 +9,13 @@
#include <Nazara/Prerequisites.hpp> #include <Nazara/Prerequisites.hpp>
#include <Nazara/Graphics/Config.hpp> #include <Nazara/Graphics/Config.hpp>
#include <Nazara/Graphics/WorldInstance.hpp>
namespace Nz namespace Nz
{ {
class AbstractViewer; class AbstractViewer;
class InstancedRenderable; class InstancedRenderable;
class RenderFrame; class RenderFrame;
class WorldInstance;
class NAZARA_GRAPHICS_API FramePipeline class NAZARA_GRAPHICS_API FramePipeline
{ {
@ -28,12 +28,12 @@ namespace Nz
virtual void InvalidateViewer(AbstractViewer* viewerInstance) = 0; virtual void InvalidateViewer(AbstractViewer* viewerInstance) = 0;
virtual void InvalidateWorldInstance(WorldInstance* worldInstance) = 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 RegisterViewer(AbstractViewer* viewerInstance) = 0;
virtual void Render(RenderFrame& renderFrame) = 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; virtual void UnregisterViewer(AbstractViewer* viewerInstance) = 0;
FramePipeline& operator=(const FramePipeline&) = delete; FramePipeline& operator=(const FramePipeline&) = delete;

View File

@ -19,6 +19,9 @@ namespace Nz
class CommandBufferBuilder; class CommandBufferBuilder;
class MaterialSettings; class MaterialSettings;
class UploadPool; class UploadPool;
class WorldInstance;
using WorldInstancePtr = std::shared_ptr<WorldInstance>;
class NAZARA_GRAPHICS_API WorldInstance class NAZARA_GRAPHICS_API WorldInstance
{ {

View File

@ -41,8 +41,10 @@ namespace Nz
m_invalidatedWorldInstances.insert(worldInstance); 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]; auto& renderableMap = m_renderables[worldInstance];
if (auto it = renderableMap.find(instancedRenderable); it == renderableMap.end()) if (auto it = renderableMap.find(instancedRenderable); it == renderableMap.end())
{ {
@ -99,6 +101,9 @@ namespace Nz
{ {
Graphics* graphics = Graphics::Instance(); Graphics* graphics = Graphics::Instance();
renderFrame.PushForRelease(std::move(m_removedWorldInstances));
m_removedWorldInstances.clear();
if (m_rebuildFrameGraph) if (m_rebuildFrameGraph)
{ {
renderFrame.PushForRelease(std::move(m_bakedFrameGraph)); 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); auto instanceIt = m_renderables.find(worldInstance);
if (instanceIt == m_renderables.end()) if (instanceIt == m_renderables.end())
@ -267,7 +272,10 @@ namespace Nz
if (instancedRenderables.size() > 1) if (instancedRenderables.size() > 1)
instancedRenderables.erase(renderableIt); instancedRenderables.erase(renderableIt);
else else
m_renderables.erase(worldInstance); {
m_removedWorldInstances.insert(worldInstance);
m_renderables.erase(instanceIt);;
}
std::size_t matCount = instancedRenderable->GetMaterialCount(); std::size_t matCount = instancedRenderable->GetMaterialCount();
for (std::size_t i = 0; i < matCount; ++i) for (std::size_t i = 0; i < matCount; ++i)

View File

@ -60,9 +60,9 @@ namespace Nz
GraphicsComponent& entityGfx = registry.get<GraphicsComponent>(entity); GraphicsComponent& entityGfx = registry.get<GraphicsComponent>(entity);
NodeComponent& entityNode = registry.get<NodeComponent>(entity); NodeComponent& entityNode = registry.get<NodeComponent>(entity);
WorldInstance& worldInstance = entityGfx.GetWorldInstance(); const WorldInstancePtr& worldInstance = entityGfx.GetWorldInstance();
for (const auto& renderable : entityGfx.GetRenderables()) for (const auto& renderable : entityGfx.GetRenderables())
m_pipeline->RegisterInstancedDrawable(&worldInstance, renderable.get()); m_pipeline->RegisterInstancedDrawable(worldInstance, renderable.get());
m_invalidatedWorldNode.insert(entity); m_invalidatedWorldNode.insert(entity);
@ -75,14 +75,14 @@ namespace Nz
graphicsEntity.onRenderableAttached.Connect(entityGfx.OnRenderableAttached, [this](GraphicsComponent* gfx, const std::shared_ptr<InstancedRenderable>& renderable) graphicsEntity.onRenderableAttached.Connect(entityGfx.OnRenderableAttached, [this](GraphicsComponent* gfx, const std::shared_ptr<InstancedRenderable>& renderable)
{ {
WorldInstance& worldInstance = gfx->GetWorldInstance(); const WorldInstancePtr& worldInstance = gfx->GetWorldInstance();
m_pipeline->RegisterInstancedDrawable(&worldInstance, renderable.get()); m_pipeline->RegisterInstancedDrawable(worldInstance, renderable.get());
}); });
graphicsEntity.onRenderableDetach.Connect(entityGfx.OnRenderableDetach, [this](GraphicsComponent* gfx, const std::shared_ptr<InstancedRenderable>& renderable) graphicsEntity.onRenderableDetach.Connect(entityGfx.OnRenderableDetach, [this](GraphicsComponent* gfx, const std::shared_ptr<InstancedRenderable>& renderable)
{ {
WorldInstance& worldInstance = gfx->GetWorldInstance(); const WorldInstancePtr& worldInstance = gfx->GetWorldInstance();
m_pipeline->UnregisterInstancedDrawable(&worldInstance, renderable.get()); m_pipeline->UnregisterInstancedDrawable(worldInstance, renderable.get());
}); });
}); });
@ -106,9 +106,9 @@ namespace Nz
m_invalidatedWorldNode.erase(entity); m_invalidatedWorldNode.erase(entity);
GraphicsComponent& entityGfx = registry.get<GraphicsComponent>(entity); GraphicsComponent& entityGfx = registry.get<GraphicsComponent>(entity);
WorldInstance& worldInstance = entityGfx.GetWorldInstance(); const WorldInstancePtr& worldInstance = entityGfx.GetWorldInstance();
for (const auto& renderable : entityGfx.GetRenderables()) 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) void RenderSystem::OnNodeDestroy(entt::registry& registry, entt::entity entity)
@ -139,10 +139,10 @@ namespace Nz
const NodeComponent& entityNode = registry.get<const NodeComponent>(entity); const NodeComponent& entityNode = registry.get<const NodeComponent>(entity);
GraphicsComponent& entityGraphics = registry.get<GraphicsComponent>(entity); GraphicsComponent& entityGraphics = registry.get<GraphicsComponent>(entity);
WorldInstance& worldInstance = entityGraphics.GetWorldInstance(); const WorldInstancePtr& worldInstance = entityGraphics.GetWorldInstance();
worldInstance.UpdateWorldMatrix(entityNode.GetTransformMatrix()); worldInstance->UpdateWorldMatrix(entityNode.GetTransformMatrix());
m_pipeline->InvalidateWorldInstance(&worldInstance); m_pipeline->InvalidateWorldInstance(worldInstance.get());
} }
m_invalidatedWorldNode.clear(); m_invalidatedWorldNode.clear();
} }

View File

@ -18,7 +18,7 @@ namespace Nz
m_worldMatrix(Nz::Matrix4f::Identity()), m_worldMatrix(Nz::Matrix4f::Identity()),
m_dataInvalided(true) m_dataInvalided(true)
{ {
Nz::PredefinedInstanceData instanceUboOffsets = Nz::PredefinedInstanceData::GetOffsets(); PredefinedInstanceData instanceUboOffsets = PredefinedInstanceData::GetOffsets();
m_instanceDataBuffer = Graphics::Instance()->GetRenderDevice()->InstantiateBuffer(BufferType::Uniform); m_instanceDataBuffer = Graphics::Instance()->GetRenderDevice()->InstantiateBuffer(BufferType::Uniform);
if (!m_instanceDataBuffer->Initialize(instanceUboOffsets.totalSize, Nz::BufferUsage::DeviceLocal | Nz::BufferUsage::Dynamic)) if (!m_instanceDataBuffer->Initialize(instanceUboOffsets.totalSize, Nz::BufferUsage::DeviceLocal | Nz::BufferUsage::Dynamic))
@ -39,11 +39,11 @@ namespace Nz
{ {
if (m_dataInvalided) if (m_dataInvalided)
{ {
Nz::PredefinedInstanceData instanceUboOffsets = Nz::PredefinedInstanceData::GetOffsets(); PredefinedInstanceData instanceUboOffsets = PredefinedInstanceData::GetOffsets();
auto& allocation = uploadPool.Allocate(m_instanceDataBuffer->GetSize()); auto& allocation = uploadPool.Allocate(m_instanceDataBuffer->GetSize());
Nz::AccessByOffset<Nz::Matrix4f&>(allocation.mappedPtr, instanceUboOffsets.worldMatrixOffset) = m_worldMatrix; AccessByOffset<Matrix4f&>(allocation.mappedPtr, instanceUboOffsets.worldMatrixOffset) = m_worldMatrix;
Nz::AccessByOffset<Nz::Matrix4f&>(allocation.mappedPtr, instanceUboOffsets.invWorldMatrixOffset) = m_invWorldMatrix; AccessByOffset<Matrix4f&>(allocation.mappedPtr, instanceUboOffsets.invWorldMatrixOffset) = m_invWorldMatrix;
builder.CopyBuffer(allocation, m_instanceDataBuffer.get()); builder.CopyBuffer(allocation, m_instanceDataBuffer.get());