diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 4fae3061a7..98869703f9 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -32,6 +32,8 @@ #include +#include + #include "mwinput/inputmanagerimp.hpp" #include "mwgui/windowmanagerimp.hpp" @@ -198,6 +200,8 @@ bool OMW::Engine::frame(float frametime) stats->setAttribute(frameNumber, "WorkQueue", mWorkQueue->getNumItems()); stats->setAttribute(frameNumber, "WorkThread", mWorkQueue->getNumActiveThreads()); + + mEnvironment.getWorld()->getNavigator()->reportStats(frameNumber, *stats); } } diff --git a/components/detournavigator/asyncnavmeshupdater.cpp b/components/detournavigator/asyncnavmeshupdater.cpp index 2013931edf..6bd4f01c9e 100644 --- a/components/detournavigator/asyncnavmeshupdater.cpp +++ b/components/detournavigator/asyncnavmeshupdater.cpp @@ -5,6 +5,8 @@ #include +#include + namespace { using DetourNavigator::ChangeType; @@ -102,6 +104,20 @@ namespace DetourNavigator mDone.wait(lock, [&] { return mJobs.empty(); }); } + void AsyncNavMeshUpdater::reportStats(unsigned int frameNumber, osg::Stats& stats) const + { + std::size_t jobs = 0; + + { + const std::lock_guard lock(mMutex); + jobs = mJobs.size(); + } + + stats.setAttribute(frameNumber, "NavMesh UpdateJobs", jobs); + + mNavMeshTilesCache.reportStats(frameNumber, stats); + } + void AsyncNavMeshUpdater::process() throw() { log("start process jobs"); diff --git a/components/detournavigator/asyncnavmeshupdater.hpp b/components/detournavigator/asyncnavmeshupdater.hpp index 55e502b453..3493ba02f6 100644 --- a/components/detournavigator/asyncnavmeshupdater.hpp +++ b/components/detournavigator/asyncnavmeshupdater.hpp @@ -44,6 +44,8 @@ namespace DetourNavigator void wait(); + void reportStats(unsigned int frameNumber, osg::Stats& stats) const; + private: struct Job { @@ -72,7 +74,7 @@ namespace DetourNavigator std::reference_wrapper mRecastMeshManager; std::reference_wrapper mOffMeshConnectionsManager; std::atomic_bool mShouldStop; - std::mutex mMutex; + mutable std::mutex mMutex; std::condition_variable mHasJob; std::condition_variable mDone; Jobs mJobs; diff --git a/components/detournavigator/navigator.hpp b/components/detournavigator/navigator.hpp index d9c5ebe0b5..561b7f02b5 100644 --- a/components/detournavigator/navigator.hpp +++ b/components/detournavigator/navigator.hpp @@ -192,6 +192,8 @@ namespace DetourNavigator virtual std::map getNavMeshes() const = 0; virtual const Settings& getSettings() const = 0; + + virtual void reportStats(unsigned int frameNumber, osg::Stats& stats) const = 0; }; } diff --git a/components/detournavigator/navigatorimpl.cpp b/components/detournavigator/navigatorimpl.cpp index a62220e555..b743f26b21 100644 --- a/components/detournavigator/navigatorimpl.cpp +++ b/components/detournavigator/navigatorimpl.cpp @@ -138,6 +138,11 @@ namespace DetourNavigator return mSettings; } + void NavigatorImpl::reportStats(unsigned int frameNumber, osg::Stats& stats) const + { + mNavMeshManager.reportStats(frameNumber, stats); + } + void NavigatorImpl::updateAvoidShapeId(const ObjectId id, const ObjectId avoidId) { updateId(id, avoidId, mWaterIds); diff --git a/components/detournavigator/navigatorimpl.hpp b/components/detournavigator/navigatorimpl.hpp index d2ff8a57bd..b6b3b1b7f5 100644 --- a/components/detournavigator/navigatorimpl.hpp +++ b/components/detournavigator/navigatorimpl.hpp @@ -48,6 +48,8 @@ namespace DetourNavigator const Settings& getSettings() const override; + void reportStats(unsigned int frameNumber, osg::Stats& stats) const override; + private: Settings mSettings; NavMeshManager mNavMeshManager; diff --git a/components/detournavigator/navigatorstub.hpp b/components/detournavigator/navigatorstub.hpp index cab93b1052..885482a453 100644 --- a/components/detournavigator/navigatorstub.hpp +++ b/components/detournavigator/navigatorstub.hpp @@ -79,6 +79,8 @@ namespace DetourNavigator return mDefaultSettings; } + void reportStats(unsigned int /*frameNumber*/, osg::Stats& /*stats*/) const override {} + private: Settings mDefaultSettings {}; SharedNavMeshCacheItem mEmptyNavMeshCacheItem; diff --git a/components/detournavigator/navmeshmanager.cpp b/components/detournavigator/navmeshmanager.cpp index fc3563acee..c3e13ad7fb 100644 --- a/components/detournavigator/navmeshmanager.cpp +++ b/components/detournavigator/navmeshmanager.cpp @@ -212,6 +212,11 @@ namespace DetourNavigator return mCache; } + void NavMeshManager::reportStats(unsigned int frameNumber, osg::Stats& stats) const + { + mAsyncNavMeshUpdater.reportStats(frameNumber, stats); + } + void NavMeshManager::addChangedTiles(const btCollisionShape& shape, const btTransform& transform, const ChangeType changeType) { diff --git a/components/detournavigator/navmeshmanager.hpp b/components/detournavigator/navmeshmanager.hpp index cee33c63df..3ef898b050 100644 --- a/components/detournavigator/navmeshmanager.hpp +++ b/components/detournavigator/navmeshmanager.hpp @@ -50,6 +50,8 @@ namespace DetourNavigator std::map getNavMeshes() const; + void reportStats(unsigned int frameNumber, osg::Stats& stats) const; + private: const Settings& mSettings; TileCachedRecastMeshManager mRecastMeshManager; diff --git a/components/detournavigator/navmeshtilescache.cpp b/components/detournavigator/navmeshtilescache.cpp index 8dd14f04c3..466d2e708d 100644 --- a/components/detournavigator/navmeshtilescache.cpp +++ b/components/detournavigator/navmeshtilescache.cpp @@ -1,6 +1,8 @@ #include "navmeshtilescache.hpp" #include "exceptions.hpp" +#include + #include namespace DetourNavigator @@ -113,6 +115,24 @@ namespace DetourNavigator return Value(*this, iterator); } + void NavMeshTilesCache::reportStats(unsigned int frameNumber, osg::Stats& stats) const + { + std::size_t navMeshCacheSize = 0; + std::size_t usedNavMeshTiles = 0; + std::size_t cachedNavMeshTiles = 0; + + { + const std::lock_guard lock(mMutex); + navMeshCacheSize = mUsedNavMeshDataSize; + usedNavMeshTiles = mBusyItems.size(); + cachedNavMeshTiles = mFreeItems.size(); + } + + stats.setAttribute(frameNumber, "NavMesh CacheSize", navMeshCacheSize); + stats.setAttribute(frameNumber, "NavMesh UsedTiles", usedNavMeshTiles); + stats.setAttribute(frameNumber, "NavMesh CachedTiles", cachedNavMeshTiles); + } + void NavMeshTilesCache::removeLeastRecentlyUsed() { const auto& item = mFreeItems.back(); diff --git a/components/detournavigator/navmeshtilescache.hpp b/components/detournavigator/navmeshtilescache.hpp index 3f2e0cc019..5d5db47a8f 100644 --- a/components/detournavigator/navmeshtilescache.hpp +++ b/components/detournavigator/navmeshtilescache.hpp @@ -12,6 +12,11 @@ #include #include +namespace osg +{ + class Stats; +} + namespace DetourNavigator { struct NavMeshDataRef @@ -105,6 +110,8 @@ namespace DetourNavigator const RecastMesh& recastMesh, const std::vector& offMeshConnections, NavMeshData&& value); + void reportStats(unsigned int frameNumber, osg::Stats& stats) const; + private: class KeyView { @@ -164,7 +171,7 @@ namespace DetourNavigator std::map mMap; }; - std::mutex mMutex; + mutable std::mutex mMutex; std::size_t mMaxNavMeshDataSize; std::size_t mUsedNavMeshDataSize; std::size_t mFreeNavMeshDataSize; diff --git a/components/resource/stats.cpp b/components/resource/stats.cpp index b23558e99b..51497cd279 100644 --- a/components/resource/stats.cpp +++ b/components/resource/stats.cpp @@ -2,6 +2,7 @@ #include #include +#include #include @@ -255,7 +256,7 @@ void StatsHandler::setUpScene(osgViewer::ViewerBase *viewer) stateset->setAttribute(new osg::PolygonMode(), osg::StateAttribute::PROTECTED); #endif - osg::Vec3 pos(_statsWidth-300.f, _statsHeight-500.0f,0.0f); + osg::Vec3 pos(_statsWidth-420.f, _statsHeight-500.0f,0.0f); osg::Vec4 backgroundColor(0.0, 0.0, 0.0f, 0.3); osg::Vec4 staticTextColor(1.0, 1.0, 0.0f, 1.0); osg::Vec4 dynamicTextColor(1.0, 1.0, 1.0f, 1.0); @@ -290,12 +291,20 @@ void StatsHandler::setUpScene(osgViewer::ViewerBase *viewer) "Composite", "", "UnrefQueue", + "", + "NavMesh UpdateJobs", + "NavMesh CacheSize", + "NavMesh UsedTiles", + "NavMesh CachedTiles", }); + static const auto longest = std::max_element(statNames.begin(), statNames.end(), + [] (const std::string& lhs, const std::string& rhs) { return lhs.size() < rhs.size(); }); const int numLines = statNames.size(); + const float statNamesWidth = 13 * _characterSize + 2 * backgroundMargin; group->addChild(createBackgroundRectangle(pos + osg::Vec3(-backgroundMargin, _characterSize + backgroundMargin, 0), - 10 * _characterSize + 2 * backgroundMargin, + statNamesWidth, numLines * _characterSize + 2 * backgroundMargin, backgroundColor)); @@ -309,7 +318,7 @@ void StatsHandler::setUpScene(osgViewer::ViewerBase *viewer) std::ostringstream viewStr; viewStr.clear(); viewStr.setf(std::ios::left, std::ios::adjustfield); - viewStr.width(14); + viewStr.width(longest->size()); for (const auto& statName : statNames) { viewStr << statName << std::endl; @@ -317,10 +326,10 @@ void StatsHandler::setUpScene(osgViewer::ViewerBase *viewer) staticText->setText(viewStr.str()); - pos.x() += 10 * _characterSize + 2 * backgroundMargin + backgroundSpacing; + pos.x() += statNamesWidth + backgroundSpacing; group->addChild(createBackgroundRectangle(pos + osg::Vec3(-backgroundMargin, _characterSize + backgroundMargin, 0), - 5 * _characterSize + 2 * backgroundMargin, + 7 * _characterSize + 2 * backgroundMargin, numLines * _characterSize + 2 * backgroundMargin, backgroundColor));