From 0f239e88523f2283508417f7127557ec2e3e4835 Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Mon, 30 Mar 2015 19:10:20 +0300 Subject: [PATCH] Fixed bugs with deferred tiles --- drape_frontend/backend_renderer.cpp | 16 +++- drape_frontend/frontend_renderer.cpp | 64 +++++++------- drape_frontend/frontend_renderer.hpp | 1 + drape_frontend/message_subclasses.hpp | 4 +- drape_frontend/tile_info.cpp | 10 +-- drape_frontend/tile_tree.cpp | 122 ++++++++++++++++---------- drape_frontend/tile_tree.hpp | 28 +++--- 7 files changed, 147 insertions(+), 98 deletions(-) diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index c7a5786dc7..c2107dd0a7 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -95,11 +95,19 @@ void BackendRenderer::AcceptMessage(dp::RefPointer message) RecacheGui(CastMessage(message)->GetElements()); break; case Message::TileReadStarted: - m_batchersPool->ReserveBatcher(df::CastMessage(message)->GetKey()); - break; + { + m_batchersPool->ReserveBatcher(df::CastMessage(message)->GetKey()); + break; + } case Message::TileReadEnded: - m_batchersPool->ReleaseBatcher(df::CastMessage(message)->GetKey()); - break; + { + TileReadEndMessage * msg = df::CastMessage(message); + m_batchersPool->ReleaseBatcher(msg->GetKey()); + + TileReadEndMessage * outputMsg = new TileReadEndMessage(msg->GetKey()); + m_commutator->PostMessage(ThreadsCommutator::RenderThread, dp::MovePointer(outputMsg), MessagePriority::Normal); + break; + } case Message::MapShapeReaded: { MapShapeReadedMessage * msg = df::CastMessage(message); diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 0e7c2a466d..5dbd41f78d 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -79,8 +79,8 @@ void FrontendRenderer::AfterDrawFrame() m_tpf = accumulate(m_tpfs.begin(), m_tpfs.end(), 0.0) / m_tpfs.size(); - //LOG(LINFO, ("Average Fps : ", m_fps)); - //LOG(LINFO, ("Average Tpf : ", m_tpf)); + LOG(LINFO, ("Average Fps : ", m_fps)); + LOG(LINFO, ("Average Tpf : ", m_tpf)); #if defined(TRACK_GPU_MEM) string report = dp::GPUMemTracker::Inst().Report(); @@ -141,6 +141,15 @@ void FrontendRenderer::AcceptMessage(dp::RefPointer message) break; } + case Message::TileReadEnded: + { + TileReadEndMessage * msg = df::CastMessage(message); + TileKey const & key = msg->GetKey(); + if (!IsUserMarkLayer(key)) + FinishTileRenderGroup(key); + break; + } + case Message::Resize: { ResizeMessage * rszMsg = df::CastMessage(message); @@ -153,13 +162,13 @@ void FrontendRenderer::AcceptMessage(dp::RefPointer message) ResolveTileKeys(); TTilesCollection tiles; - m_tileTree.GetRequestedTiles(tiles); + m_tileTree.GetTilesCollection(tiles, df::GetTileScaleBase(m_view)); m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, dp::MovePointer(new ResizeMessage(m_viewport)), MessagePriority::Normal); m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, - dp::MovePointer(new UpdateReadManagerMessage(m_view, tiles)), + dp::MovePointer(new UpdateReadManagerMessage(m_view, move(tiles))), MessagePriority::Normal); break; } @@ -237,10 +246,7 @@ void FrontendRenderer::CreateTileRenderGroup(dp::GLState const & state, auto onAddTile = [&state, &renderBucket, this](TileKey const & tileKey, TileStatus tileStatus) { if (tileStatus == TileStatus::Rendered) - { AddToRenderGroup(m_renderGroups, state, renderBucket, tileKey); - LOG(LINFO, ("Render tile", tileKey, tileStatus)); - } else if (tileStatus == TileStatus::Deferred) OnAddDeferredTile(tileKey, tileStatus); else @@ -251,31 +257,30 @@ void FrontendRenderer::CreateTileRenderGroup(dp::GLState const & state, auto onDeferTile = [&state, &renderBucket, this](TileKey const & tileKey, TileStatus tileStatus) { AddToRenderGroup(m_deferredRenderGroups, state, renderBucket, tileKey); - LOG(LINFO, ("Defer tile", tileKey, tileStatus)); }; // removing tiles auto onRemoveTile = [this](TileKey const & tileKey, TileStatus tileStatus) { OnRemoveTile(tileKey, tileStatus); - LOG(LINFO, ("Remove tile", tileKey, tileStatus)); }; bool const result = m_tileTree.ProcessTile(newTile, onAddTile, onRemoveTile, onDeferTile); if (!result) - { renderBucket.Destroy(); - LOG(LINFO, ("Skip tile", newTile)); - } +} - LOG(LINFO, ("Deferred count = ", m_deferredRenderGroups.size())); - if (m_deferredRenderGroups.size() != 0) +void FrontendRenderer::FinishTileRenderGroup(TileKey const & newTile) +{ + auto onRemoveTile = [this](TileKey const & tileKey, TileStatus tileStatus) { - LOG(LINFO, ("Zoom level: ", df::GetTileScaleBase(m_view))); - LOG(LINFO, ("Tile tree: ", m_tileTree)); - LOG(LINFO, ("Rendered tiles: ", m_renderGroups)); - LOG(LINFO, ("Deferred tiles: ", m_deferredRenderGroups)); - } + OnRemoveTile(tileKey, tileStatus); + }; + auto onAddDeferredTile = [this](TileKey const & tileKey, TileStatus tileStatus) + { + OnAddDeferredTile(tileKey, tileStatus); + }; + m_tileTree.FinishTile(newTile, onAddDeferredTile, onRemoveTile); } void FrontendRenderer::AddToRenderGroup(vector> & groups, @@ -301,8 +306,6 @@ void FrontendRenderer::OnAddDeferredTile(TileKey const & tileKey, TileStatus til else ++it; } - - LOG(LINFO, ("Add deferred tile", tileKey, tileStatus)); } void FrontendRenderer::OnRemoveTile(TileKey const & tileKey, TileStatus tileStatus) @@ -463,14 +466,15 @@ void FrontendRenderer::ResolveTileKeys(int tileScale) auto onRemoveTile = [this](TileKey const & tileKey, TileStatus tileStatus) { OnRemoveTile(tileKey, tileStatus); - LOG(LINFO, ("Clip tile", tileKey, tileStatus)); }; - - m_tileTree.ClipByRect(clipRect, bind(&FrontendRenderer::OnAddDeferredTile, this, _1, _2), - onRemoveTile); + auto onAddDeferredTile = [this](TileKey const & tileKey, TileStatus tileStatus) + { + OnAddDeferredTile(tileKey, tileStatus); + }; + m_tileTree.ClipByRect(clipRect, onAddDeferredTile, onRemoveTile); // request new tiles - m_tileTree.BeginRequesting(tileScale); + m_tileTree.BeginRequesting(tileScale, onRemoveTile); for (int tileY = minTileY; tileY < maxTileY; ++tileY) { for (int tileX = minTileX; tileX < maxTileX; ++tileX) @@ -480,9 +484,7 @@ void FrontendRenderer::ResolveTileKeys(int tileScale) m_tileTree.RequestTile(key); } } - m_tileTree.EndRequesting(); - - //LOG(LINFO, (m_tileTree)); + m_tileTree.EndRequesting(onRemoveTile); } void FrontendRenderer::StartThread() @@ -581,10 +583,10 @@ void FrontendRenderer::UpdateScene() ResolveTileKeys(); TTilesCollection tiles; - m_tileTree.GetRequestedTiles(tiles); + m_tileTree.GetTilesCollection(tiles, df::GetTileScaleBase(m_view)); m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, - dp::MovePointer(new UpdateReadManagerMessage(m_view, tiles)), + dp::MovePointer(new UpdateReadManagerMessage(m_view, move(tiles))), MessagePriority::Normal); } } diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp index 8fcea3ca4e..2bcdf6bbb8 100755 --- a/drape_frontend/frontend_renderer.hpp +++ b/drape_frontend/frontend_renderer.hpp @@ -99,6 +99,7 @@ private: void CreateTileRenderGroup(dp::GLState const & state, dp::MasterPointer & renderBucket, TileKey const & newTile); + void FinishTileRenderGroup(TileKey const & newTile); void AddToRenderGroup(vector> & groups, dp::GLState const & state, dp::MasterPointer & renderBucket, diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp index d3d9663697..b06635a74c 100644 --- a/drape_frontend/message_subclasses.hpp +++ b/drape_frontend/message_subclasses.hpp @@ -108,8 +108,8 @@ private: class UpdateReadManagerMessage : public Message { public: - UpdateReadManagerMessage(ScreenBase const & screen, TTilesCollection const & tiles) - : m_tiles(tiles) + UpdateReadManagerMessage(ScreenBase const & screen, TTilesCollection && tiles) + : m_tiles(move(tiles)) , m_screen(screen) {} diff --git a/drape_frontend/tile_info.cpp b/drape_frontend/tile_info.cpp index e6a5b5c0c2..bad057f752 100644 --- a/drape_frontend/tile_info.cpp +++ b/drape_frontend/tile_info.cpp @@ -61,17 +61,17 @@ void TileInfo::ReadFeatureIndex(MapDataProvider const & model) void TileInfo::ReadFeatures(MapDataProvider const & model, MemoryFeatureIndex & memIndex) { + m_context.BeginReadTile(); + + // Reading can be interrupted by exception throwing + MY_SCOPE_GUARD(ReleaseReadTile, bind(&EngineContext::EndReadTile, &m_context)); + CheckCanceled(); vector indexes; RequestFeatures(memIndex, indexes); if (!indexes.empty()) { - m_context.BeginReadTile(); - - // Reading can be interrupted by exception throwing - MY_SCOPE_GUARD(ReleaseReadTile, bind(&EngineContext::EndReadTile, &m_context)); - vector featuresToRead; for_each(indexes.begin(), indexes.end(), IDsAccumulator(featuresToRead, m_featureInfo)); diff --git a/drape_frontend/tile_tree.cpp b/drape_frontend/tile_tree.cpp index 1ad36eaad7..fd80d900c4 100644 --- a/drape_frontend/tile_tree.cpp +++ b/drape_frontend/tile_tree.cpp @@ -21,9 +21,9 @@ void TileTree::Clear() m_root.reset(new Node()); } -void TileTree::BeginRequesting(int const zoomLevel) +void TileTree::BeginRequesting(int const zoomLevel, TTileHandler const & removeTile) { - AbortRequestedTiles(m_root, zoomLevel); + AbortTiles(m_root, zoomLevel, removeTile); } void TileTree::RequestTile(TileKey const & tileKey) @@ -31,26 +31,21 @@ void TileTree::RequestTile(TileKey const & tileKey) InsertToNode(m_root, tileKey); } -void TileTree::EndRequesting() +void TileTree::EndRequesting(TTileHandler const & removeTile) { - SimplifyTree(nullptr); + SimplifyTree(removeTile); } -void TileTree::GetRequestedTiles(TTilesCollection & tiles) +void TileTree::GetTilesCollection(TTilesCollection & tiles, int const zoomLevel) { - FindRequestedTiles(m_root, tiles); + FillTilesCollection(m_root, tiles, zoomLevel); } -bool TileTree::ContainsTileKey(TileKey const & tileKey) -{ - return ContainsTileKey(m_root, tileKey); -} - -void TileTree::ClipByRect(m2::RectD const & rect, TTileHandler const & addTile, +void TileTree::ClipByRect(m2::RectD const & rect, TTileHandler const & addDeferredTile, TTileHandler const & removeTile) { ClipNode(m_root, rect, removeTile); - CheckDeferredTiles(m_root, addTile, removeTile); + CheckDeferredTiles(m_root, addDeferredTile, removeTile); SimplifyTree(removeTile); } @@ -64,6 +59,16 @@ bool TileTree::ProcessTile(TileKey const & tileKey, TTileHandler const & addTile return result; } +void TileTree::FinishTile(TileKey const & tileKey, TTileHandler const & addDeferredTile, + TTileHandler const & removeTile) +{ + if (FinishNode(m_root, tileKey)) + { + CheckDeferredTiles(m_root, addDeferredTile, removeTile); + SimplifyTree(removeTile); + } +} + void TileTree::InsertToNode(TNodePtr const & node, TileKey const & tileKey) { // here we try to insert new tile to the node. The tree is built in such way that @@ -148,40 +153,33 @@ void TileTree::InsertToNode(TNodePtr const & node, TileKey const & tileKey) } } -void TileTree::AbortRequestedTiles(TNodePtr const & node, int const zoomLevel) +void TileTree::AbortTiles(TNodePtr const & node, int const zoomLevel, TTileHandler const & removeTile) { for (auto it = node->m_children.begin(); it != node->m_children.end(); ++it) { - if ((*it)->m_tileStatus == TileStatus::Requested && (*it)->m_tileKey.m_zoomLevel != zoomLevel) - (*it)->m_tileStatus = TileStatus::Unknown; + if ((*it)->m_tileKey.m_zoomLevel != zoomLevel) + { + if ((*it)->m_tileStatus == TileStatus::Requested) + (*it)->m_tileStatus = TileStatus::Unknown; + else if ((*it)->m_tileStatus == TileStatus::Deferred) + RemoveTile(*it, removeTile); + } - AbortRequestedTiles(*it, zoomLevel); + AbortTiles(*it, zoomLevel, removeTile); } } -void TileTree::FindRequestedTiles(TNodePtr const & node, TTilesCollection & tiles) +void TileTree::FillTilesCollection(TNodePtr const & node, TTilesCollection & tiles, int const zoomLevel) { for (auto it = node->m_children.begin(); it != node->m_children.end(); ++it) { - if ((*it)->m_tileStatus == TileStatus::Requested) + if ((*it)->m_tileStatus != TileStatus::Unknown && (*it)->m_tileKey.m_zoomLevel == zoomLevel) tiles.insert((*it)->m_tileKey); - FindRequestedTiles(*it, tiles); + FillTilesCollection(*it, tiles, zoomLevel); } } -bool TileTree::ContainsTileKey(TNodePtr const & node, TileKey const & tileKey) -{ - for (auto it = node->m_children.begin(); it != node->m_children.end(); ++it) - { - if (tileKey == (*it)->m_tileKey) - return (*it)->m_tileStatus != TileStatus::Unknown; - else if (IsTileBelow((*it)->m_tileKey, tileKey)) - return ContainsTileKey(*it, tileKey); - } - return false; -} - void TileTree::ClipNode(TNodePtr const & node, m2::RectD const & rect, TTileHandler const & removeTile) { for (auto it = node->m_children.begin(); it != node->m_children.end();) @@ -247,6 +245,22 @@ bool TileTree::ProcessNode(TNodePtr const & node, TileKey const & tileKey, return false; } +bool TileTree::FinishNode(TNodePtr const & node, TileKey const & tileKey) +{ + bool changed = false; + for (auto it = node->m_children.begin(); it != node->m_children.end(); ++it) + { + if ((*it)->m_tileKey == tileKey && (*it)->m_tileStatus == TileStatus::Requested) + { + (*it)->m_tileStatus = TileStatus::Unknown; + changed = true; + } + + changed |= FinishNode(*it, tileKey); + } + return changed; +} + void TileTree::DeleteTilesBelow(TNodePtr const & node, TTileHandler const & removeTile) { for (auto it = node->m_children.begin(); it != node->m_children.end(); ++it) @@ -259,7 +273,7 @@ void TileTree::DeleteTilesBelow(TNodePtr const & node, TTileHandler const & remo void TileTree::DeleteTilesAbove(TNodePtr const & node, TTileHandler const & addTile, TTileHandler const & removeTile) { - if (node->m_tileStatus == TileStatus::Requested) + if (node->m_tileStatus == TileStatus::Requested || node->m_children.empty()) return; // check if all child tiles are ready @@ -287,32 +301,30 @@ void TileTree::DeleteTilesAbove(TNodePtr const & node, TTileHandler const & addT void TileTree::SimplifyTree(TTileHandler const & removeTile) { - SimplifyTree(m_root, removeTile); + ClearEmptyLevels(m_root, removeTile); ClearObsoleteTiles(m_root, removeTile); } -void TileTree::SimplifyTree(TNodePtr const & node, TTileHandler const & removeTile) +void TileTree::ClearEmptyLevels(TNodePtr const & node, TTileHandler const & removeTile) { if (HaveChildrenSameStatus(node, TileStatus::Unknown)) { - // all children of children are rendered - for (auto it = node->m_children.begin(); it != node->m_children.end(); ++it) - if (!HaveChildrenSameStatus(*it, TileStatus::Rendered)) - return; + // all grandchildren have the same zoom level? + if (!HaveGrandchildrenSameZoomLevel(node)) + return; - // move children to grandfather + // move grandchildren to grandfather list newChildren; for (auto it = node->m_children.begin(); it != node->m_children.end(); ++it) { RemoveTile(*it, removeTile); newChildren.splice(newChildren.begin(), (*it)->m_children); } - node->m_children.swap(newChildren); } for (auto it = node->m_children.begin(); it != node->m_children.end(); ++it) - SimplifyTree(*it, removeTile); + ClearEmptyLevels(*it, removeTile); } bool TileTree::ClearObsoleteTiles(TNodePtr const & node, TTileHandler const & removeTile) @@ -332,7 +344,7 @@ bool TileTree::ClearObsoleteTiles(TNodePtr const & node, TTileHandler const & re return canClear && node->m_tileStatus == TileStatus::Unknown; } -bool TileTree::HaveChildrenSameStatus(TNodePtr const & node, TileStatus tileStatus) +bool TileTree::HaveChildrenSameStatus(TNodePtr const & node, TileStatus tileStatus) const { for (auto it = node->m_children.begin(); it != node->m_children.end(); ++it) if ((*it)->m_tileStatus != tileStatus) @@ -341,11 +353,33 @@ bool TileTree::HaveChildrenSameStatus(TNodePtr const & node, TileStatus tileStat return true; } +bool TileTree::HaveGrandchildrenSameZoomLevel(TNodePtr const & node) const +{ + if (node->m_children.empty()) + return true; + + int zoomLevel = -1; + for (auto childIt = node->m_children.begin(); childIt != node->m_children.end(); ++childIt) + if (!(*childIt)->m_children.empty()) + zoomLevel = (*childIt)->m_children.front()->m_tileKey.m_zoomLevel; + + // have got grandchildren? + if (zoomLevel == -1) + return true; + + for (auto childIt = node->m_children.begin(); childIt != node->m_children.end(); ++childIt) + for (auto grandchildIt = (*childIt)->m_children.begin(); grandchildIt != (*childIt)->m_children.end(); ++grandchildIt) + if (zoomLevel != (*grandchildIt)->m_tileKey.m_zoomLevel) + return false; + + return true; +} + void TileTree::CheckDeferredTiles(TNodePtr const & node, TTileHandler const & addTile, TTileHandler const & removeTile) { for (auto it = node->m_children.begin(); it != node->m_children.end(); ++it) { - DeleteTilesAbove(node, addTile, removeTile); + DeleteTilesAbove(*it, addTile, removeTile); CheckDeferredTiles(*it, addTile, removeTile); } } diff --git a/drape_frontend/tile_tree.hpp b/drape_frontend/tile_tree.hpp index d465a2fc4e..f8d6489170 100644 --- a/drape_frontend/tile_tree.hpp +++ b/drape_frontend/tile_tree.hpp @@ -20,49 +20,53 @@ public: using TTileHandler = function; - void BeginRequesting(int const zoomLevel); + void BeginRequesting(int const zoomLevel, TTileHandler const & removeTile); void RequestTile(TileKey const & tileKey); - void EndRequesting(); + void EndRequesting(TTileHandler const & removeTile); bool ProcessTile(TileKey const & tileKey, TTileHandler const & addTile, TTileHandler const & removeTile, TTileHandler const & deferTile); - void ClipByRect(m2::RectD const & rect, TTileHandler const & addTile, + + void FinishTile(TileKey const & tileKey, TTileHandler const & addDeferredTile, + TTileHandler const & removeTile); + + void ClipByRect(m2::RectD const & rect, TTileHandler const & addDeferredTile, TTileHandler const & removeTile); void Clear(); - bool ContainsTileKey(TileKey const & tileKey); - void GetRequestedTiles(TTilesCollection & tiles); + void GetTilesCollection(TTilesCollection & tiles, int const zoomLevel); private: struct Node; using TNodePtr = unique_ptr; void InsertToNode(TNodePtr const & node, TileKey const & tileKey); - void AbortRequestedTiles(TNodePtr const & node, int const zoomLevel); + void AbortTiles(TNodePtr const & node, int const zoomLevel, TTileHandler const & removeTile); - void FindRequestedTiles(TNodePtr const & node, TTilesCollection & tiles); - bool ContainsTileKey(TNodePtr const & node, TileKey const & tileKey); + void FillTilesCollection(TNodePtr const & node, TTilesCollection & tiles, int const zoomLevel); void ClipNode(TNodePtr const & node, m2::RectD const & rect, TTileHandler const & removeTile); + void CheckDeferredTiles(TNodePtr const & node, TTileHandler const & addTile, + TTileHandler const & removeTile); void RemoveTile(TNodePtr const & node, TTileHandler const & removeTile); bool ProcessNode(TNodePtr const & node, TileKey const & tileKey, TTileHandler const & addTile, TTileHandler const & removeTile, TTileHandler const & deferTile); + bool FinishNode(TNodePtr const & node, TileKey const & tileKey); void DeleteTilesBelow(TNodePtr const & node, TTileHandler const & removeTile); void DeleteTilesAbove(TNodePtr const & node, TTileHandler const & addTile, TTileHandler const & removeTile); void SimplifyTree(TTileHandler const & removeTile); - void SimplifyTree(TNodePtr const & node, TTileHandler const & removeTile); + void ClearEmptyLevels(TNodePtr const & node, TTileHandler const & removeTile); bool ClearObsoleteTiles(TNodePtr const & node, TTileHandler const & removeTile); - void CheckDeferredTiles(TNodePtr const & node, TTileHandler const & addTile, - TTileHandler const & removeTile); - bool HaveChildrenSameStatus(TNodePtr const & node, TileStatus tileStatus); + bool HaveChildrenSameStatus(TNodePtr const & node, TileStatus tileStatus) const; + bool HaveGrandchildrenSameZoomLevel(TNodePtr const & node) const; private: struct Node