diff --git a/base/fence_manager.cpp b/base/fence_manager.cpp index 7a4ee1196f..55c47661d6 100644 --- a/base/fence_manager.cpp +++ b/base/fence_manager.cpp @@ -6,9 +6,8 @@ FenceManager::FenceManager(int conditionPoolSize) : m_currentFence(0) { - m_conditionPool.resize(conditionPoolSize); - for (unsigned i = 0; i < m_conditionPool.size(); ++i) - m_conditionPool[i] = new threads::Condition(); + for (unsigned i = 0; i < conditionPoolSize; ++i) + m_conditionPool.push_back(new threads::Condition()); } FenceManager::~FenceManager() @@ -21,10 +20,8 @@ FenceManager::~FenceManager() delete it->second; } - for (unsigned i = 0; i < m_conditionPool.size(); ++i) - { - delete m_conditionPool[i]; - } + for (list::iterator it = m_conditionPool.begin(); it != m_conditionPool.end(); ++it) + delete *it; } int FenceManager::insertFence() @@ -34,8 +31,8 @@ int FenceManager::insertFence() if (m_conditionPool.empty()) return -1; - threads::Condition * cond = m_conditionPool.back(); - m_conditionPool.pop_back(); + threads::Condition * cond = m_conditionPool.front(); + m_conditionPool.pop_front(); int id = m_currentFence++; @@ -52,20 +49,20 @@ void FenceManager::signalFence(int id) if (it == m_activeFences.end()) { - LOG(LWARNING, ("fence with id", id, "has been already signalled or hasn't been installed yet")); + LOG(LINFO, ("fence with id", id, "has been already signalled or hasn't been installed yet")); return; } threads::Condition * cond = it->second; - /// signalling to all waiting fences - cond->Signal(true); - /// erasing fence from active fences m_activeFences.erase(it); /// returning condition to the pool m_conditionPool.push_back(cond); + + /// signalling to all waiting fences + cond->Signal(true); } void FenceManager::joinFence(int id) @@ -78,7 +75,7 @@ void FenceManager::joinFence(int id) if (it == m_activeFences.end()) { - LOG(LWARNING, ("fence with id", id, "has been already reached in the past or hasn't been installed yet")); + LOG(LINFO, ("fence with id", id, "has been already reached in the past or hasn't been installed yet")); return; } diff --git a/base/fence_manager.hpp b/base/fence_manager.hpp index bd824c4769..55cb16023e 100644 --- a/base/fence_manager.hpp +++ b/base/fence_manager.hpp @@ -4,14 +4,14 @@ #include "../base/mutex.hpp" #include "../std/map.hpp" -#include "../std/vector.hpp" +#include "../std/list.hpp" class FenceManager { private: threads::Mutex m_mutex; - vector m_conditionPool; + list m_conditionPool; map m_activeFences; int m_currentFence; diff --git a/base/threaded_list.hpp b/base/threaded_list.hpp index c1a6d6522e..e72961004f 100644 --- a/base/threaded_list.hpp +++ b/base/threaded_list.hpp @@ -75,10 +75,20 @@ public: { double StartWaitTime = m_Timer.ElapsedSeconds(); + bool doFirstWait = true; + while ((m_isEmpty = m_list.empty())) { if (IsCancelled()) break; + + if (doFirstWait) + { + doFirstWait = false; + if (!m_resName.empty()) + LOG(LINFO, ("consumer is waiting for", m_resName)); + } + m_Cond.Wait(); } diff --git a/map/queued_render_policy.cpp b/map/queued_render_policy.cpp index c9723c9875..727c539744 100644 --- a/map/queued_render_policy.cpp +++ b/map/queued_render_policy.cpp @@ -77,22 +77,33 @@ void QueuedRenderPolicy::RenderQueuedCommands(int pipelineNum) list::iterator it; + yg::gl::Packet::EType bucketType = m_Pipelines[pipelineNum].m_Type; + for (it = m_Pipelines[pipelineNum].m_FrameBucket.begin(); it != m_Pipelines[pipelineNum].m_FrameBucket.end(); ++it) { - if (it->m_state) - { - it->m_state->m_isDebugging = m_IsDebugging; - it->m_state->apply(curState.get()); - curState = it->m_state; - } if (it->m_command) - { it->m_command->setIsDebugging(m_IsDebugging); - it->m_command->perform(); - } + if (bucketType == yg::gl::Packet::ECancelPoint) + { + if (it->m_command) + it->m_command->cancel(); + } + else + { + ASSERT(bucketType == yg::gl::Packet::ECheckPoint, ()); + + if (it->m_state) + { + it->m_state->m_isDebugging = m_IsDebugging; + it->m_state->apply(curState.get()); + curState = it->m_state; + } + if (it->m_command) + it->m_command->perform(); + } } /// should clear to release resources, refered from the stored commands. @@ -111,7 +122,7 @@ void QueuedRenderPolicy::PacketsPipeline::FillFrameBucket(list & { m_FrameBucket.clear(); - /// searching for "group boundary" markers + /// searching for "delimiter" markers list::iterator first = renderQueue.begin(); list::iterator last = renderQueue.begin(); @@ -121,7 +132,8 @@ void QueuedRenderPolicy::PacketsPipeline::FillFrameBucket(list & while ((packetsLeft != 0) && (last != renderQueue.end())) { yg::gl::Packet p = *last; - if (p.m_groupBoundary) + if ((p.m_type == yg::gl::Packet::ECheckPoint) + || (p.m_type == yg::gl::Packet::ECancelPoint)) { /// found frame boundary, copying copy(first, ++last, back_inserter(m_FrameBucket)); @@ -129,6 +141,9 @@ void QueuedRenderPolicy::PacketsPipeline::FillFrameBucket(list & renderQueue.erase(first, last); first = renderQueue.begin(); last = renderQueue.begin(); + m_Type = p.m_type; + if (m_Type == yg::gl::Packet::ECancelPoint) + break; } else ++last; @@ -137,12 +152,28 @@ void QueuedRenderPolicy::PacketsPipeline::FillFrameBucket(list & } } +void QueuedRenderPolicy::CopyQueuedCommands(list &l, list &r) +{ + swap(l, r); +} + void QueuedRenderPolicy::DismissQueuedCommands(int pipelineNum) { - while (!m_Pipelines[pipelineNum].m_Queue.Empty()) + if (m_IsDebugging) + LOG(LINFO, ("cancelling packetsQueue for pipeline", pipelineNum)); + + m_Pipelines[pipelineNum].m_Queue.cancel(); + + list l; + + m_Pipelines[pipelineNum].m_Queue.ProcessList(bind(&QueuedRenderPolicy::CopyQueuedCommands, this, _1, ref(l))); + + for (list::iterator it = l.begin(); it != l.end(); ++it) { - yg::gl::Packet p = m_Pipelines[pipelineNum].m_Queue.Back(true); - if (p.m_groupBoundary) + yg::gl::Packet p = *it; + + if ((p.m_type == yg::gl::Packet::ECheckPoint) + || (p.m_type == yg::gl::Packet::ECancelPoint)) { if (p.m_command) p.m_command->perform(); diff --git a/map/queued_render_policy.hpp b/map/queued_render_policy.hpp index 345c8511d8..9a8823cab1 100644 --- a/map/queued_render_policy.hpp +++ b/map/queued_render_policy.hpp @@ -15,6 +15,7 @@ private: { yg::gl::PacketsQueue m_Queue; //< all enqueued commands list m_FrameBucket; //< list of commands to execute on current frame + yg::gl::Packet::EType m_Type; void FillFrameBucket(list & QueueData); }; @@ -29,6 +30,8 @@ private: protected: + void CopyQueuedCommands(list & l, list & r); + void RenderQueuedCommands(int pipelineNum); void DismissQueuedCommands(int pipelineNum); diff --git a/map/render_queue_routine.cpp b/map/render_queue_routine.cpp index 1612d6ec20..4ce1ba6747 100644 --- a/map/render_queue_routine.cpp +++ b/map/render_queue_routine.cpp @@ -443,6 +443,10 @@ void RenderQueueRoutine::Do() glbRect, scaleLevel); + /// all unprocessed commands should be cancelled + if (m_currentRenderCommand->m_paintEvent->isCancelled() && m_glQueue) + m_glQueue->insertCancelPoint(); + if (!m_renderState->m_isEmptyModelCurrent) cumulativeEmptyModelCurrent = m_renderState->m_isEmptyModelCurrent; @@ -519,6 +523,11 @@ void RenderQueueRoutine::Invalidate::perform() bind(&WindowHandle::invalidate, _1)); } +void RenderQueueRoutine::Invalidate::cancel() +{ + perform(); +} + void RenderQueueRoutine::invalidate() { for_each(m_windowHandles.begin(), @@ -529,7 +538,7 @@ void RenderQueueRoutine::invalidate() { shared_ptr command(new Invalidate()); command->m_windowHandles = m_windowHandles; - m_glQueue->PushBack(yg::gl::Packet(command, true)); + m_glQueue->processPacket(yg::gl::Packet(command, yg::gl::Packet::ECheckPoint)); } } diff --git a/map/render_queue_routine.hpp b/map/render_queue_routine.hpp index d4ef908745..7f11b0d9b8 100644 --- a/map/render_queue_routine.hpp +++ b/map/render_queue_routine.hpp @@ -57,6 +57,7 @@ private: { list > m_windowHandles; void perform(); + void cancel(); }; shared_ptr m_renderContext; diff --git a/map/tile_renderer.cpp b/map/tile_renderer.cpp index 36d1d2bc5c..2242e6da73 100644 --- a/map/tile_renderer.cpp +++ b/map/tile_renderer.cpp @@ -28,7 +28,8 @@ TileRenderer::TileRenderer( m_renderFn(renderFn), m_skinName(skinName), m_bgColor(bgColor), - m_sequenceID(0) + m_sequenceID(0), + m_isExiting(false) { m_resourceManager = rm; m_primaryContext = primaryRC; @@ -74,7 +75,7 @@ TileRenderer::TileRenderer( TileRenderer::~TileRenderer() { - LOG(LINFO, ("deleting tile renderer")); + m_isExiting = true; m_queue.Cancel(); } @@ -175,17 +176,35 @@ void TileRenderer::DrawTile(core::CommandsQueue::Environment const & env, if (!env.isCancelled()) drawer->screen()->resetInfoLayer(); + yg::gl::PacketsQueue * glQueue = threadData.m_drawerParams.m_renderQueue; + if (!env.isCancelled()) { - yg::gl::PacketsQueue * glQueue = threadData.m_drawerParams.m_renderQueue; if (glQueue) + { + glQueue->insertCheckPoint(); glQueue->completeCommands(); + } + } + else + { + if (!m_isExiting) + { + if (glQueue) + { + glQueue->insertCancelPoint(); + glQueue->completeCommands(); + } + } } double duration = timer.ElapsedSeconds(); if (env.isCancelled()) - m_resourceManager->renderTargetTextures()->Free(tileTarget); + { + if (!m_isExiting) + m_resourceManager->renderTargetTextures()->Free(tileTarget); + } else AddTile(rectInfo, Tile(tileTarget, tileInfoLayer, frameScreen, rectInfo, duration)); } diff --git a/map/tile_renderer.hpp b/map/tile_renderer.hpp index 3980c992a5..ca8db03535 100644 --- a/map/tile_renderer.hpp +++ b/map/tile_renderer.hpp @@ -53,6 +53,7 @@ protected: string m_skinName; yg::Color m_bgColor; int m_sequenceID; + bool m_isExiting; void InitializeThreadGL(core::CommandsQueue::Environment const & env); void FinalizeThreadGL(core::CommandsQueue::Environment const & env); diff --git a/map/tiling_render_policy_st.cpp b/map/tiling_render_policy_st.cpp index 6242a3fe40..07e4239bd1 100644 --- a/map/tiling_render_policy_st.cpp +++ b/map/tiling_render_policy_st.cpp @@ -42,7 +42,7 @@ TilingRenderPolicyST::TilingRenderPolicyST(VideoTimer * videoTimer, sizeof(yg::gl::Vertex), 10000 * sizeof(unsigned short), sizeof(unsigned short), - 4, + 12, true, false, 2, @@ -188,12 +188,12 @@ TilingRenderPolicyST::~TilingRenderPolicyST() LOG(LINFO, ("deleting TilingRenderPolicyST")); - base_t::DismissQueuedCommands(0); + base_t::DismissQueuedCommands(1); LOG(LINFO, ("reseting coverageGenerator")); m_coverageGenerator.reset(); - base_t::DismissQueuedCommands(1); + base_t::DismissQueuedCommands(0); LOG(LINFO, ("reseting tileRenderer")); m_tileRenderer.reset(); diff --git a/yg/area_renderer.cpp b/yg/area_renderer.cpp index 6fa493953b..8f6f32a56e 100644 --- a/yg/area_renderer.cpp +++ b/yg/area_renderer.cpp @@ -25,7 +25,7 @@ namespace yg base_t::beginFrame(); m_areasCount = 0; m_trianglesCount = 0; - }; + } void AreaRenderer::endFrame() { diff --git a/yg/geometry_batcher.cpp b/yg/geometry_batcher.cpp index cd079601fc..4c1f52cd06 100644 --- a/yg/geometry_batcher.cpp +++ b/yg/geometry_batcher.cpp @@ -110,6 +110,11 @@ namespace yg m_storagePool->Free(m_storage); } + void GeometryBatcher::FreeStorage::cancel() + { + perform(); + } + void GeometryBatcher::freeStorage(int pipelineID) { GeometryPipeline & pipeline = m_pipelines[pipelineID]; @@ -329,6 +334,11 @@ namespace yg m_texturePool->Free(m_texture); } + void GeometryBatcher::FreeTexture::cancel() + { + perform(); + } + void GeometryBatcher::freeTexture(int pipelineID) { if (!m_skin->getPage(pipelineID)->hasTexture()) @@ -371,6 +381,11 @@ namespace yg m_storage.m_indices->unlock(); } + void GeometryBatcher::UnlockStorage::cancel() + { + perform(); + } + void GeometryBatcher::unlockPipeline(int pipelineID) { GeometryPipeline & pipeline = m_pipelines[pipelineID]; @@ -390,6 +405,11 @@ namespace yg m_storage.m_indices->discard(); } + void GeometryBatcher::DiscardStorage::cancel() + { + perform(); + } + void GeometryBatcher::discardPipeline(int pipelineID) { GeometryPipeline & pipeline = m_pipelines[pipelineID]; diff --git a/yg/geometry_batcher.hpp b/yg/geometry_batcher.hpp index 2f8d38339c..57bc8d999f 100644 --- a/yg/geometry_batcher.hpp +++ b/yg/geometry_batcher.hpp @@ -90,6 +90,7 @@ namespace yg Storage m_storage; void perform(); + void cancel(); }; struct FreeTexture : public Command @@ -98,6 +99,7 @@ namespace yg shared_ptr m_texture; void perform(); + void cancel(); }; struct UnlockStorage : public Command @@ -105,6 +107,7 @@ namespace yg Storage m_storage; void perform(); + void cancel(); }; struct DiscardStorage : public Command @@ -112,6 +115,7 @@ namespace yg Storage m_storage; void perform(); + void cancel(); }; public: diff --git a/yg/packets_queue.cpp b/yg/packets_queue.cpp index 0081796dee..52232d7cb7 100644 --- a/yg/packets_queue.cpp +++ b/yg/packets_queue.cpp @@ -1,4 +1,5 @@ #include "packets_queue.hpp" +#include "../base/logging.hpp" namespace yg { @@ -28,37 +29,52 @@ namespace yg Command::~Command() {} + void Command::cancel() + { + if ((m_isDebugging) && (!m_name.empty())) + LOG(LINFO, ("cancelling", m_name, "command")); + } + + void Command::perform() + { + if ((m_isDebugging) && (!m_name.empty())) + LOG(LINFO, ("performing", m_name, "command")); + } + Packet::Packet() - : m_groupBoundary(true) {} - Packet::Packet(bool groupBoundary) - : m_groupBoundary(groupBoundary) + Packet::Packet(EType type) + : m_type(type) {} - Packet::Packet(shared_ptr const & command, - bool groupBoundary) + Packet::Packet(shared_ptr const & command, EType type) : m_command(command), - m_groupBoundary(groupBoundary) + m_type(type) {} Packet::Packet(shared_ptr const & state, shared_ptr const & command, - bool groupBoundary) + EType type) : m_state(state), m_command(command), - m_groupBoundary(groupBoundary) + m_type(type) { if (m_state && m_command) m_state->m_isDebugging = m_command->isDebugging(); } - PacketsQueue::PacketsQueue() : m_fenceManager(10) + PacketsQueue::PacketsQueue() : m_fenceManager(5) {} - void PacketsQueue::markFrameBoundary() + void PacketsQueue::insertCheckPoint() { - PushBack(Packet(true)); + processPacket(Packet(Packet::ECheckPoint)); + } + + void PacketsQueue::insertCancelPoint() + { + processPacket(Packet(Packet::ECancelPoint)); } struct SignalFence : public Command @@ -74,12 +90,17 @@ namespace yg { m_fenceManager->signalFence(m_id); } + + void cancel() + { + perform(); + } }; int PacketsQueue::insertFence() { int id = m_fenceManager.insertFence(); - PushBack(Packet(make_shared_ptr(new SignalFence(id, &m_fenceManager)), true)); + processPacket(Packet(make_shared_ptr(new SignalFence(id, &m_fenceManager)), Packet::ECheckPoint)); return id; } @@ -92,5 +113,21 @@ namespace yg { joinFence(insertFence()); } + + void PacketsQueue::cancel() + { + Cancel(); + } + + void PacketsQueue::processPacket(Packet const & packet) + { + if (IsCancelled()) + { + if (packet.m_command) + packet.m_command->cancel(); + } + else + PushBack(packet); + } } } diff --git a/yg/packets_queue.hpp b/yg/packets_queue.hpp index 3598e16b56..afa9e9ad86 100644 --- a/yg/packets_queue.hpp +++ b/yg/packets_queue.hpp @@ -23,7 +23,10 @@ namespace yg struct Command { private: + bool m_isDebugging; + string m_name; + public: bool isDebugging() const; @@ -32,27 +35,36 @@ namespace yg Command(); virtual ~Command(); - virtual void perform() = 0; + virtual void perform(); + virtual void cancel(); friend class Renderer; }; struct Packet { - shared_ptr m_state; - shared_ptr m_command; - bool m_groupBoundary; + enum EType + { + ECommand, + ECheckPoint, + ECancelPoint + }; - explicit Packet(); + shared_ptr m_state; + shared_ptr m_command; + EType m_type; + + Packet(); /// empty packet act as a frame delimiter - explicit Packet(bool groupBoundary); + explicit Packet(EType type); /// non-opengl command, without any state - explicit Packet(shared_ptr const & command, - bool groupBoundary); + Packet(shared_ptr const & command, + EType type); /// opengl command with state - explicit Packet(shared_ptr const & state, - shared_ptr const & command, - bool groupBoundary); + Packet(shared_ptr const & state, + shared_ptr const & command, + EType type); + }; class PacketsQueue : public ThreadedList @@ -65,7 +77,11 @@ namespace yg PacketsQueue(); - void markFrameBoundary(); + void processPacket(Packet const & packet); + void cancel(); + + void insertCheckPoint(); + void insertCancelPoint(); int insertFence(); void joinFence(int id); diff --git a/yg/renderer.cpp b/yg/renderer.cpp index 3e78941582..536fcb0749 100644 --- a/yg/renderer.cpp +++ b/yg/renderer.cpp @@ -345,7 +345,7 @@ namespace yg return m_isDebugging; } - void Renderer::processCommand(shared_ptr const & command) + void Renderer::processCommand(shared_ptr const & command, Packet::EType type) { // command->m_isDebugging = false; command->m_isDebugging = renderQueue(); @@ -354,7 +354,7 @@ namespace yg { shared_ptr state = createState(); getState(state.get()); - m_renderQueue->PushBack(Packet(state, command, false)); + m_renderQueue->processPacket(Packet(state, command, type)); } else command->perform(); @@ -368,7 +368,7 @@ namespace yg void Renderer::markFrameBoundary() { if (m_renderQueue) - m_renderQueue->PushBack(Packet(true)); + m_renderQueue->processPacket(Packet(Packet::ECheckPoint)); } } } diff --git a/yg/renderer.hpp b/yg/renderer.hpp index 9ec307cf7d..b5e1b59f49 100644 --- a/yg/renderer.hpp +++ b/yg/renderer.hpp @@ -120,7 +120,7 @@ namespace yg virtual void getState(BaseState * state); - void processCommand(shared_ptr const & command); + void processCommand(shared_ptr const & command, Packet::EType type = Packet::ECommand); PacketsQueue * renderQueue(); /// insert empty packet into glQueue to mark the frame boundary diff --git a/yg/skin_page.cpp b/yg/skin_page.cpp index b347c09225..a018d4e66f 100644 --- a/yg/skin_page.cpp +++ b/yg/skin_page.cpp @@ -361,6 +361,10 @@ namespace yg static_cast(m_texture.get())->unlock(); } + void SkinPage::UploadData::cancel() + { + perform(); + } void SkinPage::uploadData(yg::gl::PacketsQueue * glQueue) { @@ -371,7 +375,7 @@ namespace yg shared_ptr cmd(new UploadData(m_uploadQueue, m_texture)); if (glQueue) - glQueue->PushBack(yg::gl::Packet(cmd, false)); + glQueue->processPacket(yg::gl::Packet(cmd, yg::gl::Packet::ECommand)); else cmd->perform(); diff --git a/yg/skin_page.hpp b/yg/skin_page.hpp index 71baf998bb..7ff571a877 100644 --- a/yg/skin_page.hpp +++ b/yg/skin_page.hpp @@ -107,6 +107,7 @@ namespace yg shared_ptr const & texture); void perform(); + void cancel(); }; void clearColorHandles(); diff --git a/yg/styles_cache.cpp b/yg/styles_cache.cpp index 91fe3c4830..f8be0c2703 100644 --- a/yg/styles_cache.cpp +++ b/yg/styles_cache.cpp @@ -55,7 +55,7 @@ namespace yg m_cachePage->uploadData(m_glQueue); if (m_glQueue) - m_glQueue->PushBack(yg::gl::Packet(make_shared_ptr(new yg::gl::Renderer::FinishCommand()), false)); + m_glQueue->processPacket(yg::gl::Packet(make_shared_ptr(new yg::gl::Renderer::FinishCommand()), yg::gl::Packet::ECommand)); /// waiting for upload to complete if (m_glQueue)