diff --git a/include/Nazara/Core/Algorithm.hpp b/include/Nazara/Core/Algorithm.hpp index 6f0754c1b..b52ddba95 100644 --- a/include/Nazara/Core/Algorithm.hpp +++ b/include/Nazara/Core/Algorithm.hpp @@ -71,6 +71,9 @@ namespace Nz using type = void; //< FIXME: I can't make SFINAE work }; + template + using Pointer = T*; + template bool Serialize(SerializationContext& context, T&& value); diff --git a/include/Nazara/Graphics/ElementRenderer.hpp b/include/Nazara/Graphics/ElementRenderer.hpp index aaba080bd..a41b9432c 100644 --- a/include/Nazara/Graphics/ElementRenderer.hpp +++ b/include/Nazara/Graphics/ElementRenderer.hpp @@ -8,6 +8,7 @@ #define NAZARA_ELEMENTRENDERER_HPP #include +#include #include #include #include @@ -23,7 +24,7 @@ namespace Nz ElementRenderer() = default; virtual ~ElementRenderer(); - virtual void Render(CommandBufferBuilder& commandBuffer, const RenderElement** elements, std::size_t elementCount) = 0; + virtual void Render(CommandBufferBuilder& commandBuffer, const Pointer* elements, std::size_t elementCount) = 0; }; } diff --git a/include/Nazara/Graphics/RenderQueue.hpp b/include/Nazara/Graphics/RenderQueue.hpp index 420272d36..3ba9067c8 100644 --- a/include/Nazara/Graphics/RenderQueue.hpp +++ b/include/Nazara/Graphics/RenderQueue.hpp @@ -8,38 +8,15 @@ #define NAZARA_RENDERQUEUE_HPP #include -#include #include namespace Nz { - class RenderQueueInternal - { - public: - using Index = UInt64; - - RenderQueueInternal() = default; - RenderQueueInternal(const RenderQueueInternal&) = default; - RenderQueueInternal(RenderQueueInternal&&) = default; - ~RenderQueueInternal() = default; - - RenderQueueInternal& operator=(const RenderQueueInternal&) = default; - RenderQueueInternal& operator=(RenderQueueInternal&&) = default; - - protected: - using RenderDataPair = std::pair; - - void Sort(); - - std::vector m_orderedRenderQueue; - }; - template - class RenderQueue : public RenderQueueInternal + class RenderQueue { public: - class const_iterator; - friend const_iterator; + using const_iterator = const RenderData*; using size_type = std::size_t; RenderQueue() = default; @@ -63,37 +40,8 @@ namespace Nz RenderQueue& operator=(RenderQueue&&) noexcept = default; private: - const RenderData& GetData(std::size_t i) const; - std::vector m_data; }; - - template - class RenderQueue::const_iterator : public std::iterator - { - friend RenderQueue; - - public: - const_iterator(const const_iterator& it); - - const RenderData& operator*() const; - - const_iterator& operator=(const const_iterator& it); - const_iterator& operator++(); - const_iterator operator++(int); - - bool operator==(const const_iterator& rhs) const; - bool operator!=(const const_iterator& rhs) const; - - void swap(const_iterator& rhs); - - private: - const_iterator(const RenderQueue* queue, std::size_t nextId); - - std::size_t m_nextDataId; - const RenderQueue* m_queue; - }; - } #include diff --git a/include/Nazara/Graphics/RenderQueue.inl b/include/Nazara/Graphics/RenderQueue.inl index 47ec03c98..8d2793407 100644 --- a/include/Nazara/Graphics/RenderQueue.inl +++ b/include/Nazara/Graphics/RenderQueue.inl @@ -3,14 +3,13 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include +#include namespace Nz { template void RenderQueue::Clear() { - m_orderedRenderQueue.clear(); m_data.clear(); } @@ -24,113 +23,33 @@ namespace Nz template void RenderQueue::Sort(IndexFunc&& func) { - m_orderedRenderQueue.clear(); - m_orderedRenderQueue.reserve(m_data.size()); - - std::size_t dataIndex = 0; - for (const RenderData& renderData : m_data) - m_orderedRenderQueue.emplace_back(func(renderData), dataIndex++); - - RenderQueueInternal::Sort(); + std::sort(m_data.begin(), m_data.end(), [&](const RenderData& lhs, const RenderData& rhs) + { + return func(lhs) < func(rhs); + }); } template - typename RenderQueue::const_iterator RenderQueue::begin() const + auto RenderQueue::begin() const -> const_iterator { - return const_iterator(this, 0); + return &m_data[0]; } template bool RenderQueue::empty() const { - return m_orderedRenderQueue.empty(); + return m_data.empty(); } template - typename RenderQueue::const_iterator RenderQueue::end() const + auto RenderQueue::end() const -> const_iterator { - return const_iterator(this, m_orderedRenderQueue.size()); + return begin() + m_data.size(); } template - typename RenderQueue::size_type RenderQueue::size() const + auto RenderQueue::size() const -> size_type { - return m_orderedRenderQueue.size(); - } - - template - const RenderData& RenderQueue::GetData(std::size_t i) const - { - NazaraAssert(i < m_orderedRenderQueue.size(), "Cannot dereference post-end iterator"); - - return m_data[m_orderedRenderQueue[i].second]; - } - - - template - RenderQueue::const_iterator::const_iterator(const RenderQueue* queue, std::size_t nextId) : - m_nextDataId(nextId), - m_queue(queue) - { - } - - template - RenderQueue::const_iterator::const_iterator(const const_iterator& it) : - m_nextDataId(it.m_nextDataId), - m_queue(it.m_queue) - { - } - - template - const RenderData& RenderQueue::const_iterator::operator*() const - { - return m_queue->GetData(m_nextDataId); - } - - template - typename RenderQueue::const_iterator& RenderQueue::const_iterator::operator=(const const_iterator& it) - { - m_nextDataId = it.m_nextDataId; - m_queue = it.m_queue; - - return *this; - } - - template - typename RenderQueue::const_iterator& RenderQueue::const_iterator::operator++() - { - ++m_nextDataId; - - return *this; - } - - template - typename RenderQueue::const_iterator RenderQueue::const_iterator::operator++(int) - { - return iterator(m_queue, m_nextDataId++); - } - - template - bool RenderQueue::const_iterator::operator==(const typename RenderQueue::const_iterator& rhs) const - { - NazaraAssert(m_queue == rhs.m_queue, "Cannot compare iterator coming from different queues"); - - return m_nextDataId == rhs.m_nextDataId; - } - - template - bool RenderQueue::const_iterator::operator!=(const typename RenderQueue::const_iterator& rhs) const - { - return !operator==(rhs); - } - - template - void RenderQueue::const_iterator::swap(typename RenderQueue::const_iterator& rhs) - { - NazaraAssert(m_queue == rhs.m_queue, "Cannot swap iterator coming from different queues"); - - using std::swap; - - swap(m_nextDataId, rhs.m_nextDataId); + return m_data.size(); } } diff --git a/include/Nazara/Graphics/SubmeshRenderer.hpp b/include/Nazara/Graphics/SubmeshRenderer.hpp index 41c5d87b4..dca15ed6b 100644 --- a/include/Nazara/Graphics/SubmeshRenderer.hpp +++ b/include/Nazara/Graphics/SubmeshRenderer.hpp @@ -18,7 +18,7 @@ namespace Nz SubmeshRenderer() = default; ~SubmeshRenderer() = default; - void Render(CommandBufferBuilder& commandBuffer, const RenderElement** elements, std::size_t elementCount) override; + void Render(CommandBufferBuilder& commandBuffer, const Pointer* elements, std::size_t elementCount) override; }; } diff --git a/src/Nazara/Graphics/ForwardFramePipeline.cpp b/src/Nazara/Graphics/ForwardFramePipeline.cpp index 1b5b85757..b047954bf 100644 --- a/src/Nazara/Graphics/ForwardFramePipeline.cpp +++ b/src/Nazara/Graphics/ForwardFramePipeline.cpp @@ -325,29 +325,7 @@ namespace Nz builder.BindShaderBinding(Graphics::ViewerBindingSet, viewer->GetViewerInstance().GetShaderBinding()); - auto it = m_depthPrepassRenderQueue.begin(); - while (it != m_depthPrepassRenderQueue.end()) - { - const RenderElement* element = *it; - UInt8 elementType = element->GetElementType(); - - m_temporaryElementList.push_back(element); - - ++it; - while (it != m_depthPrepassRenderQueue.end() && (*it)->GetElementType() == elementType) - { - m_temporaryElementList.push_back(*it); - ++it; - } - - if (elementType >= m_elementRenderers.size() || !m_elementRenderers[elementType]) - continue; - - ElementRenderer& elementRenderer = *m_elementRenderers[elementType]; - elementRenderer.Render(builder, m_temporaryElementList.data(), m_temporaryElementList.size()); - - m_temporaryElementList.clear(); - } + ProcessRenderQueue(builder, m_depthPrepassRenderQueue); }); FramePass& forwardPass = frameGraph.AddPass("Forward pass"); @@ -375,29 +353,7 @@ namespace Nz builder.BindShaderBinding(Graphics::ViewerBindingSet, viewer->GetViewerInstance().GetShaderBinding()); - auto it = m_forwardRenderQueue.begin(); - while (it != m_forwardRenderQueue.end()) - { - const RenderElement* element = *it; - UInt8 elementType = element->GetElementType(); - - m_temporaryElementList.push_back(element); - - ++it; - while (it != m_forwardRenderQueue.end() && (*it)->GetElementType() == elementType) - { - m_temporaryElementList.push_back(*it); - ++it; - } - - if (elementType >= m_elementRenderers.size() || !m_elementRenderers[elementType]) - continue; - - ElementRenderer& elementRenderer = *m_elementRenderers[elementType]; - elementRenderer.Render(builder, m_temporaryElementList.data(), m_temporaryElementList.size()); - - m_temporaryElementList.clear(); - } + ProcessRenderQueue(builder, m_forwardRenderQueue); }); } @@ -425,6 +381,31 @@ namespace Nz it->second.usedCount++; } + void ForwardFramePipeline::ProcessRenderQueue(CommandBufferBuilder& builder, const RenderQueue& renderQueue) + { + 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; + + ElementRenderer& elementRenderer = *m_elementRenderers[elementType]; + elementRenderer.Render(builder, first, count); + } + } + void ForwardFramePipeline::UnregisterMaterialPass(MaterialPass* material) { auto it = m_materials.find(material); diff --git a/src/Nazara/Graphics/RenderQueue.cpp b/src/Nazara/Graphics/RenderQueue.cpp deleted file mode 100644 index 50f2a6690..000000000 --- a/src/Nazara/Graphics/RenderQueue.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (C) 2017 Jérôme Leclercq -// 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 -{ - void RenderQueueInternal::Sort() - { - std::sort(m_orderedRenderQueue.begin(), m_orderedRenderQueue.end(), [](const RenderDataPair& lhs, const RenderDataPair& rhs) - { - /* - Original code: - if (lhs.first == rhs.first) - return lhs.second < rhs.second; - else - return lhs.first < rhs.first; - - Clang seems to the the only one to prevent branching with the original code (using cmov) - Rewriting the code with bit ops seems to prevent branching with Clang/GCC/MSVC - */ - bool equal = lhs.first == rhs.first; - bool compareFirst = lhs.first < rhs.first; - bool compareSecond = lhs.second < rhs.second; - - return (equal & compareSecond) | (!equal & compareFirst); - }); - } -} diff --git a/src/Nazara/Graphics/SubmeshRenderer.cpp b/src/Nazara/Graphics/SubmeshRenderer.cpp index f2dff3ae8..4b86f1509 100644 --- a/src/Nazara/Graphics/SubmeshRenderer.cpp +++ b/src/Nazara/Graphics/SubmeshRenderer.cpp @@ -10,7 +10,7 @@ namespace Nz { - void SubmeshRenderer::Render(CommandBufferBuilder& commandBuffer, const RenderElement** elements, std::size_t elementCount) + void SubmeshRenderer::Render(CommandBufferBuilder& commandBuffer, const Pointer* elements, std::size_t elementCount) { const AbstractBuffer* currentIndexBuffer = nullptr; const AbstractBuffer* currentVertexBuffer = nullptr;