Fixed bugs with deferred tiles

This commit is contained in:
r.kuznetsov 2015-03-30 19:10:20 +03:00
parent 8cb22bf52d
commit 0f239e8852
7 changed files with 147 additions and 98 deletions

View file

@ -95,11 +95,19 @@ void BackendRenderer::AcceptMessage(dp::RefPointer<Message> message)
RecacheGui(CastMessage<GuiRecacheMessage>(message)->GetElements());
break;
case Message::TileReadStarted:
m_batchersPool->ReserveBatcher(df::CastMessage<BaseTileMessage>(message)->GetKey());
break;
{
m_batchersPool->ReserveBatcher(df::CastMessage<BaseTileMessage>(message)->GetKey());
break;
}
case Message::TileReadEnded:
m_batchersPool->ReleaseBatcher(df::CastMessage<BaseTileMessage>(message)->GetKey());
break;
{
TileReadEndMessage * msg = df::CastMessage<TileReadEndMessage>(message);
m_batchersPool->ReleaseBatcher(msg->GetKey());
TileReadEndMessage * outputMsg = new TileReadEndMessage(msg->GetKey());
m_commutator->PostMessage(ThreadsCommutator::RenderThread, dp::MovePointer<df::Message>(outputMsg), MessagePriority::Normal);
break;
}
case Message::MapShapeReaded:
{
MapShapeReadedMessage * msg = df::CastMessage<MapShapeReadedMessage>(message);

View file

@ -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> message)
break;
}
case Message::TileReadEnded:
{
TileReadEndMessage * msg = df::CastMessage<TileReadEndMessage>(message);
TileKey const & key = msg->GetKey();
if (!IsUserMarkLayer(key))
FinishTileRenderGroup(key);
break;
}
case Message::Resize:
{
ResizeMessage * rszMsg = df::CastMessage<ResizeMessage>(message);
@ -153,13 +162,13 @@ void FrontendRenderer::AcceptMessage(dp::RefPointer<Message> message)
ResolveTileKeys();
TTilesCollection tiles;
m_tileTree.GetRequestedTiles(tiles);
m_tileTree.GetTilesCollection(tiles, df::GetTileScaleBase(m_view));
m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
dp::MovePointer<Message>(new ResizeMessage(m_viewport)),
MessagePriority::Normal);
m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
dp::MovePointer<Message>(new UpdateReadManagerMessage(m_view, tiles)),
dp::MovePointer<Message>(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<unique_ptr<RenderGroup>> & 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<Message>(new UpdateReadManagerMessage(m_view, tiles)),
dp::MovePointer<Message>(new UpdateReadManagerMessage(m_view, move(tiles))),
MessagePriority::Normal);
}
}

View file

@ -99,6 +99,7 @@ private:
void CreateTileRenderGroup(dp::GLState const & state,
dp::MasterPointer<dp::RenderBucket> & renderBucket,
TileKey const & newTile);
void FinishTileRenderGroup(TileKey const & newTile);
void AddToRenderGroup(vector<unique_ptr<RenderGroup>> & groups,
dp::GLState const & state,
dp::MasterPointer<dp::RenderBucket> & renderBucket,

View file

@ -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)
{}

View file

@ -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<size_t> 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<FeatureID> featuresToRead;
for_each(indexes.begin(), indexes.end(), IDsAccumulator(featuresToRead, m_featureInfo));

View file

@ -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<TNodePtr> 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);
}
}

View file

@ -20,49 +20,53 @@ public:
using TTileHandler = function<void(TileKey const &, TileStatus)>;
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<Node>;
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