forked from organicmaps/organicmaps
Merge pull request #1581 from ExMix/uvr-dev
[drape] Memory and cache optimization
This commit is contained in:
commit
cc019f6480
11 changed files with 321 additions and 241 deletions
|
@ -13,13 +13,13 @@
|
|||
namespace dp
|
||||
{
|
||||
|
||||
class Batcher::CallbacksWrapper
|
||||
class Batcher::CallbacksWrapper : public BatchCallbacks
|
||||
{
|
||||
public:
|
||||
CallbacksWrapper(GLState const & state, ref_ptr<OverlayHandle> overlay)
|
||||
CallbacksWrapper(GLState const & state, ref_ptr<OverlayHandle> overlay, ref_ptr<Batcher> batcher)
|
||||
: m_state(state)
|
||||
, m_overlay(overlay)
|
||||
, m_vaoChanged(false)
|
||||
, m_batcher(batcher)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ public:
|
|||
m_indicesRange.m_idxStart = m_buffer->GetIndexCount();
|
||||
}
|
||||
|
||||
void FlushData(BindingInfo const & info, void const * data, uint32_t count)
|
||||
void FlushData(BindingInfo const & info, void const * data, uint32_t count) override
|
||||
{
|
||||
if (m_overlay != nullptr && info.IsDynamic())
|
||||
{
|
||||
|
@ -44,7 +44,7 @@ public:
|
|||
m_buffer->UploadData(info, data, count);
|
||||
}
|
||||
|
||||
void * GetIndexStorage(uint32_t size, uint32_t & startIndex)
|
||||
void * GetIndexStorage(uint32_t size, uint32_t & startIndex) override
|
||||
{
|
||||
startIndex = m_buffer->GetStartIndexValue();
|
||||
if (m_overlay == nullptr || !m_overlay->IndexesRequired())
|
||||
|
@ -56,22 +56,27 @@ public:
|
|||
return m_overlay->IndexStorage(size);
|
||||
}
|
||||
|
||||
void SubmitIndexes()
|
||||
void SubmitIndeces() override
|
||||
{
|
||||
if (m_overlay == nullptr || !m_overlay->IndexesRequired())
|
||||
m_buffer->UploadIndexes(m_indexStorage.GetRawConst(), m_indexStorage.Size());
|
||||
}
|
||||
|
||||
uint32_t GetAvailableVertexCount() const
|
||||
uint32_t GetAvailableVertexCount() const override
|
||||
{
|
||||
return m_buffer->GetAvailableVertexCount();
|
||||
}
|
||||
|
||||
uint32_t GetAvailableIndexCount() const
|
||||
uint32_t GetAvailableIndexCount() const override
|
||||
{
|
||||
return m_buffer->GetAvailableIndexCount();
|
||||
}
|
||||
|
||||
void ChangeBuffer() override
|
||||
{
|
||||
m_batcher->ChangeBuffer(make_ref(this));
|
||||
}
|
||||
|
||||
GLState const & GetState() const
|
||||
{
|
||||
return m_state;
|
||||
|
@ -89,11 +94,12 @@ public:
|
|||
|
||||
private:
|
||||
GLState const & m_state;
|
||||
ref_ptr<VertexArrayBuffer> m_buffer;
|
||||
ref_ptr<OverlayHandle> m_overlay;
|
||||
ref_ptr<Batcher> m_batcher;
|
||||
ref_ptr<VertexArrayBuffer> m_buffer;
|
||||
IndexStorage m_indexStorage;
|
||||
IndicesRange m_indicesRange;
|
||||
bool m_vaoChanged;
|
||||
bool m_vaoChanged = false;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
@ -221,18 +227,10 @@ IndicesRange Batcher::InsertTriangles(GLState const & state, ref_ptr<AttributePr
|
|||
drape_ptr<OverlayHandle> handle = move(transferHandle);
|
||||
|
||||
{
|
||||
Batcher::CallbacksWrapper wrapper(state, make_ref(handle));
|
||||
Batcher::CallbacksWrapper wrapper(state, make_ref(handle), make_ref(this));
|
||||
wrapper.SetVAO(vao);
|
||||
|
||||
BatchCallbacks callbacks;
|
||||
callbacks.m_flushVertex = bind(&CallbacksWrapper::FlushData, &wrapper, _1, _2, _3);
|
||||
callbacks.m_getIndexStorage = bind(&CallbacksWrapper::GetIndexStorage, &wrapper, _1, _2);
|
||||
callbacks.m_submitIndex = bind(&CallbacksWrapper::SubmitIndexes, &wrapper);
|
||||
callbacks.m_getAvailableVertex = bind(&CallbacksWrapper::GetAvailableVertexCount, &wrapper);
|
||||
callbacks.m_getAvailableIndex = bind(&CallbacksWrapper::GetAvailableIndexCount, &wrapper);
|
||||
callbacks.m_changeBuffer = bind(&Batcher::ChangeBuffer, this, make_ref(&wrapper));
|
||||
|
||||
TBatcher batch(callbacks);
|
||||
TBatcher batch(wrapper);
|
||||
batch.SetIsCanDevideStreams(handle == nullptr);
|
||||
batch.SetVertexStride(vertexStride);
|
||||
batch.BatchData(params);
|
||||
|
|
|
@ -140,7 +140,7 @@ private:
|
|||
|
||||
} // namespace
|
||||
|
||||
TriangleBatch::TriangleBatch(BatchCallbacks const & callbacks)
|
||||
TriangleBatch::TriangleBatch(BatchCallbacks & callbacks)
|
||||
: m_callbacks(callbacks)
|
||||
, m_canDevideStreams(true)
|
||||
{
|
||||
|
@ -169,38 +169,32 @@ void TriangleBatch::FlushData(ref_ptr<AttributeProvider> streams, uint32_t verte
|
|||
|
||||
void TriangleBatch::FlushData(BindingInfo const & info, void const * data, uint32_t elementCount) const
|
||||
{
|
||||
ASSERT(m_callbacks.m_flushVertex != NULL, ());
|
||||
return m_callbacks.m_flushVertex(info, data, elementCount);
|
||||
m_callbacks.FlushData(info, data, elementCount);
|
||||
}
|
||||
|
||||
void * TriangleBatch::GetIndexStorage(uint32_t indexCount, uint32_t & startIndex)
|
||||
{
|
||||
ASSERT(m_callbacks.m_getIndexStorage, ());
|
||||
return m_callbacks.m_getIndexStorage(indexCount, startIndex);
|
||||
return m_callbacks.GetIndexStorage(indexCount, startIndex);
|
||||
}
|
||||
|
||||
void TriangleBatch::SubmitIndex()
|
||||
{
|
||||
ASSERT(m_callbacks.m_submitIndex, ());
|
||||
m_callbacks.m_submitIndex();
|
||||
m_callbacks.SubmitIndeces();
|
||||
}
|
||||
|
||||
uint32_t TriangleBatch::GetAvailableVertexCount() const
|
||||
{
|
||||
ASSERT(m_callbacks.m_getAvailableVertex!= NULL, ());
|
||||
return m_callbacks.m_getAvailableVertex();
|
||||
return m_callbacks.GetAvailableVertexCount();
|
||||
}
|
||||
|
||||
uint32_t TriangleBatch::GetAvailableIndexCount() const
|
||||
{
|
||||
ASSERT(m_callbacks.m_getAvailableIndex != NULL, ());
|
||||
return m_callbacks.m_getAvailableIndex();
|
||||
return m_callbacks.GetAvailableIndexCount();
|
||||
}
|
||||
|
||||
void TriangleBatch::ChangeBuffer() const
|
||||
{
|
||||
ASSERT(m_callbacks.m_changeBuffer != NULL, ());
|
||||
m_callbacks.m_changeBuffer();
|
||||
return m_callbacks.ChangeBuffer();
|
||||
}
|
||||
|
||||
uint8_t TriangleBatch::GetVertexStride() const
|
||||
|
@ -213,7 +207,7 @@ bool TriangleBatch::IsBufferFilled(uint32_t availableVerticesCount, uint32_t ava
|
|||
return availableVerticesCount < 3 || availableIndicesCount < 3;
|
||||
}
|
||||
|
||||
TriangleListBatch::TriangleListBatch(BatchCallbacks const & callbacks) : TBase(callbacks) {}
|
||||
TriangleListBatch::TriangleListBatch(BatchCallbacks & callbacks) : TBase(callbacks) {}
|
||||
|
||||
void TriangleListBatch::BatchData(ref_ptr<AttributeProvider> streams)
|
||||
{
|
||||
|
@ -252,7 +246,7 @@ void TriangleListBatch::BatchData(ref_ptr<AttributeProvider> streams)
|
|||
}
|
||||
}
|
||||
|
||||
FanStripHelper::FanStripHelper(BatchCallbacks const & callbacks)
|
||||
FanStripHelper::FanStripHelper(BatchCallbacks & callbacks)
|
||||
: TBase(callbacks)
|
||||
, m_isFullUploaded(false)
|
||||
{
|
||||
|
@ -336,7 +330,7 @@ uint32_t FanStripHelper::AlignICount(uint32_t iCount) const
|
|||
return iCount - iCount % 3;
|
||||
}
|
||||
|
||||
TriangleStripBatch::TriangleStripBatch(BatchCallbacks const & callbacks)
|
||||
TriangleStripBatch::TriangleStripBatch(BatchCallbacks & callbacks)
|
||||
: TBase(callbacks)
|
||||
{
|
||||
}
|
||||
|
@ -362,7 +356,7 @@ void TriangleStripBatch::GenerateIndexes(void * indexStorage, uint32_t count, ui
|
|||
GenerateIndices<StripIndexGenerator>(indexStorage, count, startIndex);
|
||||
}
|
||||
|
||||
TriangleFanBatch::TriangleFanBatch(BatchCallbacks const & callbacks) : TBase(callbacks) {}
|
||||
TriangleFanBatch::TriangleFanBatch(BatchCallbacks & callbacks) : TBase(callbacks) {}
|
||||
|
||||
|
||||
/*
|
||||
|
@ -469,7 +463,7 @@ void TriangleFanBatch::GenerateIndexes(void * indexStorage, uint32_t count, uint
|
|||
GenerateIndices<FanIndexGenerator>(indexStorage, count, startIndex);
|
||||
}
|
||||
|
||||
TriangleListOfStripBatch::TriangleListOfStripBatch(BatchCallbacks const & callbacks)
|
||||
TriangleListOfStripBatch::TriangleListOfStripBatch(BatchCallbacks & callbacks)
|
||||
: TBase(callbacks)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -13,24 +13,18 @@ class BindingInfo;
|
|||
class BatchCallbacks
|
||||
{
|
||||
public:
|
||||
typedef function<void (BindingInfo const &, void const *, uint32_t)> TFlushVertexFn;
|
||||
typedef function<void * (uint32_t, uint32_t &)> TGetIndexStorageFn;
|
||||
typedef function<void ()> TSubmitIndexFn;
|
||||
typedef function<uint32_t ()> TGetAvailableFn;
|
||||
typedef function<void ()> ChangeBufferFn;
|
||||
|
||||
TFlushVertexFn m_flushVertex;
|
||||
TGetIndexStorageFn m_getIndexStorage;
|
||||
TSubmitIndexFn m_submitIndex;
|
||||
TGetAvailableFn m_getAvailableVertex;
|
||||
TGetAvailableFn m_getAvailableIndex;
|
||||
ChangeBufferFn m_changeBuffer;
|
||||
virtual void FlushData(BindingInfo const & binding, void const * data, uint32_t count) = 0;
|
||||
virtual void * GetIndexStorage(uint32_t indexCount, uint32_t & startIndex) = 0;
|
||||
virtual void SubmitIndeces() = 0;
|
||||
virtual uint32_t GetAvailableVertexCount() const = 0;
|
||||
virtual uint32_t GetAvailableIndexCount() const = 0;
|
||||
virtual void ChangeBuffer() = 0;
|
||||
};
|
||||
|
||||
class TriangleBatch
|
||||
{
|
||||
public:
|
||||
TriangleBatch(BatchCallbacks const & callbacks);
|
||||
TriangleBatch(BatchCallbacks & callbacks);
|
||||
virtual ~TriangleBatch(){}
|
||||
|
||||
virtual void BatchData(ref_ptr<AttributeProvider> streams) = 0;
|
||||
|
@ -51,7 +45,7 @@ protected:
|
|||
virtual bool IsBufferFilled(uint32_t availableVerticesCount, uint32_t availableIndicesCount) const;
|
||||
|
||||
private:
|
||||
BatchCallbacks m_callbacks;
|
||||
BatchCallbacks & m_callbacks;
|
||||
bool m_canDevideStreams;
|
||||
uint8_t m_vertexStride;
|
||||
};
|
||||
|
@ -61,7 +55,7 @@ class TriangleListBatch : public TriangleBatch
|
|||
typedef TriangleBatch TBase;
|
||||
|
||||
public:
|
||||
TriangleListBatch(BatchCallbacks const & callbacks);
|
||||
TriangleListBatch(BatchCallbacks & callbacks);
|
||||
|
||||
virtual void BatchData(ref_ptr<AttributeProvider> streams);
|
||||
};
|
||||
|
@ -71,7 +65,7 @@ class FanStripHelper : public TriangleBatch
|
|||
typedef TriangleBatch TBase;
|
||||
|
||||
public:
|
||||
FanStripHelper(BatchCallbacks const & callbacks);
|
||||
FanStripHelper(BatchCallbacks & callbacks);
|
||||
|
||||
protected:
|
||||
uint32_t BatchIndexes(uint32_t vertexCount);
|
||||
|
@ -94,7 +88,7 @@ class TriangleStripBatch : public FanStripHelper
|
|||
typedef FanStripHelper TBase;
|
||||
|
||||
public:
|
||||
TriangleStripBatch(BatchCallbacks const & callbacks);
|
||||
TriangleStripBatch(BatchCallbacks & callbacks);
|
||||
|
||||
virtual void BatchData(ref_ptr<AttributeProvider> streams);
|
||||
protected:
|
||||
|
@ -106,7 +100,7 @@ class TriangleFanBatch : public FanStripHelper
|
|||
typedef FanStripHelper TBase;
|
||||
|
||||
public:
|
||||
TriangleFanBatch(BatchCallbacks const & callbacks);
|
||||
TriangleFanBatch(BatchCallbacks & callbacks);
|
||||
|
||||
virtual void BatchData(ref_ptr<AttributeProvider> streams);
|
||||
protected:
|
||||
|
@ -118,7 +112,7 @@ class TriangleListOfStripBatch : public FanStripHelper
|
|||
typedef FanStripHelper TBase;
|
||||
|
||||
public:
|
||||
TriangleListOfStripBatch(BatchCallbacks const & callbacks);
|
||||
TriangleListOfStripBatch(BatchCallbacks & callbacks);
|
||||
|
||||
virtual void BatchData(ref_ptr<AttributeProvider> streams);
|
||||
|
||||
|
|
|
@ -105,15 +105,26 @@ bool GLState::operator==(GLState const & other) const
|
|||
|
||||
namespace
|
||||
{
|
||||
void ApplyUniformValue(UniformValue const & value, ref_ptr<GpuProgram> program)
|
||||
|
||||
struct UniformApplyer
|
||||
{
|
||||
ref_ptr<GpuProgram> m_program;
|
||||
|
||||
void operator()(UniformValue const & value) const
|
||||
{
|
||||
value.Apply(program);
|
||||
ASSERT(m_program != nullptr, ());
|
||||
value.Apply(m_program);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void ApplyUniforms(UniformValuesStorage const & uniforms, ref_ptr<GpuProgram> program)
|
||||
{
|
||||
uniforms.ForeachValue(bind(&ApplyUniformValue, _1, program));
|
||||
static UniformApplyer applyer;
|
||||
applyer.m_program = program;
|
||||
uniforms.ForeachValue(applyer);
|
||||
applyer.m_program = nullptr;
|
||||
}
|
||||
|
||||
void ApplyTextures(GLState state, ref_ptr<GpuProgram> program)
|
||||
|
|
|
@ -38,7 +38,6 @@ public:
|
|||
{
|
||||
/// Do not change order
|
||||
GeometryLayer,
|
||||
DynamicGeometry,
|
||||
OverlayLayer,
|
||||
UserMarkLayer,
|
||||
Gui
|
||||
|
|
|
@ -89,11 +89,6 @@ void UniformValuesStorage::SetMatrix4x4Value(string const & name, float const *
|
|||
m_uniforms.emplace_back(name, matrixValue);
|
||||
}
|
||||
|
||||
void UniformValuesStorage::ForeachValue(enum_uniforms_fn action) const
|
||||
{
|
||||
for_each(m_uniforms.begin(), m_uniforms.end(), action);
|
||||
}
|
||||
|
||||
bool UniformValuesStorage::operator< (UniformValuesStorage const & other) const
|
||||
{
|
||||
if (m_uniforms.size() < other.m_uniforms.size())
|
||||
|
|
|
@ -24,8 +24,11 @@ public:
|
|||
|
||||
void SetMatrix4x4Value(string const & name, float const * matrixValue);
|
||||
|
||||
typedef function<void (UniformValue const & )> enum_uniforms_fn;
|
||||
void ForeachValue(enum_uniforms_fn action) const;
|
||||
template<typename TFunctor>
|
||||
void ForeachValue(TFunctor & functor) const
|
||||
{
|
||||
for_each(m_uniforms.begin(), m_uniforms.end(), functor);
|
||||
}
|
||||
|
||||
bool operator< (UniformValuesStorage const & other) const;
|
||||
|
||||
|
|
|
@ -58,6 +58,97 @@ struct MergedGroupKey
|
|||
}
|
||||
};
|
||||
|
||||
template <typename ToDo>
|
||||
bool RemoveGroups(ToDo & filter, vector<drape_ptr<RenderGroup>> & groups)
|
||||
{
|
||||
size_t startCount = groups.size();
|
||||
size_t count = startCount;
|
||||
size_t current = 0;
|
||||
while (current < count)
|
||||
{
|
||||
drape_ptr<RenderGroup> & group = groups[current];
|
||||
if (filter(move(group)))
|
||||
{
|
||||
swap(group, groups.back());
|
||||
groups.pop_back();
|
||||
--count;
|
||||
}
|
||||
else
|
||||
++current;
|
||||
}
|
||||
|
||||
return startCount != count;
|
||||
}
|
||||
|
||||
struct ActivateTilePredicate
|
||||
{
|
||||
TileKey const & m_tileKey;
|
||||
|
||||
ActivateTilePredicate(TileKey const & tileKey)
|
||||
: m_tileKey(tileKey)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()(drape_ptr<RenderGroup> & group) const
|
||||
{
|
||||
if (group->GetTileKey() == m_tileKey)
|
||||
{
|
||||
group->Appear();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct RemoveTilePredicate
|
||||
{
|
||||
mutable bool m_deletionMark = false;
|
||||
function<bool(drape_ptr<RenderGroup> const &)> const & m_predicate;
|
||||
|
||||
RemoveTilePredicate(function<bool(drape_ptr<RenderGroup> const &)> const & predicate)
|
||||
: m_predicate(predicate)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()(drape_ptr<RenderGroup> && group) const
|
||||
{
|
||||
if (m_predicate(group))
|
||||
{
|
||||
group->Disappear();
|
||||
group->DeleteLater();
|
||||
m_deletionMark = true;
|
||||
return group->CanBeDeleted();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TPredicate>
|
||||
struct MoveTileFunctor
|
||||
{
|
||||
TPredicate m_predicate;
|
||||
vector<drape_ptr<RenderGroup>> & m_targetGroups;
|
||||
|
||||
MoveTileFunctor(TPredicate predicate, vector<drape_ptr<RenderGroup>> & groups)
|
||||
: m_predicate(predicate)
|
||||
, m_targetGroups(groups)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()(drape_ptr<RenderGroup> && group)
|
||||
{
|
||||
if (m_predicate(group))
|
||||
{
|
||||
m_targetGroups.push_back(move(group));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
FrontendRenderer::FrontendRenderer(Params const & params)
|
||||
|
@ -435,8 +526,12 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
|
|||
m_tileTree->Invalidate();
|
||||
|
||||
// Clear all graphics.
|
||||
m_renderGroups.clear();
|
||||
m_deferredRenderGroups.clear();
|
||||
for (RenderLayer & layer : m_layers)
|
||||
{
|
||||
layer.m_renderGroups.clear();
|
||||
layer.m_deferredRenderGroups.clear();
|
||||
layer.m_isDirty = false;
|
||||
}
|
||||
|
||||
// Invalidate read manager.
|
||||
{
|
||||
|
@ -613,20 +708,17 @@ void FrontendRenderer::InvalidateRect(m2::RectD const & gRect)
|
|||
m_tileTree->Invalidate();
|
||||
ResolveTileKeys(rect, tiles);
|
||||
|
||||
auto eraseFunction = [&tiles](vector<drape_ptr<RenderGroup>> & groups)
|
||||
auto eraseFunction = [&tiles](drape_ptr<RenderGroup> && group)
|
||||
{
|
||||
vector<drape_ptr<RenderGroup> > newGroups;
|
||||
for (drape_ptr<RenderGroup> & group : groups)
|
||||
{
|
||||
if (tiles.find(group->GetTileKey()) == tiles.end())
|
||||
newGroups.push_back(move(group));
|
||||
}
|
||||
|
||||
swap(groups, newGroups);
|
||||
return tiles.count(group->GetTileKey()) == 0;
|
||||
};
|
||||
|
||||
eraseFunction(m_renderGroups);
|
||||
eraseFunction(m_deferredRenderGroups);
|
||||
for (RenderLayer & layer : m_layers)
|
||||
{
|
||||
RemoveGroups(eraseFunction, layer.m_renderGroups);
|
||||
RemoveGroups(eraseFunction, layer.m_deferredRenderGroups);
|
||||
layer.m_isDirty = true;
|
||||
}
|
||||
|
||||
BaseBlockingMessage::Blocker blocker;
|
||||
m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
|
||||
|
@ -673,30 +765,26 @@ void FrontendRenderer::AddToRenderGroup(vector<drape_ptr<RenderGroup>> & groups,
|
|||
void FrontendRenderer::OnAddRenderGroup(TileKey const & tileKey, dp::GLState const & state,
|
||||
drape_ptr<dp::RenderBucket> && renderBucket)
|
||||
{
|
||||
AddToRenderGroup(m_renderGroups, state, move(renderBucket), tileKey);
|
||||
m_renderGroups.back()->Appear();
|
||||
RenderLayer::RenderLayerID id = RenderLayer::GetLayerID(state);
|
||||
RenderLayer & layer = m_layers[id];
|
||||
AddToRenderGroup(layer.m_renderGroups, state, move(renderBucket), tileKey);
|
||||
layer.m_renderGroups.back()->Appear();
|
||||
layer.m_isDirty = true;
|
||||
}
|
||||
|
||||
void FrontendRenderer::OnDeferRenderGroup(TileKey const & tileKey, dp::GLState const & state,
|
||||
drape_ptr<dp::RenderBucket> && renderBucket)
|
||||
{
|
||||
AddToRenderGroup(m_deferredRenderGroups, state, move(renderBucket), tileKey);
|
||||
RenderLayer::RenderLayerID id = RenderLayer::GetLayerID(state);
|
||||
AddToRenderGroup(m_layers[id].m_deferredRenderGroups, state, move(renderBucket), tileKey);
|
||||
}
|
||||
|
||||
void FrontendRenderer::OnActivateTile(TileKey const & tileKey)
|
||||
{
|
||||
for(auto it = m_deferredRenderGroups.begin(); it != m_deferredRenderGroups.end();)
|
||||
for (RenderLayer & layer : m_layers)
|
||||
{
|
||||
if ((*it)->GetTileKey() == tileKey)
|
||||
{
|
||||
m_renderGroups.push_back(move(*it));
|
||||
it = m_deferredRenderGroups.erase(it);
|
||||
m_renderGroups.back()->Appear();
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
MoveTileFunctor<ActivateTilePredicate> f(ActivateTilePredicate(tileKey), layer.m_renderGroups);
|
||||
layer.m_isDirty |= RemoveGroups(f, layer.m_deferredRenderGroups);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -714,19 +802,13 @@ void FrontendRenderer::RemoveRenderGroups(TRenderGroupRemovePredicate const & pr
|
|||
ASSERT(predicate != nullptr, ());
|
||||
m_overlayTree->ForceUpdate();
|
||||
|
||||
for(auto const & group : m_renderGroups)
|
||||
for (RenderLayer & layer : m_layers)
|
||||
{
|
||||
if (predicate(group))
|
||||
{
|
||||
group->DeleteLater();
|
||||
group->Disappear();
|
||||
}
|
||||
RemoveTilePredicate f(predicate);
|
||||
RemoveGroups(f, layer.m_renderGroups);
|
||||
RemoveGroups(predicate, layer.m_deferredRenderGroups);
|
||||
layer.m_isDirty |= f.m_deletionMark;
|
||||
}
|
||||
|
||||
m_deferredRenderGroups.erase(remove_if(m_deferredRenderGroups.begin(),
|
||||
m_deferredRenderGroups.end(),
|
||||
predicate),
|
||||
m_deferredRenderGroups.end());
|
||||
}
|
||||
|
||||
bool FrontendRenderer::CheckTileGenerations(TileKey const & tileKey)
|
||||
|
@ -817,78 +899,17 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView)
|
|||
|
||||
bool const isPerspective = modelView.isPerspective();
|
||||
|
||||
RenderGroupComparator comparator;
|
||||
sort(m_renderGroups.begin(), m_renderGroups.end(), bind(&RenderGroupComparator::operator (), &comparator, _1, _2));
|
||||
|
||||
BeginUpdateOverlayTree(modelView);
|
||||
size_t eraseCount = 0;
|
||||
GLFunctions::glEnable(gl_const::GLDepthTest);
|
||||
for (size_t i = 0; i < m_renderGroups.size(); ++i)
|
||||
{
|
||||
drape_ptr<RenderGroup> & group = m_renderGroups[i];
|
||||
if (group->IsEmpty())
|
||||
continue;
|
||||
|
||||
if (group->CanBeDeleted())
|
||||
{
|
||||
group.reset();
|
||||
++eraseCount;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (group->GetState().GetDepthLayer())
|
||||
{
|
||||
case dp::GLState::OverlayLayer:
|
||||
UpdateOverlayTree(modelView, group);
|
||||
break;
|
||||
case dp::GLState::DynamicGeometry:
|
||||
group->Update(modelView);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
EndUpdateOverlayTree();
|
||||
m_renderGroups.resize(m_renderGroups.size() - eraseCount);
|
||||
|
||||
m_viewport.Apply();
|
||||
RefreshBgColor();
|
||||
GLFunctions::glClear();
|
||||
|
||||
dp::GLState::DepthLayer prevLayer = dp::GLState::GeometryLayer;
|
||||
size_t currentRenderGroup = 0;
|
||||
bool has3dAreas = false;
|
||||
size_t area3dRenderGroupStart = 0;
|
||||
size_t area3dRenderGroupEnd = 0;
|
||||
for (; currentRenderGroup < m_renderGroups.size(); ++currentRenderGroup)
|
||||
{
|
||||
drape_ptr<RenderGroup> const & group = m_renderGroups[currentRenderGroup];
|
||||
Render2dLayer(modelView);
|
||||
|
||||
dp::GLState const & state = group->GetState();
|
||||
|
||||
if ((isPerspective || m_isIsometry) && state.GetProgram3dIndex() == gpu::AREA_3D_PROGRAM)
|
||||
{
|
||||
if (!has3dAreas)
|
||||
{
|
||||
area3dRenderGroupStart = currentRenderGroup;
|
||||
has3dAreas = true;
|
||||
}
|
||||
area3dRenderGroupEnd = currentRenderGroup;
|
||||
continue;
|
||||
}
|
||||
|
||||
dp::GLState::DepthLayer layer = state.GetDepthLayer();
|
||||
if (prevLayer != layer && layer == dp::GLState::OverlayLayer)
|
||||
break;
|
||||
|
||||
prevLayer = layer;
|
||||
RenderSingleGroup(modelView, make_ref(group));
|
||||
}
|
||||
|
||||
GLFunctions::glDisable(gl_const::GLDepthTest);
|
||||
bool hasSelectedPOI = false;
|
||||
if (m_selectionShape != nullptr)
|
||||
{
|
||||
GLFunctions::glDisable(gl_const::GLDepthTest);
|
||||
SelectionShape::ESelectedObject selectedObject = m_selectionShape->GetSelectedObject();
|
||||
if (selectedObject == SelectionShape::OBJECT_MY_POSITION)
|
||||
{
|
||||
|
@ -898,7 +919,7 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView)
|
|||
}
|
||||
else if (selectedObject == SelectionShape::OBJECT_POI)
|
||||
{
|
||||
if (!isPerspective && !has3dAreas)
|
||||
if (!isPerspective && m_layers[RenderLayer::Geometry3dID].m_renderGroups.empty())
|
||||
m_selectionShape->Render(modelView, make_ref(m_gpuProgramManager), m_generalUniforms);
|
||||
else
|
||||
hasSelectedPOI = true;
|
||||
|
@ -908,34 +929,20 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView)
|
|||
m_myPositionController->Render(MyPositionController::RenderAccuracy,
|
||||
modelView, make_ref(m_gpuProgramManager), m_generalUniforms);
|
||||
|
||||
if (has3dAreas)
|
||||
if (m_framebuffer->IsSupported())
|
||||
{
|
||||
if (m_framebuffer->IsSupported())
|
||||
{
|
||||
m_framebuffer->Enable();
|
||||
GLFunctions::glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
GLFunctions::glClear();
|
||||
GLFunctions::glClearDepth();
|
||||
}
|
||||
else
|
||||
{
|
||||
GLFunctions::glClearDepth();
|
||||
}
|
||||
|
||||
GLFunctions::glEnable(gl_const::GLDepthTest);
|
||||
for (size_t index = area3dRenderGroupStart; index <= area3dRenderGroupEnd; ++index)
|
||||
{
|
||||
drape_ptr<RenderGroup> const & group = m_renderGroups[index];
|
||||
if (group->GetState().GetProgram3dIndex() == gpu::AREA_3D_PROGRAM)
|
||||
RenderSingleGroup(modelView, make_ref(group));
|
||||
}
|
||||
|
||||
if (m_framebuffer->IsSupported())
|
||||
{
|
||||
m_framebuffer->Disable();
|
||||
GLFunctions::glDisable(gl_const::GLDepthTest);
|
||||
m_transparentLayer->Render(m_framebuffer->GetTextureId(), make_ref(m_gpuProgramManager));
|
||||
}
|
||||
m_framebuffer->Enable();
|
||||
GLFunctions::glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
GLFunctions::glClear();
|
||||
Render3dLayer(modelView);
|
||||
m_framebuffer->Disable();
|
||||
GLFunctions::glDisable(gl_const::GLDepthTest);
|
||||
m_transparentLayer->Render(m_framebuffer->GetTextureId(), make_ref(m_gpuProgramManager));
|
||||
}
|
||||
else
|
||||
{
|
||||
GLFunctions::glClearDepth();
|
||||
Render3dLayer(modelView);
|
||||
}
|
||||
|
||||
if (hasSelectedPOI)
|
||||
|
@ -946,11 +953,7 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView)
|
|||
|
||||
GLFunctions::glEnable(gl_const::GLDepthTest);
|
||||
GLFunctions::glClearDepth();
|
||||
for (; currentRenderGroup < m_renderGroups.size(); ++currentRenderGroup)
|
||||
{
|
||||
drape_ptr<RenderGroup> const & group = m_renderGroups[currentRenderGroup];
|
||||
RenderSingleGroup(modelView, make_ref(group));
|
||||
}
|
||||
RenderOverlayLayer(modelView);
|
||||
|
||||
m_gpsTrackRenderer->RenderTrack(modelView, GetCurrentZoomLevel(),
|
||||
make_ref(m_gpuProgramManager), m_generalUniforms);
|
||||
|
@ -1001,6 +1004,36 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView)
|
|||
MergeBuckets();
|
||||
}
|
||||
|
||||
void FrontendRenderer::Render2dLayer(ScreenBase const & modelView)
|
||||
{
|
||||
RenderLayer & layer2d = m_layers[RenderLayer::Geometry2dID];
|
||||
layer2d.Sort();
|
||||
|
||||
for (drape_ptr<RenderGroup> const & group : layer2d.m_renderGroups)
|
||||
RenderSingleGroup(modelView, make_ref(group));
|
||||
}
|
||||
|
||||
void FrontendRenderer::Render3dLayer(ScreenBase const & modelView)
|
||||
{
|
||||
GLFunctions::glEnable(gl_const::GLDepthTest);
|
||||
RenderLayer & layer = m_layers[RenderLayer::Geometry3dID];
|
||||
layer.Sort();
|
||||
for (drape_ptr<RenderGroup> const & group : layer.m_renderGroups)
|
||||
RenderSingleGroup(modelView, make_ref(group));
|
||||
}
|
||||
|
||||
void FrontendRenderer::RenderOverlayLayer(ScreenBase const & modelView)
|
||||
{
|
||||
RenderLayer & overlay = m_layers[RenderLayer::OverlayID];
|
||||
overlay.Sort();
|
||||
BeginUpdateOverlayTree(modelView);
|
||||
for (drape_ptr<RenderGroup> & group : overlay.m_renderGroups)
|
||||
UpdateOverlayTree(modelView, group);
|
||||
EndUpdateOverlayTree();
|
||||
for (drape_ptr<RenderGroup> & group : overlay.m_renderGroups)
|
||||
RenderSingleGroup(modelView, make_ref(group));
|
||||
}
|
||||
|
||||
void FrontendRenderer::MergeBuckets()
|
||||
{
|
||||
if (BatchMergeHelper::IsMergeSupported() == false)
|
||||
|
@ -1010,37 +1043,43 @@ void FrontendRenderer::MergeBuckets()
|
|||
if (m_mergeBucketsCounter < 60)
|
||||
return;
|
||||
|
||||
if (m_renderGroups.empty())
|
||||
return;
|
||||
|
||||
using TGroupMap = map<MergedGroupKey, vector<drape_ptr<RenderGroup>>>;
|
||||
TGroupMap forMerge;
|
||||
|
||||
vector<drape_ptr<RenderGroup>> newGroups;
|
||||
newGroups.reserve(m_renderGroups.size());
|
||||
|
||||
m_mergeBucketsCounter = 0;
|
||||
size_t groupsCount = m_renderGroups.size();
|
||||
for (size_t i = 0; i < groupsCount; ++i)
|
||||
|
||||
auto mergeFn = [](RenderLayer & layer, bool isPerspective)
|
||||
{
|
||||
ref_ptr<RenderGroup> group = make_ref(m_renderGroups[i]);
|
||||
dp::GLState state = group->GetState();
|
||||
if (state.GetDepthLayer() == dp::GLState::GeometryLayer && !group->IsPendingOnDelete())
|
||||
if (layer.m_renderGroups.empty())
|
||||
return;
|
||||
|
||||
using TGroupMap = map<MergedGroupKey, vector<drape_ptr<RenderGroup>>>;
|
||||
TGroupMap forMerge;
|
||||
|
||||
vector<drape_ptr<RenderGroup>> newGroups;
|
||||
newGroups.reserve(layer.m_renderGroups.size());
|
||||
|
||||
size_t groupsCount = layer.m_renderGroups.size();
|
||||
for (size_t i = 0; i < groupsCount; ++i)
|
||||
{
|
||||
MergedGroupKey const key(state, group->GetTileKey());
|
||||
forMerge[key].push_back(move(m_renderGroups[i]));
|
||||
ref_ptr<RenderGroup> group = make_ref(layer.m_renderGroups[i]);
|
||||
if (!group->IsPendingOnDelete())
|
||||
{
|
||||
dp::GLState state = group->GetState();
|
||||
ASSERT_EQUAL(state.GetDepthLayer(), dp::GLState::GeometryLayer, ());
|
||||
forMerge[MergedGroupKey(state, group->GetTileKey())].push_back(move(layer.m_renderGroups[i]));
|
||||
}
|
||||
else
|
||||
newGroups.push_back(move(layer.m_renderGroups[i]));
|
||||
}
|
||||
else
|
||||
{
|
||||
newGroups.push_back(move(m_renderGroups[i]));
|
||||
}
|
||||
}
|
||||
|
||||
for (TGroupMap::value_type & node : forMerge)
|
||||
BatchMergeHelper::MergeBatches(node.second, newGroups, isPerspective);
|
||||
|
||||
layer.m_renderGroups = move(newGroups);
|
||||
layer.m_isDirty = true;
|
||||
};
|
||||
|
||||
bool const isPerspective = m_userEventStream.GetCurrentScreen().isPerspective();
|
||||
for (TGroupMap::value_type & node : forMerge)
|
||||
BatchMergeHelper::MergeBatches(node.second, newGroups, isPerspective);
|
||||
|
||||
m_renderGroups = move(newGroups);
|
||||
mergeFn(m_layers[RenderLayer::Geometry2dID], isPerspective);
|
||||
mergeFn(m_layers[RenderLayer::Geometry3dID], isPerspective);
|
||||
}
|
||||
|
||||
bool FrontendRenderer::IsPerspective() const
|
||||
|
@ -1426,8 +1465,11 @@ void FrontendRenderer::Routine::Do()
|
|||
void FrontendRenderer::ReleaseResources()
|
||||
{
|
||||
m_tileTree.reset();
|
||||
m_renderGroups.clear();
|
||||
m_deferredRenderGroups.clear();
|
||||
for (RenderLayer & layer : m_layers)
|
||||
{
|
||||
layer.m_renderGroups.clear();
|
||||
layer.m_deferredRenderGroups.clear();
|
||||
}
|
||||
m_userMarkRenderGroups.clear();
|
||||
m_guiRenderer.reset();
|
||||
m_myPositionController.reset();
|
||||
|
@ -1514,4 +1556,28 @@ void FrontendRenderer::EmitModelViewChanged(ScreenBase const & modelView) const
|
|||
m_modelViewChangedFn(modelView);
|
||||
}
|
||||
|
||||
FrontendRenderer::RenderLayer::RenderLayerID FrontendRenderer::RenderLayer::GetLayerID(dp::GLState const & state)
|
||||
{
|
||||
if (state.GetDepthLayer() == dp::GLState::OverlayLayer)
|
||||
return OverlayID;
|
||||
|
||||
if (state.GetProgram3dIndex() == gpu::AREA_3D_PROGRAM)
|
||||
return Geometry3dID;
|
||||
|
||||
return Geometry2dID;
|
||||
}
|
||||
|
||||
void FrontendRenderer::RenderLayer::Sort()
|
||||
{
|
||||
if (!m_isDirty)
|
||||
return;
|
||||
|
||||
RenderGroupComparator comparator;
|
||||
sort(m_renderGroups.begin(), m_renderGroups.end(), ref(comparator));
|
||||
m_isDirty = comparator.m_pendingOnDeleteFound;
|
||||
|
||||
while (!m_renderGroups.empty() && m_renderGroups.back()->CanBeDeleted())
|
||||
m_renderGroups.pop_back();
|
||||
}
|
||||
|
||||
} // namespace df
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
#include "std/function.hpp"
|
||||
#include "std/map.hpp"
|
||||
#include "std/array.hpp"
|
||||
|
||||
namespace dp
|
||||
{
|
||||
|
@ -148,6 +149,12 @@ private:
|
|||
void RefreshPivotTransform(ScreenBase const & screen);
|
||||
void RefreshBgColor();
|
||||
|
||||
//////
|
||||
/// Render part of scene
|
||||
void Render2dLayer(ScreenBase const & modelView);
|
||||
void Render3dLayer(ScreenBase const & modelView);
|
||||
void RenderOverlayLayer(ScreenBase const & modelView);
|
||||
//////
|
||||
ScreenBase const & ProcessEvents(bool & modelViewChanged, bool & viewportChanged);
|
||||
void PrepareScene(ScreenBase const & modelView);
|
||||
void UpdateScene(ScreenBase const & modelView);
|
||||
|
@ -230,8 +237,26 @@ private:
|
|||
private:
|
||||
drape_ptr<dp::GpuProgramManager> m_gpuProgramManager;
|
||||
|
||||
vector<drape_ptr<RenderGroup>> m_renderGroups;
|
||||
vector<drape_ptr<RenderGroup>> m_deferredRenderGroups;
|
||||
struct RenderLayer
|
||||
{
|
||||
enum RenderLayerID
|
||||
{
|
||||
Geometry2dID,
|
||||
OverlayID,
|
||||
Geometry3dID,
|
||||
LayerCountID
|
||||
};
|
||||
|
||||
static RenderLayerID GetLayerID(dp::GLState const & renderGroup);
|
||||
|
||||
vector<drape_ptr<RenderGroup>> m_renderGroups;
|
||||
vector<drape_ptr<RenderGroup>> m_deferredRenderGroups;
|
||||
bool m_isDirty = false;
|
||||
|
||||
inline void Sort();
|
||||
};
|
||||
|
||||
array<RenderLayer, RenderLayer::LayerCountID> m_layers;
|
||||
vector<drape_ptr<UserMarkRenderGroup>> m_userMarkRenderGroups;
|
||||
set<TileKey> m_userMarkVisibility;
|
||||
|
||||
|
|
|
@ -190,20 +190,14 @@ void RenderGroup::Disappear()
|
|||
|
||||
bool RenderGroupComparator::operator()(drape_ptr<RenderGroup> const & l, drape_ptr<RenderGroup> const & r)
|
||||
{
|
||||
dp::GLState const & lState = l->GetState();
|
||||
dp::GLState const & rState = r->GetState();
|
||||
|
||||
if (!l->CanBeDeleted() && l->IsEmpty())
|
||||
l->DeleteLater();
|
||||
|
||||
if (!r->CanBeDeleted() && r->IsEmpty())
|
||||
r->DeleteLater();
|
||||
|
||||
m_pendingOnDeleteFound |= (l->IsPendingOnDelete() || r->IsPendingOnDelete());
|
||||
bool const lCanBeDeleted = l->CanBeDeleted();
|
||||
bool const rCanBeDeleted = r->CanBeDeleted();
|
||||
|
||||
if (rCanBeDeleted == lCanBeDeleted)
|
||||
{
|
||||
dp::GLState const & lState = l->GetState();
|
||||
dp::GLState const & rState = r->GetState();
|
||||
dp::GLState::DepthLayer lDepth = lState.GetDepthLayer();
|
||||
dp::GLState::DepthLayer rDepth = rState.GetDepthLayer();
|
||||
if (lDepth != rDepth)
|
||||
|
|
|
@ -90,6 +90,7 @@ class RenderGroupComparator
|
|||
{
|
||||
public:
|
||||
bool operator()(drape_ptr<RenderGroup> const & l, drape_ptr<RenderGroup> const & r);
|
||||
bool m_pendingOnDeleteFound = false;
|
||||
};
|
||||
|
||||
class UserMarkRenderGroup : public BaseRenderGroup
|
||||
|
|
Loading…
Add table
Reference in a new issue