From 0a8333ddef22570d4a3fead13556b86c1b831a93 Mon Sep 17 00:00:00 2001 From: ExMix Date: Wed, 20 Nov 2013 12:09:30 +0300 Subject: [PATCH] [drape] backend renderer refactoring. Use new cross-thread communication. --- drape_frontend/backend_renderer.cpp | 261 +----------------- drape_frontend/backend_renderer.hpp | 25 +- drape_frontend/drape_frontend.pro | 25 +- drape_frontend/impl/backend_renderer_impl.cpp | 230 +++++++++++++++ drape_frontend/impl/backend_renderer_impl.hpp | 72 +++++ drape_frontend/read_mwm_task.cpp | 57 ++++ drape_frontend/read_mwm_task.hpp | 37 +++ 7 files changed, 446 insertions(+), 261 deletions(-) create mode 100644 drape_frontend/impl/backend_renderer_impl.cpp create mode 100644 drape_frontend/impl/backend_renderer_impl.hpp create mode 100644 drape_frontend/read_mwm_task.cpp create mode 100644 drape_frontend/read_mwm_task.hpp diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index 529b9ffdda..a1ff6ca46f 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -1,272 +1,35 @@ #include "backend_renderer.hpp" -#include "render_thread.hpp" -#include "tile_info.hpp" -#include "memory_feature_index.hpp" - -#include "../map/tiler.hpp" -#include "../map/scales_processor.hpp" - -#include "../geometry/screenbase.hpp" - -#include "../drape/batcher.hpp" - -#include "../base/thread.hpp" -#include "../base/thread_pool.hpp" -#include "../base/buffer_vector.hpp" -#include "../base/object_tracker.hpp" +#include "threads_commutator.hpp" +#include "update_coverage_message.hpp" +#include "resize_message.hpp" +#include "impl/backend_renderer_impl.hpp" #include "../std/bind.hpp" -#include "../std/set.hpp" - -namespace -{ - class ReadMWMTask : public threads::IRoutine - { - public: - ReadMWMTask(Tiler::RectInfo const & tileId, df::MemoryFeatureIndex & index) - : m_tileInfo(tileId.m_x, tileId.m_y, tileId.m_tileScale) - , m_isFinished(false) - , m_index(index) - { - } - - df::TileInfo const & GetTileInfo() const - { - return m_tileInfo; - } - - virtual void Do() - { - if (m_tileInfo.m_featureInfo.empty()) - ReadTileIndex(); - - vector indexesToRead; - m_index.ReadFeaturesRequest(m_tileInfo.m_featureInfo, indexesToRead); - for (size_t i = 0; i < indexesToRead.size(); ++i) - { - df::FeatureInfo & info = m_tileInfo.m_featureInfo[i]; - ReadGeometry(info.m_id); - info.m_isOwner = true; - } - } - - void PrepareToRestart() - { - m_isFinished = false; - } - - void Finish() - { - m_isFinished = true; - } - - bool IsFinished() - { - return m_isFinished; - } - - private: - void ReadTileIndex() - { - /// TODO read index specified by m_tileInfo(m_x & m_y & m_zoomLevel) - /// TODO insert readed FeatureIDs into m_tileInfo.m_featureInfo; - } - - void ReadGeometry(const FeatureID & id) - { - ///TODO read geometry - } - - private: - df::TileInfo m_tileInfo; - bool m_isFinished; - df::MemoryFeatureIndex & m_index; - -#ifdef DEBUG - dbg::ObjectTracker m_objTracker; -#endif - }; - - struct CoverageCellComparer - { - bool operator()(ReadMWMTask const * task, Tiler::RectInfo const & rectInfo) const - { - /// TODO remove RectInfo to TileInfo covertion after rewrite tiler on TileInfo returning - return task->GetTileInfo() < df::TileInfo(rectInfo.m_x, rectInfo.m_y, rectInfo.m_tileScale); - } - - bool operator()(Tiler::RectInfo const & rectInfo, ReadMWMTask const * task) const - { - /// TODO remove RectInfo to TileInfo covertion after rewrite tiler on TileInfo returning - return df::TileInfo(rectInfo.m_x, rectInfo.m_y, rectInfo.m_tileScale) < task->GetTileInfo(); - } - }; -} namespace df { - class BackendRenderer::Impl + BackendRenderer::BackendRenderer(ThreadsCommutator * commutator, + double visualScale, + int surfaceWidth, + int surfaceHeight) { - public: - Impl(threads::ThreadPool * pool, size_t tileSize) - : m_pool(pool) - , m_scaleProcessor(tileSize) - { - /// TODO create batcher with thread thansfer interface - } - - ~Impl() - { - m_pool->Stop(); - delete m_pool; - - typedef set::iterator index_iter; - for (index_iter it = m_taskIndex.begin(); it != m_taskIndex.end(); ++it) - delete (*it); - - m_taskIndex.clear(); - } - - void UpdateCoverage(const ScreenBase & screen) - { - m_tiler.seed(screen, screen.GlobalRect().GlobalCenter(), m_scaleProcessor.GetTileSize()); - - vector tiles; - m_tiler.tiles(tiles, 1); - - if (!m_currentViewport.GlobalRect().IsIntersect(screen.GlobalRect()) || - m_scaleProcessor.GetTileScaleBase(m_currentViewport) != m_scaleProcessor.GetTileScaleBase(screen)) - { - typedef set::iterator index_iter; - for (index_iter it = m_taskIndex.begin(); it != m_taskIndex.end(); ++it) - CancelTask(*it, false); - - m_taskIndex.clear(); - - for (size_t i = 0; i < tiles.size(); ++i) - CreateTask(tiles[i]); - } - else - { - set rectInfoSet; - for (size_t i = 0 ; i < tiles.size(); ++i) - rectInfoSet.insert(tiles[i]); - - // Find rects that go out from viewport - buffer_vector outdatedTasks; - set_difference(m_taskIndex.begin(), m_taskIndex.end(), - rectInfoSet.begin(), rectInfoSet.end(), - back_inserter(outdatedTasks), CoverageCellComparer()); - - // Find rects that go in into viewport - buffer_vector inputRects; - set_difference(rectInfoSet.begin(), rectInfoSet.end(), - m_taskIndex.begin(), m_taskIndex.end(), - back_inserter(inputRects), CoverageCellComparer()); - - for (size_t i = 0; i < outdatedTasks.size(); ++i) - CancelTask(outdatedTasks[i], true); - - RestartExistTasks(); - - for (size_t i = 0; i < inputRects.size(); ++i) - CreateTask(inputRects[i]); - } - } - - void Resize(m2::RectI const & rect) - { - m_currentViewport.OnSize(rect); - } - - void FinishTask(threads::IRoutine * routine) - { - ReadMWMTask * readTask = static_cast(routine); - readTask->Finish(); - if (routine->IsCancelled()) - { - ASSERT(m_taskIndex.find(readTask) == m_taskIndex.end(), ()); - - /// TODO remove geometry from render loop - /// TODO remove unflushed backets - m_index.RemoveFeatures(readTask->GetTileInfo().m_featureInfo); - - delete readTask; - } - else - { - /// TODO flush geometry backet on frontend renderer - } - } - - private: - void CreateTask(Tiler::RectInfo const & info) - { - ReadMWMTask * task = new ReadMWMTask(info, m_index); - m_taskIndex.insert(task); - m_pool->AddTask(task); - } - - void CancelTask(ReadMWMTask * task, bool removeFromIndex) - { - task->Cancel(); - if (removeFromIndex) - m_taskIndex.erase(task); - m_index.RemoveFeatures(task->GetTileInfo().m_featureInfo); - if (task->IsFinished()) - delete task; - } - - void RestartExistTasks() - { - typedef set::iterator index_iter; - for (index_iter it = m_taskIndex.begin(); it != m_taskIndex.end(); ++it) - { - (*it)->PrepareToRestart(); - m_pool->AddTask(*it); - } - } - - private: - threads::ThreadPool * m_pool; - - ScreenBase m_currentViewport; - set m_taskIndex; - - Tiler m_tiler; - ScalesProcessor m_scaleProcessor; - - MemoryFeatureIndex m_index; - - //Batcher * m_batcher; - }; - - BackendRenderer::BackendRenderer(int cpuCoreCount, size_t tileSize) - : m_queue(1) - { - m_impl = new Impl(new threads::ThreadPool(cpuCoreCount, bind(&BackendRenderer::FinishTask, this, _1)), tileSize); - m_queue.AddInitCommand(bind(&InitRenderThread)); + m_impl = new BackendRendererImpl(commutator, visualScale, surfaceWidth, surfaceHeight); + m_post = bind(&ThreadsCommutator::PostMessage, commutator, ThreadsCommutator::ResourceUploadThread, _1); } BackendRenderer::~BackendRenderer() { - m_queue.Cancel(); delete m_impl; } void BackendRenderer::UpdateCoverage(const ScreenBase & screen) { - m_queue.AddCommand(bind(&BackendRenderer::Impl::UpdateCoverage, m_impl, screen)); + m_post(new UpdateCoverageMessage(screen)); } void BackendRenderer::Resize(int x0, int y0, int w, int h) { - m_queue.AddCommand(bind(&BackendRenderer::Impl::Resize, m_impl, m2::RectI(x0, y0, x0 + w, y0 + h))); - } - - void BackendRenderer::FinishTask(threads::IRoutine * routine) - { - m_queue.AddCommand(bind(&BackendRenderer::Impl::FinishTask, m_impl, routine)); + m_post(new ResizeMessage(x0, y0, w, h)); } } diff --git a/drape_frontend/backend_renderer.hpp b/drape_frontend/backend_renderer.hpp index f88a719aed..9f7469cf7e 100644 --- a/drape_frontend/backend_renderer.hpp +++ b/drape_frontend/backend_renderer.hpp @@ -1,27 +1,32 @@ #pragma once -#include "../base/commands_queue.hpp" #include "../geometry/screenbase.hpp" +#include "../std/function.hpp" + namespace df { + class ThreadsCommutator; + class BackendRendererImpl; + class Message; + + typedef function post_message_fn_t; + class BackendRenderer { public: - BackendRenderer(int cpuCoreCount, size_t tileSize); + BackendRenderer(ThreadsCommutator * commutator, + double visualScale, + int surfaceWidth, + int surfaceHeight); + ~BackendRenderer(); void UpdateCoverage(const ScreenBase & screen); void Resize(int x0, int y0, int w, int h); private: - void FinishTask(threads::IRoutine * routine); - - private: - class Impl; - Impl * m_impl; - - private: - core::CommandsQueue m_queue; + BackendRendererImpl * m_impl; + post_message_fn_t m_post; }; } diff --git a/drape_frontend/drape_frontend.pro b/drape_frontend/drape_frontend.pro index 8945315c54..3381e033c5 100644 --- a/drape_frontend/drape_frontend.pro +++ b/drape_frontend/drape_frontend.pro @@ -9,11 +9,32 @@ include($$ROOT_DIR/common.pri) SOURCES += \ backend_renderer.cpp \ engine_context.cpp \ - memory_feature_index.cpp + memory_feature_index.cpp \ + message_queue.cpp \ + message.cpp \ + threads_commutator.cpp \ + message_acceptor.cpp \ + drop_tile_message.cpp \ + impl/backend_renderer_impl.cpp \ + update_coverage_message.cpp \ + resize_message.cpp \ + task_finish_message.cpp \ + read_mwm_task.cpp HEADERS += \ backend_renderer.hpp \ render_thread.hpp \ engine_context.hpp \ memory_feature_index.hpp \ - tile_info.hpp + tile_info.hpp \ + message_queue.hpp \ + message.hpp \ + threads_commutator.hpp \ + message_acceptor.hpp \ + drop_tile_message.hpp \ + impl/backend_renderer_impl.hpp \ + update_coverage_message.hpp \ + resize_message.hpp \ + task_finish_message.hpp \ + read_mwm_task.hpp \ + drop_coverage_message.hpp diff --git a/drape_frontend/impl/backend_renderer_impl.cpp b/drape_frontend/impl/backend_renderer_impl.cpp new file mode 100644 index 0000000000..1ef5f0c2e5 --- /dev/null +++ b/drape_frontend/impl/backend_renderer_impl.cpp @@ -0,0 +1,230 @@ +#include "backend_renderer_impl.hpp" + +#include "threads_commutator.hpp" +#include "render_thread.hpp" +#include "tile_info.hpp" +#include "memory_feature_index.hpp" +#include "read_mwm_task.hpp" + +#include "message.hpp" +#include "update_coverage_message.hpp" +#include "resize_message.hpp" +#include "task_finish_message.hpp" +#include "drop_tile_message.hpp" +#include "drop_coverage_message.hpp" + +#include "../geometry/screenbase.hpp" + +#include "../base/buffer_vector.hpp" +#include "../base/object_tracker.hpp" + +#include "../std/bind.hpp" + +namespace +{ + void PostFinishTask(df::ThreadsCommutator * commutator, threads::IRoutine * routine) + { + commutator->PostMessage(df::ThreadsCommutator::ResourceUploadThread, new df::TaskFinishMessage(routine)); + } + + struct CoverageCellComparer + { + bool operator()(df::ReadMWMTask const * task, Tiler::RectInfo const & rectInfo) const + { + /// TODO remove RectInfo to TileInfo covertion after rewrite tiler on TileInfo returning + return task->GetTileInfo() < df::TileInfo(rectInfo.m_x, rectInfo.m_y, rectInfo.m_tileScale); + } + + bool operator()(Tiler::RectInfo const & rectInfo, df::ReadMWMTask const * task) const + { + /// TODO remove RectInfo to TileInfo covertion after rewrite tiler on TileInfo returning + return df::TileInfo(rectInfo.m_x, rectInfo.m_y, rectInfo.m_tileScale) < task->GetTileInfo(); + } + }; +} + +namespace df +{ + BackendRendererImpl::BackendRendererImpl(ThreadsCommutator * commutator, + double visualScale, + int surfaceWidth, + int surfaceHeight) + : m_commutator(commutator) + { + m_scaleProcessor.SetParams(visualScale, ScalesProcessor::CalculateTileSize(surfaceWidth, surfaceHeight)); + + m_commutator->RegisterThread(ThreadsCommutator::ResourceUploadThread, this); + m_pool = new threads::ThreadPool(max(1, GetPlatform().CpuCores() - 2), bind(&PostFinishTask, commutator, _1)); + + /// TODO create batcher with thread thansfer interface + StartThread(); + } + + BackendRendererImpl::~BackendRendererImpl() + { + StopThread(); + CloseQueue(); + + m_pool->Stop(); + delete m_pool; + + typedef set::iterator index_iter; + for (index_iter it = m_taskIndex.begin(); it != m_taskIndex.end(); ++it) + delete (*it); + + m_taskIndex.clear(); + } + + void BackendRendererImpl::UpdateCoverage(const ScreenBase & screen) + { + m_tiler.seed(screen, screen.GlobalRect().GlobalCenter(), m_scaleProcessor.GetTileSize()); + + vector tiles; + m_tiler.tiles(tiles, 1); + + if (!m_currentViewport.GlobalRect().IsIntersect(screen.GlobalRect()) || + m_scaleProcessor.GetTileScaleBase(m_currentViewport) != m_scaleProcessor.GetTileScaleBase(screen)) + { + typedef set::iterator index_iter; + for (index_iter it = m_taskIndex.begin(); it != m_taskIndex.end(); ++it) + CancelTask(*it, false, false); + + m_taskIndex.clear(); + PostToRenderThreads(new DropCoverageMessage()); + + for (size_t i = 0; i < tiles.size(); ++i) + CreateTask(tiles[i]); + } + else + { + set rectInfoSet; + for (size_t i = 0 ; i < tiles.size(); ++i) + rectInfoSet.insert(tiles[i]); + + // Find rects that go out from viewport + buffer_vector outdatedTasks; + set_difference(m_taskIndex.begin(), m_taskIndex.end(), + rectInfoSet.begin(), rectInfoSet.end(), + back_inserter(outdatedTasks), CoverageCellComparer()); + + // Find rects that go in into viewport + buffer_vector inputRects; + set_difference(rectInfoSet.begin(), rectInfoSet.end(), + m_taskIndex.begin(), m_taskIndex.end(), + back_inserter(inputRects), CoverageCellComparer()); + + for (size_t i = 0; i < outdatedTasks.size(); ++i) + CancelTask(outdatedTasks[i], true, true); + + RestartExistTasks(); + + for (size_t i = 0; i < inputRects.size(); ++i) + CreateTask(inputRects[i]); + } + } + + void BackendRendererImpl::FinishTask(threads::IRoutine * routine) + { + ReadMWMTask * readTask = static_cast(routine); + readTask->Finish(); + if (routine->IsCancelled()) + { + ASSERT(m_taskIndex.find(readTask) == m_taskIndex.end(), ()); + CancelTask(readTask, false, true); + } + else + { + /// TODO flush geometry backet on frontend renderer + } + } + + void BackendRendererImpl::Resize(m2::RectI const & rect) + { + m_currentViewport.OnSize(rect); + } + + void BackendRendererImpl::CreateTask(Tiler::RectInfo const & info) + { + ReadMWMTask * task = new ReadMWMTask(TileKey(info.m_x, info.m_y, info.m_tileScale), m_index); + m_taskIndex.insert(task); + m_pool->AddTask(task); + } + + void BackendRendererImpl::CancelTask(ReadMWMTask * task, bool removefromIndex, bool postToRenderer) + { + task->Cancel(); + + if (postToRenderer) + PostToRenderThreads(new DropTileMessage(task->GetTileInfo().m_key)); + + if (removefromIndex) + m_taskIndex.erase(task); + + m_index.RemoveFeatures(task->GetTileInfo().m_featureInfo); + if (task->IsFinished()) + delete task; + } + + void BackendRendererImpl::RestartExistTasks() + { + typedef set::iterator index_iter; + for (index_iter it = m_taskIndex.begin(); it != m_taskIndex.end(); ++it) + { + (*it)->PrepareToRestart(); + m_pool->AddTask(*it); + } + } + + ///////////////////////////////////////// + // MessageAcceptor // + ///////////////////////////////////////// + void BackendRendererImpl::AcceptMessage(Message * message) + { + switch (message->GetType()) + { + case Message::UpdateCoverage: + UpdateCoverage(static_cast(message)->GetScreen()); + break; + case Message::Resize: + Resize(static_cast(message)->GetRect()); + break; + case Message::TaskFinish: + FinishTask(static_cast(message)->GetRoutine()); + break; + default: + ASSERT(false, ()); + break; + } + } + + ///////////////////////////////////////// + // ThreadPart // + ///////////////////////////////////////// + void BackendRendererImpl::StartThread() + { + m_selfThread.Create(this); + } + + void BackendRendererImpl::StopThread() + { + m_selfThread.Cancel(); + } + + void BackendRendererImpl::ThreadMain() + { + InitRenderThread(); + + while (!IsCancelled()) + ProcessSingleMessage(true); + } + + void BackendRendererImpl::Do() + { + ThreadMain(); + } + + void BackendRendererImpl::PostToRenderThreads(Message * message) + { + m_commutator->PostMessage(ThreadsCommutator::RenderThread, message); + } +} diff --git a/drape_frontend/impl/backend_renderer_impl.hpp b/drape_frontend/impl/backend_renderer_impl.hpp new file mode 100644 index 0000000000..51922c42b7 --- /dev/null +++ b/drape_frontend/impl/backend_renderer_impl.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include "message_acceptor.hpp" +#include "memory_feature_index.hpp" + +#include "../map/scales_processor.hpp" +#include "../map/tiler.hpp" + +#include "../platform/platform.hpp" + +#include "../base/thread.hpp" +#include "../base/thread_pool.hpp" + +#include "../std/set.hpp" + +namespace df +{ + class Message; + class ThreadsCommutator; + class ReadMWMTask; + + class BackendRendererImpl : public MessageAcceptor, + public threads::IRoutine + { + public: + BackendRendererImpl(ThreadsCommutator * commutator, + double visualScale, + int surfaceWidth, + int surfaceHeight); + ~BackendRendererImpl(); + + private: + void UpdateCoverage(const ScreenBase & screen); + void Resize(m2::RectI const & rect); + void FinishTask(threads::IRoutine * routine); + + private: + void CreateTask(Tiler::RectInfo const & info); + void CancelTask(ReadMWMTask * task, bool removefromIndex, bool postToRenderer); + void RestartExistTasks(); + + private: + ScreenBase m_currentViewport; + set m_taskIndex; + + MemoryFeatureIndex m_index; + Tiler m_tiler; + ScalesProcessor m_scaleProcessor; + + ///////////////////////////////////////// + // MessageAcceptor // + ///////////////////////////////////////// + private: + void AcceptMessage(Message *message); + + ///////////////////////////////////////// + // ThreadPart // + ///////////////////////////////////////// + private: + void StartThread(); + void StopThread(); + void ThreadMain(); + virtual void Do(); + + void PostToRenderThreads(Message * message); + + private: + threads::Thread m_selfThread; + threads::ThreadPool * m_pool; + ThreadsCommutator * m_commutator; + }; +} diff --git a/drape_frontend/read_mwm_task.cpp b/drape_frontend/read_mwm_task.cpp new file mode 100644 index 0000000000..91d9eaf8e3 --- /dev/null +++ b/drape_frontend/read_mwm_task.cpp @@ -0,0 +1,57 @@ +#include "read_mwm_task.hpp" + +namespace df +{ + ReadMWMTask::ReadMWMTask(TileKey const & tileKey, df::MemoryFeatureIndex & index) + : m_tileInfo(tileKey) + , m_isFinished(false) + , m_index(index) + { + } + + void ReadMWMTask::Do() + { + if (m_tileInfo.m_featureInfo.empty()) + ReadTileIndex(); + + vector indexesToRead; + m_index.ReadFeaturesRequest(m_tileInfo.m_featureInfo, indexesToRead); + for (size_t i = 0; i < indexesToRead.size(); ++i) + { + df::FeatureInfo & info = m_tileInfo.m_featureInfo[i]; + ReadGeometry(info.m_id); + info.m_isOwner = true; + } + } + + df::TileInfo const & ReadMWMTask::GetTileInfo() const + { + return m_tileInfo; + } + + void ReadMWMTask::PrepareToRestart() + { + m_isFinished = false; + } + + void ReadMWMTask::Finish() + { + m_isFinished = true; + } + + bool ReadMWMTask::IsFinished() + { + return m_isFinished; + } + + void ReadMWMTask::ReadTileIndex() + { + /// TODO read index specified by m_tileInfo(m_x & m_y & m_zoomLevel) + /// TODO insert readed FeatureIDs into m_tileInfo.m_featureInfo; + } + + void ReadMWMTask::ReadGeometry(const FeatureID & id) + { + ///TODO read geometry + } +} diff --git a/drape_frontend/read_mwm_task.hpp b/drape_frontend/read_mwm_task.hpp new file mode 100644 index 0000000000..8c5b319e39 --- /dev/null +++ b/drape_frontend/read_mwm_task.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include "tile_info.hpp" +#include "memory_feature_index.hpp" + +#include "../base/thread.hpp" +#include "../base/object_tracker.hpp" + +namespace df +{ + class ReadMWMTask : public threads::IRoutine + { + public: + ReadMWMTask(TileKey const & tileKey, df::MemoryFeatureIndex & index); + + virtual void Do(); + + df::TileInfo const & GetTileInfo() const; + + void PrepareToRestart(); + void Finish(); + bool IsFinished(); + + private: + void ReadTileIndex(); + void ReadGeometry(const FeatureID & id); + + private: + df::TileInfo m_tileInfo; + bool m_isFinished; + df::MemoryFeatureIndex & m_index; + + #ifdef DEBUG + dbg::ObjectTracker m_objTracker; + #endif + }; +}