Bind every tile to sequence id, and remove active tile from tile cache only with less of equal sequence id

This commit is contained in:
ExMix 2013-03-18 17:35:56 +03:00 committed by Alex Zolotarev
parent e23fb6bdf1
commit b2202565dd
8 changed files with 94 additions and 70 deletions

View file

@ -111,6 +111,7 @@ CoverageGenerator::~CoverageGenerator()
void CoverageGenerator::Cancel()
{
LOG(LDEBUG, ("UVRLOG : CoverageGenerator::Cancel"));
m_queue.Cancel();
}
@ -239,10 +240,12 @@ void CoverageGenerator::MergeTile(core::CommandsQueue::Environment const & env,
{
if (sequenceID < m_sequenceID)
{
m_tileRenderer->RemoveActiveTile(rectInfo);
LOG(LDEBUG, ("UVRLOG : MergeTile fail. s=", rectInfo.m_tileScale, " x=", rectInfo.m_x, " y=", rectInfo.m_y, " SequenceID=", sequenceID, " m_SequenceID=", m_sequenceID));
m_tileRenderer->RemoveActiveTile(rectInfo, sequenceID);
return;
}
LOG(LDEBUG, ("UVRLOG : MergeTile s=", rectInfo.m_tileScale, " x=", rectInfo.m_x, " y=", rectInfo.m_y, " SequenceID=", sequenceID, " m_SequenceID=", m_sequenceID));
m_currentCoverage->CopyInto(*m_workCoverage);
m_workCoverage->SetSequenceID(sequenceID);
m_workCoverage->Merge(rectInfo);

View file

@ -101,29 +101,10 @@ void ScreenCoverage::Merge(Tiler::RectInfo const & ri)
{
ASSERT(m_tileRects.find(ri) != m_tileRects.end(), ());
TileCache & tileCache = m_tileRenderer->GetTileCache();
TileSet & tileSet = m_tileRenderer->GetTileSet();
Tile const * tile = m_tileRenderer->GetTile(ri);
Tile const * tile = 0;
bool hasTile = false;
/// every code that works both with tileSet and tileCache
/// should lock them in the same order to avoid deadlocks
/// (unlocking should be done in reverse order)
tileSet.Lock();
tileCache.Lock();
hasTile = tileSet.HasTile(ri);
if (hasTile)
if (tile != NULL)
{
ASSERT(tileCache.HasTile(ri), ());
tile = &tileCache.GetTile(ri);
ASSERT(m_tiles.find(tile) == m_tiles.end(), ());
/// while in the TileSet, the tile is assumed to be locked
m_tiles.insert(tile);
m_tileRects.erase(ri);
m_newTileRects.erase(ri);
@ -135,14 +116,6 @@ void ScreenCoverage::Merge(Tiler::RectInfo const & ri)
m_leafTilesToRender--;
}
tileSet.RemoveTile(ri);
}
tileCache.Unlock();
tileSet.Unlock();
if (hasTile)
{
if (m_tiler.isLeaf(ri))
{
graphics::Overlay * tileOverlayCopy = tile->m_overlay->clone();
@ -152,6 +125,8 @@ void ScreenCoverage::Merge(Tiler::RectInfo const & ri)
delete tileOverlayCopy;
}
}
else
LOG(LDEBUG, ("UVRLOG : Tile not found s=", ri.m_tileScale, " x=", ri.m_x, " y=", ri.m_y));
}
void FilterElementsBySharpness(shared_ptr<graphics::OverlayElement> const & e,
@ -239,6 +214,7 @@ bool ScreenCoverage::Cache(core::CommandsQueue::Environment const & env)
void ScreenCoverage::SetScreen(ScreenBase const & screen)
{
LOG(LDEBUG, ("UVRLOG : Start ScreenCoverage::SetScreen. m_SequenceID=", GetSequenceID()));
m_screen = screen;
m_newTileRects.clear();
@ -326,6 +302,7 @@ void ScreenCoverage::SetScreen(ScreenBase const & screen)
for (unsigned i = 0; i < newRectsCount; ++i)
{
Tiler::RectInfo nr = newRects[i];
LOG(LDEBUG, ("UVRLOG : NewRect add s=", nr.m_tileScale, " x=", nr.m_x, " y=", nr.m_y, " m_SequenceID=", GetSequenceID()));
Tiler::RectInfo cr[4] =
{
@ -356,7 +333,7 @@ void ScreenCoverage::SetScreen(ScreenBase const & screen)
m_tileRenderer->ClearCommands();
/// setting new sequenceID
m_tileRenderer->SetSequenceID(GetSequenceID());
LOG(LDEBUG, ("UVRLOG : Cancel commands from set rect. m_SequenceID =", GetSequenceID()));
m_tileRenderer->CancelCommands();
// filtering out rects that are fully covered by its descedants
@ -397,7 +374,8 @@ void ScreenCoverage::SetScreen(ScreenBase const & screen)
chain.addCommand(bind(&TileRenderer::RemoveActiveTile,
m_tileRenderer,
ri));
ri,
GetSequenceID()));
if (curNewTile == newRectsCount - 1)
chain.addCommand(bind(&CoverageGenerator::AddFinishSequenceTask,

View file

@ -10,13 +10,15 @@ Tile::Tile(shared_ptr<graphics::gl::BaseTexture> const & renderTarget,
ScreenBase const & tileScreen,
Tiler::RectInfo const & rectInfo,
double duration,
bool isEmptyDrawing)
bool isEmptyDrawing,
int sequenceID)
: m_renderTarget(renderTarget),
m_overlay(overlay),
m_tileScreen(tileScreen),
m_rectInfo(rectInfo),
m_duration(duration),
m_isEmptyDrawing(isEmptyDrawing)
m_isEmptyDrawing(isEmptyDrawing),
m_sequenceID(sequenceID)
{}
Tile::~Tile()

View file

@ -24,6 +24,7 @@ struct Tile
Tiler::RectInfo m_rectInfo; //< taken from tiler
double m_duration; //< how long does it take to render tile
bool m_isEmptyDrawing; //< does this tile contains only coasts and oceans
int m_sequenceID; // SequenceID in witch tile was rendered
Tile();
@ -32,7 +33,8 @@ struct Tile
ScreenBase const & tileScreen,
Tiler::RectInfo const & rectInfo,
double duration,
bool isEmptyDrawing);
bool isEmptyDrawing,
int sequenceID);
~Tile();
};

View file

@ -18,6 +18,30 @@
#include "../base/condition.hpp"
#include "../base/shared_buffer_manager.hpp"
namespace
{
class TileStructuresLockGuard
{
public:
TileStructuresLockGuard(TileCache & tileCache, TileSet & tileSet)
: m_tileCache(tileCache), m_tileSet(tileSet)
{
m_tileSet.Lock();
m_tileCache.Lock();
}
~TileStructuresLockGuard()
{
m_tileCache.Unlock();
m_tileSet.Unlock();
}
private:
TileCache & m_tileCache;
TileSet & m_tileSet;
};
}
TileRenderer::TileRenderer(
size_t tileSize,
string const & skinName,
@ -91,6 +115,7 @@ TileRenderer::~TileRenderer()
{
m_isExiting = true;
LOG(LDEBUG, ("UVRLOG : Cancel from ~TileRenderer"));
m_queue.Cancel();
for (size_t i = 0; i < m_threadData.size(); ++i)
@ -157,7 +182,12 @@ void TileRenderer::DrawTile(core::CommandsQueue::Environment const & env,
/// commands from the previous sequence are ignored
if (sequenceID < m_sequenceID)
{
LOG(LDEBUG, ("UVRLOG : tile not rendered. SequenceID=", sequenceID, " m_SequenceID", m_sequenceID));
return;
}
LOG(LDEBUG, ("UVRLOG : start render tile m_SequenceID=", m_sequenceID));
if (HasTile(rectInfo))
return;
@ -274,7 +304,8 @@ void TileRenderer::DrawTile(core::CommandsQueue::Environment const & env,
frameScreen,
rectInfo,
0,
paintEvent->isEmptyDrawing()));
paintEvent->isEmptyDrawing(),
sequenceID));
}
}
@ -309,9 +340,31 @@ TileCache & TileRenderer::GetTileCache()
return m_tileCache;
}
TileSet & TileRenderer::GetTileSet()
Tile const * TileRenderer::GetTile(const Tiler::RectInfo & rectInfo)
{
return m_tileSet;
TileStructuresLockGuard lock(m_tileCache, m_tileSet);
if (m_tileSet.HasTile(rectInfo))
{
ASSERT(!m_tileCache.HasTile(rectInfo), (""));
Tile tile = m_tileSet.GetTile(rectInfo);
if (m_tileCache.CanFit() == 0)
{
LOG(LINFO, ("resizing tileCache to", m_tileCache.CacheSize() + 1, "elements"));
m_tileCache.Resize(m_tileCache.CacheSize() + 1);
}
m_tileCache.AddTile(rectInfo, TileCache::Entry(tile, m_resourceManager));
m_tileCache.LockTile(rectInfo);
m_tileSet.RemoveTile(rectInfo);
}
if (m_tileCache.HasTile(rectInfo))
return &m_tileCache.GetTile(rectInfo);
return NULL;
}
void TileRenderer::WaitForEmptyAndFinished()
@ -335,11 +388,7 @@ void TileRenderer::SetIsPaused(bool flag)
void TileRenderer::AddActiveTile(Tile const & tile)
{
/// every code that works both with tileSet and tileCache
/// should lock them in the same order to avoid deadlocks
/// (unlocking should be done in reverse order)
m_tileSet.Lock();
m_tileCache.Lock();
TileStructuresLockGuard lock(m_tileCache, m_tileSet);
Tiler::RectInfo const & key = tile.m_rectInfo;
@ -347,39 +396,21 @@ void TileRenderer::AddActiveTile(Tile const & tile)
m_resourceManager->texturePool(graphics::ERenderTargetTexture)->Free(tile.m_renderTarget);
else
{
LOG(LDEBUG, ("UVRLOG : Add tile to set s=", key.m_tileScale, " x=", key.m_x, " y=", key.m_y, " m_SequenceID=", m_sequenceID));
m_tileSet.AddTile(tile);
if (m_tileCache.CanFit() == 0)
{
LOG(LINFO, ("resizing tileCache to", m_tileCache.CacheSize() + 1, "elements"));
m_tileCache.Resize(m_tileCache.CacheSize() + 1);
}
m_tileCache.AddTile(key, TileCache::Entry(tile, m_resourceManager));
m_tileCache.LockTile(key);
}
m_tileCache.Unlock();
m_tileSet.Unlock();
}
void TileRenderer::RemoveActiveTile(Tiler::RectInfo const & rectInfo)
void TileRenderer::RemoveActiveTile(Tiler::RectInfo const & rectInfo, int sequenceID)
{
/// every code that works both with tileSet and tileCache
/// should lock them in the same order to avoid deadlocks
/// (unlocking should be done in reverse order)
m_tileSet.Lock();
m_tileCache.Lock();
TileStructuresLockGuard lock(m_tileCache, m_tileSet);
if (m_tileSet.HasTile(rectInfo))
if (m_tileSet.HasTile(rectInfo) && m_tileSet.GetTileSequenceID(rectInfo) <= sequenceID)
{
ASSERT(m_tileCache.HasTile(rectInfo), ());
m_tileCache.UnlockTile(rectInfo);
ASSERT(!m_tileCache.HasTile(rectInfo), ("Tile cannot be in tileSet and tileCache at the same time"));
LOG(LDEBUG, ("UVRLOG : Remove tile from set s=", rectInfo.m_tileScale, " x=", rectInfo.m_x, " y=", rectInfo.m_y, " m_SequenceID=", m_sequenceID));
m_tileSet.RemoveTile(rectInfo);
}
m_tileCache.Unlock();
m_tileSet.Unlock();
}
size_t TileRenderer::TileSize() const

View file

@ -103,8 +103,8 @@ public:
core::CommandsQueue::Chain const & afterTileFns = core::CommandsQueue::Chain());
/// get tile cache.
TileCache & GetTileCache();
/// get tile set
TileSet & GetTileSet();
/// get tile from render if tile already rendered, otherwise return NULL
Tile const * GetTile(Tiler::RectInfo const & rectInfo);
/// wait on a condition variable for an empty queue.
void WaitForEmptyAndFinished();
@ -122,7 +122,7 @@ public:
void AddActiveTile(Tile const & tile);
/// remove tile from the TileSet.
/// @param doUpdateCache shows, whether we should
void RemoveActiveTile(Tiler::RectInfo const & rectInfo);
void RemoveActiveTile(Tiler::RectInfo const & rectInfo, int sequenceID);
void SetIsPaused(bool flag);

View file

@ -20,6 +20,12 @@ void TileSet::AddTile(Tile const & tile)
m_tiles[tile.m_rectInfo] = tile;
}
int TileSet::GetTileSequenceID(Tiler::RectInfo const & rectInfo)
{
ASSERT(HasTile(rectInfo), ());
return m_tiles[rectInfo].m_sequenceID;
}
void TileSet::RemoveTile(const Tiler::RectInfo &rectInfo)
{
m_tiles.erase(rectInfo);

View file

@ -24,6 +24,8 @@ public:
bool HasTile(Tiler::RectInfo const & rectInfo);
/// add tile to the set
void AddTile(Tile const & tile);
/// get sequenceID in witch tile was rendered
int GetTileSequenceID(Tiler::RectInfo const & rectInfo);
/// get tile from the set
Tile const & GetTile(Tiler::RectInfo const & rectInfo);
/// remove tile from the set