diff --git a/drape/CMakeLists.txt b/drape/CMakeLists.txt index 4cc46e6093..c5fc48816d 100644 --- a/drape/CMakeLists.txt +++ b/drape/CMakeLists.txt @@ -40,6 +40,7 @@ set( ${DRAPE_ROOT}/data_buffer_impl.hpp ${DRAPE_ROOT}/debug_rect_renderer.cpp ${DRAPE_ROOT}/debug_rect_renderer.hpp + ${DRAPE_ROOT}/drape_diagnostics.hpp ${DRAPE_ROOT}/drape_global.hpp ${DRAPE_ROOT}/dynamic_texture.hpp ${DRAPE_ROOT}/font_texture.cpp diff --git a/drape/debug_rect_renderer.hpp b/drape/debug_rect_renderer.hpp index 19e0ef5820..2c98279bf4 100644 --- a/drape/debug_rect_renderer.hpp +++ b/drape/debug_rect_renderer.hpp @@ -1,5 +1,7 @@ #pragma once +#include "drape/drape_diagnostics.hpp" + #include "drape/gpu_program_manager.hpp" #include "drape/overlay_tree.hpp" #include "drape/pointers.hpp" @@ -7,8 +9,6 @@ #include "geometry/rect2d.hpp" #include "geometry/screenbase.hpp" -//#define RENDER_DEBUG_RECTS - namespace dp { @@ -39,3 +39,4 @@ private: }; } // namespace dp + diff --git a/drape/drape_common.pri b/drape/drape_common.pri index 132d156d30..eb987ee144 100644 --- a/drape/drape_common.pri +++ b/drape/drape_common.pri @@ -66,6 +66,7 @@ HEADERS += \ $$DRAPE_DIR/data_buffer.hpp \ $$DRAPE_DIR/data_buffer_impl.hpp \ $$DRAPE_DIR/debug_rect_renderer.hpp \ + $$DRAPE_DIR/drape_diagnostics.hpp \ $$DRAPE_DIR/drape_global.hpp \ $$DRAPE_DIR/dynamic_texture.hpp \ $$DRAPE_DIR/font_texture.hpp \ diff --git a/drape/drape_diagnostics.hpp b/drape/drape_diagnostics.hpp new file mode 100644 index 0000000000..d8fc2a5a9b --- /dev/null +++ b/drape/drape_diagnostics.hpp @@ -0,0 +1,19 @@ +#pragma once + +//#define DRAW_TILE_NET +//#define RENDER_DEBUG_RECTS +//#define COLLECT_DISPLACEMENT_INFO + +//#define DRAPE_MEASURER +//#define SCENARIO_ENABLE + +#ifdef DRAPE_MEASURER + +//#define RENDER_STATISTIC +//#define TILES_STATISTIC +//#define GENERATING_STATISTIC + +//#define TRACK_GPU_MEM +//#define TRACK_GLYPH_USAGE + +#endif diff --git a/drape/overlay_tree.hpp b/drape/overlay_tree.hpp index ef669d1a7b..061540efb3 100644 --- a/drape/overlay_tree.hpp +++ b/drape/overlay_tree.hpp @@ -1,5 +1,6 @@ #pragma once +#include "drape/drape_diagnostics.hpp" #include "drape/overlay_handle.hpp" #include "geometry/screenbase.hpp" @@ -14,8 +15,6 @@ namespace dp { -//#define COLLECT_DISPLACEMENT_INFO - namespace detail { diff --git a/drape/utils/glyph_usage_tracker.cpp b/drape/utils/glyph_usage_tracker.cpp index b4d4a0f67b..0713944df7 100644 --- a/drape/utils/glyph_usage_tracker.cpp +++ b/drape/utils/glyph_usage_tracker.cpp @@ -9,18 +9,10 @@ namespace dp { -GlyphUsageTracker & GlyphUsageTracker::Instance() +string GlyphUsageTracker::GlyphUsageStatistic::ToString() const { - static GlyphUsageTracker s_inst; - return s_inst; -} - -string GlyphUsageTracker::Report() -{ - lock_guard lock(m_mutex); - ostringstream ss; - ss << "\n ===== Glyphs Usage Report ===== \n"; + ss << " ----- Glyphs usage report ----- \n"; ss << " Current language = " << languages::GetCurrentOrig() << "\n"; ss << " Invalid glyphs count = " << m_invalidGlyphs.size() << "\n"; ss << " Invalid glyphs: { "; @@ -40,11 +32,23 @@ string GlyphUsageTracker::Report() ss << "}\n"; } ss << " }\n"; - ss << " ===== Glyphs Usage Report ===== \n"; + ss << " ----- Glyphs usage report ----- \n"; return ss.str(); } +GlyphUsageTracker & GlyphUsageTracker::Instance() +{ + static GlyphUsageTracker s_inst; + return s_inst; +} + +GlyphUsageTracker::GlyphUsageStatistic GlyphUsageTracker::Report() +{ + lock_guard lock(m_mutex); + return m_glyphStat; +} + void GlyphUsageTracker::AddInvalidGlyph(strings::UniString const & str, strings::UniChar const & c) { lock_guard lock(m_mutex); @@ -52,7 +56,7 @@ void GlyphUsageTracker::AddInvalidGlyph(strings::UniString const & str, strings: if (m_processedStrings.find(strings::ToUtf8(str)) != m_processedStrings.end()) return; - ++m_invalidGlyphs[c]; + ++m_glyphStat.m_invalidGlyphs[c]; m_processedStrings.insert(strings::ToUtf8(str)); } @@ -65,7 +69,7 @@ void GlyphUsageTracker::AddUnexpectedGlyph(strings::UniString const & str, strin if (m_processedStrings.find(strings::ToUtf8(str)) != m_processedStrings.end()) return; - UnexpectedGlyphData & data = m_unexpectedGlyphs[c]; + UnexpectedGlyphData & data = m_glyphStat.m_unexpectedGlyphs[c]; ++data.m_counter; data.m_expectedGroups.emplace(expectedGroup); data.m_group = group; diff --git a/drape/utils/glyph_usage_tracker.hpp b/drape/utils/glyph_usage_tracker.hpp index 8555265e09..ee92268ef2 100644 --- a/drape/utils/glyph_usage_tracker.hpp +++ b/drape/utils/glyph_usage_tracker.hpp @@ -1,5 +1,7 @@ #pragma once +#include "drape/drape_diagnostics.hpp" + #include "base/string_utils.hpp" #include "std/map.hpp" @@ -9,31 +11,12 @@ #include "std/string.hpp" #include "std/unordered_set.hpp" -//#define TRACK_GLYPH_USAGE - namespace dp { class GlyphUsageTracker { public: - static GlyphUsageTracker & Instance(); - - void AddInvalidGlyph(strings::UniString const & str, strings::UniChar const & c); - void AddUnexpectedGlyph(strings::UniString const & str, strings::UniChar const & c, - size_t const group, size_t const expectedGroup); - - string Report(); - -private: - GlyphUsageTracker() = default; - GlyphUsageTracker(GlyphUsageTracker const & rhs) = delete; - GlyphUsageTracker(GlyphUsageTracker && rhs) = delete; - -private: - using InvalidGlyphs = map; - InvalidGlyphs m_invalidGlyphs; - struct UnexpectedGlyphData { size_t m_counter = 0; @@ -41,8 +24,31 @@ private: set m_expectedGroups; }; using UnexpectedGlyphs = map; - UnexpectedGlyphs m_unexpectedGlyphs; + using InvalidGlyphs = map; + struct GlyphUsageStatistic + { + string ToString() const; + + InvalidGlyphs m_invalidGlyphs; + UnexpectedGlyphs m_unexpectedGlyphs; + }; + + static GlyphUsageTracker & Instance(); + + void AddInvalidGlyph(strings::UniString const & str, strings::UniChar const & c); + void AddUnexpectedGlyph(strings::UniString const & str, strings::UniChar const & c, + size_t const group, size_t const expectedGroup); + + GlyphUsageStatistic Report(); + +private: + GlyphUsageTracker() = default; + GlyphUsageTracker(GlyphUsageTracker const & rhs) = delete; + GlyphUsageTracker(GlyphUsageTracker && rhs) = delete; + +private: + GlyphUsageStatistic m_glyphStat; unordered_set m_processedStrings; mutex m_mutex; diff --git a/drape/utils/gpu_mem_tracker.cpp b/drape/utils/gpu_mem_tracker.cpp index 7aa95c2021..2c477440c4 100644 --- a/drape/utils/gpu_mem_tracker.cpp +++ b/drape/utils/gpu_mem_tracker.cpp @@ -6,50 +6,58 @@ namespace dp { +string GPUMemTracker::GPUMemorySnapshot::ToString() const +{ + ostringstream ss; + ss << " Summary Allocated = " << m_summaryAllocatedInMb << "Mb\n"; + ss << " Summary Used = " << m_summaryUsedInMb << "Mb\n"; + ss << " Tags registered = " << m_tagStats.size() << "\n"; + + for (auto const it : m_tagStats) + { + ss << " Tag = " << it.first << " \n"; + ss << " Object count = " << it.second.m_objectsCount << "\n"; + ss << " Allocated = " << it.second.m_alocatedInMb << "Mb\n"; + ss << " Used = " << it.second.m_usedInMb << "Mb\n"; + } + + return ss.str(); +} + GPUMemTracker & GPUMemTracker::Inst() { static GPUMemTracker s_inst; return s_inst; } -string GPUMemTracker::Report() +GPUMemTracker::GPUMemorySnapshot GPUMemTracker::GetMemorySnapshot() { - uint32_t summaryUsed = 0; - uint32_t summaryAllocated = 0; + GPUMemorySnapshot memStat; - typedef tuple TTagStat; - map tagStats; - - for (auto const it : m_memTracker) { - TTagStat & stat = tagStats[it.first.first]; - get<0>(stat)++; - get<1>(stat) += it.second.first; - get<2>(stat) += it.second.second; + threads::MutexGuard g(m_mutex); + for (auto const it : m_memTracker) + { + TagMemorySnapshot & tagStat = memStat.m_tagStats[it.first.first]; + tagStat.m_objectsCount++; + tagStat.m_alocatedInMb += it.second.first; + tagStat.m_usedInMb += it.second.second; - summaryAllocated += it.second.first; - summaryUsed += it.second.second; + memStat.m_summaryAllocatedInMb += it.second.first; + memStat.m_summaryUsedInMb += it.second.second; + } } float byteToMb = static_cast(1024 * 1024); - - ostringstream ss; - ss << " ===== Mem Report ===== \n"; - ss << " Summary Allocated = " << summaryAllocated / byteToMb << "\n"; - ss << " Summary Used = " << summaryUsed / byteToMb << "\n"; - ss << " Tags registered = " << tagStats.size() << "\n"; - - for (auto const it : tagStats) + for (auto & it : memStat.m_tagStats) { - ss << " Tag = " << it.first << " \n"; - ss << " Object count = " << get<0>(it.second) << "\n"; - ss << " Allocated = " << get<1>(it.second) / byteToMb << "\n"; - ss << " Used = " << get<2>(it.second) / byteToMb << "\n"; + it.second.m_alocatedInMb /= byteToMb; + it.second.m_usedInMb /= byteToMb; } + memStat.m_summaryAllocatedInMb /= byteToMb; + memStat.m_summaryUsedInMb /= byteToMb; - ss << " ===== Mem Report ===== \n"; - - return ss.str(); + return memStat; } void GPUMemTracker::AddAllocated(string const & tag, uint32_t id, uint32_t size) @@ -63,7 +71,7 @@ void GPUMemTracker::SetUsed(string const & tag, uint32_t id, uint32_t size) threads::MutexGuard g(m_mutex); TAlocUsedMem & node = m_memTracker[make_pair(tag, id)]; node.second = size; - ASSERT_LESS_OR_EQUAL(node.second, node.first, ("Can't use more then allocated")); + ASSERT_LESS_OR_EQUAL(node.second, node.first, ("Can't use more than allocated")); } void GPUMemTracker::RemoveDeallocated(string const & tag, uint32_t id) diff --git a/drape/utils/gpu_mem_tracker.hpp b/drape/utils/gpu_mem_tracker.hpp index eb350f9f22..724bd2c6ac 100644 --- a/drape/utils/gpu_mem_tracker.hpp +++ b/drape/utils/gpu_mem_tracker.hpp @@ -1,5 +1,7 @@ #pragma once +#include "drape/drape_diagnostics.hpp" + #include "base/mutex.hpp" #include "std/map.hpp" @@ -7,18 +9,32 @@ #include "std/string.hpp" #include "std/utility.hpp" - -//#define TRACK_GPU_MEM - namespace dp { class GPUMemTracker : private noncopyable { public: + struct TagMemorySnapshot + { + uint32_t m_objectsCount = 0; + uint32_t m_alocatedInMb = 0; + uint32_t m_usedInMb = 0; + }; + + struct GPUMemorySnapshot + { + string ToString() const; + + uint32_t m_summaryAllocatedInMb = 0; + uint32_t m_summaryUsedInMb = 0; + map m_tagStats; + }; + static GPUMemTracker & Inst(); - string Report(); + GPUMemorySnapshot GetMemorySnapshot(); + void AddAllocated(string const & tag, uint32_t id, uint32_t size); void SetUsed(string const & tag, uint32_t id, uint32_t size); void RemoveDeallocated(string const & tag, uint32_t id); diff --git a/drape_frontend/CMakeLists.txt b/drape_frontend/CMakeLists.txt index 8195ee30df..8cae36a799 100644 --- a/drape_frontend/CMakeLists.txt +++ b/drape_frontend/CMakeLists.txt @@ -69,6 +69,8 @@ set( drape_api_renderer.hpp drape_engine.cpp drape_engine.hpp + drape_measurer.cpp + drape_measurer.hpp engine_context.cpp engine_context.hpp framebuffer.cpp @@ -150,6 +152,8 @@ set( route_shape.hpp rule_drawer.cpp rule_drawer.hpp + scenario_manager.cpp + scenario_manager.hpp screen_animations.cpp screen_animations.hpp screen_operations.cpp diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index 0d4d4ba2de..aafe232c2e 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -3,6 +3,7 @@ #include "drape_frontend/backend_renderer.hpp" #include "drape_frontend/batchers_pool.hpp" #include "drape_frontend/drape_api_builder.hpp" +#include "drape_frontend/drape_measurer.hpp" #include "drape_frontend/gps_track_shape.hpp" #include "drape_frontend/map_shape.hpp" #include "drape_frontend/message_subclasses.hpp" @@ -204,11 +205,17 @@ void BackendRenderer::AcceptMessage(ref_ptr message) if (m_requestedTiles->CheckTileKey(tileKey) && m_readManager->CheckTileKey(tileKey)) { ref_ptr batcher = m_batchersPool->GetBatcher(tileKey); +#if defined(DRAPE_MEASURER) && defined(GENERATING_STATISTIC) + DrapeMeasurer::Instance().StartShapesGeneration(); +#endif for (drape_ptr const & shape : msg->GetShapes()) { batcher->SetFeatureMinZoom(shape->GetFeatureMinZoom()); shape->Draw(batcher, m_texMng); } +#if defined(DRAPE_MEASURER) && defined(GENERATING_STATISTIC) + DrapeMeasurer::Instance().EndShapesGeneration(static_cast(msg->GetShapes().size())); +#endif } break; } @@ -221,6 +228,9 @@ void BackendRenderer::AcceptMessage(ref_ptr message) { CleanupOverlays(tileKey); +#if defined(DRAPE_MEASURER) && defined(GENERATING_STATISTIC) + DrapeMeasurer::Instance().StartOverlayShapesGeneration(); +#endif OverlayBatcher batcher(tileKey); for (drape_ptr const & shape : msg->GetShapes()) batcher.Batch(shape, m_texMng); @@ -232,6 +242,11 @@ void BackendRenderer::AcceptMessage(ref_ptr message) m_overlays.reserve(m_overlays.size() + renderData.size()); move(renderData.begin(), renderData.end(), back_inserter(m_overlays)); } + +#if defined(DRAPE_MEASURER) && defined(GENERATING_STATISTIC) + DrapeMeasurer::Instance().EndOverlayShapesGeneration( + static_cast(msg->GetShapes().size())); +#endif } break; } diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index 4f8e2c899d..3edb8a5d4b 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -574,4 +574,13 @@ void DrapeEngine::SetFontScaleFactor(double scaleFactor) VisualParams::Instance().SetFontScale(scaleFactor); } +void DrapeEngine::RunScenario(ScenarioManager::ScenarioData && scenarioData, + ScenarioManager::ScenarioCallback const & onStartFn, + ScenarioManager::ScenarioCallback const & onFinishFn) +{ + auto const & manager = m_frontend->GetScenarioManager(); + if (manager != nullptr) + manager->RunScenario(move(scenarioData), onStartFn, onFinishFn); +} + } // namespace df diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp index 381f3f0a4e..2e42ba7a55 100644 --- a/drape_frontend/drape_engine.hpp +++ b/drape_frontend/drape_engine.hpp @@ -4,6 +4,7 @@ #include "drape_frontend/color_constants.hpp" #include "drape_frontend/frontend_renderer.hpp" #include "drape_frontend/route_shape.hpp" +#include "drape_frontend/scenario_manager.hpp" #include "drape_frontend/selection_shape.hpp" #include "drape_frontend/threads_commutator.hpp" @@ -176,6 +177,10 @@ public: void SetFontScaleFactor(double scaleFactor); + void RunScenario(ScenarioManager::ScenarioData && scenarioData, + ScenarioManager::ScenarioCallback const & onStartFn, + ScenarioManager::ScenarioCallback const & onFinishFn); + private: void AddUserEvent(drape_ptr && e); void ModelViewChanged(ScreenBase const & screen); @@ -188,7 +193,6 @@ private: void RecacheGui(bool needResetOldGui); void RecacheMapShapes(); -private: drape_ptr m_frontend; drape_ptr m_backend; drape_ptr m_threadCommutator; diff --git a/drape_frontend/drape_frontend.pro b/drape_frontend/drape_frontend.pro index b65e2f9ce9..6f2e85a753 100755 --- a/drape_frontend/drape_frontend.pro +++ b/drape_frontend/drape_frontend.pro @@ -8,7 +8,6 @@ include($$ROOT_DIR/common.pri) INCLUDEPATH *= $$ROOT_DIR/3party/protobuf/src INCLUDEPATH *= $$ROOT_DIR/3party/expat/lib INCLUDEPATH *= $$ROOT_DIR/3party/freetype/include -#DEFINES += DRAW_INFO SOURCES += \ $$ROOT_DIR/3party/agg/agg_curves.cpp \ @@ -50,6 +49,7 @@ SOURCES += \ drape_api_builder.cpp \ drape_api_renderer.cpp \ drape_engine.cpp \ + drape_measurer.cpp \ engine_context.cpp \ framebuffer.cpp \ frontend_renderer.cpp \ @@ -76,6 +76,7 @@ SOURCES += \ route_renderer.cpp \ route_shape.cpp \ rule_drawer.cpp \ + scenario_manager.cpp \ screen_animations.cpp \ screen_operations.cpp \ selection_shape.cpp \ @@ -149,6 +150,7 @@ HEADERS += \ drape_api_builder.hpp \ drape_api_renderer.hpp \ drape_engine.hpp \ + drape_measurer.hpp \ engine_context.hpp \ framebuffer.hpp \ frontend_renderer.hpp \ @@ -180,6 +182,7 @@ HEADERS += \ route_renderer.hpp \ route_shape.hpp \ rule_drawer.hpp \ + scenario_manager.hpp \ screen_animations.hpp \ screen_operations.hpp \ selection_shape.hpp \ diff --git a/drape_frontend/drape_measurer.cpp b/drape_frontend/drape_measurer.cpp new file mode 100644 index 0000000000..18f95cbeb3 --- /dev/null +++ b/drape_frontend/drape_measurer.cpp @@ -0,0 +1,417 @@ +#include "drape_measurer.hpp" + +namespace df +{ + +DrapeMeasurer & DrapeMeasurer::Instance() +{ + static DrapeMeasurer s_inst; + return s_inst; +} + +void DrapeMeasurer::StartBenchmark() +{ + using namespace std::chrono; + m_isEnabled = true; + + auto currentTime = std::chrono::steady_clock::now(); + +#ifdef GENERATING_STATISTIC + m_startScenePreparingTime = currentTime; + m_maxScenePreparingTime = steady_clock::duration::zero(); + + m_startShapesGenTime = currentTime; + m_totalShapesGenTime = steady_clock::duration::zero(); + m_totalShapesCount = 0; + + m_startOverlayShapesGenTime = currentTime; + m_totalOverlayShapesGenTime = steady_clock::duration::zero(); + m_totalOverlayShapesCount = 0; +#endif + +#ifdef TILES_STATISTIC + { + lock_guard lock(m_tilesMutex); + m_tilesReadInfo.clear(); + } +#endif + +#ifdef RENDER_STATISTIC + m_totalTPF = steady_clock::duration::zero(); + m_totalTPFCount = 0; + + m_minFPS = std::numeric_limits::max(); + m_totalFPS = 0.0; + m_totalFPSCount = 0; +#endif + +#if defined(RENDER_STATISTIC) || defined(TRACK_GPU_MEM) + m_startFrameRenderTime = currentTime; + m_totalFrameRenderTime = steady_clock::duration::zero(); + m_totalFramesCount = 0; +#endif + +#ifdef TRACK_GPU_MEM + m_maxSnapshotValues = dp::GPUMemTracker::GPUMemorySnapshot(); + m_summarySnapshotValues = dp::GPUMemTracker::GPUMemorySnapshot(); + m_numberOfSnapshots = 0; +#endif +} + +void DrapeMeasurer::StopBenchmark() +{ + m_isEnabled = false; +} + +#ifdef GENERATING_STATISTIC +void DrapeMeasurer::StartScenePreparing() +{ + if (!m_isEnabled) + return; + + m_startScenePreparingTime = std::chrono::steady_clock::now(); +} + +void DrapeMeasurer::EndScenePreparing() +{ + if (!m_isEnabled) + return; + + m_maxScenePreparingTime = max(m_maxScenePreparingTime, + std::chrono::steady_clock::now() - m_startScenePreparingTime); +} + +void DrapeMeasurer::StartShapesGeneration() +{ + m_startShapesGenTime = std::chrono::steady_clock::now(); +} + +void DrapeMeasurer::EndShapesGeneration(uint32_t shapesCount) +{ + m_totalShapesGenTime += std::chrono::steady_clock::now() - m_startShapesGenTime; + m_totalShapesCount += shapesCount; +} + +void DrapeMeasurer::StartOverlayShapesGeneration() +{ + m_startOverlayShapesGenTime = std::chrono::steady_clock::now(); +} + +void DrapeMeasurer::EndOverlayShapesGeneration(uint32_t shapesCount) +{ + m_totalOverlayShapesGenTime += std::chrono::steady_clock::now() - m_startOverlayShapesGenTime; + m_totalOverlayShapesCount += shapesCount; +} + +std::string DrapeMeasurer::GeneratingStatistic::ToString() const +{ + std::ostringstream ss; + ss << " ----- Generation statistic report ----- \n"; + ss << " Max scene preparing time, ms = " << m_maxScenePreparingTimeInMs << "\n"; + ss << " Shapes total generation time, ms = " << m_shapeGenTimeInMs << "\n"; + ss << " Shapes total count = " << m_shapesCount + << ", (" << static_cast(m_shapeGenTimeInMs) / m_shapesCount << " ms per shape)\n"; + ss << " Overlay shapes total generation time, ms = " << m_overlayShapeGenTimeInMs << "\n"; + ss << " Overlay shapes total count = " << m_overlayShapesCount + << ", (" << static_cast(m_overlayShapeGenTimeInMs) / m_overlayShapesCount << " ms per overlay)\n"; + ss << " ----- Generation statistic report ----- \n"; + + return ss.str(); +} + +DrapeMeasurer::GeneratingStatistic DrapeMeasurer::GetGeneratingStatistic() +{ + using namespace std::chrono; + + GeneratingStatistic statistic; + statistic.m_shapesCount = m_totalShapesCount; + statistic.m_shapeGenTimeInMs = + static_cast(duration_cast(m_totalShapesGenTime).count()); + + statistic.m_overlayShapesCount = m_totalOverlayShapesCount; + statistic.m_overlayShapeGenTimeInMs = + static_cast(duration_cast(m_totalOverlayShapesGenTime).count()); + + statistic.m_maxScenePreparingTimeInMs = + static_cast(duration_cast(m_maxScenePreparingTime).count()); + + return statistic; +} + +#endif + +#ifdef RENDER_STATISTIC +std::string DrapeMeasurer::RenderStatistic::ToString() const +{ + std::ostringstream ss; + ss << " ----- Render statistic report ----- \n"; + ss << " FPS = " << m_FPS << "\n"; + ss << " min FPS = " << m_minFPS << "\n"; + ss << " Frame render time, ms = " << m_frameRenderTimeInMs << "\n"; + ss << " ----- Render statistic report ----- \n"; + + return ss.str(); +} + +DrapeMeasurer::RenderStatistic DrapeMeasurer::GetRenderStatistic() +{ + using namespace std::chrono; + + RenderStatistic statistic; + statistic.m_FPS = m_totalFPS / m_totalFPSCount; + statistic.m_minFPS = m_minFPS; + statistic.m_frameRenderTimeInMs = + static_cast(duration_cast(m_totalTPF).count()) / m_totalTPFCount; + + return statistic; +} +#endif + +#if defined(RENDER_STATISTIC) || defined(TRACK_GPU_MEM) +void DrapeMeasurer::BeforeRenderFrame() +{ + if (!m_isEnabled) + return; + + m_startFrameRenderTime = std::chrono::steady_clock::now(); +} + +void DrapeMeasurer::AfterRenderFrame() +{ + using namespace std::chrono; + + if (!m_isEnabled) + return; + + ++m_totalFramesCount; + m_totalFrameRenderTime += steady_clock::now() - m_startFrameRenderTime; + + auto elapsed = duration_cast(m_totalFrameRenderTime).count(); + if (elapsed > 1000) + { +#ifdef RENDER_STATISTIC + double fps = m_totalFramesCount * 1000.0 / elapsed; + m_minFPS = std::min(m_minFPS, static_cast(fps)); + + m_totalFPS += fps; + ++m_totalFPSCount; + + m_totalTPF += m_totalFrameRenderTime / m_totalFramesCount; + ++m_totalTPFCount; +#endif + + m_totalFramesCount = 0; + m_totalFrameRenderTime = steady_clock::duration::zero(); + +#ifdef TRACK_GPU_MEM + TakeGPUMemorySnapshot(); +#endif + } +} +#endif + +#ifdef TILES_STATISTIC +std::string DrapeMeasurer::TileStatistic::ToString() const +{ + std::ostringstream ss; + ss << " ----- Tiles read statistic report ----- \n"; + ss << " Tile read time, ms = " << m_tileReadTimeInMs << "\n"; + ss << " Tiles count = " << m_totalTilesCount << "\n"; + ss << " ----- Tiles read statistic report ----- \n"; + + return ss.str(); +} + +void DrapeMeasurer::StartTileReading() +{ + if (!m_isEnabled) + return; + + threads::ThreadID tid = threads::GetCurrentThreadID(); + std::shared_ptr tileInfo; + { + lock_guard lock(m_tilesMutex); + auto const it = m_tilesReadInfo.find(tid); + if (it != m_tilesReadInfo.end()) + { + tileInfo = it->second; + } + else + { + tileInfo = std::make_shared(); + m_tilesReadInfo.insert(make_pair(tid, tileInfo)); + } + } + + auto const currentTime = std::chrono::steady_clock::now(); + tileInfo->m_startTileReadTime = currentTime; +} + +void DrapeMeasurer::EndTileReading() +{ + if (!m_isEnabled) + return; + + auto const currentTime = std::chrono::steady_clock::now(); + + threads::ThreadID tid = threads::GetCurrentThreadID(); + std::shared_ptr tileInfo; + { + lock_guard lock(m_tilesMutex); + auto const it = m_tilesReadInfo.find(tid); + if (it != m_tilesReadInfo.end()) + tileInfo = it->second; + else + return; + } + + auto passedTime = currentTime - tileInfo->m_startTileReadTime; + tileInfo->m_totalTileReadTime += passedTime; + ++tileInfo->m_totalTilesCount; +} + +DrapeMeasurer::TileStatistic DrapeMeasurer::GetTileStatistic() +{ + using namespace std::chrono; + TileStatistic statistic; + { + lock_guard lock(m_tilesMutex); + for (auto const & it : m_tilesReadInfo) + { + statistic.m_tileReadTimeInMs += + static_cast(duration_cast(it.second->m_totalTileReadTime).count()); + statistic.m_totalTilesCount += it.second->m_totalTilesCount; + } + } + if (statistic.m_totalTilesCount > 0) + statistic.m_tileReadTimeInMs /= statistic.m_totalTilesCount; + + return statistic; +} +#endif + +#ifdef TRACK_GPU_MEM +std::string DrapeMeasurer::GPUMemoryStatistic::ToString() const +{ + std::ostringstream ss; + ss << " ----- GPU memory report ----- \n"; + ss << " --Max memory values:\n"; + ss << m_maxMemoryValues.ToString(); + ss << "\n --Average memory values:\n"; + ss << m_averageMemoryValues.ToString(); + ss << " ----- GPU memory report ----- \n"; + + return ss.str(); +} + +void DrapeMeasurer::TakeGPUMemorySnapshot() +{ + dp::GPUMemTracker::GPUMemorySnapshot snap = dp::GPUMemTracker::Inst().GetMemorySnapshot(); + for (auto const & tagPair : snap.m_tagStats) + { + auto itMax = m_maxSnapshotValues.m_tagStats.find(tagPair.first); + if (itMax != m_maxSnapshotValues.m_tagStats.end()) + { + itMax->second.m_objectsCount = std::max(itMax->second.m_objectsCount, + tagPair.second.m_objectsCount); + itMax->second.m_alocatedInMb = std::max(itMax->second.m_alocatedInMb, + tagPair.second.m_alocatedInMb); + itMax->second.m_usedInMb = std::max(itMax->second.m_alocatedInMb, + tagPair.second.m_usedInMb); + } + else + { + m_maxSnapshotValues.m_tagStats.insert(tagPair); + } + + auto itSummary = m_summarySnapshotValues.m_tagStats.find(tagPair.first); + if (itSummary != m_summarySnapshotValues.m_tagStats.end()) + { + itSummary->second.m_objectsCount += tagPair.second.m_objectsCount; + itSummary->second.m_alocatedInMb += tagPair.second.m_alocatedInMb; + itSummary->second.m_usedInMb += tagPair.second.m_usedInMb; + } + else + { + m_summarySnapshotValues.m_tagStats.insert(tagPair); + } + } + + m_maxSnapshotValues.m_summaryAllocatedInMb = std::max(snap.m_summaryAllocatedInMb, + m_maxSnapshotValues.m_summaryAllocatedInMb); + m_maxSnapshotValues.m_summaryUsedInMb = std::max(snap.m_summaryUsedInMb, + m_maxSnapshotValues.m_summaryUsedInMb); + + m_summarySnapshotValues.m_summaryAllocatedInMb += snap.m_summaryAllocatedInMb; + m_summarySnapshotValues.m_summaryUsedInMb += snap.m_summaryUsedInMb; + + ++m_numberOfSnapshots; +} + +DrapeMeasurer::GPUMemoryStatistic DrapeMeasurer::GetGPUMemoryStatistic() +{ + GPUMemoryStatistic statistic; + statistic.m_maxMemoryValues = m_maxSnapshotValues; + + statistic.m_averageMemoryValues = m_summarySnapshotValues; + if (m_numberOfSnapshots > 0) + { + for (auto & tagPair : statistic.m_averageMemoryValues.m_tagStats) + { + tagPair.second.m_objectsCount /= m_numberOfSnapshots; + tagPair.second.m_alocatedInMb /= m_numberOfSnapshots; + tagPair.second.m_usedInMb /= m_numberOfSnapshots; + } + statistic.m_averageMemoryValues.m_summaryAllocatedInMb /= m_numberOfSnapshots; + statistic.m_averageMemoryValues.m_summaryUsedInMb /= m_numberOfSnapshots; + } + return statistic; +} +#endif + +std::string DrapeMeasurer::DrapeStatistic::ToString() const +{ + std::ostringstream ss; + ss << "\n ===== Drape statistic report ===== \n"; +#ifdef RENDER_STATISTIC + ss << "\n" << m_renderStatistic.ToString() << "\n"; +#endif +#ifdef TILES_STATISTIC + ss << "\n" << m_tileStatistic.ToString() << "\n"; +#endif +#ifdef GENERATING_STATISTIC + ss << "\n" << m_generatingStatistic.ToString() << "\n"; +#endif +#ifdef TRACK_GPU_MEM + ss << "\n" << m_gpuMemStatistic.ToString() << "\n"; +#endif +#ifdef TRACK_GLYPH_USAGE + ss << "\n" << m_glyphStatistic.ToString() << "\n"; +#endif + ss << "\n ===== Drape statistic report ===== \n\n"; + + return ss.str(); +} + +DrapeMeasurer::DrapeStatistic DrapeMeasurer::GetDrapeStatistic() +{ + DrapeStatistic statistic; +#ifdef RENDER_STATISTIC + statistic.m_renderStatistic = GetRenderStatistic(); +#endif +#ifdef TILES_STATISTIC + statistic.m_tileStatistic = GetTileStatistic(); +#endif +#ifdef GENERATING_STATISTIC + statistic.m_generatingStatistic = GetGeneratingStatistic(); +#endif +#ifdef TRACK_GPU_MEM + statistic.m_gpuMemStatistic = GetGPUMemoryStatistic(); +#endif +#ifdef TRACK_GLYPH_USAGE + statistic.m_glyphStatistic = dp::GlyphUsageTracker::Instance().Report(); +#endif + return statistic; +} + +} // namespace df diff --git a/drape_frontend/drape_measurer.hpp b/drape_frontend/drape_measurer.hpp new file mode 100644 index 0000000000..b64d46e1ee --- /dev/null +++ b/drape_frontend/drape_measurer.hpp @@ -0,0 +1,175 @@ +#pragma once + +#include "drape/drape_diagnostics.hpp" +#include "drape/utils/gpu_mem_tracker.hpp" +#include "drape/utils/glyph_usage_tracker.hpp" + +#include "base/thread.hpp" +#include "base/timer.hpp" + +#include +#include +#include +#include +#include +#include + +namespace df +{ + +class DrapeMeasurer +{ +public: + static DrapeMeasurer & Instance(); + + void StartBenchmark(); + void StopBenchmark(); + +#ifdef RENDER_STATISTIC + struct RenderStatistic + { + std::string ToString() const; + + uint32_t m_FPS = 0; + uint32_t m_minFPS = 0; + uint32_t m_frameRenderTimeInMs = 0; + }; + + RenderStatistic GetRenderStatistic(); +#endif + +#ifdef TILES_STATISTIC + struct TileStatistic + { + std::string ToString() const; + + uint32_t m_totalTilesCount = 0; + uint32_t m_tileReadTimeInMs = 0; + }; + + void StartTileReading(); + void EndTileReading(); + + TileStatistic GetTileStatistic(); +#endif + +#ifdef GENERATING_STATISTIC + struct GeneratingStatistic + { + std::string ToString() const; + + uint32_t m_maxScenePreparingTimeInMs = 0; + + uint32_t m_shapesCount = 0; + uint32_t m_shapeGenTimeInMs = 0; + + uint32_t m_overlayShapesCount = 0; + uint32_t m_overlayShapeGenTimeInMs = 0; + }; + + void StartScenePreparing(); + void EndScenePreparing(); + + void StartShapesGeneration(); + void EndShapesGeneration(uint32_t shapesCount); + + void StartOverlayShapesGeneration(); + void EndOverlayShapesGeneration(uint32_t shapesCount); + + GeneratingStatistic GetGeneratingStatistic(); +#endif + +#ifdef TRACK_GPU_MEM + struct GPUMemoryStatistic + { + std::string ToString() const; + + dp::GPUMemTracker::GPUMemorySnapshot m_averageMemoryValues; + dp::GPUMemTracker::GPUMemorySnapshot m_maxMemoryValues; + }; + + GPUMemoryStatistic GetGPUMemoryStatistic(); +#endif + +#if defined(RENDER_STATISTIC) || defined(TRACK_GPU_MEM) + void BeforeRenderFrame(); + void AfterRenderFrame(); +#endif + + struct DrapeStatistic + { + std::string ToString() const; + +#ifdef RENDER_STATISTIC + RenderStatistic m_renderStatistic; +#endif +#ifdef TILES_STATISTIC + TileStatistic m_tileStatistic; +#endif +#ifdef GENERATING_STATISTIC + GeneratingStatistic m_generatingStatistic; +#endif +#ifdef TRACK_GPU_MEM + GPUMemoryStatistic m_gpuMemStatistic; +#endif +#ifdef TRACK_GLYPH_USAGE + dp::GlyphUsageTracker::GlyphUsageStatistic m_glyphStatistic; +#endif + }; + + DrapeStatistic GetDrapeStatistic(); + +private: + DrapeMeasurer() = default; + + bool m_isEnabled = false; + +#ifdef GENERATING_STATISTIC + std::chrono::time_point m_startScenePreparingTime; + std::chrono::nanoseconds m_maxScenePreparingTime; + + std::chrono::time_point m_startShapesGenTime; + std::chrono::nanoseconds m_totalShapesGenTime; + uint32_t m_totalShapesCount = 0; + + std::chrono::time_point m_startOverlayShapesGenTime; + std::chrono::nanoseconds m_totalOverlayShapesGenTime; + uint32_t m_totalOverlayShapesCount = 0; +#endif + +#ifdef TILES_STATISTIC + struct TileReadInfo + { + std::chrono::time_point m_startTileReadTime; + std::chrono::nanoseconds m_totalTileReadTime; + uint32_t m_totalTilesCount = 0; + }; + std::map> m_tilesReadInfo; + std::mutex m_tilesMutex; +#endif + +#ifdef RENDER_STATISTIC + std::chrono::nanoseconds m_totalTPF; + uint32_t m_totalTPFCount = 0; + + uint32_t m_minFPS = std::numeric_limits::max(); + double m_totalFPS = 0.0; + uint32_t m_totalFPSCount = 0; +#endif + +#if defined(RENDER_STATISTIC) || defined(TRACK_GPU_MEM) + std::chrono::time_point m_startFrameRenderTime; + std::chrono::nanoseconds m_totalFrameRenderTime; + uint32_t m_totalFramesCount = 0; +#endif + +#ifdef TRACK_GPU_MEM + void TakeGPUMemorySnapshot(); + + dp::GPUMemTracker::GPUMemorySnapshot m_maxSnapshotValues; + dp::GPUMemTracker::GPUMemorySnapshot m_summarySnapshotValues; + uint32_t m_numberOfSnapshots = 0; +#endif +}; + +} diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 94572c324d..21f764f83e 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -2,14 +2,17 @@ #include "drape_frontend/gui/drape_gui.hpp" #include "drape_frontend/gui/ruler_helper.hpp" #include "drape_frontend/animation_system.hpp" +#include "drape_frontend/batch_merge_helper.hpp" +#include "drape_frontend/drape_measurer.hpp" #include "drape_frontend/framebuffer.hpp" #include "drape_frontend/frontend_renderer.hpp" #include "drape_frontend/message_subclasses.hpp" +#include "drape_frontend/scenario_manager.hpp" #include "drape_frontend/screen_operations.hpp" #include "drape_frontend/transparent_layer.hpp" #include "drape_frontend/visual_params.hpp" #include "drape_frontend/user_mark_shapes.hpp" -#include "drape_frontend/batch_merge_helper.hpp" + #include "drape/debug_rect_renderer.hpp" #include "drape/shader_def.hpp" @@ -135,12 +138,10 @@ FrontendRenderer::FrontendRenderer(Params const & params) , m_needRestoreSize(false) , m_needRegenerateTraffic(false) , m_trafficEnabled(params.m_trafficEnabled) -{ -#ifdef DRAW_INFO - m_tpf = 0.0; - m_fps = 0.0; +#ifdef SCENARIO_ENABLE + , m_scenarioManager(new ScenarioManager(this)) #endif - +{ #ifdef DEBUG m_isTeardowned = false; #endif @@ -163,49 +164,13 @@ FrontendRenderer::~FrontendRenderer() void FrontendRenderer::Teardown() { + m_scenarioManager.reset(); StopThread(); #ifdef DEBUG m_isTeardowned = true; #endif } -#ifdef DRAW_INFO -void FrontendRenderer::BeforeDrawFrame() -{ - m_frameStartTime = m_timer.ElapsedSeconds(); -} - -void FrontendRenderer::AfterDrawFrame() -{ - m_drawedFrames++; - - double elapsed = m_timer.ElapsedSeconds(); - m_tpfs.push_back(elapsed - m_frameStartTime); - - if (elapsed > 1.0) - { - m_timer.Reset(); - m_fps = m_drawedFrames / elapsed; - m_drawedFrames = 0; - - m_tpf = accumulate(m_tpfs.begin(), m_tpfs.end(), 0.0) / m_tpfs.size(); - - LOG(LINFO, ("Average Fps : ", m_fps)); - LOG(LINFO, ("Average Tpf : ", m_tpf)); - -#if defined(TRACK_GPU_MEM) - string report = dp::GPUMemTracker::Inst().Report(); - LOG(LINFO, (report)); -#endif -#if defined(TRACK_GLYPH_USAGE) - string glyphReport = dp::GlyphUsageTracker::Instance().Report(); - LOG(LINFO, (glyphReport)); -#endif - } -} - -#endif - void FrontendRenderer::UpdateCanBeDeletedStatus() { m2::RectD const & screenRect = m_userEventStream.GetCurrentScreen().ClipRect(); @@ -297,7 +262,12 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) UpdateCanBeDeletedStatus(); if (m_notFinishedTiles.empty()) + { +#if defined(DRAPE_MEASURER) && defined(GENERATING_STATISTIC) + DrapeMeasurer::Instance().EndScenePreparing(); +#endif m_trafficRenderer->OnGeometryReady(m_currentZoomLevel); + } break; } @@ -429,6 +399,10 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) case Message::GpsInfo: { +#ifdef SCENARIO_ENABLE + if (m_scenarioManager->IsRunning()) + break; +#endif ref_ptr msg = message; m_myPositionController->OnLocationUpdate(msg->GetInfo(), msg->IsNavigable(), m_userEventStream.GetCurrentScreen()); @@ -1101,8 +1075,8 @@ void FrontendRenderer::EndUpdateOverlayTree() void FrontendRenderer::RenderScene(ScreenBase const & modelView) { -#ifdef DRAW_INFO - BeforeDrawFrame(); +#if defined(DRAPE_MEASURER) && (defined(RENDER_STATISTIC) || defined(TRACK_GPU_MEM)) + DrapeMeasurer::Instance().BeforeRenderFrame(); #endif GLFunctions::glEnable(gl_const::GLDepthTest); @@ -1165,8 +1139,8 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView) dp::DebugRectRenderer::Instance().DrawArrow(modelView, arrow); #endif -#ifdef DRAW_INFO - AfterDrawFrame(); +#if defined(DRAPE_MEASURER) && (defined(RENDER_STATISTIC) || defined(TRACK_GPU_MEM)) + DrapeMeasurer::Instance().AfterRenderFrame(); #endif MergeBuckets(); @@ -1611,6 +1585,10 @@ TTilesCollection FrontendRenderer::ResolveTileKeys(ScreenBase const & screen) m_trafficRenderer->OnUpdateViewport(result, m_currentZoomLevel, tilesToDelete); +#if defined(DRAPE_MEASURER) && defined(GENERATING_STATISTIC) + DrapeMeasurer::Instance().StartScenePreparing(); +#endif + return tiles; } @@ -1808,6 +1786,10 @@ void FrontendRenderer::ReleaseResources() void FrontendRenderer::AddUserEvent(drape_ptr && event) { +#ifdef SCENARIO_ENABLE + if (m_scenarioManager->IsRunning() && event->GetType() == UserEvent::EventType::Touch) + return; +#endif m_userEventStream.AddEvent(move(event)); if (IsInInfinityWaiting()) CancelMessageWaiting(); @@ -1904,6 +1886,11 @@ void FrontendRenderer::OnCacheRouteArrows(int routeIndex, vector c MessagePriority::Normal); } +drape_ptr const & FrontendRenderer::GetScenarioManager() const +{ + return m_scenarioManager; +} + FrontendRenderer::RenderLayer::RenderLayerID FrontendRenderer::RenderLayer::GetLayerID(dp::GLState const & state) { if (state.GetDepthLayer() == dp::GLState::OverlayLayer) diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp index d4c6603f96..e06ee32451 100755 --- a/drape_frontend/frontend_renderer.hpp +++ b/drape_frontend/frontend_renderer.hpp @@ -2,12 +2,6 @@ #include "base/thread.hpp" -#ifdef DRAW_INFO - #include "base/timer.hpp" - #include "std/vector.hpp" - #include "std/numeric.hpp" -#endif - #include "drape_frontend/gui/layer_render.hpp" #include "drape_frontend/backend_renderer.hpp" @@ -54,6 +48,7 @@ class SelectionShape; class Framebuffer; class TransparentLayer; class SelectObjectMessage; +class ScenarioManager; struct TapInfo { @@ -129,19 +124,6 @@ public: void Teardown(); -#ifdef DRAW_INFO - double m_tpf; - double m_fps; - - my::Timer m_timer; - double m_frameStartTime; - vector m_tpfs; - int m_drawedFrames; - - void BeforeDrawFrame(); - void AfterDrawFrame(); -#endif - void AddUserEvent(drape_ptr && event); /// MyPositionController::Listener @@ -154,6 +136,8 @@ public: void ChangeModelView(double autoScale, m2::PointD const & userPos, double azimuth, m2::PointD const & pxZero, TAnimationCreator const & parallelAnimCreator) override; + drape_ptr const & GetScenarioManager() const; + protected: void AcceptMessage(ref_ptr message) override; unique_ptr CreateRoutine() override; @@ -346,6 +330,8 @@ private: bool m_needRegenerateTraffic; bool m_trafficEnabled; + drape_ptr m_scenarioManager; + #ifdef DEBUG bool m_isTeardowned; #endif diff --git a/drape_frontend/rule_drawer.cpp b/drape_frontend/rule_drawer.cpp index 92989c3bf2..4939725eee 100644 --- a/drape_frontend/rule_drawer.cpp +++ b/drape_frontend/rule_drawer.cpp @@ -6,6 +6,8 @@ #include "drape_frontend/traffic_renderer.hpp" #include "drape_frontend/visual_params.hpp" +#include "drape/drape_diagnostics.hpp" + #include "indexer/feature.hpp" #include "indexer/feature_algo.hpp" #include "indexer/feature_visibility.hpp" @@ -17,8 +19,6 @@ #include "std/bind.hpp" -//#define DRAW_TILE_NET - #ifdef DRAW_TILE_NET #include "drape_frontend/line_shape.hpp" #include "drape_frontend/text_shape.hpp" diff --git a/drape_frontend/scenario_manager.cpp b/drape_frontend/scenario_manager.cpp new file mode 100644 index 0000000000..37d17d0904 --- /dev/null +++ b/drape_frontend/scenario_manager.cpp @@ -0,0 +1,144 @@ +#include "drape_frontend/scenario_manager.hpp" + +#include "drape_frontend/user_event_stream.hpp" + +namespace df +{ + +ScenarioManager::ScenarioManager(FrontendRenderer * frontendRenderer) + : m_frontendRenderer(frontendRenderer) + , m_needInterrupt(false) + , m_isFinished(false) +{ + ASSERT(m_frontendRenderer != nullptr, ()); +} + +ScenarioManager::~ScenarioManager() +{ + std::lock_guard lock(m_mutex); + if (m_thread != nullptr) + { + m_thread->join(); + m_thread.reset(); + } +} + +void ScenarioManager::Interrupt() +{ + std::lock_guard lock(m_mutex); + InterruptImpl(); +} + +bool ScenarioManager::RunScenario(ScenarioData && scenarioData, ScenarioCallback const & onStartFn, ScenarioCallback const & onFinishFn) +{ + std::lock_guard lock(m_mutex); + if (m_thread != nullptr) + { + if (m_isFinished) + InterruptImpl(); + else + return false; // The only scenario can be executed currently. + } + + std::swap(m_scenarioData, scenarioData); + m_onStartHandler = onStartFn; + m_onFinishHandler = onFinishFn; + m_thread = my::make_unique(&ScenarioManager::ThreadRoutine, this); +#ifdef DEBUG + m_threadId = m_thread->get_id(); +#endif + return true; +} + +bool ScenarioManager::IsRunning() +{ + std::lock_guard lock(m_mutex); + if (m_thread == nullptr) + return false; + + if (m_isFinished) + { + InterruptImpl(); + return false; + } + return true; +} + +void ScenarioManager::ThreadRoutine() +{ + string const scenarioName = m_scenarioData.m_name; + if (m_onStartHandler != nullptr) + m_onStartHandler(scenarioName); + + for (auto const & action : m_scenarioData.m_scenario) + { + // Interrupt scenario if it's necessary. + { + std::lock_guard lock(m_mutex); + if (m_needInterrupt) + { + m_needInterrupt = false; + break; + } + } + + switch(action->GetType()) + { + case ActionType::CenterViewport: + { + CenterViewportAction * centerViewportAction = static_cast(action.get()); + m_frontendRenderer->AddUserEvent(make_unique_dp(centerViewportAction->GetCenter(), + centerViewportAction->GetZoomLevel(), + true)); + break; + } + + case ActionType::WaitForTime: + { + WaitForTimeAction * waitForTimeAction = static_cast(action.get()); + std::this_thread::sleep_for(waitForTimeAction->GetDuration()); + break; + } + + default: + LOG(LINFO, ("Unknown action in scenario")); + } + } + + ScenarioCallback handler = nullptr; + { + std::lock_guard lock(m_mutex); + m_scenarioData.m_scenario.clear(); + m_isFinished = true; + if (m_onFinishHandler != nullptr) + { + handler = m_onFinishHandler; + m_onFinishHandler = nullptr; + } + } + + if (handler != nullptr) + handler(scenarioName); +} + +void ScenarioManager::InterruptImpl() +{ + if (m_thread == nullptr) + return; + + ASSERT_NOT_EQUAL(m_threadId, std::this_thread::get_id(), ()); + + if (m_isFinished) + { + m_thread->join(); + m_thread.reset(); + m_isFinished = false; + m_needInterrupt = false; + } + else + { + m_needInterrupt = true; + } +} + +} // namespace df diff --git a/drape_frontend/scenario_manager.hpp b/drape_frontend/scenario_manager.hpp new file mode 100644 index 0000000000..a174a62095 --- /dev/null +++ b/drape_frontend/scenario_manager.hpp @@ -0,0 +1,102 @@ +#pragma once + +#include "drape_frontend/frontend_renderer.hpp" + +#include "drape/drape_diagnostics.hpp" + +#include "geometry/point2d.hpp" + +#include "base/stl_add.hpp" +#include "base/thread.hpp" + +#include +#include +#include +#include +#include + +namespace df +{ + +class ScenarioManager +{ +public: + enum class ActionType + { + CenterViewport, + WaitForTime + }; + + class Action + { + public: + virtual ~Action() {} + virtual ActionType GetType() = 0; + }; + + class CenterViewportAction : public Action + { + public: + CenterViewportAction(m2::PointD const & pt, int zoomLevel) + : m_center(pt), m_zoomLevel(zoomLevel) {} + + ActionType GetType() override { return ActionType::CenterViewport; } + + m2::PointD const & GetCenter() const { return m_center; } + int GetZoomLevel() const { return m_zoomLevel; } + private: + m2::PointD const m_center; + int const m_zoomLevel; + }; + + class WaitForTimeAction : public Action + { + public: + using Duration = std::chrono::steady_clock::duration; + + WaitForTimeAction(Duration const & duration) + : m_duration(duration) {} + + ActionType GetType() override { return ActionType::WaitForTime; } + + Duration const & GetDuration() const { return m_duration; } + private: + Duration m_duration; + }; + + using Scenario = std::vector>; + using ScenarioCallback = std::function; + + struct ScenarioData + { + std::string m_name; + Scenario m_scenario; + }; + + ScenarioManager(FrontendRenderer * frontendRenderer); + ~ScenarioManager(); + + bool RunScenario(ScenarioData && scenarioData, + ScenarioCallback const & startHandler, ScenarioCallback const & finishHandler); + void Interrupt(); + bool IsRunning(); + +private: + void ThreadRoutine(); + void InterruptImpl(); + + FrontendRenderer * m_frontendRenderer; + + std::mutex m_mutex; + ScenarioData m_scenarioData; + bool m_needInterrupt; + bool m_isFinished; + ScenarioCallback m_onStartHandler; + ScenarioCallback m_onFinishHandler; +#ifdef DEBUG + std::thread::id m_threadId; +#endif + std::unique_ptr m_thread; +}; + +} // namespace df diff --git a/drape_frontend/tile_info.cpp b/drape_frontend/tile_info.cpp index b8ffbc54c3..d147e4bb14 100644 --- a/drape_frontend/tile_info.cpp +++ b/drape_frontend/tile_info.cpp @@ -1,3 +1,4 @@ +#include "drape_frontend/drape_measurer.hpp" #include "drape_frontend/engine_context.hpp" #include "drape_frontend/map_data_provider.hpp" #include "drape_frontend/rule_drawer.hpp" @@ -57,6 +58,9 @@ void TileInfo::ReadFeatureIndex(MapDataProvider const & model) void TileInfo::ReadFeatures(MapDataProvider const & model) { +#if defined(DRAPE_MEASURER) && defined(TILES_STATISTIC) + DrapeMeasurer::Instance().StartTileReading(); +#endif m_context->BeginReadTile(); // Reading can be interrupted by exception throwing @@ -73,6 +77,9 @@ void TileInfo::ReadFeatures(MapDataProvider const & model) make_ref(m_context), m_is3dBuildings, m_trafficEnabled); model.ReadFeatures(bind(ref(drawer), _1), m_featureInfo); } +#if defined(DRAPE_MEASURER) && defined(TILES_STATISTIC) + DrapeMeasurer::Instance().EndTileReading(); +#endif } void TileInfo::Cancel() diff --git a/map/CMakeLists.txt b/map/CMakeLists.txt index 9085909490..c62a9dccf9 100644 --- a/map/CMakeLists.txt +++ b/map/CMakeLists.txt @@ -15,6 +15,8 @@ set( address_finder.cpp api_mark_point.cpp api_mark_point.hpp + benchmark_tools.hpp + benchmark_tools.cpp bookmark_manager.cpp bookmark_manager.hpp bookmark.cpp diff --git a/map/benchmark_engine.cpp b/map/benchmark_engine.cpp deleted file mode 100644 index 08ac130052..0000000000 --- a/map/benchmark_engine.cpp +++ /dev/null @@ -1,272 +0,0 @@ -#include "map/benchmark_engine.hpp" -#include "map/framework.hpp" - -#include "indexer/data_header.hpp" - -#include "platform/settings.hpp" - -#include "coding/file_container.hpp" -#include "coding/reader_streambuf.hpp" - -#include "std/fstream.hpp" - - -class DoGetBenchmarks -{ - set m_processed; - - BenchmarkEngine & m_engine; - -public: - explicit DoGetBenchmarks(BenchmarkEngine & engine) : m_engine(engine) {} - - void operator() (vector const & v) - { - if (v[0][0] == '#') - return; - - BenchmarkEngine::Benchmark b; - b.m_name = v[1]; - - m2::RectD r; - if (m_processed.insert(v[0]).second) - { - try - { - feature::DataHeader header(v[0]); - r = header.GetBounds(); - } - catch (RootException const & e) - { - LOG(LINFO, ("Can't add", v[0], "file to benchmark:", e.Msg())); - return; - } - } - - int lastScale; - if (v.size() > 3) - { - double lat1, lon1, lat2, lon2; - CHECK(strings::to_double(v[2], lat1), (v[2])); - CHECK(strings::to_double(v[3], lon1), (v[3])); - CHECK(strings::to_double(v[4], lat2), (v[4])); - CHECK(strings::to_double(v[5], lon2), (v[5])); - - r = m2::RectD(m2::PointD(MercatorBounds::LonToX(lon1), MercatorBounds::LatToY(lat1)), - m2::PointD(MercatorBounds::LonToX(lon2), MercatorBounds::LatToY(lat2))); - CHECK(strings::to_int(v[6], lastScale), (v[6])); - } - else - CHECK(strings::to_int(v[2], lastScale), (v[2])); - - ASSERT ( r != m2::RectD::GetEmptyRect(), (r) ); - - Navigator & nav = m_engine.m_framework->GetNavigator(); - - nav.SetFromRect(m2::AnyRectD(r)); - r = nav.Screen().GlobalRect().GetGlobalRect(); - - b.m_provider.reset(new BenchmarkRectProvider(nav.GetDrawScale(), r, lastScale)); - - m_engine.m_benchmarks.push_back(b); - } -}; - -template -void ForEachBenchmarkRecord(ToDo & toDo) -{ - try - { - string configPath; - if (!Settings::Get("BenchmarkConfig", configPath)) - return; - - ReaderStreamBuf buffer(GetPlatform().GetReader(configPath, "w")); - istream stream(&buffer); - - string line; - while (stream.good()) - { - getline(stream, line); - - vector parts; - strings::SimpleTokenizer it(line, " \t"); - while (it) - { - parts.push_back(*it); - ++it; - } - - if (!parts.empty()) - toDo(parts); - } - } - catch (RootException const & e) - { - LOG(LERROR, ("Error reading benchmarks:", e.Msg())); - } -} - -struct MapsCollector -{ - vector m_maps; - - void operator() (vector const & v) - { - ASSERT(!v[0].empty(), ()); - if (v[0][0] != '#') - m_maps.push_back(v[0]); - } -}; - -void BenchmarkEngine::PrepareMaps() -{ - // Deregister all previously registered maps in framework constructor. - m_framework->DeregisterAllMaps(); - - // add only maps needed for benchmarks - MapsCollector collector; - ForEachBenchmarkRecord(collector); - for (string const & map : collector.m_maps) - { - LOG(LINFO, ("Looking for:", map)); - m_framework->RegisterMap(platform::LocalCountryFile::MakeForTesting(map)); - } -} - -BenchmarkEngine::BenchmarkEngine(Framework * fw) - : m_paintDuration(0), - m_maxDuration(0), - m_framework(fw) -{ -} - -void BenchmarkEngine::BenchmarkCommandFinished() -{ - double duration = m_paintDuration; - - if (duration > m_maxDuration) - { - m_maxDuration = duration; - m_maxDurationRect = m_curBenchmarkRect; - } - - BenchmarkResult res; - res.m_name = m_benchmarks[m_curBenchmark].m_name; - res.m_rect = m_curBenchmarkRect; - res.m_time = duration; - m_benchmarkResults.push_back(res); - - if (m_benchmarkResults.size() > 100) - SaveBenchmarkResults(); - - m_paintDuration = 0; -} - -void BenchmarkEngine::SaveBenchmarkResults() -{ - string resultsPath; - Settings::Get("BenchmarkResults", resultsPath); - - ofstream fout(GetPlatform().WritablePathForFile(resultsPath).c_str(), ios::app); - for (size_t i = 0; i < m_benchmarkResults.size(); ++i) - { - /// @todo Place correct version here from bundle (platform). - - fout << GetPlatform().DeviceName() << " " - << "3.0.0" << " " - << m_startTime << " " - << m_benchmarkResults[i].m_name << " " - << m_benchmarkResults[i].m_rect.minX() << " " - << m_benchmarkResults[i].m_rect.minY() << " " - << m_benchmarkResults[i].m_rect.maxX() << " " - << m_benchmarkResults[i].m_rect.maxY() << " " - << m_benchmarkResults[i].m_time << endl; - } - - m_benchmarkResults.clear(); -} - -void BenchmarkEngine::SendBenchmarkResults() -{ -} - -void BenchmarkEngine::MarkBenchmarkResultsEnd() -{ - string resultsPath; - Settings::Get("BenchmarkResults", resultsPath); - ofstream fout(GetPlatform().WritablePathForFile(resultsPath).c_str(), ios::app); - fout << "END " << m_startTime << endl; -} - -void BenchmarkEngine::MarkBenchmarkResultsStart() -{ - string resultsPath; - Settings::Get("BenchmarkResults", resultsPath); - ofstream fout(GetPlatform().WritablePathForFile(resultsPath).c_str(), ios::app); - fout << "START " << m_startTime << endl; -} - -bool BenchmarkEngine::NextBenchmarkCommand() -{ -#ifndef USE_DRAPE - if (m_benchmarks[m_curBenchmark].m_provider->hasRect() || ++m_curBenchmark < m_benchmarks.size()) - { - double const s = m_benchmarksTimer.ElapsedSeconds(); - - int const fenceID = m_framework->GetRenderPolicy()->InsertBenchmarkFence(); - - m_framework->ShowRect(m_benchmarks[m_curBenchmark].m_provider->nextRect()); - m_curBenchmarkRect = m_framework->GetCurrentViewport(); - - m_framework->GetRenderPolicy()->JoinBenchmarkFence(fenceID); - - m_paintDuration += m_benchmarksTimer.ElapsedSeconds() - s; - BenchmarkCommandFinished(); - - return true; - } - else - { - SaveBenchmarkResults(); - MarkBenchmarkResultsEnd(); - SendBenchmarkResults(); - - LOG(LINFO, ("Bechmarks took", m_benchmarksTimer.ElapsedSeconds(), "seconds to complete")); - return false; - } -#else - return false; -#endif // USE_DRAPE -} - -void BenchmarkEngine::Start() -{ - m_thread.Create(make_unique(*this)); -} - -BenchmarkEngine::Routine::Routine(BenchmarkEngine & engine) : m_engine(engine) {} - -void BenchmarkEngine::Routine::Do() -{ - m_engine.PrepareMaps(); - - int benchMarkCount = 1; - (void) Settings::Get("BenchmarkCyclesCount", benchMarkCount); - - for (int i = 0; i < benchMarkCount; ++i) - { - DoGetBenchmarks doGet(m_engine); - ForEachBenchmarkRecord(doGet); - - m_engine.m_curBenchmark = 0; - - m_engine.m_benchmarksTimer.Reset(); - m_engine.m_startTime = my::FormatCurrentTime(); - - m_engine.MarkBenchmarkResultsStart(); - while (m_engine.NextBenchmarkCommand()){}; - - m_engine.m_benchmarks.clear(); - } -} diff --git a/map/benchmark_engine.hpp b/map/benchmark_engine.hpp deleted file mode 100644 index 4ec5bf1648..0000000000 --- a/map/benchmark_engine.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once -#include "map/benchmark_provider.hpp" - -#include "geometry/rect2d.hpp" - -#include "base/timer.hpp" -#include "base/thread.hpp" - -#include "std/string.hpp" -#include "std/vector.hpp" -#include "std/shared_ptr.hpp" - - -class Framework; - -/// BenchmarkEngine is class which: -/// - Creates it's own thread -/// - Feeds the Framework with the paint tasks he wants to performs -/// - Wait until each tasks completion -/// - Measure the time of each task and save the result -class BenchmarkEngine -{ - threads::Thread m_thread; - - double m_paintDuration; - double m_maxDuration; - m2::RectD m_maxDurationRect; - m2::RectD m_curBenchmarkRect; - - string m_startTime; - - struct BenchmarkResult - { - string m_name; - m2::RectD m_rect; - double m_time; - }; - - vector m_benchmarkResults; - my::Timer m_benchmarksTimer; - - struct Benchmark - { - shared_ptr m_provider; - string m_name; - }; - - class Routine : public threads::IRoutine - { - public: - Routine(BenchmarkEngine & engine); - - // threads::IRoutine overrides: - void Do() override; - - private: - BenchmarkEngine & m_engine; - }; - - vector m_benchmarks; - size_t m_curBenchmark; - - Framework * m_framework; - - void BenchmarkCommandFinished(); - bool NextBenchmarkCommand(); - void SaveBenchmarkResults(); - void SendBenchmarkResults(); - - void MarkBenchmarkResultsStart(); - void MarkBenchmarkResultsEnd(); - - void PrepareMaps(); - - friend class DoGetBenchmarks; - -public: - BenchmarkEngine(Framework * fw); - - void Start(); -}; diff --git a/map/benchmark_provider.cpp b/map/benchmark_provider.cpp deleted file mode 100644 index 779325ab01..0000000000 --- a/map/benchmark_provider.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "base/SRC_FIRST.hpp" -#include "map/benchmark_provider.hpp" -#include "geometry/mercator.hpp" - -BenchmarkRectProvider::BenchmarkRectProvider(int startLevel, m2::RectD const & startRect, int endLevel) - : m_endLevel(endLevel) -{ - m_rects.push_back(make_pair(startRect, startLevel)); -} - -bool BenchmarkRectProvider::hasRect() const -{ - return !m_rects.empty(); -} - -m2::RectD const BenchmarkRectProvider::nextRect() -{ - pair const & f = m_rects.front(); - m2::RectD r = f.first; - - if (f.second < m_endLevel) - { - int nextLevel = f.second + 1; - - m_rects.push_back(make_pair(m2::RectD(r.minX(), r.minY(), r.minX() + r.SizeX() / 2, r.minY() + r.SizeY() / 2), nextLevel)); - m_rects.push_back(make_pair(m2::RectD(r.minX() + r.SizeX() / 2, r.minY(), r.maxX(), r.minY() + r.SizeY() / 2), nextLevel)); - m_rects.push_back(make_pair(m2::RectD(r.minX(), r.minY() + r.SizeY() / 2, r.minX() + r.SizeX() / 2, r.maxY()), nextLevel)); - m_rects.push_back(make_pair(m2::RectD(r.minX() + r.SizeX() / 2, r.minY() + r.SizeY() / 2, r.maxX(), r.maxY()), nextLevel)); - } - - m_rects.pop_front(); - return r; -} diff --git a/map/benchmark_provider.hpp b/map/benchmark_provider.hpp deleted file mode 100644 index 045fe8d5d9..0000000000 --- a/map/benchmark_provider.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include "geometry/rect2d.hpp" -#include "std/list.hpp" - -struct BenchmarkRectProvider -{ - int m_endLevel; - list > m_rects; - BenchmarkRectProvider(int startLevel, m2::RectD const & startRect, int endLevel); - - bool hasRect() const; - m2::RectD const nextRect(); -}; - diff --git a/map/benchmark_tools.cpp b/map/benchmark_tools.cpp new file mode 100644 index 0000000000..6ed66a76e0 --- /dev/null +++ b/map/benchmark_tools.cpp @@ -0,0 +1,190 @@ +#include "map/benchmark_tools.hpp" +#include "map/framework.hpp" + +#include "drape_frontend/drape_measurer.hpp" +#include "drape_frontend/scenario_manager.hpp" + +#include "platform/http_client.hpp" +#include "platform/platform.hpp" + +#include "3party/jansson/myjansson.hpp" + +#include +#include +#include +#include +#include + +namespace +{ + +struct BenchmarkHandle +{ + std::vector m_scenariosToRun; + size_t m_currentScenario = 0; + std::vector m_regionsToDownload; + size_t m_regionsToDownloadCounter = 0; + +#ifdef DRAPE_MEASURER + std::vector> m_drapeStatistic; +#endif +}; + +void RunScenario(Framework * framework, std::shared_ptr handle) +{ + if (handle->m_currentScenario >= handle->m_scenariosToRun.size()) + { +#ifdef DRAPE_MEASURER + for (auto const & it : handle->m_drapeStatistic) + { + LOG(LINFO, ("\n ***** Report for scenario", it.first, "*****\n", + it.second.ToString(), + "\n ***** Report for scenario", it.first, "*****\n")); + + } +#endif + return; + } + + auto & scenarioData = handle->m_scenariosToRun[handle->m_currentScenario]; + + framework->GetDrapeEngine()->RunScenario(std::move(scenarioData), + [handle](std::string const & name) + { +#ifdef DRAPE_MEASURER + df::DrapeMeasurer::Instance().StartBenchmark(); +#endif + }, + [framework, handle](std::string const & name) + { +#ifdef DRAPE_MEASURER + df::DrapeMeasurer::Instance().StopBenchmark(); + auto const drapeStatistic = df::DrapeMeasurer::Instance().GetDrapeStatistic(); + handle->m_drapeStatistic.push_back(make_pair(name, drapeStatistic)); +#endif + GetPlatform().RunOnGuiThread([framework, handle]() + { + handle->m_currentScenario++; + RunScenario(framework, handle); + }); + }); +} +} // namespace + +namespace benchmark +{ +void RunGraphicsBenchmark(Framework * framework) +{ +#ifdef SCENARIO_ENABLE + using namespace df; + + // Request scenarios from the server. + platform::HttpClient request("http://osmz.ru/mwm/graphics_benchmark.json"); + if (!request.RunHttpRequest()) + return; + + std::shared_ptr handle = std::make_shared(); + + // Parse scenarios. + std::vector points; + string const & result = request.ServerResponse(); + try + { + my::Json root(result.c_str()); + json_t * scenariosNode = json_object_get(root.get(), "scenarios"); + if (scenariosNode == nullptr || !json_is_array(scenariosNode)) + return; + size_t const sz = json_array_size(scenariosNode); + handle->m_scenariosToRun.resize(sz); + for (size_t i = 0; i < sz; ++i) + { + auto scenarioElem = json_array_get(scenariosNode, i); + if (scenarioElem == nullptr) + return; + my::FromJSONObject(scenarioElem, "name", handle->m_scenariosToRun[i].m_name); + json_t * stepsNode = json_object_get(scenarioElem, "steps"); + if (stepsNode != nullptr && json_is_array(stepsNode)) + { + size_t const stepsCount = json_array_size(stepsNode); + auto & scenario = handle->m_scenariosToRun[i].m_scenario; + scenario.reserve(stepsCount); + for (size_t j = 0; j < stepsCount; ++j) + { + auto stepElem = json_array_get(stepsNode, j); + if (stepElem == nullptr) + return; + string actionType; + my::FromJSONObject(stepElem, "actionType", actionType); + if (actionType == "waitForTime") + { + json_int_t timeInSeconds = 0; + my::FromJSONObject(stepElem, "time", timeInSeconds); + scenario.push_back(std::unique_ptr( + new ScenarioManager::WaitForTimeAction(seconds(timeInSeconds)))); + } + else if (actionType == "centerViewport") + { + json_t * centerNode = json_object_get(stepElem, "center"); + if (centerNode == nullptr) + return; + double x = 0.0, y = 0.0; + my::FromJSONObject(centerNode, "x", x); + my::FromJSONObject(centerNode, "y", y); + json_int_t zoomLevel = -1; + my::FromJSONObject(stepElem, "zoomLevel", zoomLevel); + m2::PointD const pt(x, y); + points.push_back(pt); + scenario.push_back(std::unique_ptr( + new ScenarioManager::CenterViewportAction(pt, static_cast(zoomLevel)))); + } + } + } + } + } + catch (my::Json::Exception const & e) + { + return; + } + if (handle->m_scenariosToRun.empty()) + return; + + // Find out regions to download. + std::set regions; + for (m2::PointD const & pt : points) + regions.insert(framework->GetCountryInfoGetter().GetRegionCountryId(pt)); + + for (auto const & countryId : regions) + { + storage::NodeStatuses statuses; + framework->GetStorage().GetNodeStatuses(countryId, statuses); + if (statuses.m_status != storage::NodeStatus::OnDisk) + handle->m_regionsToDownload.push_back(countryId); + } + + // Download regions and run scenarios after downloading. + if (!handle->m_regionsToDownload.empty()) + { + framework->GetStorage().Subscribe([framework, handle](storage::TCountryId const & countryId) + { + if (std::find(handle->m_regionsToDownload.begin(), + handle->m_regionsToDownload.end(), countryId) != handle->m_regionsToDownload.end()) + { + handle->m_regionsToDownloadCounter++; + if (handle->m_regionsToDownloadCounter == handle->m_regionsToDownload.size()) + { + handle->m_regionsToDownload.clear(); + RunScenario(framework, handle); + } + } + }, [](storage::TCountryId const &, storage::MapFilesDownloader::TProgress const &){}); + + for (auto const & countryId : handle->m_regionsToDownload) + framework->GetStorage().DownloadNode(countryId); + return; + } + + // Run scenarios without downloading. + RunScenario(framework, handle); +#endif +} +} // namespace benchmark diff --git a/map/benchmark_tools.hpp b/map/benchmark_tools.hpp new file mode 100644 index 0000000000..2e084c4331 --- /dev/null +++ b/map/benchmark_tools.hpp @@ -0,0 +1,8 @@ +#pragma once + +class Framework; + +namespace benchmark +{ +void RunGraphicsBenchmark(Framework * framework); +} // namespace benchmark diff --git a/map/framework.cpp b/map/framework.cpp index 09a895f8cb..1cce5b23d4 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -1,4 +1,5 @@ #include "map/framework.hpp" +#include "map/benchmark_tools.hpp" #include "map/chart_generator.hpp" #include "map/ge0_parser.hpp" #include "map/geourl_process.hpp" @@ -1731,6 +1732,8 @@ void Framework::CreateDrapeEngine(ref_ptr contextFactory, m_drapeApi.SetEngine(make_ref(m_drapeEngine)); m_trafficManager.SetDrapeEngine(make_ref(m_drapeEngine)); + + benchmark::RunGraphicsBenchmark(this); } void Framework::OnRecoverGLContext(int width, int height) diff --git a/map/map.pro b/map/map.pro index 1816bd1e9a..44725e4043 100644 --- a/map/map.pro +++ b/map/map.pro @@ -12,6 +12,7 @@ include($$ROOT_DIR/common.pri) HEADERS += \ api_mark_point.hpp \ + benchmark_tools.hpp \ bookmark.hpp \ bookmark_manager.hpp \ chart_generator.hpp \ @@ -37,6 +38,7 @@ SOURCES += \ ../api/src/c/api-client.c \ address_finder.cpp \ api_mark_point.cpp \ + benchmark_tools.cpp \ bookmark.cpp \ bookmark_manager.cpp \ chart_generator.cpp \ diff --git a/xcode/drape/drape.xcodeproj/project.pbxproj b/xcode/drape/drape.xcodeproj/project.pbxproj index f34823173f..ea7158dfa5 100644 --- a/xcode/drape/drape.xcodeproj/project.pbxproj +++ b/xcode/drape/drape.xcodeproj/project.pbxproj @@ -105,6 +105,7 @@ 6743D3451C3533AE0095054B /* support_manager.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 6743D3431C3533AE0095054B /* support_manager.hpp */; }; 675D21991BFB876E00717E4F /* projection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 675D21971BFB876E00717E4F /* projection.cpp */; }; 675D219A1BFB876E00717E4F /* projection.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 675D21981BFB876E00717E4F /* projection.hpp */; }; + BB035F6C1E3A2A5C00519962 /* drape_diagnostics.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BB035F6B1E3A2A5C00519962 /* drape_diagnostics.hpp */; }; BB06FBE91DDDFFBE00B41AF0 /* area_vertex_shader.vsh in Sources */ = {isa = PBXBuildFile; fileRef = BB06FBC01DDDFDC300B41AF0 /* area_vertex_shader.vsh */; }; BB06FBEA1DDDFFBE00B41AF0 /* area3d_outline_vertex_shader.vsh in Sources */ = {isa = PBXBuildFile; fileRef = BB06FBC11DDDFDC300B41AF0 /* area3d_outline_vertex_shader.vsh */; }; BB06FBEB1DDDFFBE00B41AF0 /* area3d_vertex_shader.vsh in Sources */ = {isa = PBXBuildFile; fileRef = BB06FBC21DDDFDC300B41AF0 /* area3d_vertex_shader.vsh */; }; @@ -278,6 +279,7 @@ 6743D3431C3533AE0095054B /* support_manager.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = support_manager.hpp; sourceTree = ""; }; 675D21971BFB876E00717E4F /* projection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = projection.cpp; sourceTree = ""; }; 675D21981BFB876E00717E4F /* projection.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = projection.hpp; sourceTree = ""; }; + BB035F6B1E3A2A5C00519962 /* drape_diagnostics.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = drape_diagnostics.hpp; sourceTree = ""; }; BB06FBC01DDDFDC300B41AF0 /* area_vertex_shader.vsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = area_vertex_shader.vsh; sourceTree = ""; }; BB06FBC11DDDFDC300B41AF0 /* area3d_outline_vertex_shader.vsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = area3d_outline_vertex_shader.vsh; sourceTree = ""; }; BB06FBC21DDDFDC300B41AF0 /* area3d_vertex_shader.vsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = area3d_vertex_shader.vsh; sourceTree = ""; }; @@ -391,6 +393,7 @@ 6729A50E1A69213A007D5872 /* cpu_buffer.hpp */, 6729A50F1A69213A007D5872 /* data_buffer.cpp */, 6729A5101A69213A007D5872 /* data_buffer.hpp */, + BB035F6B1E3A2A5C00519962 /* drape_diagnostics.hpp */, 6729A5111A69213A007D5872 /* drape_global.hpp */, 347F32F71C45383E009758CC /* debug_rect_renderer.cpp */, 347F32F81C45383E009758CC /* debug_rect_renderer.hpp */, @@ -577,6 +580,7 @@ 6729A57F1A69213A007D5872 /* glIncludes.hpp in Headers */, 6729A5A91A69213A007D5872 /* texture_of_colors.hpp in Headers */, 6729A5871A69213A007D5872 /* gpu_buffer.hpp in Headers */, + BB035F6C1E3A2A5C00519962 /* drape_diagnostics.hpp in Headers */, 6729A56E1A69213A007D5872 /* buffer_base.hpp in Headers */, 6729A58F1A69213A007D5872 /* index_buffer.hpp in Headers */, ); diff --git a/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj b/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj index fbc5766290..52f0853a43 100644 --- a/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj +++ b/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj @@ -39,6 +39,8 @@ 454C19BB1CCE3EC0002A2C86 /* animation_constants.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 454C19B81CCE3EC0002A2C86 /* animation_constants.hpp */; }; 454C19BC1CCE3EC0002A2C86 /* animation_system.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 454C19B91CCE3EC0002A2C86 /* animation_system.cpp */; }; 454C19BD1CCE3EC0002A2C86 /* animation_system.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 454C19BA1CCE3EC0002A2C86 /* animation_system.hpp */; }; + 45580ABA1E28DB2600CD535D /* scenario_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45580AB81E28DB2600CD535D /* scenario_manager.cpp */; }; + 45580ABB1E28DB2600CD535D /* scenario_manager.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 45580AB91E28DB2600CD535D /* scenario_manager.hpp */; }; 45B4B8CB1CF5C16B00A54761 /* screen_animations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45B4B8C71CF5C16B00A54761 /* screen_animations.cpp */; }; 45B4B8CC1CF5C16B00A54761 /* screen_animations.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 45B4B8C81CF5C16B00A54761 /* screen_animations.hpp */; }; 45B4B8CD1CF5C16B00A54761 /* screen_operations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45B4B8C91CF5C16B00A54761 /* screen_operations.cpp */; }; @@ -206,6 +208,8 @@ 67E91C7C1BDFC85E005CEE88 /* selection_shape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 670947701BDF9BE0005014C0 /* selection_shape.cpp */; }; 67E91C7D1BDFC85E005CEE88 /* user_marks_provider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6709478B1BDF9BE0005014C0 /* user_marks_provider.cpp */; }; 67E91C7E1BDFC85E005CEE88 /* visual_params.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6709478F1BDF9BE1005014C0 /* visual_params.cpp */; }; + BB035F6F1E3A2AAE00519962 /* drape_measurer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB035F6D1E3A2AAE00519962 /* drape_measurer.cpp */; }; + BB035F701E3A2AAE00519962 /* drape_measurer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BB035F6E1E3A2AAE00519962 /* drape_measurer.hpp */; }; F6B283101C1B04680081957A /* gps_track_point.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F6B2830B1C1B04680081957A /* gps_track_point.hpp */; }; F6B283111C1B04680081957A /* gps_track_renderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F6B2830C1C1B04680081957A /* gps_track_renderer.cpp */; }; F6B283121C1B04680081957A /* gps_track_renderer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F6B2830D1C1B04680081957A /* gps_track_renderer.hpp */; }; @@ -248,6 +252,8 @@ 454C19B81CCE3EC0002A2C86 /* animation_constants.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = animation_constants.hpp; sourceTree = ""; }; 454C19B91CCE3EC0002A2C86 /* animation_system.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = animation_system.cpp; sourceTree = ""; }; 454C19BA1CCE3EC0002A2C86 /* animation_system.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = animation_system.hpp; sourceTree = ""; }; + 45580AB81E28DB2600CD535D /* scenario_manager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scenario_manager.cpp; sourceTree = ""; }; + 45580AB91E28DB2600CD535D /* scenario_manager.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = scenario_manager.hpp; sourceTree = ""; }; 45B4B8C71CF5C16B00A54761 /* screen_animations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = screen_animations.cpp; sourceTree = ""; }; 45B4B8C81CF5C16B00A54761 /* screen_animations.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = screen_animations.hpp; sourceTree = ""; }; 45B4B8C91CF5C16B00A54761 /* screen_operations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = screen_operations.cpp; sourceTree = ""; }; @@ -417,6 +423,8 @@ 675D218B1BFB871D00717E4F /* text_engine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = text_engine.h; sourceTree = ""; }; 677A2DE31C0DD55D00635A00 /* requested_tiles.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = requested_tiles.cpp; sourceTree = ""; }; 677A2DE41C0DD55D00635A00 /* requested_tiles.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = requested_tiles.hpp; sourceTree = ""; }; + BB035F6D1E3A2AAE00519962 /* drape_measurer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = drape_measurer.cpp; sourceTree = ""; }; + BB035F6E1E3A2AAE00519962 /* drape_measurer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = drape_measurer.hpp; sourceTree = ""; }; F6B2830B1C1B04680081957A /* gps_track_point.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = gps_track_point.hpp; sourceTree = ""; }; F6B2830C1C1B04680081957A /* gps_track_renderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gps_track_renderer.cpp; sourceTree = ""; }; F6B2830D1C1B04680081957A /* gps_track_renderer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = gps_track_renderer.hpp; sourceTree = ""; }; @@ -464,6 +472,8 @@ 347F520A1DC2334A0064B273 /* drape_api_renderer.hpp */, 347F520B1DC2334A0064B273 /* drape_api.cpp */, 347F520C1DC2334A0064B273 /* drape_api.hpp */, + BB035F6D1E3A2AAE00519962 /* drape_measurer.cpp */, + BB035F6E1E3A2AAE00519962 /* drape_measurer.hpp */, 34C624BF1DABDB0400510300 /* traffic_generator.cpp */, 34C624C01DABDB0400510300 /* traffic_generator.hpp */, 34C624C11DABDB0400510300 /* traffic_renderer.cpp */, @@ -487,6 +497,8 @@ 6743D3681C3A9F090095054B /* arrow3d.hpp */, 6743D3691C3A9F090095054B /* framebuffer.cpp */, 6743D36A1C3A9F090095054B /* framebuffer.hpp */, + 45580AB91E28DB2600CD535D /* scenario_manager.hpp */, + 45580AB81E28DB2600CD535D /* scenario_manager.cpp */, 6743D36B1C3A9F090095054B /* transparent_layer.cpp */, 6743D36C1C3A9F090095054B /* transparent_layer.hpp */, F6B2830B1C1B04680081957A /* gps_track_point.hpp */, @@ -700,6 +712,7 @@ files = ( 670947971BDF9BE1005014C0 /* line_shape.hpp in Headers */, 56BF56DB1C7608C0006DD7CB /* choose_position_mark.hpp in Headers */, + 45580ABB1E28DB2600CD535D /* scenario_manager.hpp in Headers */, 670948031BDF9BF5005014C0 /* drape_engine.hpp in Headers */, 6709486A1BDF9C7F005014C0 /* brush_info.hpp in Headers */, 675D218E1BFB871D00717E4F /* rect.h in Headers */, @@ -799,6 +812,7 @@ 670948751BDF9C7F005014C0 /* geometry_processors.hpp in Headers */, 6709487A1BDF9C7F005014C0 /* icon_info.hpp in Headers */, 670948151BDF9C39005014C0 /* base_interpolator.hpp in Headers */, + BB035F701E3A2AAE00519962 /* drape_measurer.hpp in Headers */, 670947A61BDF9BE1005014C0 /* my_position.hpp in Headers */, 675D21901BFB871D00717E4F /* software_renderer.hpp in Headers */, 670947A81BDF9BE1005014C0 /* navigator.hpp in Headers */, @@ -913,8 +927,10 @@ F6B283131C1B04680081957A /* gps_track_shape.cpp in Sources */, 45B4B8CB1CF5C16B00A54761 /* screen_animations.cpp in Sources */, 6709483D1BDF9C48005014C0 /* copyright_label.cpp in Sources */, + 45580ABA1E28DB2600CD535D /* scenario_manager.cpp in Sources */, 670947C81BDF9BE1005014C0 /* text_shape.cpp in Sources */, 34C624C31DABDB0400510300 /* traffic_generator.cpp in Sources */, + BB035F6F1E3A2AAE00519962 /* drape_measurer.cpp in Sources */, 670947CC1BDF9BE1005014C0 /* tile_info.cpp in Sources */, 34C624C51DABDB0400510300 /* traffic_renderer.cpp in Sources */, 670947961BDF9BE1005014C0 /* line_shape.cpp in Sources */, diff --git a/xcode/map/map.xcodeproj/project.pbxproj b/xcode/map/map.xcodeproj/project.pbxproj index bee4148a73..2984469e17 100644 --- a/xcode/map/map.xcodeproj/project.pbxproj +++ b/xcode/map/map.xcodeproj/project.pbxproj @@ -19,6 +19,8 @@ 34DDA1811DBE5DF40088A609 /* libpartners_api.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34DDA17F1DBE5DF40088A609 /* libpartners_api.a */; }; 34DDA1821DBE5DF40088A609 /* libtracking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34DDA1801DBE5DF40088A609 /* libtracking.a */; }; 45201E931CE4AC90008A4842 /* api_mark_point.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45201E921CE4AC90008A4842 /* api_mark_point.cpp */; }; + 45580ABE1E2CBD5E00CD535D /* benchmark_tools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45580ABC1E2CBD5E00CD535D /* benchmark_tools.cpp */; }; + 45580ABF1E2CBD5E00CD535D /* benchmark_tools.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 45580ABD1E2CBD5E00CD535D /* benchmark_tools.hpp */; }; 670E39401C46C5C700E9C0A6 /* gps_tracker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 670E393E1C46C5C700E9C0A6 /* gps_tracker.cpp */; }; 670E39411C46C5C700E9C0A6 /* gps_tracker.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 670E393F1C46C5C700E9C0A6 /* gps_tracker.hpp */; }; 674231CB1DF984F600913FEB /* libtraffic.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 674231CA1DF984F600913FEB /* libtraffic.a */; }; @@ -129,6 +131,8 @@ 34DDA17F1DBE5DF40088A609 /* libpartners_api.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpartners_api.a; path = "/Users/igrechuhin/Repo/omim/xcode/partners_api/../../../omim-xcode-build/Debug/libpartners_api.a"; sourceTree = ""; }; 34DDA1801DBE5DF40088A609 /* libtracking.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtracking.a; path = "/Users/igrechuhin/Repo/omim/xcode/tracking/../../../omim-xcode-build/Debug/libtracking.a"; sourceTree = ""; }; 45201E921CE4AC90008A4842 /* api_mark_point.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = api_mark_point.cpp; sourceTree = ""; }; + 45580ABC1E2CBD5E00CD535D /* benchmark_tools.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = benchmark_tools.cpp; sourceTree = ""; }; + 45580ABD1E2CBD5E00CD535D /* benchmark_tools.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = benchmark_tools.hpp; sourceTree = ""; }; 670E393E1C46C5C700E9C0A6 /* gps_tracker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gps_tracker.cpp; sourceTree = ""; }; 670E393F1C46C5C700E9C0A6 /* gps_tracker.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = gps_tracker.hpp; sourceTree = ""; }; 674231CA1DF984F600913FEB /* libtraffic.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtraffic.a; path = "../../../omim-build/xcode/Debug/libtraffic.a"; sourceTree = ""; }; @@ -390,6 +394,8 @@ 675345BD1A4054AD00A0A8C3 /* map */ = { isa = PBXGroup; children = ( + 45580ABD1E2CBD5E00CD535D /* benchmark_tools.hpp */, + 45580ABC1E2CBD5E00CD535D /* benchmark_tools.cpp */, F63421F61DF9BF9100A96868 /* reachable_by_taxi_checker.cpp */, F63421F71DF9BF9100A96868 /* reachable_by_taxi_checker.hpp */, 347B60741DD9926D0050FA24 /* traffic_manager.cpp */, @@ -466,6 +472,7 @@ 675346651A4054E800A0A8C3 /* framework.hpp in Headers */, 674A2A381B2715FB001A525C /* osm_opening_hours.hpp in Headers */, 670E39411C46C5C700E9C0A6 /* gps_tracker.hpp in Headers */, + 45580ABF1E2CBD5E00CD535D /* benchmark_tools.hpp in Headers */, 342D833B1D5233E8000D8AEA /* displacement_mode_manager.hpp in Headers */, F6B283041C1B03320081957A /* gps_track_collection.hpp in Headers */, ); @@ -590,6 +597,7 @@ 6753463A1A4054E800A0A8C3 /* address_finder.cpp in Sources */, 670E39401C46C5C700E9C0A6 /* gps_tracker.cpp in Sources */, 6753464A1A4054E800A0A8C3 /* bookmark.cpp in Sources */, + 45580ABE1E2CBD5E00CD535D /* benchmark_tools.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };