diff --git a/drape_frontend/batch_merge_helper.cpp b/drape_frontend/batch_merge_helper.cpp index 891af09cb6..d328d58274 100644 --- a/drape_frontend/batch_merge_helper.cpp +++ b/drape_frontend/batch_merge_helper.cpp @@ -61,7 +61,8 @@ bool BatchMergeHelper::IsMergeSupported() } void BatchMergeHelper::MergeBatches(vector> & batches, - vector> & mergedBatches) + vector> & mergedBatches, + bool isPerspective) { ASSERT(!batches.empty(), ()); if (batches.size() < 2) @@ -90,7 +91,11 @@ void BatchMergeHelper::MergeBatches(vector> & batches, newGroup->AddBucket(move(bucket)); buffer->Preflush(); - buffer->Build(newGroup->m_shader); + if (isPerspective) + newGroup->m_shader3d->Bind(); + else + newGroup->m_shader->Bind(); + buffer->Build(isPerspective ? newGroup->m_shader3d : newGroup->m_shader); mergedBatches.push_back(move(newGroup)); }; @@ -142,12 +147,12 @@ void BatchMergeHelper::MergeBatches(vector> & batches, uint32_t indexOffset = newBuffer->GetStartIndexValue(); - for (dp::VertexArrayBuffer::TBuffersMap::value_type const & vboNode : buffer->m_staticBuffers) + for (auto const & vboNode : buffer->m_staticBuffers) { copyVertecesFn(vboNode, rawDataBuffer, newBuffer); } - for (dp::VertexArrayBuffer::TBuffersMap::value_type const & vboNode : buffer->m_dynamicBuffers) + for (auto const & vboNode : buffer->m_dynamicBuffers) { copyVertecesFn(vboNode, rawDataBuffer, newBuffer); } diff --git a/drape_frontend/batch_merge_helper.hpp b/drape_frontend/batch_merge_helper.hpp index 012a9d999d..7196cb9c93 100644 --- a/drape_frontend/batch_merge_helper.hpp +++ b/drape_frontend/batch_merge_helper.hpp @@ -17,7 +17,8 @@ public: static bool IsMergeSupported(); static void MergeBatches(vector> & batches, - vector> & mergedBatches); + vector> & mergedBatches, + bool isPerspective); }; } diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index cac7ce7dd9..340be008e2 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -39,6 +39,24 @@ constexpr float kIsometryAngle = math::pi * 80.0f / 180.0f; const double VSyncInterval = 0.06; //const double VSyncInterval = 0.014; +struct MergedGroupKey +{ + dp::GLState m_state; + TileKey m_key; + + MergedGroupKey(dp::GLState const & state, TileKey const & tileKey) + : m_state(state), m_key(tileKey) + {} + + bool operator <(MergedGroupKey const & other) const + { + if (!(m_state == other.m_state)) + return m_state < other.m_state; + + return m_key.LessStrict(other.m_key); + } +}; + } // namespace FrontendRenderer::FrontendRenderer(Params const & params) @@ -789,7 +807,7 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView) if (group->IsEmpty()) continue; - if (group->IsPendingOnDelete()) + if (group->CanBeDeleted()) { group.reset(); ++eraseCount; @@ -958,8 +976,7 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView) AfterDrawFrame(); #endif - //TODO: there is a bug in this function, commented until investigation completion. - //MergeBuckets(); + MergeBuckets(); } void FrontendRenderer::MergeBuckets() @@ -974,8 +991,7 @@ void FrontendRenderer::MergeBuckets() if (m_renderGroups.empty()) return; - using TGroup = pair; - using TGroupMap = map>>; + using TGroupMap = map>>; TGroupMap forMerge; vector> newGroups; @@ -987,18 +1003,20 @@ void FrontendRenderer::MergeBuckets() { ref_ptr group = make_ref(m_renderGroups[i]); dp::GLState state = group->GetState(); - if (state.GetDepthLayer() == dp::GLState::GeometryLayer && - group->IsPendingOnDelete() == false) + if (state.GetDepthLayer() == dp::GLState::GeometryLayer && !group->IsPendingOnDelete()) { - TGroup const key = make_pair(state, group->GetTileKey()); + MergedGroupKey const key = MergedGroupKey(state, group->GetTileKey()); forMerge[key].push_back(move(m_renderGroups[i])); } else + { newGroups.push_back(move(m_renderGroups[i])); + } } + bool const isPerspective = m_userEventStream.GetCurrentScreen().isPerspective(); for (TGroupMap::value_type & node : forMerge) - BatchMergeHelper::MergeBatches(node.second, newGroups); + BatchMergeHelper::MergeBatches(node.second, newGroups, isPerspective); m_renderGroups = move(newGroups); } diff --git a/drape_frontend/render_group.cpp b/drape_frontend/render_group.cpp index 0ee5139a80..29dfaab54e 100755 --- a/drape_frontend/render_group.cpp +++ b/drape_frontend/render_group.cpp @@ -193,16 +193,16 @@ bool RenderGroupComparator::operator()(drape_ptr const & l, drape_p dp::GLState const & lState = l->GetState(); dp::GLState const & rState = r->GetState(); - if (!l->IsPendingOnDelete() && l->IsEmpty()) + if (!l->CanBeDeleted() && l->IsEmpty()) l->DeleteLater(); - if (!r->IsPendingOnDelete() && r->IsEmpty()) + if (!r->CanBeDeleted() && r->IsEmpty()) r->DeleteLater(); - bool lPendingOnDelete = l->IsPendingOnDelete(); - bool rPendingOnDelete = r->IsPendingOnDelete(); + bool const lCanBeDeleted = l->CanBeDeleted(); + bool const rCanBeDeleted = r->CanBeDeleted(); - if (rPendingOnDelete == lPendingOnDelete) + if (rCanBeDeleted == lCanBeDeleted) { dp::GLState::DepthLayer lDepth = lState.GetDepthLayer(); dp::GLState::DepthLayer rDepth = rState.GetDepthLayer(); @@ -215,7 +215,7 @@ bool RenderGroupComparator::operator()(drape_ptr const & l, drape_p return l->GetOpacity() > r->GetOpacity(); } - if (rPendingOnDelete) + if (rCanBeDeleted) return true; return false; diff --git a/drape_frontend/render_group.hpp b/drape_frontend/render_group.hpp index 0cda779dfa..6f15277dee 100755 --- a/drape_frontend/render_group.hpp +++ b/drape_frontend/render_group.hpp @@ -63,7 +63,8 @@ public: bool IsEmpty() const { return m_renderBuckets.empty(); } void DeleteLater() const { m_pendingOnDelete = true; } - bool IsPendingOnDelete() const { return m_pendingOnDelete && !IsAnimating(); } + bool IsPendingOnDelete() const { return m_pendingOnDelete; } + bool CanBeDeleted() const { return IsPendingOnDelete() && !IsAnimating(); } bool IsLess(RenderGroup const & other) const; diff --git a/drape_frontend/tile_key.cpp b/drape_frontend/tile_key.cpp index 3df98714ca..5805fe6efa 100755 --- a/drape_frontend/tile_key.cpp +++ b/drape_frontend/tile_key.cpp @@ -44,6 +44,23 @@ bool TileKey::operator ==(TileKey const & other) const m_zoomLevel == other.m_zoomLevel; } +bool TileKey::LessStrict(TileKey const & other) const +{ + if (m_generation != other.m_generation) + return m_generation < other.m_generation; + + if (m_zoomLevel != other.m_zoomLevel) + return m_zoomLevel < other.m_zoomLevel; + + if (m_styleZoomLevel != other.m_styleZoomLevel) + return m_styleZoomLevel < other.m_styleZoomLevel; + + if (m_y != other.m_y) + return m_y < other.m_y; + + return m_x < other.m_x; +} + m2::RectD TileKey::GetGlobalRect(bool considerStyleZoom) const { double const worldSizeDevisor = 1 << (considerStyleZoom ? m_styleZoomLevel : m_zoomLevel); diff --git a/drape_frontend/tile_key.hpp b/drape_frontend/tile_key.hpp index 20d4c0a677..57d1ad0e7c 100755 --- a/drape_frontend/tile_key.hpp +++ b/drape_frontend/tile_key.hpp @@ -26,6 +26,8 @@ struct TileKey bool operator < (TileKey const & other) const; bool operator == (TileKey const & other) const; + bool LessStrict(TileKey const & other) const; + m2::RectD GetGlobalRect(bool considerStyleZoom = false) const; int m_x;