Merge pull request #1581 from ExMix/uvr-dev

[drape] Memory and cache optimization
This commit is contained in:
Roman Kuznetsov 2016-02-04 17:12:12 +03:00
commit cc019f6480
11 changed files with 321 additions and 241 deletions

View file

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

View file

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

View file

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

View file

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

View file

@ -38,7 +38,6 @@ public:
{
/// Do not change order
GeometryLayer,
DynamicGeometry,
OverlayLayer,
UserMarkLayer,
Gui

View file

@ -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())

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

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

View file

@ -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