diff --git a/drape/batcher.cpp b/drape/batcher.cpp index b407e3f076..c8f9b5ac31 100644 --- a/drape/batcher.cpp +++ b/drape/batcher.cpp @@ -205,7 +205,7 @@ void Batcher::ChangeBuffer(ref_ptr wrapper) ref_ptr Batcher::GetBucket(GLState const & state) { - TBuckets::iterator it = m_buckets.find(state); + TBuckets::iterator it = m_buckets.find(BucketId(state, m_currentFeature.IsValid())); if (it != m_buckets.end()) return make_ref(it->second); @@ -215,17 +215,18 @@ ref_ptr Batcher::GetBucket(GLState const & state) if (m_currentFeature.IsValid()) result->StartFeatureRecord(m_currentFeature, m_featureLimitRect); - m_buckets.emplace(state, move(buffer)); + m_buckets.emplace(BucketId(state, m_currentFeature.IsValid()), move(buffer)); return result; } void Batcher::FinalizeBucket(GLState const & state) { - TBuckets::iterator it = m_buckets.find(state); + BucketId bucketId(state, m_currentFeature.IsValid()); + TBuckets::iterator it = m_buckets.find(bucketId); ASSERT(it != m_buckets.end(), ("Have no bucket for finalize with given state")); drape_ptr bucket = move(it->second); - m_buckets.erase(state); + m_buckets.erase(bucketId); if (m_currentFeature.IsValid()) bucket->EndFeatureRecord(false); @@ -242,7 +243,7 @@ void Batcher::Flush() if (m_currentFeature.IsValid()) bucket.second->EndFeatureRecord(true); bucket.second->GetBuffer()->Preflush(); - m_flushInterface(bucket.first, move(bucket.second)); + m_flushInterface(bucket.first.m_state, move(bucket.second)); }); m_buckets.clear(); diff --git a/drape/batcher.hpp b/drape/batcher.hpp index 81a5142d0c..3c71dc7002 100644 --- a/drape/batcher.hpp +++ b/drape/batcher.hpp @@ -69,7 +69,26 @@ private: TFlushFn m_flushInterface; private: - using TBuckets = map>; + struct BucketId + { + BucketId() = default; + BucketId(GLState const & state, bool sharedFeatures) + : m_state(state) + , m_sharedFeatures(sharedFeatures) + {} + + bool operator < (BucketId const & other) const + { + if (m_state == other.m_state) + return m_sharedFeatures < other.m_sharedFeatures; + return m_state < other.m_state; + } + + GLState m_state; + bool m_sharedFeatures; + }; + + using TBuckets = map>; TBuckets m_buckets; uint32_t m_indexBufferSize; diff --git a/drape/render_bucket.cpp b/drape/render_bucket.cpp index a17905eb69..830b9dc0c5 100644 --- a/drape/render_bucket.cpp +++ b/drape/render_bucket.cpp @@ -125,7 +125,7 @@ void RenderBucket::AddFeaturesInfo(RenderBucket const & bucket) bool RenderBucket::IsFeaturesWaiting(TCheckFeaturesWaiting isFeaturesWaiting) { - ASSERT(!m_featuresGeometryInfo.empty(), ()); + ASSERT(IsShared(), ()); for (auto const & featureRange : m_featuresGeometryInfo) if (isFeaturesWaiting(featureRange.second.m_limitRect)) return true; diff --git a/drape/render_bucket.hpp b/drape/render_bucket.hpp index 6ac231603e..c66e51be72 100644 --- a/drape/render_bucket.hpp +++ b/drape/render_bucket.hpp @@ -49,6 +49,7 @@ public: todo(make_ref(h)); } + bool IsShared() const { return !m_featuresGeometryInfo.empty(); } void StartFeatureRecord(FeatureGeometryId feature, m2::RectD const & limitRect); void EndFeatureRecord(bool featureCompleted); diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index 8c386b67a1..83dd0ef3e5 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -180,9 +180,14 @@ void BackendRenderer::AcceptMessage(ref_ptr message) ref_ptr batcher = m_batchersPool->GetTileBatcher(tileKey); for (drape_ptr const & shape : msg->GetShapes()) { - batcher->StartFeatureRecord(shape->GetFeatureInfo(), shape->GetFeatureLimitRect()); + bool const sharedFeature = shape->GetFeatureInfo().IsValid(); + if (sharedFeature) + batcher->StartFeatureRecord(shape->GetFeatureInfo(), shape->GetFeatureLimitRect()); + shape->Draw(batcher, m_texMng); - batcher->EndFeatureRecord(); + + if (sharedFeature) + batcher->EndFeatureRecord(); } } break; diff --git a/drape_frontend/batch_merge_helper.cpp b/drape_frontend/batch_merge_helper.cpp index 92648181f3..b3ec78386e 100644 --- a/drape_frontend/batch_merge_helper.cpp +++ b/drape_frontend/batch_merge_helper.cpp @@ -62,7 +62,7 @@ bool BatchMergeHelper::IsMergeSupported() void BatchMergeHelper::MergeBatches(vector> & batches, vector> & mergedBatches, - bool isPerspective) + bool isPerspective, bool sharedFeatures) { ASSERT(!batches.empty(), ()); if (batches.size() < 2) @@ -133,6 +133,8 @@ void BatchMergeHelper::MergeBatches(vector> & batches, { for (drape_ptr const & b : group->m_renderBuckets) { + if (b->IsShared() != sharedFeatures) + continue; ASSERT(b->m_overlay.empty(), ()); ref_ptr buffer = b->GetBuffer(); uint32_t vertexCount = buffer->GetStartIndexValue(); @@ -145,7 +147,8 @@ void BatchMergeHelper::MergeBatches(vector> & batches, allocateFn(bucket, newBuffer); } - bucket->AddFeaturesInfo(*b); + if (b->IsShared()) + bucket->AddFeaturesInfo(*b); uint32_t indexOffset = newBuffer->GetStartIndexValue(); diff --git a/drape_frontend/batch_merge_helper.hpp b/drape_frontend/batch_merge_helper.hpp index 7196cb9c93..27b2f68414 100644 --- a/drape_frontend/batch_merge_helper.hpp +++ b/drape_frontend/batch_merge_helper.hpp @@ -18,7 +18,7 @@ public: static void MergeBatches(vector> & batches, vector> & mergedBatches, - bool isPerspective); + bool isPerspective, bool sharedFeatures); }; } diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 3b135e724a..9fa77db149 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -53,7 +53,6 @@ struct MergedGroupKey { if (!(m_state == other.m_state)) return m_state < other.m_state; - return m_key.LessStrict(other.m_key); } }; @@ -891,8 +890,7 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView) for (RenderLayer & layer : m_layers) { for (auto & group : layer.m_renderGroups) - if (group->UpdateFeaturesWaitingStatus(isFeaturesWaiting)) - layer.m_isDirty = true; + layer.m_isDirty |= group->UpdateFeaturesWaitingStatus(isFeaturesWaiting); } bool const isPerspective = modelView.isPerspective(); @@ -1081,7 +1079,15 @@ void FrontendRenderer::MergeBuckets() } for (TGroupMap::value_type & node : forMerge) - BatchMergeHelper::MergeBatches(node.second, newGroups, isPerspective); + { + if (node.second.size() < 2) + newGroups.emplace_back(move(node.second.front())); + else + { + BatchMergeHelper::MergeBatches(node.second, newGroups, isPerspective, true); + BatchMergeHelper::MergeBatches(node.second, newGroups, isPerspective, false); + } + } layer.m_renderGroups = move(newGroups); layer.m_isDirty = true; diff --git a/drape_frontend/map_shape.hpp b/drape_frontend/map_shape.hpp index 8e1da20d6c..2f138b939b 100644 --- a/drape_frontend/map_shape.hpp +++ b/drape_frontend/map_shape.hpp @@ -32,7 +32,7 @@ public: virtual MapShapeType GetType() const { return MapShapeType::GeometryType; } void SetFeatureInfo(dp::FeatureGeometryId const & feature) { m_featureInfo = feature; } - dp::FeatureGeometryId GetFeatureInfo() const { return m_featureInfo; } + dp::FeatureGeometryId const & GetFeatureInfo() const { return m_featureInfo; } void SetFeatureLimitRect(m2::RectD rect) { m_limitRect = rect; } m2::RectD const & GetFeatureLimitRect() const { return m_limitRect; } diff --git a/drape_frontend/overlay_batcher.cpp b/drape_frontend/overlay_batcher.cpp index 64f761bd97..09ce323bd1 100644 --- a/drape_frontend/overlay_batcher.cpp +++ b/drape_frontend/overlay_batcher.cpp @@ -26,9 +26,12 @@ OverlayBatcher::OverlayBatcher(TileKey const & key) void OverlayBatcher::Batch(drape_ptr const & shape, ref_ptr texMng) { - m_batcher.StartFeatureRecord(shape->GetFeatureInfo(), shape->GetFeatureLimitRect()); + bool const sharedFeature = shape->GetFeatureInfo().IsValid(); + if (sharedFeature) + m_batcher.StartFeatureRecord(shape->GetFeatureInfo(), shape->GetFeatureLimitRect()); shape->Draw(make_ref(&m_batcher), texMng); - m_batcher.EndFeatureRecord(); + if (sharedFeature) + m_batcher.EndFeatureRecord(); } void OverlayBatcher::Finish(TOverlaysRenderData & data) diff --git a/drape_frontend/render_group.cpp b/drape_frontend/render_group.cpp index 31370e7425..4dea663140 100755 --- a/drape_frontend/render_group.cpp +++ b/drape_frontend/render_group.cpp @@ -183,18 +183,28 @@ void RenderGroup::Disappear() bool RenderGroup::UpdateFeaturesWaitingStatus(TCheckFeaturesWaiting isFeaturesWaiting) { - bool statusChanged = false; - if (m_sharedFeaturesWaiting) { - for (auto const & bucket : m_renderBuckets) - if (bucket->IsFeaturesWaiting(isFeaturesWaiting)) - return statusChanged; + m2::RectD const tileRect = GetTileKey().GetGlobalRect(); + bool const isTileVisible = isFeaturesWaiting(tileRect); - m_sharedFeaturesWaiting = false; - statusChanged = true; + for (size_t i = 0; i < m_renderBuckets.size(); ) + { + bool visibleBucket = m_renderBuckets[i]->IsShared() ? m_renderBuckets[i]->IsFeaturesWaiting(isFeaturesWaiting) + : isTileVisible; + if (!visibleBucket) + { + swap(m_renderBuckets[i], m_renderBuckets.back()); + m_renderBuckets.pop_back(); + } + else + { + ++i; + } + } + m_sharedFeaturesWaiting = !m_renderBuckets.empty(); } - return statusChanged; + return m_renderBuckets.empty(); } bool RenderGroupComparator::operator()(drape_ptr const & l, drape_ptr const & r) diff --git a/drape_frontend/rule_drawer.cpp b/drape_frontend/rule_drawer.cpp index 6d6ab14f9f..240a0e8232 100644 --- a/drape_frontend/rule_drawer.cpp +++ b/drape_frontend/rule_drawer.cpp @@ -119,15 +119,19 @@ void RuleDrawer::operator()(FeatureType const & f) int const minVisibleScale = feature::GetMinDrawableScale(f); + m2::RectD const tileRect = m_context->GetTileKey().GetGlobalRect(); uint32_t shapesCount = 0; - auto insertShape = [this, zoomLevel, &shapesCount, &f](drape_ptr && shape) + auto insertShape = [this, zoomLevel, &tileRect, &shapesCount, &f](drape_ptr && shape) { int const index = static_cast(shape->GetType()); ASSERT_LESS(index, m_mapShapes.size(), ()); m2::RectD const limitRect = f.GetLimitRect(zoomLevel); - shape->SetFeatureInfo(dp::FeatureGeometryId(f.GetID(), shapesCount)); - shape->SetFeatureLimitRect(limitRect); + if (!tileRect.IsRectInside(limitRect)) + { + shape->SetFeatureInfo(dp::FeatureGeometryId(f.GetID(), shapesCount)); + shape->SetFeatureLimitRect(limitRect); + } m_mapShapes[index].push_back(move(shape)); ++shapesCount; };