diff --git a/examples/DeferredShading/main.cpp b/examples/DeferredShading/main.cpp index 71ce63ce0..b00d768db 100644 --- a/examples/DeferredShading/main.cpp +++ b/examples/DeferredShading/main.cpp @@ -688,6 +688,8 @@ int main() std::exit(__LINE__); } + Nz::ElementRendererRegistry elementRegistry; + Nz::FrameGraph graph; colorTexture = graph.AddAttachment({ @@ -793,16 +795,26 @@ int main() { builder.SetViewport(env.renderRect); - std::vector> elements; - spaceshipModel.BuildElement(forwardPassIndex, modelInstance1, nullptr, elements, env.renderRect); - spaceshipModel.BuildElement(forwardPassIndex, modelInstance2, nullptr, elements, env.renderRect); - planeModel.BuildElement(forwardPassIndex, planeInstance, nullptr, elements, env.renderRect); + Nz::InstancedRenderable::ElementData elementData; + elementData.scissorBox = &env.renderRect; + elementData.skeletonInstance = nullptr; + + std::vector elements; + + elementData.worldInstance = &modelInstance1; + spaceshipModel.BuildElement(elementRegistry, elementData, forwardPassIndex, elements); + + elementData.worldInstance = &modelInstance2; + spaceshipModel.BuildElement(elementRegistry, elementData, forwardPassIndex, elements); + + elementData.worldInstance = &planeInstance; + planeModel.BuildElement(elementRegistry, elementData, forwardPassIndex, elements); std::vector> elementPointers; std::vector renderStates(elements.size()); elementPointers.reserve(elements.size()); - for (const auto& element : elements) - elementPointers.emplace_back(element.get()); + for (const auto& elementOwner : elements) + elementPointers.emplace_back(elementOwner.GetElement()); submeshRenderer.Prepare(viewerInstance, *submeshRendererData, *currentFrame, elementPointers.size(), elementPointers.data(), renderStates.data()); submeshRenderer.PrepareEnd(*currentFrame, *spriteRendererData); @@ -859,15 +871,20 @@ int main() builder.DrawIndexed(Nz::SafeCast(cubeMeshGfx->GetIndexCount(0))); - std::vector> elements; - flareSprite.BuildElement(forwardPassIndex, flareInstance, nullptr, elements, env.renderRect); + Nz::InstancedRenderable::ElementData elementData; + elementData.scissorBox = &env.renderRect; + elementData.skeletonInstance = nullptr; + elementData.worldInstance = &flareInstance; + + std::vector elements; + flareSprite.BuildElement(elementRegistry, elementData, forwardPassIndex, elements); std::vector> elementPointers; std::vector renderStates(elements.size()); elementPointers.reserve(elements.size()); for (const auto& element : elements) - elementPointers.emplace_back(element.get()); + elementPointers.emplace_back(element.GetElement()); spritechainRenderer.Prepare(viewerInstance, *spriteRendererData, *currentFrame, elementPointers.size(), elementPointers.data(), renderStates.data()); spritechainRenderer.Render(viewerInstance, *spriteRendererData, builder, elementPointers.size(), elementPointers.data()); @@ -888,15 +905,20 @@ int main() { builder.SetViewport(env.renderRect); - std::vector> elements; - flareSprite.BuildElement(forwardPassIndex, flareInstance, nullptr, elements, env.renderRect); + Nz::InstancedRenderable::ElementData elementData; + elementData.scissorBox = &env.renderRect; + elementData.skeletonInstance = nullptr; + elementData.worldInstance = &flareInstance; + + std::vector elements; + flareSprite.BuildElement(elementRegistry, elementData, forwardPassIndex, elements); std::vector> elementPointers; std::vector renderStates(elements.size()); elementPointers.reserve(elements.size()); for (const auto& element : elements) - elementPointers.emplace_back(element.get()); + elementPointers.emplace_back(element.GetElement()); spritechainRenderer.Prepare(viewerInstance, *spriteRendererData, *currentFrame, elementPointers.size(), elementPointers.data(), renderStates.data()); spritechainRenderer.PrepareEnd(*currentFrame, *spriteRendererData); diff --git a/examples/GraphicsTest/main.cpp b/examples/GraphicsTest/main.cpp index f1577641c..f7882be5d 100644 --- a/examples/GraphicsTest/main.cpp +++ b/examples/GraphicsTest/main.cpp @@ -98,7 +98,8 @@ int main() Nz::Recti scissorBox(Nz::Vector2i(window.GetSize())); - Nz::ForwardFramePipeline framePipeline; + Nz::ElementRendererRegistry elementRegistry; + Nz::ForwardFramePipeline framePipeline(elementRegistry); std::size_t cameraIndex = framePipeline.RegisterViewer(&camera, 0); std::size_t worldInstanceIndex1 = framePipeline.RegisterWorldInstance(modelInstance); std::size_t worldInstanceIndex2 = framePipeline.RegisterWorldInstance(modelInstance2); diff --git a/examples/PhysicallyBasedRendering/main.cpp b/examples/PhysicallyBasedRendering/main.cpp index b34f14d38..a14f9052e 100644 --- a/examples/PhysicallyBasedRendering/main.cpp +++ b/examples/PhysicallyBasedRendering/main.cpp @@ -91,7 +91,8 @@ int main() Nz::Recti scissorBox(Nz::Vector2i(window.GetSize())); - Nz::ForwardFramePipeline framePipeline; + Nz::ElementRendererRegistry elementRegistry; + Nz::ForwardFramePipeline framePipeline(elementRegistry); std::size_t cameraIndex = framePipeline.RegisterViewer(&camera, 0); std::size_t worldInstanceIndex1 = framePipeline.RegisterWorldInstance(modelInstance); framePipeline.RegisterRenderable(worldInstanceIndex1, Nz::FramePipeline::NoSkeletonInstance, &model, 0xFFFFFFFF, scissorBox); diff --git a/include/Nazara/Graphics.hpp b/include/Nazara/Graphics.hpp index 1e9b6d3ba..c235a51ae 100644 --- a/include/Nazara/Graphics.hpp +++ b/include/Nazara/Graphics.hpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -65,6 +66,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/include/Nazara/Graphics/DepthPipelinePass.hpp b/include/Nazara/Graphics/DepthPipelinePass.hpp index 7e2fe5855..58d771201 100644 --- a/include/Nazara/Graphics/DepthPipelinePass.hpp +++ b/include/Nazara/Graphics/DepthPipelinePass.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,7 @@ namespace Nz { class AbstractViewer; + class ElementRendererRegistry; class FrameGraph; class FramePipeline; class Material; @@ -27,7 +29,7 @@ namespace Nz class NAZARA_GRAPHICS_API DepthPipelinePass : public FramePipelinePass { public: - DepthPipelinePass(FramePipeline& owner, AbstractViewer* viewer); + DepthPipelinePass(FramePipeline& owner, ElementRendererRegistry& elementRegistry, AbstractViewer* viewer); DepthPipelinePass(const DepthPipelinePass&) = delete; DepthPipelinePass(DepthPipelinePass&&) = delete; ~DepthPipelinePass(); @@ -57,12 +59,13 @@ namespace Nz std::size_t m_depthPassIndex; std::size_t m_lastVisibilityHash; std::vector> m_elementRendererData; - std::vector> m_renderElements; std::vector m_renderStates; + std::vector m_renderElements; std::unordered_map m_materialPasses; - RenderQueue m_renderQueue; + RenderQueue m_renderQueue; RenderQueueRegistry m_renderQueueRegistry; AbstractViewer* m_viewer; + ElementRendererRegistry& m_elementRegistry; FramePipeline& m_pipeline; bool m_rebuildCommandBuffer; bool m_rebuildElements; diff --git a/include/Nazara/Graphics/ElementRenderer.hpp b/include/Nazara/Graphics/ElementRenderer.hpp index 80b343134..ec55fdc54 100644 --- a/include/Nazara/Graphics/ElementRenderer.hpp +++ b/include/Nazara/Graphics/ElementRenderer.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -32,6 +33,8 @@ namespace Nz ElementRenderer() = default; virtual ~ElementRenderer(); + virtual RenderElementPoolBase& GetPool() = 0; + virtual std::unique_ptr InstanciateData() = 0; virtual void Prepare(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, RenderFrame& currentFrame, std::size_t elementCount, const Pointer* elements, const RenderStates* renderStates); virtual void PrepareEnd(RenderFrame& currentFrame, ElementRendererData& rendererData); @@ -41,7 +44,6 @@ namespace Nz struct RenderStates { RenderBufferView lightData; - RenderBufferView skeletalData; }; }; diff --git a/include/Nazara/Graphics/ElementRendererRegistry.hpp b/include/Nazara/Graphics/ElementRendererRegistry.hpp new file mode 100644 index 000000000..eb99fa011 --- /dev/null +++ b/include/Nazara/Graphics/ElementRendererRegistry.hpp @@ -0,0 +1,51 @@ +// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_GRAPHICS_ELEMENTRENDERERREGISTRY_HPP +#define NAZARA_GRAPHICS_ELEMENTRENDERERREGISTRY_HPP + +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class ElementRenderer; + + class NAZARA_GRAPHICS_API ElementRendererRegistry + { + public: + ElementRendererRegistry(); + ElementRendererRegistry(const ElementRendererRegistry&) = delete; + ElementRendererRegistry(ElementRendererRegistry&&) = delete; + ~ElementRendererRegistry() = default; + + template RenderElementOwner AllocateElement(Args&&... args); + + template void ForEachElementRenderer(F&& callback); + + inline ElementRenderer& GetElementRenderer(std::size_t elementIndex); + inline std::size_t GetElementRendererCount() const; + + template void ProcessRenderQueue(const RenderQueue& renderQueue, F&& callback); + + template void RegisterElementRenderer(std::unique_ptr renderer); + inline void RegisterElementRenderer(std::size_t elementIndex, std::unique_ptr renderer); + + ElementRendererRegistry& operator=(const ElementRendererRegistry&) = delete; + ElementRendererRegistry& operator=(ElementRendererRegistry&&) = delete; + + private: + std::vector> m_elementRenderers; + }; +} + +#include + +#endif // NAZARA_GRAPHICS_ELEMENTRENDERERREGISTRY_HPP diff --git a/include/Nazara/Graphics/ElementRendererRegistry.inl b/include/Nazara/Graphics/ElementRendererRegistry.inl new file mode 100644 index 000000000..f79792d4b --- /dev/null +++ b/include/Nazara/Graphics/ElementRendererRegistry.inl @@ -0,0 +1,84 @@ +// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ + template + RenderElementOwner ElementRendererRegistry::AllocateElement(Args&&... args) + { + ElementRenderer& elementRenderer = GetElementRenderer(SafeCast(T::ElementType)); + RenderElementPool& pool = SafeCast&>(elementRenderer.GetPool()); + + return pool.Allocate(std::forward(args)...); + } + + inline ElementRenderer& ElementRendererRegistry::GetElementRenderer(std::size_t elementIndex) + { + assert(elementIndex < m_elementRenderers.size()); + return *m_elementRenderers[elementIndex]; + } + + inline std::size_t ElementRendererRegistry::GetElementRendererCount() const + { + return m_elementRenderers.size(); + } + + template + void ElementRendererRegistry::ForEachElementRenderer(F&& callback) + { + for (std::size_t i = 0; i < m_elementRenderers.size(); ++i) + { + if (m_elementRenderers[i]) + callback(i, *m_elementRenderers[i]); + } + } + + template + void ElementRendererRegistry::ProcessRenderQueue(const RenderQueue& renderQueue, F&& callback) + { + if (renderQueue.empty()) + return; + + auto it = renderQueue.begin(); + auto itEnd = renderQueue.end(); + while (it != itEnd) + { + const RenderElement* element = *it; + UInt8 elementType = element->GetElementType(); + + const Pointer* first = it; + + ++it; + while (it != itEnd && (*it)->GetElementType() == elementType) + ++it; + + std::size_t count = it - first; + if (elementType >= m_elementRenderers.size() || !m_elementRenderers[elementType]) + continue; + + callback(elementType, first, count); + } + } + + template + inline void ElementRendererRegistry::RegisterElementRenderer(std::unique_ptr renderer) + { + return RegisterElementRenderer(SafeCast(T::ElementType), std::move(renderer)); + } + + inline void ElementRendererRegistry::RegisterElementRenderer(std::size_t elementIndex, std::unique_ptr renderer) + { + if (elementIndex >= m_elementRenderers.size()) + m_elementRenderers.resize(elementIndex + 1); + + assert(!m_elementRenderers[elementIndex]); + m_elementRenderers[elementIndex] = std::move(renderer); + } +} + +#include diff --git a/include/Nazara/Graphics/ForwardFramePipeline.hpp b/include/Nazara/Graphics/ForwardFramePipeline.hpp index e0e9b7d76..f335c123c 100644 --- a/include/Nazara/Graphics/ForwardFramePipeline.hpp +++ b/include/Nazara/Graphics/ForwardFramePipeline.hpp @@ -37,7 +37,7 @@ namespace Nz class NAZARA_GRAPHICS_API ForwardFramePipeline : public FramePipeline { public: - ForwardFramePipeline(); + ForwardFramePipeline(ElementRendererRegistry& elementRegistry); ForwardFramePipeline(const ForwardFramePipeline&) = delete; ForwardFramePipeline(ForwardFramePipeline&&) = delete; ~ForwardFramePipeline(); @@ -137,6 +137,7 @@ namespace Nz Bitset m_removedSkeletonInstances; Bitset m_removedViewerInstances; Bitset m_removedWorldInstances; + ElementRendererRegistry& m_elementRegistry; MemoryPool m_renderablePool; MemoryPool m_lightPool; MemoryPool m_skeletonInstances; diff --git a/include/Nazara/Graphics/ForwardPipelinePass.hpp b/include/Nazara/Graphics/ForwardPipelinePass.hpp index 95278fa7d..90fc3aef1 100644 --- a/include/Nazara/Graphics/ForwardPipelinePass.hpp +++ b/include/Nazara/Graphics/ForwardPipelinePass.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -22,6 +23,7 @@ namespace Nz { class AbstractViewer; + class ElementRendererRegistry; class FrameGraph; class FramePipeline; class Light; @@ -30,7 +32,7 @@ namespace Nz class NAZARA_GRAPHICS_API ForwardPipelinePass : public FramePipelinePass { public: - ForwardPipelinePass(FramePipeline& owner, AbstractViewer* viewer); + ForwardPipelinePass(FramePipeline& owner, ElementRendererRegistry& elementRegistry, AbstractViewer* viewer); ForwardPipelinePass(const ForwardPipelinePass&) = delete; ForwardPipelinePass(ForwardPipelinePass&&) = delete; ~ForwardPipelinePass(); @@ -82,16 +84,17 @@ namespace Nz std::size_t m_lastVisibilityHash; std::shared_ptr m_lightUboPool; std::vector> m_elementRendererData; - std::vector> m_renderElements; std::vector m_renderStates; + std::vector m_renderElements; std::unordered_map m_materialPasses; std::unordered_map m_lightPerRenderElement; std::unordered_map m_lightBufferPerLights; std::vector m_lightDataBuffers; std::vector m_renderableLights; - RenderQueue m_renderQueue; + RenderQueue m_renderQueue; RenderQueueRegistry m_renderQueueRegistry; AbstractViewer* m_viewer; + ElementRendererRegistry& m_elementRegistry; FramePipeline& m_pipeline; bool m_rebuildCommandBuffer; bool m_rebuildElements; diff --git a/include/Nazara/Graphics/FramePipeline.hpp b/include/Nazara/Graphics/FramePipeline.hpp index 6d5ade71b..3fa694222 100644 --- a/include/Nazara/Graphics/FramePipeline.hpp +++ b/include/Nazara/Graphics/FramePipeline.hpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -20,7 +19,6 @@ namespace Nz { class AbstractViewer; - class ElementRenderer; class InstancedRenderable; class Light; class MaterialPass; @@ -34,18 +32,12 @@ namespace Nz FramePipeline(FramePipeline&&) noexcept = default; virtual ~FramePipeline(); - template void ForEachElementRenderer(F&& callback); - inline DebugDrawer& GetDebugDrawer(); - inline ElementRenderer& GetElementRenderer(std::size_t elementIndex); - inline std::size_t GetElementRendererCount() const; virtual void InvalidateSkeletalInstance(std::size_t skeletalInstanceIndex) = 0; virtual void InvalidateViewer(std::size_t viewerIndex) = 0; virtual void InvalidateWorldInstance(std::size_t worldInstance) = 0; - template void ProcessRenderQueue(const RenderQueue& renderQueue, F&& callback); - virtual std::size_t RegisterLight(std::shared_ptr light, UInt32 renderMask) = 0; virtual void RegisterMaterialPass(MaterialPass* materialPass) = 0; virtual std::size_t RegisterRenderable(std::size_t worldInstanceIndex, std::size_t skeletonInstanceIndex, const InstancedRenderable* instancedRenderable, UInt32 renderMask, const Recti& scissorBox) = 0; @@ -75,7 +67,6 @@ namespace Nz static constexpr std::size_t NoSkeletonInstance = std::numeric_limits::max(); private: - std::vector> m_elementRenderers; DebugDrawer m_debugDrawer; }; } diff --git a/include/Nazara/Graphics/FramePipeline.inl b/include/Nazara/Graphics/FramePipeline.inl index d0c2e9899..d3290f93e 100644 --- a/include/Nazara/Graphics/FramePipeline.inl +++ b/include/Nazara/Graphics/FramePipeline.inl @@ -12,54 +12,6 @@ namespace Nz { return m_debugDrawer; } - - inline ElementRenderer& FramePipeline::GetElementRenderer(std::size_t elementIndex) - { - assert(elementIndex < m_elementRenderers.size()); - return *m_elementRenderers[elementIndex]; - } - - inline std::size_t FramePipeline::GetElementRendererCount() const - { - return m_elementRenderers.size(); - } - - template - void FramePipeline::ForEachElementRenderer(F&& callback) - { - for (std::size_t i = 0; i < m_elementRenderers.size(); ++i) - { - if (m_elementRenderers[i]) - callback(i, *m_elementRenderers[i]); - } - } - - template - void FramePipeline::ProcessRenderQueue(const RenderQueue& renderQueue, F&& callback) - { - if (renderQueue.empty()) - return; - - auto it = renderQueue.begin(); - auto itEnd = renderQueue.end(); - while (it != itEnd) - { - const RenderElement* element = *it; - UInt8 elementType = element->GetElementType(); - - const Pointer* first = it; - - ++it; - while (it != itEnd && (*it)->GetElementType() == elementType) - ++it; - - std::size_t count = it - first; - if (elementType >= m_elementRenderers.size() || !m_elementRenderers[elementType]) - continue; - - callback(elementType, first, count); - } - } } #include diff --git a/include/Nazara/Graphics/InstancedRenderable.hpp b/include/Nazara/Graphics/InstancedRenderable.hpp index 4bd01cf26..4438f0350 100644 --- a/include/Nazara/Graphics/InstancedRenderable.hpp +++ b/include/Nazara/Graphics/InstancedRenderable.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -16,6 +17,7 @@ namespace Nz { class CommandBufferBuilder; + class ElementRendererRegistry; class Material; class RenderElement; class SkeletonInstance; @@ -24,12 +26,14 @@ namespace Nz class NAZARA_GRAPHICS_API InstancedRenderable { public: + struct ElementData; + inline InstancedRenderable(); InstancedRenderable(const InstancedRenderable&) = delete; InstancedRenderable(InstancedRenderable&&) noexcept = default; ~InstancedRenderable(); - virtual void BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, const SkeletonInstance* skeletonInstance, std::vector>& elements, const Recti& scissorBox) const = 0; + virtual void BuildElement(ElementRendererRegistry& registry, const ElementData& elementData, std::size_t passIndex, std::vector& elements) const = 0; inline const Boxf& GetAABB() const; virtual const std::shared_ptr& GetMaterial(std::size_t i) const = 0; @@ -45,6 +49,13 @@ namespace Nz NazaraSignal(OnElementInvalidated, InstancedRenderable* /*instancedRenderable*/); NazaraSignal(OnMaterialInvalidated, InstancedRenderable* /*instancedRenderable*/, std::size_t /*materialIndex*/, const std::shared_ptr& /*newMaterial*/); + struct ElementData + { + const Recti* scissorBox; + const SkeletonInstance* skeletonInstance; + const WorldInstance* worldInstance; + }; + protected: inline void UpdateAABB(Boxf aabb); diff --git a/include/Nazara/Graphics/LinearSlicedSprite.hpp b/include/Nazara/Graphics/LinearSlicedSprite.hpp index af502174b..55998603b 100644 --- a/include/Nazara/Graphics/LinearSlicedSprite.hpp +++ b/include/Nazara/Graphics/LinearSlicedSprite.hpp @@ -30,7 +30,7 @@ namespace Nz inline void AddSection(float size, float textureCoord); - void BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, const SkeletonInstance* skeletonInstance, std::vector>& elements, const Recti& scissorBox) const override; + void BuildElement(ElementRendererRegistry& registry, const ElementData& elementData, std::size_t passIndex, std::vector& elements) const override; inline void Clear(); diff --git a/include/Nazara/Graphics/Model.hpp b/include/Nazara/Graphics/Model.hpp index 37221f4b5..3675607f3 100644 --- a/include/Nazara/Graphics/Model.hpp +++ b/include/Nazara/Graphics/Model.hpp @@ -28,7 +28,7 @@ namespace Nz Model(Model&&) noexcept = default; ~Model() = default; - void BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, const SkeletonInstance* skeletonInstance, std::vector>& elements, const Recti& scissorBox) const override; + void BuildElement(ElementRendererRegistry& registry, const ElementData& elementData, std::size_t passIndex, std::vector& elements) const override; const std::shared_ptr& GetIndexBuffer(std::size_t subMeshIndex) const; std::size_t GetIndexCount(std::size_t subMeshIndex) const; diff --git a/include/Nazara/Graphics/RenderElementOwner.hpp b/include/Nazara/Graphics/RenderElementOwner.hpp new file mode 100644 index 000000000..9216f23a1 --- /dev/null +++ b/include/Nazara/Graphics/RenderElementOwner.hpp @@ -0,0 +1,45 @@ +// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_GRAPHICS_RENDERELEMENTOWNER_HPP +#define NAZARA_GRAPHICS_RENDERELEMENTOWNER_HPP + +#include +#include +#include + +namespace Nz +{ + class RenderElement; + class RenderElementPoolBase; + + class NAZARA_GRAPHICS_API RenderElementOwner + { + public: + inline RenderElementOwner(RenderElementPoolBase* pool, std::size_t poolIndex, RenderElement* element); + RenderElementOwner(const RenderElementOwner&) = delete; + RenderElementOwner(RenderElementOwner&&) noexcept = default; + ~RenderElementOwner(); + + inline RenderElement* GetElement(); + inline const RenderElement* GetElement() const; + + inline RenderElement* operator->(); + inline const RenderElement* operator->() const; + + RenderElementOwner& operator=(const RenderElementOwner&) = delete; + RenderElementOwner& operator=(RenderElementOwner&&) noexcept = default; + + private: + std::size_t m_poolIndex; + MovablePtr m_element; + MovablePtr m_pool; + }; +} + +#include + +#endif // NAZARA_GRAPHICS_RENDERELEMENTOWNER_HPP diff --git a/include/Nazara/Graphics/RenderElementOwner.inl b/include/Nazara/Graphics/RenderElementOwner.inl new file mode 100644 index 000000000..866eaee90 --- /dev/null +++ b/include/Nazara/Graphics/RenderElementOwner.inl @@ -0,0 +1,39 @@ +// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + inline RenderElementOwner::RenderElementOwner(RenderElementPoolBase* pool, std::size_t poolIndex, RenderElement* element) : + m_poolIndex(poolIndex), + m_element(element), + m_pool(pool) + { + } + + inline RenderElement* RenderElementOwner::GetElement() + { + return m_element; + } + + inline const RenderElement* RenderElementOwner::GetElement() const + { + return m_element; + } + + inline RenderElement* RenderElementOwner::operator->() + { + // FIXME: Element pointer could also be retrieved from memory pool using poolIndex at the cost of a division + return m_element; + } + + inline const RenderElement* RenderElementOwner::operator->() const + { + return m_element; + } +} + +#include diff --git a/include/Nazara/Graphics/RenderElementPool.hpp b/include/Nazara/Graphics/RenderElementPool.hpp new file mode 100644 index 000000000..15c77b9ac --- /dev/null +++ b/include/Nazara/Graphics/RenderElementPool.hpp @@ -0,0 +1,60 @@ +// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_GRAPHICS_RENDERELEMENTPOOL_HPP +#define NAZARA_GRAPHICS_RENDERELEMENTPOOL_HPP + +#include +#include +#include +#include + +namespace Nz +{ + class RenderElementOwner; + + class NAZARA_GRAPHICS_API RenderElementPoolBase + { + public: + RenderElementPoolBase() = default; + RenderElementPoolBase(const RenderElementPoolBase&) = delete; + RenderElementPoolBase(RenderElementPoolBase&&) = delete; + virtual ~RenderElementPoolBase(); + + virtual void Clear() = 0; + + virtual void Free(std::size_t index) = 0; + + RenderElementPoolBase& operator=(const RenderElementPoolBase&) = delete; + RenderElementPoolBase& operator=(RenderElementPoolBase&&) = delete; + }; + + template + class RenderElementPool final : public RenderElementPoolBase + { + public: + RenderElementPool(); + RenderElementPool(const RenderElementPool&) = delete; + RenderElementPool(RenderElementPool&&) = delete; + ~RenderElementPool() = default; + + template RenderElementOwner Allocate(Args&&... args); + + void Clear() override; + + void Free(std::size_t index) override; + + RenderElementPool& operator=(const RenderElementPool&) = delete; + RenderElementPool& operator=(RenderElementPool&&) = delete; + + private: + MemoryPool m_pool; + }; +} + +#include + +#endif // NAZARA_GRAPHICS_RENDERELEMENTPOOL_HPP diff --git a/include/Nazara/Graphics/RenderElementPool.inl b/include/Nazara/Graphics/RenderElementPool.inl new file mode 100644 index 000000000..6a0758588 --- /dev/null +++ b/include/Nazara/Graphics/RenderElementPool.inl @@ -0,0 +1,39 @@ +// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + template + template + RenderElementOwner RenderElementPool::Allocate(Args&&... args) + { + std::size_t poolIndex; + T* element = m_pool.Allocate(poolIndex, std::forward(args)...); + + return RenderElementOwner(this, poolIndex, element); + } + + template + RenderElementPool::RenderElementPool() : + m_pool(4096) //< TODO: Allow to adjust pool count + { + } + + template + void RenderElementPool::Clear() + { + m_pool.Clear(); + } + + template + void RenderElementPool::Free(std::size_t index) + { + m_pool.Free(index); + } +} + +#include diff --git a/include/Nazara/Graphics/RenderSpriteChain.hpp b/include/Nazara/Graphics/RenderSpriteChain.hpp index ff61e01a1..69582fca4 100644 --- a/include/Nazara/Graphics/RenderSpriteChain.hpp +++ b/include/Nazara/Graphics/RenderSpriteChain.hpp @@ -39,6 +39,8 @@ namespace Nz inline void Register(RenderQueueRegistry& registry) const override; + static constexpr BasicRenderElement ElementType = BasicRenderElement::SpriteChain; + private: std::shared_ptr m_materialPass; std::shared_ptr m_renderPipeline; diff --git a/include/Nazara/Graphics/RenderSubmesh.hpp b/include/Nazara/Graphics/RenderSubmesh.hpp index a04a947fa..e1cc4134d 100644 --- a/include/Nazara/Graphics/RenderSubmesh.hpp +++ b/include/Nazara/Graphics/RenderSubmesh.hpp @@ -41,6 +41,8 @@ namespace Nz inline void Register(RenderQueueRegistry& registry) const override; + static constexpr BasicRenderElement ElementType = BasicRenderElement::Submesh; + private: std::shared_ptr m_indexBuffer; std::shared_ptr m_vertexBuffer; diff --git a/include/Nazara/Graphics/SlicedSprite.hpp b/include/Nazara/Graphics/SlicedSprite.hpp index 1da860243..c19b7905e 100644 --- a/include/Nazara/Graphics/SlicedSprite.hpp +++ b/include/Nazara/Graphics/SlicedSprite.hpp @@ -27,7 +27,7 @@ namespace Nz SlicedSprite(SlicedSprite&&) noexcept = default; ~SlicedSprite() = default; - void BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, const SkeletonInstance* skeletonInstance, std::vector>& elements, const Recti& scissorBox) const override; + void BuildElement(ElementRendererRegistry& registry, const ElementData& elementData, std::size_t passIndex, std::vector& elements) const override; inline const Color& GetColor() const; inline const Corner& GetBottomRightCorner() const; diff --git a/include/Nazara/Graphics/Sprite.hpp b/include/Nazara/Graphics/Sprite.hpp index 485bce66f..4201a0f38 100644 --- a/include/Nazara/Graphics/Sprite.hpp +++ b/include/Nazara/Graphics/Sprite.hpp @@ -25,7 +25,7 @@ namespace Nz Sprite(Sprite&&) noexcept = default; ~Sprite() = default; - void BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, const SkeletonInstance* skeletonInstance, std::vector>& elements, const Recti& scissorBox) const override; + void BuildElement(ElementRendererRegistry& registry, const ElementData& elementData, std::size_t passIndex, std::vector& elements) const override; inline const Color& GetColor() const; inline const Color& GetCornerColor(RectCorner corner) const; diff --git a/include/Nazara/Graphics/SpriteChainRenderer.hpp b/include/Nazara/Graphics/SpriteChainRenderer.hpp index 3193e2501..87575cfa1 100644 --- a/include/Nazara/Graphics/SpriteChainRenderer.hpp +++ b/include/Nazara/Graphics/SpriteChainRenderer.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -21,7 +22,6 @@ namespace Nz class MaterialPass; class RenderDevice; class RenderPipeline; - class RenderSpriteChain; class ShaderBinding; class Texture; class VertexDeclaration; @@ -57,6 +57,8 @@ namespace Nz SpriteChainRenderer(RenderDevice& device, std::size_t maxVertexBufferSize = 32 * 1024); ~SpriteChainRenderer() = default; + RenderElementPool& GetPool() override; + std::unique_ptr InstanciateData() override; void Prepare(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, RenderFrame& currentFrame, std::size_t elementCount, const Pointer* elements, const RenderStates* renderStates) override; void PrepareEnd(RenderFrame& currentFrame, ElementRendererData& rendererData) override; @@ -103,6 +105,7 @@ namespace Nz std::size_t m_maxVertexCount; std::vector m_pendingCopies; std::vector m_bindingCache; + RenderElementPool m_spriteChainPool; PendingData m_pendingData; RenderDevice& m_device; }; diff --git a/include/Nazara/Graphics/SubmeshRenderer.hpp b/include/Nazara/Graphics/SubmeshRenderer.hpp index f537cb283..d73abcc5d 100644 --- a/include/Nazara/Graphics/SubmeshRenderer.hpp +++ b/include/Nazara/Graphics/SubmeshRenderer.hpp @@ -9,21 +9,23 @@ #include #include +#include #include #include namespace Nz { class RenderPipeline; - class RenderSubmesh; class ShaderBinding; - class NAZARA_GRAPHICS_API SubmeshRenderer : public ElementRenderer + class NAZARA_GRAPHICS_API SubmeshRenderer final : public ElementRenderer { public: SubmeshRenderer() = default; ~SubmeshRenderer() = default; + RenderElementPool& GetPool() override; + std::unique_ptr InstanciateData() override; void Prepare(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, RenderFrame& currentFrame, std::size_t elementCount, const Pointer* elements, const RenderStates* renderStates) override; void Render(const ViewerInstance& viewerInstance, ElementRendererData& rendererData, CommandBufferBuilder& commandBuffer, std::size_t elementCount, const Pointer* elements) override; @@ -31,6 +33,7 @@ namespace Nz private: std::vector m_bindingCache; + RenderElementPool m_submeshPool; }; struct SubmeshRendererData : public ElementRendererData diff --git a/include/Nazara/Graphics/Systems/RenderSystem.hpp b/include/Nazara/Graphics/Systems/RenderSystem.hpp index d7685ba8a..fa9febf9e 100644 --- a/include/Nazara/Graphics/Systems/RenderSystem.hpp +++ b/include/Nazara/Graphics/Systems/RenderSystem.hpp @@ -8,6 +8,7 @@ #define NAZARA_GRAPHICS_SYSTEMS_RENDERSYSTEM_HPP #include +#include #include #include #include @@ -132,6 +133,7 @@ namespace Nz std::unordered_set m_newlyHiddenLightEntities; std::unordered_set m_newlyVisibleLightEntities; std::vector> m_renderWindows; + ElementRendererRegistry m_elementRegistry; MemoryPool m_cameraEntityPool; MemoryPool m_graphicsEntityPool; MemoryPool m_lightEntityPool; diff --git a/include/Nazara/Graphics/TextSprite.hpp b/include/Nazara/Graphics/TextSprite.hpp index 6e5e381f7..6b472fe00 100644 --- a/include/Nazara/Graphics/TextSprite.hpp +++ b/include/Nazara/Graphics/TextSprite.hpp @@ -28,7 +28,7 @@ namespace Nz TextSprite(TextSprite&&) noexcept = default; ~TextSprite() = default; - void BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, const SkeletonInstance* skeletonInstance, std::vector>& elements, const Recti& scissorBox) const override; + void BuildElement(ElementRendererRegistry& registry, const ElementData& elementData, std::size_t passIndex, std::vector& elements) const override; inline void Clear(); diff --git a/src/Nazara/Graphics/DepthPipelinePass.cpp b/src/Nazara/Graphics/DepthPipelinePass.cpp index 0280cdd0f..5d9453309 100644 --- a/src/Nazara/Graphics/DepthPipelinePass.cpp +++ b/src/Nazara/Graphics/DepthPipelinePass.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -15,9 +16,10 @@ namespace Nz { - DepthPipelinePass::DepthPipelinePass(FramePipeline& owner, AbstractViewer* viewer) : + DepthPipelinePass::DepthPipelinePass(FramePipeline& owner, ElementRendererRegistry& elementRegistry, AbstractViewer* viewer) : m_lastVisibilityHash(0), m_viewer(viewer), + m_elementRegistry(elementRegistry), m_pipeline(owner), m_rebuildCommandBuffer(false), m_rebuildElements(false) @@ -39,7 +41,15 @@ namespace Nz m_renderElements.clear(); for (const auto& renderableData : visibleRenderables) - renderableData.instancedRenderable->BuildElement(m_depthPassIndex, *renderableData.worldInstance, renderableData.skeletonInstance, m_renderElements, renderableData.scissorBox); + { + InstancedRenderable::ElementData elementData{ + &renderableData.scissorBox, + renderableData.skeletonInstance, + renderableData.worldInstance + }; + + renderableData.instancedRenderable->BuildElement(m_elementRegistry, elementData, m_depthPassIndex, m_renderElements); + } m_renderQueueRegistry.Clear(); m_renderQueue.Clear(); @@ -47,7 +57,7 @@ namespace Nz for (const auto& renderElement : m_renderElements) { renderElement->Register(m_renderQueueRegistry); - m_renderQueue.Insert(renderElement.get()); + m_renderQueue.Insert(renderElement.GetElement()); } m_renderQueueRegistry.Finalize(); @@ -64,7 +74,7 @@ namespace Nz if (m_rebuildElements) { - m_pipeline.ForEachElementRenderer([&](std::size_t elementType, ElementRenderer& elementRenderer) + m_elementRegistry.ForEachElementRenderer([&](std::size_t elementType, ElementRenderer& elementRenderer) { if (elementType >= m_elementRendererData.size() || !m_elementRendererData[elementType]) { @@ -79,9 +89,9 @@ namespace Nz const auto& viewerInstance = m_viewer->GetViewerInstance(); - m_pipeline.ProcessRenderQueue(m_renderQueue, [&](std::size_t elementType, const Pointer* elements, std::size_t elementCount) + m_elementRegistry.ProcessRenderQueue(m_renderQueue, [&](std::size_t elementType, const Pointer* elements, std::size_t elementCount) { - ElementRenderer& elementRenderer = m_pipeline.GetElementRenderer(elementType); + ElementRenderer& elementRenderer = m_elementRegistry.GetElementRenderer(elementType); m_renderStates.clear(); m_renderStates.resize(elementCount); @@ -89,7 +99,7 @@ namespace Nz elementRenderer.Prepare(viewerInstance, *m_elementRendererData[elementType], renderFrame, elementCount, elements, m_renderStates.data()); }); - m_pipeline.ForEachElementRenderer([&](std::size_t elementType, ElementRenderer& elementRenderer) + m_elementRegistry.ForEachElementRenderer([&](std::size_t elementType, ElementRenderer& elementRenderer) { elementRenderer.PrepareEnd(renderFrame, *m_elementRendererData[elementType]); }); @@ -146,9 +156,9 @@ namespace Nz const auto& viewerInstance = m_viewer->GetViewerInstance(); - m_pipeline.ProcessRenderQueue(m_renderQueue, [&](std::size_t elementType, const Pointer* elements, std::size_t elementCount) + m_elementRegistry.ProcessRenderQueue(m_renderQueue, [&](std::size_t elementType, const Pointer* elements, std::size_t elementCount) { - ElementRenderer& elementRenderer = m_pipeline.GetElementRenderer(elementType); + ElementRenderer& elementRenderer = m_elementRegistry.GetElementRenderer(elementType); elementRenderer.Render(viewerInstance, *m_elementRendererData[elementType], builder, elementCount, elements); }); diff --git a/src/Nazara/Graphics/ElementRendererRegistry.cpp b/src/Nazara/Graphics/ElementRendererRegistry.cpp new file mode 100644 index 000000000..b460399dc --- /dev/null +++ b/src/Nazara/Graphics/ElementRendererRegistry.cpp @@ -0,0 +1,21 @@ +// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + ElementRendererRegistry::ElementRendererRegistry() + { + RegisterElementRenderer(std::make_unique(*Graphics::Instance()->GetRenderDevice())); + RegisterElementRenderer(std::make_unique()); + } +} diff --git a/src/Nazara/Graphics/ForwardFramePipeline.cpp b/src/Nazara/Graphics/ForwardFramePipeline.cpp index 22838127d..b0b5d3fee 100644 --- a/src/Nazara/Graphics/ForwardFramePipeline.cpp +++ b/src/Nazara/Graphics/ForwardFramePipeline.cpp @@ -26,7 +26,8 @@ namespace Nz { - ForwardFramePipeline::ForwardFramePipeline() : + ForwardFramePipeline::ForwardFramePipeline(ElementRendererRegistry& elementRegistry) : + m_elementRegistry(elementRegistry), m_renderablePool(4096), m_lightPool(64), m_skeletonInstances(1024), @@ -182,8 +183,8 @@ namespace Nz auto& viewerData = *m_viewerPool.Allocate(viewerIndex); viewerData.renderOrder = renderOrder; viewerData.debugDrawPass = std::make_unique(*this, viewerInstance); - viewerData.depthPrepass = std::make_unique(*this, viewerInstance); - viewerData.forwardPass = std::make_unique(*this, viewerInstance); + viewerData.depthPrepass = std::make_unique(*this, m_elementRegistry, viewerInstance); + viewerData.forwardPass = std::make_unique(*this, m_elementRegistry, viewerInstance); viewerData.viewer = viewerInstance; m_invalidatedViewerInstances.UnboundedSet(viewerIndex); diff --git a/src/Nazara/Graphics/ForwardPipelinePass.cpp b/src/Nazara/Graphics/ForwardPipelinePass.cpp index 0ce09502d..767dcf021 100644 --- a/src/Nazara/Graphics/ForwardPipelinePass.cpp +++ b/src/Nazara/Graphics/ForwardPipelinePass.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -16,9 +17,10 @@ namespace Nz { - ForwardPipelinePass::ForwardPipelinePass(FramePipeline& owner, AbstractViewer* viewer) : + ForwardPipelinePass::ForwardPipelinePass(FramePipeline& owner, ElementRendererRegistry& elementRegistry, AbstractViewer* viewer) : m_lastVisibilityHash(0), m_viewer(viewer), + m_elementRegistry(elementRegistry), m_pipeline(owner), m_rebuildCommandBuffer(false), m_rebuildElements(false) @@ -147,11 +149,17 @@ namespace Nz else lightUboView = it->second; + InstancedRenderable::ElementData elementData{ + &renderableData.scissorBox, + renderableData.skeletonInstance, + renderableData.worldInstance + }; + std::size_t previousCount = m_renderElements.size(); - renderableData.instancedRenderable->BuildElement(m_forwardPassIndex, *renderableData.worldInstance, renderableData.skeletonInstance, m_renderElements, renderableData.scissorBox); + renderableData.instancedRenderable->BuildElement(m_elementRegistry, elementData, m_forwardPassIndex, m_renderElements); for (std::size_t i = previousCount; i < m_renderElements.size(); ++i) { - const RenderElement* element = m_renderElements[i].get(); + const RenderElement* element = m_renderElements[i].GetElement(); m_lightPerRenderElement.emplace(element, lightUboView); } } @@ -159,7 +167,7 @@ namespace Nz for (const auto& renderElement : m_renderElements) { renderElement->Register(m_renderQueueRegistry); - m_renderQueue.Insert(renderElement.get()); + m_renderQueue.Insert(renderElement.GetElement()); } m_renderQueueRegistry.Finalize(); @@ -193,15 +201,13 @@ namespace Nz if (m_rebuildElements) { - m_pipeline.ForEachElementRenderer([&](std::size_t elementType, ElementRenderer& elementRenderer) + m_elementRegistry.ForEachElementRenderer([&](std::size_t elementType, ElementRenderer& elementRenderer) { - if (elementType >= m_elementRendererData.size() || !m_elementRendererData[elementType]) - { - if (elementType >= m_elementRendererData.size()) - m_elementRendererData.resize(elementType + 1); + if (elementType >= m_elementRendererData.size()) + m_elementRendererData.resize(elementType + 1); + if (!m_elementRendererData[elementType]) m_elementRendererData[elementType] = elementRenderer.InstanciateData(); - } elementRenderer.Reset(*m_elementRendererData[elementType], renderFrame); }); @@ -209,9 +215,9 @@ namespace Nz const auto& viewerInstance = m_viewer->GetViewerInstance(); auto& lightPerRenderElement = m_lightPerRenderElement; - m_pipeline.ProcessRenderQueue(m_renderQueue, [&](std::size_t elementType, const Pointer* elements, std::size_t elementCount) + m_elementRegistry.ProcessRenderQueue(m_renderQueue, [&](std::size_t elementType, const Pointer* elements, std::size_t elementCount) { - ElementRenderer& elementRenderer = m_pipeline.GetElementRenderer(elementType); + ElementRenderer& elementRenderer = m_elementRegistry.GetElementRenderer(elementType); m_renderStates.clear(); @@ -228,7 +234,7 @@ namespace Nz elementRenderer.Prepare(viewerInstance, *m_elementRendererData[elementType], renderFrame, elementCount, elements, m_renderStates.data()); }); - m_pipeline.ForEachElementRenderer([&](std::size_t elementType, ElementRenderer& elementRenderer) + m_elementRegistry.ForEachElementRenderer([&](std::size_t elementType, ElementRenderer& elementRenderer) { elementRenderer.PrepareEnd(renderFrame, *m_elementRendererData[elementType]); }); @@ -291,9 +297,9 @@ namespace Nz const auto& viewerInstance = m_viewer->GetViewerInstance(); - m_pipeline.ProcessRenderQueue(m_renderQueue, [&](std::size_t elementType, const Pointer* elements, std::size_t elementCount) + m_elementRegistry.ProcessRenderQueue(m_renderQueue, [&](std::size_t elementType, const Pointer* elements, std::size_t elementCount) { - ElementRenderer& elementRenderer = m_pipeline.GetElementRenderer(elementType); + ElementRenderer& elementRenderer = m_elementRegistry.GetElementRenderer(elementType); elementRenderer.Render(viewerInstance, *m_elementRendererData[elementType], builder, elementCount, elements); }); diff --git a/src/Nazara/Graphics/FramePipeline.cpp b/src/Nazara/Graphics/FramePipeline.cpp index 93686ec88..6581539c1 100644 --- a/src/Nazara/Graphics/FramePipeline.cpp +++ b/src/Nazara/Graphics/FramePipeline.cpp @@ -3,20 +3,14 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include #include -#include -#include #include namespace Nz { FramePipeline::FramePipeline() : - m_elementRenderers(BasicRenderElementCount), m_debugDrawer(*Graphics::Instance()->GetRenderDevice()) { - m_elementRenderers[UnderlyingCast(BasicRenderElement::SpriteChain)] = std::make_unique(*Graphics::Instance()->GetRenderDevice()); - m_elementRenderers[UnderlyingCast(BasicRenderElement::Submesh)] = std::make_unique(); } FramePipeline::~FramePipeline() = default; diff --git a/src/Nazara/Graphics/LinearSlicedSprite.cpp b/src/Nazara/Graphics/LinearSlicedSprite.cpp index 4e76bb9da..d3977e1c9 100644 --- a/src/Nazara/Graphics/LinearSlicedSprite.cpp +++ b/src/Nazara/Graphics/LinearSlicedSprite.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -22,7 +23,7 @@ namespace Nz UpdateVertices(); } - void LinearSlicedSprite::BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, const SkeletonInstance* skeletonInstance, std::vector>& elements, const Recti& scissorBox) const + void LinearSlicedSprite::BuildElement(ElementRendererRegistry& registry, const ElementData& elementData, std::size_t passIndex, std::vector& elements) const { const auto& materialPass = m_material->GetPass(passIndex); if (!materialPass) @@ -42,7 +43,7 @@ namespace Nz const auto& whiteTexture = Graphics::Instance()->GetDefaultTextures().whiteTextures[UnderlyingCast(ImageType::E2D)]; - elements.emplace_back(std::make_unique(GetRenderLayer(), materialPass, renderPipeline, worldInstance, vertexDeclaration, whiteTexture, m_spriteCount, m_vertices.data(), scissorBox)); + elements.emplace_back(registry.AllocateElement(GetRenderLayer(), materialPass, renderPipeline, *elementData.worldInstance, vertexDeclaration, whiteTexture, m_spriteCount, m_vertices.data(), *elementData.scissorBox)); } const std::shared_ptr& LinearSlicedSprite::GetMaterial(std::size_t i) const diff --git a/src/Nazara/Graphics/Model.cpp b/src/Nazara/Graphics/Model.cpp index e67ff50d6..721367a2a 100644 --- a/src/Nazara/Graphics/Model.cpp +++ b/src/Nazara/Graphics/Model.cpp @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include #include #include @@ -37,7 +38,7 @@ namespace Nz UpdateAABB(aabb); } - void Model::BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, const SkeletonInstance* skeletonInstance, std::vector>& elements, const Recti& scissorBox) const + void Model::BuildElement(ElementRendererRegistry& registry, const ElementData& elementData, std::size_t passIndex, std::vector& elements) const { for (std::size_t i = 0; i < m_submeshes.size(); ++i) { @@ -54,7 +55,7 @@ namespace Nz std::size_t indexCount = m_graphicalMesh->GetIndexCount(i); IndexType indexType = m_graphicalMesh->GetIndexType(i); - elements.emplace_back(std::make_unique(GetRenderLayer(), materialPass, renderPipeline, worldInstance, skeletonInstance, indexCount, indexType, indexBuffer, vertexBuffer, scissorBox)); + elements.emplace_back(registry.AllocateElement(GetRenderLayer(), materialPass, renderPipeline, *elementData.worldInstance, elementData.skeletonInstance, indexCount, indexType, indexBuffer, vertexBuffer, *elementData.scissorBox)); } } diff --git a/src/Nazara/Graphics/RenderElementOwner.cpp b/src/Nazara/Graphics/RenderElementOwner.cpp new file mode 100644 index 000000000..ec145c7e9 --- /dev/null +++ b/src/Nazara/Graphics/RenderElementOwner.cpp @@ -0,0 +1,16 @@ +// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ + RenderElementOwner::~RenderElementOwner() + { + if (m_pool) + m_pool->Free(m_poolIndex); + } +} diff --git a/src/Nazara/Graphics/RenderElementPool.cpp b/src/Nazara/Graphics/RenderElementPool.cpp new file mode 100644 index 000000000..d5065caf4 --- /dev/null +++ b/src/Nazara/Graphics/RenderElementPool.cpp @@ -0,0 +1,11 @@ +// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + RenderElementPoolBase::~RenderElementPoolBase() = default; +} diff --git a/src/Nazara/Graphics/SlicedSprite.cpp b/src/Nazara/Graphics/SlicedSprite.cpp index 73dbe9c37..dbffe6c94 100644 --- a/src/Nazara/Graphics/SlicedSprite.cpp +++ b/src/Nazara/Graphics/SlicedSprite.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -19,7 +20,7 @@ namespace Nz UpdateVertices(); } - void SlicedSprite::BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, const SkeletonInstance* skeletonInstance, std::vector>& elements, const Recti& scissorBox) const + void SlicedSprite::BuildElement(ElementRendererRegistry& registry, const ElementData& elementData, std::size_t passIndex, std::vector& elements) const { const auto& materialPass = m_material->GetPass(passIndex); if (!materialPass) @@ -39,7 +40,7 @@ namespace Nz const auto& whiteTexture = Graphics::Instance()->GetDefaultTextures().whiteTextures[UnderlyingCast(ImageType::E2D)]; - elements.emplace_back(std::make_unique(GetRenderLayer(), materialPass, renderPipeline, worldInstance, vertexDeclaration, whiteTexture, m_spriteCount, m_vertices.data(), scissorBox)); + elements.emplace_back(registry.AllocateElement(GetRenderLayer(), materialPass, renderPipeline, *elementData.worldInstance, vertexDeclaration, whiteTexture, m_spriteCount, m_vertices.data(), *elementData.scissorBox)); } const std::shared_ptr& SlicedSprite::GetMaterial(std::size_t i) const diff --git a/src/Nazara/Graphics/Sprite.cpp b/src/Nazara/Graphics/Sprite.cpp index 117786a9a..5e1f2ef8b 100644 --- a/src/Nazara/Graphics/Sprite.cpp +++ b/src/Nazara/Graphics/Sprite.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -23,7 +24,7 @@ namespace Nz UpdateVertices(); } - void Sprite::BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, const SkeletonInstance* skeletonInstance, std::vector>& elements, const Recti& scissorBox) const + void Sprite::BuildElement(ElementRendererRegistry& registry, const ElementData& elementData, std::size_t passIndex, std::vector& elements) const { const auto& materialPass = m_material->GetPass(passIndex); if (!materialPass) @@ -43,7 +44,7 @@ namespace Nz const auto& whiteTexture = Graphics::Instance()->GetDefaultTextures().whiteTextures[UnderlyingCast(ImageType::E2D)]; - elements.emplace_back(std::make_unique(GetRenderLayer(), materialPass, renderPipeline, worldInstance, vertexDeclaration, whiteTexture, 1, m_vertices.data(), scissorBox)); + elements.emplace_back(registry.AllocateElement(GetRenderLayer(), materialPass, renderPipeline, *elementData.worldInstance, vertexDeclaration, whiteTexture, 1, m_vertices.data(), *elementData.scissorBox)); } const std::shared_ptr& Sprite::GetMaterial(std::size_t i) const diff --git a/src/Nazara/Graphics/SpriteChainRenderer.cpp b/src/Nazara/Graphics/SpriteChainRenderer.cpp index 0619ea81b..0aba848f9 100644 --- a/src/Nazara/Graphics/SpriteChainRenderer.cpp +++ b/src/Nazara/Graphics/SpriteChainRenderer.cpp @@ -45,6 +45,11 @@ namespace Nz m_indexBuffer = m_device.InstantiateBuffer(BufferType::Index, indexCount * sizeof(UInt16), BufferUsage::DeviceLocal | BufferUsage::Write, indices.data()); } + RenderElementPool& SpriteChainRenderer::GetPool() + { + return m_spriteChainPool; + } + std::unique_ptr SpriteChainRenderer::InstanciateData() { return std::make_unique(); diff --git a/src/Nazara/Graphics/SubmeshRenderer.cpp b/src/Nazara/Graphics/SubmeshRenderer.cpp index 26f7ee94e..5578611f3 100644 --- a/src/Nazara/Graphics/SubmeshRenderer.cpp +++ b/src/Nazara/Graphics/SubmeshRenderer.cpp @@ -13,6 +13,11 @@ namespace Nz { + RenderElementPool& SubmeshRenderer::GetPool() + { + return m_submeshPool; + } + std::unique_ptr SubmeshRenderer::InstanciateData() { return std::make_unique(); diff --git a/src/Nazara/Graphics/Systems/RenderSystem.cpp b/src/Nazara/Graphics/Systems/RenderSystem.cpp index 9e831b310..8c4f71693 100644 --- a/src/Nazara/Graphics/Systems/RenderSystem.cpp +++ b/src/Nazara/Graphics/Systems/RenderSystem.cpp @@ -37,7 +37,7 @@ namespace Nz m_sharedSkeletonDestroyConnection = registry.on_destroy().connect<&RenderSystem::OnSharedSkeletonDestroy>(this); m_skeletonDestroyConnection = registry.on_destroy().connect<&RenderSystem::OnSkeletonDestroy>(this); - m_pipeline = std::make_unique(); + m_pipeline = std::make_unique(m_elementRegistry); } RenderSystem::~RenderSystem() @@ -45,6 +45,7 @@ namespace Nz m_cameraConstructObserver.disconnect(); m_graphicsConstructObserver.disconnect(); m_lightConstructObserver.disconnect(); + m_pipeline.reset(); } void RenderSystem::Update(float /*elapsedTime*/) diff --git a/src/Nazara/Graphics/TextSprite.cpp b/src/Nazara/Graphics/TextSprite.cpp index 9f394a767..cb28c1442 100644 --- a/src/Nazara/Graphics/TextSprite.cpp +++ b/src/Nazara/Graphics/TextSprite.cpp @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include #include #include @@ -18,7 +19,7 @@ namespace Nz { } - void TextSprite::BuildElement(std::size_t passIndex, const WorldInstance& worldInstance, const SkeletonInstance* skeletonInstance, std::vector>& elements, const Recti& scissorBox) const + void TextSprite::BuildElement(ElementRendererRegistry& registry, const ElementData& elementData, std::size_t passIndex, std::vector& elements) const { const auto& materialPass = m_material->GetPass(passIndex); if (!materialPass) @@ -42,7 +43,7 @@ namespace Nz RenderIndices& indices = pair.second; if (indices.count > 0) - elements.emplace_back(std::make_unique(GetRenderLayer(), materialPass, renderPipeline, worldInstance, vertexDeclaration, key.texture->shared_from_this(), indices.count, &m_vertices[indices.first * 4], scissorBox)); + elements.emplace_back(registry.AllocateElement(GetRenderLayer(), materialPass, renderPipeline, *elementData.worldInstance, vertexDeclaration, key.texture->shared_from_this(), indices.count, &m_vertices[indices.first * 4], *elementData.scissorBox)); } } diff --git a/src/Nazara/Utility/Components/NodeComponent.cpp b/src/Nazara/Utility/Components/NodeComponent.cpp index 6f766dd54..304ea360e 100644 --- a/src/Nazara/Utility/Components/NodeComponent.cpp +++ b/src/Nazara/Utility/Components/NodeComponent.cpp @@ -3,9 +3,9 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include #include -#include #include namespace Nz