From 7cd7fa2f08eaba7de05532a2a1998f2f751959f7 Mon Sep 17 00:00:00 2001 From: Frederic Chardon Date: Wed, 27 Jan 2021 08:04:33 +0000 Subject: [PATCH] Collect all available stats if OPENMW_OSG_STATS_FILE is set and point to a valid file. --- apps/openmw/engine.cpp | 27 ++++--- apps/openmw/mwphysics/mtphysics.cpp | 2 + components/resource/stats.cpp | 110 +++++++++++++++++++++++++++- components/resource/stats.hpp | 11 ++- 4 files changed, 135 insertions(+), 15 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index ead2726cd..a81a37337 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -177,6 +177,8 @@ namespace ~ScopedProfile() { + if (!mStats.collectStats("engine")) + return; const osg::Timer_t end = mTimer.tick(); const UserStats& stats = UserStatsValue::sValue; @@ -863,16 +865,29 @@ void OMW::Engine::go() prepareEngine (settings); + std::ofstream stats; + if (const auto path = std::getenv("OPENMW_OSG_STATS_FILE")) + { + stats.open(path, std::ios_base::out); + if (stats.is_open()) + Log(Debug::Info) << "Stats will be written to: " << path; + else + Log(Debug::Warning) << "Failed to open file for stats: " << path; + } + // Setup profiler - osg::ref_ptr statshandler = new Resource::Profiler; + osg::ref_ptr statshandler = new Resource::Profiler(stats.is_open()); initStatsHandler(*statshandler); mViewer->addEventHandler(statshandler); - osg::ref_ptr resourceshandler = new Resource::StatsHandler; + osg::ref_ptr resourceshandler = new Resource::StatsHandler(stats.is_open()); mViewer->addEventHandler(resourceshandler); + if (stats.is_open()) + Resource::CollectStatistics(mViewer); + // Start the game if (!mSaveGameFile.empty()) { @@ -897,14 +912,6 @@ void OMW::Engine::go() mEnvironment.getWindowManager()->executeInConsole(mStartupScript); } - std::ofstream stats; - if (const auto path = std::getenv("OPENMW_OSG_STATS_FILE")) - { - stats.open(path, std::ios_base::out); - if (!stats) - Log(Debug::Warning) << "Failed to open file for stats: " << path; - } - // Start the main rendering loop osg::Timer frameTimer; double simulationTime = 0.0; diff --git a/apps/openmw/mwphysics/mtphysics.cpp b/apps/openmw/mwphysics/mtphysics.cpp index 6c7c573a4..754bb60af 100644 --- a/apps/openmw/mwphysics/mtphysics.cpp +++ b/apps/openmw/mwphysics/mtphysics.cpp @@ -540,6 +540,8 @@ namespace MWPhysics void PhysicsTaskScheduler::updateStats(osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats) { + if (!stats.collectStats("engine")) + return; if (mFrameNumber == frameNumber - 1) { stats.setAttribute(mFrameNumber, "physicsworker_time_begin", mTimer->delta_s(mFrameStart, mTimeBegin)); diff --git a/components/resource/stats.cpp b/components/resource/stats.cpp index 942bd92d8..28b90c31c 100644 --- a/components/resource/stats.cpp +++ b/components/resource/stats.cpp @@ -18,10 +18,72 @@ namespace Resource { -StatsHandler::StatsHandler(): +static bool collectStatRendering = false; +static bool collectStatCameraObjects = false; +static bool collectStatViewerObjects = false; +static bool collectStatResource = false; +static bool collectStatGPU = false; +static bool collectStatEvent = false; +static bool collectStatFrameRate = false; +static bool collectStatUpdate = false; +static bool collectStatEngine = false; + +static void setupStatCollection() +{ + const char* envList = getenv("OPENMW_OSG_STATS_LIST"); + if (envList == nullptr) + return; + + std::string_view kwList(envList); + + auto kwBegin = kwList.begin(); + + while (kwBegin != kwList.end()) + { + auto kwEnd = std::find(kwBegin, kwList.end(), ';'); + + const auto kw = kwList.substr(std::distance(kwList.begin(), kwBegin), std::distance(kwBegin, kwEnd)); + + if (kw.compare("gpu") == 0) + collectStatGPU = true; + else if (kw.compare("event") == 0) + collectStatEvent = true; + else if (kw.compare("frame_rate") == 0) + collectStatFrameRate = true; + else if (kw.compare("update") == 0) + collectStatUpdate = true; + else if (kw.compare("engine") == 0) + collectStatEngine = true; + else if (kw.compare("rendering") == 0) + collectStatRendering = true; + else if (kw.compare("cameraobjects") == 0) + collectStatCameraObjects = true; + else if (kw.compare("viewerobjects") == 0) + collectStatViewerObjects = true; + else if (kw.compare("resource") == 0) + collectStatResource = true; + else if (kw.compare("times") == 0) + { + collectStatGPU = true; + collectStatEvent = true; + collectStatFrameRate = true; + collectStatUpdate = true; + collectStatEngine = true; + collectStatRendering = true; + } + + if (kwEnd == kwList.end()) + break; + + kwBegin = std::next(kwEnd); + } +} + +StatsHandler::StatsHandler(bool offlineCollect): _key(osgGA::GUIEventAdapter::KEY_F4), _initialized(false), _statsType(false), + _offlineCollect(offlineCollect), _statsWidth(1280.0f), _statsHeight(1024.0f), _font(""), @@ -38,7 +100,8 @@ StatsHandler::StatsHandler(): _font = osgMyGUI::DataManager::getInstance().getDataPath("DejaVuLGCSansMono.ttf"); } -Profiler::Profiler() +Profiler::Profiler(bool offlineCollect): + _offlineCollect(offlineCollect) { if (osgDB::Registry::instance()->getReaderWriterForExtension("ttf")) _font = osgMyGUI::DataManager::getInstance().getDataPath("DejaVuLGCSansMono.ttf"); @@ -48,6 +111,28 @@ Profiler::Profiler() _characterSize = 18; setKeyEventTogglesOnScreenStats(osgGA::GUIEventAdapter::KEY_F3); + setupStatCollection(); +} + +bool Profiler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa) +{ + osgViewer::ViewerBase* viewer = nullptr; + + bool handled = StatsHandler::handle(ea, aa); + + auto* view = dynamic_cast(&aa); + if (view) + viewer = view->getViewerBase(); + + if (viewer) + { + // Add/remove openmw stats to the osd as necessary + viewer->getViewerStats()->collectStats("engine", _statsType == StatsHandler::StatsType::VIEWER_STATS); + + if (_offlineCollect) + CollectStatistics(viewer); + } + return handled; } bool StatsHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa) @@ -67,6 +152,9 @@ bool StatsHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdap toggle(viewer); + if (_offlineCollect) + CollectStatistics(viewer); + aa.requestRedraw(); return true; } @@ -370,6 +458,22 @@ void StatsHandler::getUsage(osg::ApplicationUsage &usage) const usage.addKeyboardMouseBinding(_key, "On screen resource usage stats."); } - +void CollectStatistics(osgViewer::ViewerBase* viewer) +{ + osgViewer::Viewer::Cameras cameras; + viewer->getCameras(cameras); + for (auto* camera : cameras) + { + if (collectStatGPU) camera->getStats()->collectStats("gpu", true); + if (collectStatRendering) camera->getStats()->collectStats("rendering", true); + if (collectStatCameraObjects) camera->getStats()->collectStats("scene", true); + } + if (collectStatEvent) viewer->getViewerStats()->collectStats("event", true); + if (collectStatFrameRate) viewer->getViewerStats()->collectStats("frame_rate", true); + if (collectStatUpdate) viewer->getViewerStats()->collectStats("update", true); + if (collectStatResource) viewer->getViewerStats()->collectStats("resource", true); + if (collectStatViewerObjects) viewer->getViewerStats()->collectStats("scene", true); + if (collectStatEngine) viewer->getViewerStats()->collectStats("engine", true); +} } diff --git a/components/resource/stats.hpp b/components/resource/stats.hpp index 9fa583cca..560275d70 100644 --- a/components/resource/stats.hpp +++ b/components/resource/stats.hpp @@ -18,13 +18,17 @@ namespace Resource class Profiler : public osgViewer::StatsHandler { public: - Profiler(); + Profiler(bool offlineCollect); + bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) override; + + private: + bool _offlineCollect; }; class StatsHandler : public osgGA::GUIEventHandler { public: - StatsHandler(); + StatsHandler(bool offlineCollect); void setKey(int key) { _key = key; } int getKey() const { return _key; } @@ -47,6 +51,7 @@ namespace Resource osg::ref_ptr _camera; bool _initialized; bool _statsType; + bool _offlineCollect; float _statsWidth; float _statsHeight; @@ -58,6 +63,8 @@ namespace Resource }; + void CollectStatistics(osgViewer::ViewerBase* viewer); + } #endif