From 8d4a0b8124f3280acb90e0ebf428a83332860b0c Mon Sep 17 00:00:00 2001 From: ExMix Date: Wed, 20 Jan 2016 20:09:08 +0300 Subject: [PATCH 1/3] reduce small memory allocations in std::bind --- drape/batcher.cpp | 38 +++++++++++++++----------------- drape/batcher_helpers.cpp | 30 ++++++++++--------------- drape/batcher_helpers.hpp | 32 +++++++++++---------------- drape/glstate.cpp | 19 ++++++++++++---- drape/uniform_values_storage.cpp | 5 ----- drape/uniform_values_storage.hpp | 7 ++++-- 6 files changed, 63 insertions(+), 68 deletions(-) diff --git a/drape/batcher.cpp b/drape/batcher.cpp index 5f4e38c0cc..5a72a6ef7c 100644 --- a/drape/batcher.cpp +++ b/drape/batcher.cpp @@ -13,13 +13,13 @@ namespace dp { -class Batcher::CallbacksWrapper +class Batcher::CallbacksWrapper : public BatchCallbacks { public: - CallbacksWrapper(GLState const & state, ref_ptr overlay) + CallbacksWrapper(GLState const & state, ref_ptr overlay, ref_ptr batcher) : m_state(state) , m_overlay(overlay) - , m_vaoChanged(false) + , m_batcher(batcher) { } @@ -34,7 +34,7 @@ public: m_indicesRange.m_idxStart = m_buffer->GetIndexCount(); } - void FlushData(BindingInfo const & info, void const * data, uint32_t count) + void FlushData(BindingInfo const & info, void const * data, uint32_t count) override { if (m_overlay != nullptr && info.IsDynamic()) { @@ -44,7 +44,7 @@ public: m_buffer->UploadData(info, data, count); } - void * GetIndexStorage(uint32_t size, uint32_t & startIndex) + void * GetIndexStorage(uint32_t size, uint32_t & startIndex) override { startIndex = m_buffer->GetStartIndexValue(); if (m_overlay == nullptr || !m_overlay->IndexesRequired()) @@ -56,22 +56,27 @@ public: return m_overlay->IndexStorage(size); } - void SubmitIndexes() + void SubmitIndeces() override { if (m_overlay == nullptr || !m_overlay->IndexesRequired()) m_buffer->UploadIndexes(m_indexStorage.GetRawConst(), m_indexStorage.Size()); } - uint32_t GetAvailableVertexCount() const + uint32_t GetAvailableVertexCount() const override { return m_buffer->GetAvailableVertexCount(); } - uint32_t GetAvailableIndexCount() const + uint32_t GetAvailableIndexCount() const override { return m_buffer->GetAvailableIndexCount(); } + void ChangeBuffer() override + { + m_batcher->ChangeBuffer(make_ref(this)); + } + GLState const & GetState() const { return m_state; @@ -89,11 +94,12 @@ public: private: GLState const & m_state; - ref_ptr m_buffer; ref_ptr m_overlay; + ref_ptr m_batcher; + ref_ptr m_buffer; IndexStorage m_indexStorage; IndicesRange m_indicesRange; - bool m_vaoChanged; + bool m_vaoChanged = false; }; //////////////////////////////////////////////////////////////// @@ -221,18 +227,10 @@ IndicesRange Batcher::InsertTriangles(GLState const & state, ref_ptr handle = move(transferHandle); { - Batcher::CallbacksWrapper wrapper(state, make_ref(handle)); + Batcher::CallbacksWrapper wrapper(state, make_ref(handle), make_ref(this)); wrapper.SetVAO(vao); - BatchCallbacks callbacks; - callbacks.m_flushVertex = bind(&CallbacksWrapper::FlushData, &wrapper, _1, _2, _3); - callbacks.m_getIndexStorage = bind(&CallbacksWrapper::GetIndexStorage, &wrapper, _1, _2); - callbacks.m_submitIndex = bind(&CallbacksWrapper::SubmitIndexes, &wrapper); - callbacks.m_getAvailableVertex = bind(&CallbacksWrapper::GetAvailableVertexCount, &wrapper); - callbacks.m_getAvailableIndex = bind(&CallbacksWrapper::GetAvailableIndexCount, &wrapper); - callbacks.m_changeBuffer = bind(&Batcher::ChangeBuffer, this, make_ref(&wrapper)); - - TBatcher batch(callbacks); + TBatcher batch(wrapper); batch.SetIsCanDevideStreams(handle == nullptr); batch.SetVertexStride(vertexStride); batch.BatchData(params); diff --git a/drape/batcher_helpers.cpp b/drape/batcher_helpers.cpp index 3d3b1c9930..7fea0d6f82 100644 --- a/drape/batcher_helpers.cpp +++ b/drape/batcher_helpers.cpp @@ -140,7 +140,7 @@ private: } // namespace -TriangleBatch::TriangleBatch(BatchCallbacks const & callbacks) +TriangleBatch::TriangleBatch(BatchCallbacks & callbacks) : m_callbacks(callbacks) , m_canDevideStreams(true) { @@ -169,38 +169,32 @@ void TriangleBatch::FlushData(ref_ptr streams, uint32_t verte void TriangleBatch::FlushData(BindingInfo const & info, void const * data, uint32_t elementCount) const { - ASSERT(m_callbacks.m_flushVertex != NULL, ()); - return m_callbacks.m_flushVertex(info, data, elementCount); + m_callbacks.FlushData(info, data, elementCount); } void * TriangleBatch::GetIndexStorage(uint32_t indexCount, uint32_t & startIndex) { - ASSERT(m_callbacks.m_getIndexStorage, ()); - return m_callbacks.m_getIndexStorage(indexCount, startIndex); + return m_callbacks.GetIndexStorage(indexCount, startIndex); } void TriangleBatch::SubmitIndex() { - ASSERT(m_callbacks.m_submitIndex, ()); - m_callbacks.m_submitIndex(); + m_callbacks.SubmitIndeces(); } uint32_t TriangleBatch::GetAvailableVertexCount() const { - ASSERT(m_callbacks.m_getAvailableVertex!= NULL, ()); - return m_callbacks.m_getAvailableVertex(); + return m_callbacks.GetAvailableVertexCount(); } uint32_t TriangleBatch::GetAvailableIndexCount() const { - ASSERT(m_callbacks.m_getAvailableIndex != NULL, ()); - return m_callbacks.m_getAvailableIndex(); + return m_callbacks.GetAvailableIndexCount(); } void TriangleBatch::ChangeBuffer() const { - ASSERT(m_callbacks.m_changeBuffer != NULL, ()); - m_callbacks.m_changeBuffer(); + return m_callbacks.ChangeBuffer(); } uint8_t TriangleBatch::GetVertexStride() const @@ -213,7 +207,7 @@ bool TriangleBatch::IsBufferFilled(uint32_t availableVerticesCount, uint32_t ava return availableVerticesCount < 3 || availableIndicesCount < 3; } -TriangleListBatch::TriangleListBatch(BatchCallbacks const & callbacks) : TBase(callbacks) {} +TriangleListBatch::TriangleListBatch(BatchCallbacks & callbacks) : TBase(callbacks) {} void TriangleListBatch::BatchData(ref_ptr streams) { @@ -252,7 +246,7 @@ void TriangleListBatch::BatchData(ref_ptr streams) } } -FanStripHelper::FanStripHelper(BatchCallbacks const & callbacks) +FanStripHelper::FanStripHelper(BatchCallbacks & callbacks) : TBase(callbacks) , m_isFullUploaded(false) { @@ -336,7 +330,7 @@ uint32_t FanStripHelper::AlignICount(uint32_t iCount) const return iCount - iCount % 3; } -TriangleStripBatch::TriangleStripBatch(BatchCallbacks const & callbacks) +TriangleStripBatch::TriangleStripBatch(BatchCallbacks & callbacks) : TBase(callbacks) { } @@ -362,7 +356,7 @@ void TriangleStripBatch::GenerateIndexes(void * indexStorage, uint32_t count, ui GenerateIndices(indexStorage, count, startIndex); } -TriangleFanBatch::TriangleFanBatch(BatchCallbacks const & callbacks) : TBase(callbacks) {} +TriangleFanBatch::TriangleFanBatch(BatchCallbacks & callbacks) : TBase(callbacks) {} /* @@ -469,7 +463,7 @@ void TriangleFanBatch::GenerateIndexes(void * indexStorage, uint32_t count, uint GenerateIndices(indexStorage, count, startIndex); } -TriangleListOfStripBatch::TriangleListOfStripBatch(BatchCallbacks const & callbacks) +TriangleListOfStripBatch::TriangleListOfStripBatch(BatchCallbacks & callbacks) : TBase(callbacks) { } diff --git a/drape/batcher_helpers.hpp b/drape/batcher_helpers.hpp index 2f91685f8e..b099c2314d 100644 --- a/drape/batcher_helpers.hpp +++ b/drape/batcher_helpers.hpp @@ -13,24 +13,18 @@ class BindingInfo; class BatchCallbacks { public: - typedef function TFlushVertexFn; - typedef function TGetIndexStorageFn; - typedef function TSubmitIndexFn; - typedef function TGetAvailableFn; - typedef function ChangeBufferFn; - - TFlushVertexFn m_flushVertex; - TGetIndexStorageFn m_getIndexStorage; - TSubmitIndexFn m_submitIndex; - TGetAvailableFn m_getAvailableVertex; - TGetAvailableFn m_getAvailableIndex; - ChangeBufferFn m_changeBuffer; + virtual void FlushData(BindingInfo const & binding, void const * data, uint32_t count) = 0; + virtual void * GetIndexStorage(uint32_t indexCount, uint32_t & startIndex) = 0; + virtual void SubmitIndeces() = 0; + virtual uint32_t GetAvailableVertexCount() const = 0; + virtual uint32_t GetAvailableIndexCount() const = 0; + virtual void ChangeBuffer() = 0; }; class TriangleBatch { public: - TriangleBatch(BatchCallbacks const & callbacks); + TriangleBatch(BatchCallbacks & callbacks); virtual ~TriangleBatch(){} virtual void BatchData(ref_ptr streams) = 0; @@ -51,7 +45,7 @@ protected: virtual bool IsBufferFilled(uint32_t availableVerticesCount, uint32_t availableIndicesCount) const; private: - BatchCallbacks m_callbacks; + BatchCallbacks & m_callbacks; bool m_canDevideStreams; uint8_t m_vertexStride; }; @@ -61,7 +55,7 @@ class TriangleListBatch : public TriangleBatch typedef TriangleBatch TBase; public: - TriangleListBatch(BatchCallbacks const & callbacks); + TriangleListBatch(BatchCallbacks & callbacks); virtual void BatchData(ref_ptr streams); }; @@ -71,7 +65,7 @@ class FanStripHelper : public TriangleBatch typedef TriangleBatch TBase; public: - FanStripHelper(BatchCallbacks const & callbacks); + FanStripHelper(BatchCallbacks & callbacks); protected: uint32_t BatchIndexes(uint32_t vertexCount); @@ -94,7 +88,7 @@ class TriangleStripBatch : public FanStripHelper typedef FanStripHelper TBase; public: - TriangleStripBatch(BatchCallbacks const & callbacks); + TriangleStripBatch(BatchCallbacks & callbacks); virtual void BatchData(ref_ptr streams); protected: @@ -106,7 +100,7 @@ class TriangleFanBatch : public FanStripHelper typedef FanStripHelper TBase; public: - TriangleFanBatch(BatchCallbacks const & callbacks); + TriangleFanBatch(BatchCallbacks & callbacks); virtual void BatchData(ref_ptr streams); protected: @@ -118,7 +112,7 @@ class TriangleListOfStripBatch : public FanStripHelper typedef FanStripHelper TBase; public: - TriangleListOfStripBatch(BatchCallbacks const & callbacks); + TriangleListOfStripBatch(BatchCallbacks & callbacks); virtual void BatchData(ref_ptr streams); diff --git a/drape/glstate.cpp b/drape/glstate.cpp index a5b1417941..83b0763050 100644 --- a/drape/glstate.cpp +++ b/drape/glstate.cpp @@ -105,15 +105,26 @@ bool GLState::operator==(GLState const & other) const namespace { - void ApplyUniformValue(UniformValue const & value, ref_ptr program) + +struct UniformApplyer +{ + ref_ptr m_program; + + void operator()(UniformValue const & value) const { - value.Apply(program); + ASSERT(m_program != nullptr, ()); + value.Apply(m_program); } -} +}; + +} // namespace void ApplyUniforms(UniformValuesStorage const & uniforms, ref_ptr program) { - uniforms.ForeachValue(bind(&ApplyUniformValue, _1, program)); + static UniformApplyer applyer; + applyer.m_program = program; + uniforms.ForeachValue(applyer); + applyer.m_program = nullptr; } void ApplyTextures(GLState state, ref_ptr program) diff --git a/drape/uniform_values_storage.cpp b/drape/uniform_values_storage.cpp index 9fbce973e9..96a55fe485 100644 --- a/drape/uniform_values_storage.cpp +++ b/drape/uniform_values_storage.cpp @@ -89,11 +89,6 @@ void UniformValuesStorage::SetMatrix4x4Value(string const & name, float const * m_uniforms.emplace_back(name, matrixValue); } -void UniformValuesStorage::ForeachValue(enum_uniforms_fn action) const -{ - for_each(m_uniforms.begin(), m_uniforms.end(), action); -} - bool UniformValuesStorage::operator< (UniformValuesStorage const & other) const { if (m_uniforms.size() < other.m_uniforms.size()) diff --git a/drape/uniform_values_storage.hpp b/drape/uniform_values_storage.hpp index e3e5864182..3250287f3c 100644 --- a/drape/uniform_values_storage.hpp +++ b/drape/uniform_values_storage.hpp @@ -24,8 +24,11 @@ public: void SetMatrix4x4Value(string const & name, float const * matrixValue); - typedef function enum_uniforms_fn; - void ForeachValue(enum_uniforms_fn action) const; + template + void ForeachValue(TFunctor & functor) const + { + for_each(m_uniforms.begin(), m_uniforms.end(), functor); + } bool operator< (UniformValuesStorage const & other) const; From ccfe29b198ab9ad59a4a9aeacbe95deb69aad1ed Mon Sep 17 00:00:00 2001 From: ExMix Date: Sat, 23 Jan 2016 13:53:51 +0300 Subject: [PATCH 2/3] [drape] make render scene loop more linear and cache friendly --- drape/glstate.hpp | 1 - drape_frontend/frontend_renderer.cpp | 382 ++++++++++++++++----------- drape_frontend/frontend_renderer.hpp | 29 +- drape_frontend/render_group.cpp | 12 +- drape_frontend/render_group.hpp | 1 + 5 files changed, 252 insertions(+), 173 deletions(-) diff --git a/drape/glstate.hpp b/drape/glstate.hpp index e06f0013fc..3fa7788128 100644 --- a/drape/glstate.hpp +++ b/drape/glstate.hpp @@ -38,7 +38,6 @@ public: { /// Do not change order GeometryLayer, - DynamicGeometry, OverlayLayer, UserMarkLayer, Gui diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index ac19ec4348..8e904febc2 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -58,6 +58,97 @@ struct MergedGroupKey } }; +template +bool RemoveGroups(ToDo & filter, vector> & groups) +{ + size_t startCount = groups.size(); + size_t count = startCount; + size_t current = 0; + while (current < count) + { + drape_ptr & group = groups[current]; + if (filter(move(group))) + { + swap(group, groups.back()); + groups.pop_back(); + --count; + } + else + ++current; + } + + return startCount != count; +} + +struct ActivateTilePredicate +{ + TileKey const & m_tileKey; + + ActivateTilePredicate(TileKey const & tileKey) + : m_tileKey(tileKey) + { + } + + bool operator()(drape_ptr & group) const + { + if (group->GetTileKey() == m_tileKey) + { + group->Appear(); + return true; + } + + return false; + } +}; + +struct RemoveTilePredicate +{ + mutable bool m_deletionMark = false; + function const &)> const & m_predicate; + + RemoveTilePredicate(function const &)> const & predicate) + : m_predicate(predicate) + { + } + + bool operator()(drape_ptr && group) const + { + if (m_predicate(group)) + { + group->Disappear(); + group->DeleteLater(); + m_deletionMark = true; + return group->CanBeDeleted(); + } + + return false; + } +}; + +template +struct MoveTileFunctor +{ + TPredicate m_predicate; + vector> & m_targetGroups; + + MoveTileFunctor(TPredicate predicate, vector> & groups) + : m_predicate(predicate) + , m_targetGroups(groups) + { + } + + bool operator()(drape_ptr && group) + { + if (m_predicate(group)) + { + m_targetGroups.push_back(move(group)); + return true; + } + + return false; + } +}; + } // namespace FrontendRenderer::FrontendRenderer(Params const & params) @@ -435,8 +526,12 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) m_tileTree->Invalidate(); // Clear all graphics. - m_renderGroups.clear(); - m_deferredRenderGroups.clear(); + for (RenderLayer & layer : m_layers) + { + layer.m_renderGroups.clear(); + layer.m_deferredRenderGroups.clear(); + layer.m_isDirty = false; + } // Invalidate read manager. { @@ -613,20 +708,17 @@ void FrontendRenderer::InvalidateRect(m2::RectD const & gRect) m_tileTree->Invalidate(); ResolveTileKeys(rect, tiles); - auto eraseFunction = [&tiles](vector> & groups) + auto eraseFunction = [&tiles](drape_ptr && group) { - vector > newGroups; - for (drape_ptr & group : groups) - { - if (tiles.find(group->GetTileKey()) == tiles.end()) - newGroups.push_back(move(group)); - } - - swap(groups, newGroups); + return tiles.count(group->GetTileKey()) == 0; }; - eraseFunction(m_renderGroups); - eraseFunction(m_deferredRenderGroups); + for (RenderLayer & layer : m_layers) + { + RemoveGroups(eraseFunction, layer.m_renderGroups); + RemoveGroups(eraseFunction, layer.m_deferredRenderGroups); + layer.m_isDirty = true; + } BaseBlockingMessage::Blocker blocker; m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, @@ -673,30 +765,26 @@ void FrontendRenderer::AddToRenderGroup(vector> & groups, void FrontendRenderer::OnAddRenderGroup(TileKey const & tileKey, dp::GLState const & state, drape_ptr && renderBucket) { - AddToRenderGroup(m_renderGroups, state, move(renderBucket), tileKey); - m_renderGroups.back()->Appear(); + RenderLayer::RenderLayerID id = RenderLayer::GetLayerID(state); + RenderLayer & layer = m_layers[id]; + AddToRenderGroup(layer.m_renderGroups, state, move(renderBucket), tileKey); + layer.m_renderGroups.back()->Appear(); + layer.m_isDirty = true; } void FrontendRenderer::OnDeferRenderGroup(TileKey const & tileKey, dp::GLState const & state, drape_ptr && renderBucket) { - AddToRenderGroup(m_deferredRenderGroups, state, move(renderBucket), tileKey); + RenderLayer::RenderLayerID id = RenderLayer::GetLayerID(state); + AddToRenderGroup(m_layers[id].m_deferredRenderGroups, state, move(renderBucket), tileKey); } void FrontendRenderer::OnActivateTile(TileKey const & tileKey) { - for(auto it = m_deferredRenderGroups.begin(); it != m_deferredRenderGroups.end();) + for (RenderLayer & layer : m_layers) { - if ((*it)->GetTileKey() == tileKey) - { - m_renderGroups.push_back(move(*it)); - it = m_deferredRenderGroups.erase(it); - m_renderGroups.back()->Appear(); - } - else - { - ++it; - } + MoveTileFunctor f(ActivateTilePredicate(tileKey), layer.m_renderGroups); + layer.m_isDirty |= RemoveGroups(f, layer.m_deferredRenderGroups); } } @@ -714,19 +802,13 @@ void FrontendRenderer::RemoveRenderGroups(TRenderGroupRemovePredicate const & pr ASSERT(predicate != nullptr, ()); m_overlayTree->ForceUpdate(); - for(auto const & group : m_renderGroups) + for (RenderLayer & layer : m_layers) { - if (predicate(group)) - { - group->DeleteLater(); - group->Disappear(); - } + RemoveTilePredicate f(predicate); + RemoveGroups(f, layer.m_renderGroups); + RemoveGroups(predicate, layer.m_deferredRenderGroups); + layer.m_isDirty |= f.m_deletionMark; } - - m_deferredRenderGroups.erase(remove_if(m_deferredRenderGroups.begin(), - m_deferredRenderGroups.end(), - predicate), - m_deferredRenderGroups.end()); } bool FrontendRenderer::CheckTileGenerations(TileKey const & tileKey) @@ -817,78 +899,17 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView) bool const isPerspective = modelView.isPerspective(); - RenderGroupComparator comparator; - sort(m_renderGroups.begin(), m_renderGroups.end(), bind(&RenderGroupComparator::operator (), &comparator, _1, _2)); - - BeginUpdateOverlayTree(modelView); - size_t eraseCount = 0; GLFunctions::glEnable(gl_const::GLDepthTest); - for (size_t i = 0; i < m_renderGroups.size(); ++i) - { - drape_ptr & group = m_renderGroups[i]; - if (group->IsEmpty()) - continue; - - if (group->CanBeDeleted()) - { - group.reset(); - ++eraseCount; - continue; - } - - switch (group->GetState().GetDepthLayer()) - { - case dp::GLState::OverlayLayer: - UpdateOverlayTree(modelView, group); - break; - case dp::GLState::DynamicGeometry: - group->Update(modelView); - break; - default: - break; - } - } - EndUpdateOverlayTree(); - m_renderGroups.resize(m_renderGroups.size() - eraseCount); - m_viewport.Apply(); RefreshBgColor(); GLFunctions::glClear(); - dp::GLState::DepthLayer prevLayer = dp::GLState::GeometryLayer; - size_t currentRenderGroup = 0; - bool has3dAreas = false; - size_t area3dRenderGroupStart = 0; - size_t area3dRenderGroupEnd = 0; - for (; currentRenderGroup < m_renderGroups.size(); ++currentRenderGroup) - { - drape_ptr const & group = m_renderGroups[currentRenderGroup]; + Render2dLayer(modelView); - dp::GLState const & state = group->GetState(); - - if ((isPerspective || m_isIsometry) && state.GetProgram3dIndex() == gpu::AREA_3D_PROGRAM) - { - if (!has3dAreas) - { - area3dRenderGroupStart = currentRenderGroup; - has3dAreas = true; - } - area3dRenderGroupEnd = currentRenderGroup; - continue; - } - - dp::GLState::DepthLayer layer = state.GetDepthLayer(); - if (prevLayer != layer && layer == dp::GLState::OverlayLayer) - break; - - prevLayer = layer; - RenderSingleGroup(modelView, make_ref(group)); - } - - GLFunctions::glDisable(gl_const::GLDepthTest); bool hasSelectedPOI = false; if (m_selectionShape != nullptr) { + GLFunctions::glDisable(gl_const::GLDepthTest); SelectionShape::ESelectedObject selectedObject = m_selectionShape->GetSelectedObject(); if (selectedObject == SelectionShape::OBJECT_MY_POSITION) { @@ -898,7 +919,7 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView) } else if (selectedObject == SelectionShape::OBJECT_POI) { - if (!isPerspective && !has3dAreas) + if (!isPerspective && m_layers[RenderLayer::Geometry3dID].m_renderGroups.empty()) m_selectionShape->Render(modelView, make_ref(m_gpuProgramManager), m_generalUniforms); else hasSelectedPOI = true; @@ -908,34 +929,20 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView) m_myPositionController->Render(MyPositionController::RenderAccuracy, modelView, make_ref(m_gpuProgramManager), m_generalUniforms); - if (has3dAreas) + if (m_framebuffer->IsSupported()) { - if (m_framebuffer->IsSupported()) - { - m_framebuffer->Enable(); - GLFunctions::glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - GLFunctions::glClear(); - GLFunctions::glClearDepth(); - } - else - { - GLFunctions::glClearDepth(); - } - - GLFunctions::glEnable(gl_const::GLDepthTest); - for (size_t index = area3dRenderGroupStart; index <= area3dRenderGroupEnd; ++index) - { - drape_ptr const & group = m_renderGroups[index]; - if (group->GetState().GetProgram3dIndex() == gpu::AREA_3D_PROGRAM) - RenderSingleGroup(modelView, make_ref(group)); - } - - if (m_framebuffer->IsSupported()) - { - m_framebuffer->Disable(); - GLFunctions::glDisable(gl_const::GLDepthTest); - m_transparentLayer->Render(m_framebuffer->GetTextureId(), make_ref(m_gpuProgramManager)); - } + m_framebuffer->Enable(); + GLFunctions::glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + GLFunctions::glClear(); + Render3dLayer(modelView); + m_framebuffer->Disable(); + GLFunctions::glDisable(gl_const::GLDepthTest); + m_transparentLayer->Render(m_framebuffer->GetTextureId(), make_ref(m_gpuProgramManager)); + } + else + { + GLFunctions::glClearDepth(); + Render3dLayer(modelView); } if (hasSelectedPOI) @@ -946,11 +953,7 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView) GLFunctions::glEnable(gl_const::GLDepthTest); GLFunctions::glClearDepth(); - for (; currentRenderGroup < m_renderGroups.size(); ++currentRenderGroup) - { - drape_ptr const & group = m_renderGroups[currentRenderGroup]; - RenderSingleGroup(modelView, make_ref(group)); - } + RenderOverlayLayer(modelView); m_gpsTrackRenderer->RenderTrack(modelView, GetCurrentZoomLevel(), make_ref(m_gpuProgramManager), m_generalUniforms); @@ -1001,6 +1004,36 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView) MergeBuckets(); } +void FrontendRenderer::Render2dLayer(ScreenBase const & modelView) +{ + RenderLayer & layer2d = m_layers[RenderLayer::Geometry2dID]; + layer2d.Sort(); + + for (drape_ptr const & group : layer2d.m_renderGroups) + RenderSingleGroup(modelView, make_ref(group)); +} + +void FrontendRenderer::Render3dLayer(ScreenBase const & modelView) +{ + GLFunctions::glEnable(gl_const::GLDepthTest); + RenderLayer & layer = m_layers[RenderLayer::Geometry3dID]; + layer.Sort(); + for (drape_ptr const & group : layer.m_renderGroups) + RenderSingleGroup(modelView, make_ref(group)); +} + +void FrontendRenderer::RenderOverlayLayer(ScreenBase const & modelView) +{ + RenderLayer & overlay = m_layers[RenderLayer::OverlayID]; + overlay.Sort(); + BeginUpdateOverlayTree(modelView); + for (drape_ptr & group : overlay.m_renderGroups) + UpdateOverlayTree(modelView, group); + EndUpdateOverlayTree(); + for (drape_ptr & group : overlay.m_renderGroups) + RenderSingleGroup(modelView, make_ref(group)); +} + void FrontendRenderer::MergeBuckets() { if (BatchMergeHelper::IsMergeSupported() == false) @@ -1010,37 +1043,37 @@ void FrontendRenderer::MergeBuckets() if (m_mergeBucketsCounter < 60) return; - if (m_renderGroups.empty()) - return; - - using TGroupMap = map>>; - TGroupMap forMerge; - - vector> newGroups; - newGroups.reserve(m_renderGroups.size()); - m_mergeBucketsCounter = 0; - size_t groupsCount = m_renderGroups.size(); - for (size_t i = 0; i < groupsCount; ++i) + + auto mergeFn = [](RenderLayer & layer, bool isPerspective) { - ref_ptr group = make_ref(m_renderGroups[i]); - dp::GLState state = group->GetState(); - if (state.GetDepthLayer() == dp::GLState::GeometryLayer && !group->IsPendingOnDelete()) + if (layer.m_renderGroups.empty()) + return; + + using TGroupMap = map>>; + TGroupMap forMerge; + + vector> newGroups; + newGroups.reserve(layer.m_renderGroups.size()); + + size_t groupsCount = layer.m_renderGroups.size(); + for (size_t i = 0; i < groupsCount; ++i) { - MergedGroupKey const key(state, group->GetTileKey()); - forMerge[key].push_back(move(m_renderGroups[i])); + ref_ptr group = make_ref(layer.m_renderGroups[i]); + dp::GLState state = group->GetState(); + ASSERT_EQUAL(state.GetDepthLayer(), dp::GLState::GeometryLayer, ()); + forMerge[MergedGroupKey(state, group->GetTileKey())].push_back(move(layer.m_renderGroups[i])); } - else - { - newGroups.push_back(move(m_renderGroups[i])); - } - } + + for (TGroupMap::value_type & node : forMerge) + BatchMergeHelper::MergeBatches(node.second, newGroups, isPerspective); + + layer.m_renderGroups = move(newGroups); + }; bool const isPerspective = m_userEventStream.GetCurrentScreen().isPerspective(); - for (TGroupMap::value_type & node : forMerge) - BatchMergeHelper::MergeBatches(node.second, newGroups, isPerspective); - - m_renderGroups = move(newGroups); + mergeFn(m_layers[RenderLayer::Geometry2dID], isPerspective); + mergeFn(m_layers[RenderLayer::Geometry3dID], isPerspective); } bool FrontendRenderer::IsPerspective() const @@ -1426,8 +1459,11 @@ void FrontendRenderer::Routine::Do() void FrontendRenderer::ReleaseResources() { m_tileTree.reset(); - m_renderGroups.clear(); - m_deferredRenderGroups.clear(); + for (RenderLayer & layer : m_layers) + { + layer.m_renderGroups.clear(); + layer.m_deferredRenderGroups.clear(); + } m_userMarkRenderGroups.clear(); m_guiRenderer.reset(); m_myPositionController.reset(); @@ -1514,4 +1550,28 @@ void FrontendRenderer::EmitModelViewChanged(ScreenBase const & modelView) const m_modelViewChangedFn(modelView); } +FrontendRenderer::RenderLayer::RenderLayerID FrontendRenderer::RenderLayer::GetLayerID(dp::GLState const & state) +{ + if (state.GetDepthLayer() == dp::GLState::OverlayLayer) + return OverlayID; + + if (state.GetProgram3dIndex() == gpu::AREA_3D_PROGRAM) + return Geometry3dID; + + return Geometry2dID; +} + +void FrontendRenderer::RenderLayer::Sort() +{ + if (!m_isDirty) + return; + + RenderGroupComparator comparator; + sort(m_renderGroups.begin(), m_renderGroups.end(), comparator); + m_isDirty = comparator.m_pendingOnDeleteFound; + + while (!m_renderGroups.empty() && m_renderGroups.back()->CanBeDeleted()) + m_renderGroups.pop_back(); +} + } // namespace df diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp index 8967f5cd06..9761c77aaa 100755 --- a/drape_frontend/frontend_renderer.hpp +++ b/drape_frontend/frontend_renderer.hpp @@ -36,6 +36,7 @@ #include "std/function.hpp" #include "std/map.hpp" +#include "std/array.hpp" namespace dp { @@ -148,6 +149,12 @@ private: void RefreshPivotTransform(ScreenBase const & screen); void RefreshBgColor(); + ////// + /// Render part of scene + void Render2dLayer(ScreenBase const & modelView); + void Render3dLayer(ScreenBase const & modelView); + void RenderOverlayLayer(ScreenBase const & modelView); + ////// ScreenBase const & ProcessEvents(bool & modelViewChanged, bool & viewportChanged); void PrepareScene(ScreenBase const & modelView); void UpdateScene(ScreenBase const & modelView); @@ -230,8 +237,26 @@ private: private: drape_ptr m_gpuProgramManager; - vector> m_renderGroups; - vector> m_deferredRenderGroups; + struct RenderLayer + { + enum RenderLayerID + { + Geometry2dID, + OverlayID, + Geometry3dID, + LayerCountID + }; + + static RenderLayerID GetLayerID(dp::GLState const & renderGroup); + + vector> m_renderGroups; + vector> m_deferredRenderGroups; + bool m_isDirty = false; + + inline void Sort(); + }; + + array m_layers; vector> m_userMarkRenderGroups; set m_userMarkVisibility; diff --git a/drape_frontend/render_group.cpp b/drape_frontend/render_group.cpp index 29dfaab54e..1a2aa10369 100755 --- a/drape_frontend/render_group.cpp +++ b/drape_frontend/render_group.cpp @@ -190,20 +190,14 @@ void RenderGroup::Disappear() bool RenderGroupComparator::operator()(drape_ptr const & l, drape_ptr const & r) { - dp::GLState const & lState = l->GetState(); - dp::GLState const & rState = r->GetState(); - - if (!l->CanBeDeleted() && l->IsEmpty()) - l->DeleteLater(); - - if (!r->CanBeDeleted() && r->IsEmpty()) - r->DeleteLater(); - + m_pendingOnDeleteFound |= (l->IsPendingOnDelete() || r->IsPendingOnDelete()); bool const lCanBeDeleted = l->CanBeDeleted(); bool const rCanBeDeleted = r->CanBeDeleted(); if (rCanBeDeleted == lCanBeDeleted) { + dp::GLState const & lState = l->GetState(); + dp::GLState const & rState = r->GetState(); dp::GLState::DepthLayer lDepth = lState.GetDepthLayer(); dp::GLState::DepthLayer rDepth = rState.GetDepthLayer(); if (lDepth != rDepth) diff --git a/drape_frontend/render_group.hpp b/drape_frontend/render_group.hpp index 6f15277dee..49f61a5063 100755 --- a/drape_frontend/render_group.hpp +++ b/drape_frontend/render_group.hpp @@ -90,6 +90,7 @@ class RenderGroupComparator { public: bool operator()(drape_ptr const & l, drape_ptr const & r); + bool m_pendingOnDeleteFound = false; }; class UserMarkRenderGroup : public BaseRenderGroup From 2f697b9b6b3684d923f6b759dfa220d08746bc74 Mon Sep 17 00:00:00 2001 From: ExMix Date: Sat, 30 Jan 2016 08:31:37 +0300 Subject: [PATCH 3/3] [drape] bugfix --- drape_frontend/frontend_renderer.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 8e904febc2..6b02ab7286 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -1060,15 +1060,21 @@ void FrontendRenderer::MergeBuckets() for (size_t i = 0; i < groupsCount; ++i) { ref_ptr group = make_ref(layer.m_renderGroups[i]); - dp::GLState state = group->GetState(); - ASSERT_EQUAL(state.GetDepthLayer(), dp::GLState::GeometryLayer, ()); - forMerge[MergedGroupKey(state, group->GetTileKey())].push_back(move(layer.m_renderGroups[i])); + if (!group->IsPendingOnDelete()) + { + dp::GLState state = group->GetState(); + ASSERT_EQUAL(state.GetDepthLayer(), dp::GLState::GeometryLayer, ()); + forMerge[MergedGroupKey(state, group->GetTileKey())].push_back(move(layer.m_renderGroups[i])); + } + else + newGroups.push_back(move(layer.m_renderGroups[i])); } for (TGroupMap::value_type & node : forMerge) BatchMergeHelper::MergeBatches(node.second, newGroups, isPerspective); layer.m_renderGroups = move(newGroups); + layer.m_isDirty = true; }; bool const isPerspective = m_userEventStream.GetCurrentScreen().isPerspective(); @@ -1567,7 +1573,7 @@ void FrontendRenderer::RenderLayer::Sort() return; RenderGroupComparator comparator; - sort(m_renderGroups.begin(), m_renderGroups.end(), comparator); + sort(m_renderGroups.begin(), m_renderGroups.end(), ref(comparator)); m_isDirty = comparator.m_pendingOnDeleteFound; while (!m_renderGroups.empty() && m_renderGroups.back()->CanBeDeleted())