mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-28 20:09:42 +00:00
Merge branch 'more_stats' into 'master'
Report more stats in F4 See merge request OpenMW/openmw!3956
This commit is contained in:
commit
3da6b4f529
25 changed files with 602 additions and 408 deletions
|
@ -965,17 +965,17 @@ void OMW::Engine::go()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup profiler
|
// Setup profiler
|
||||||
osg::ref_ptr<Resource::Profiler> statshandler = new Resource::Profiler(stats.is_open(), mVFS.get());
|
osg::ref_ptr<Resource::Profiler> statsHandler = new Resource::Profiler(stats.is_open(), *mVFS);
|
||||||
|
|
||||||
initStatsHandler(*statshandler);
|
initStatsHandler(*statsHandler);
|
||||||
|
|
||||||
mViewer->addEventHandler(statshandler);
|
mViewer->addEventHandler(statsHandler);
|
||||||
|
|
||||||
osg::ref_ptr<Resource::StatsHandler> resourceshandler = new Resource::StatsHandler(stats.is_open(), mVFS.get());
|
osg::ref_ptr<Resource::StatsHandler> resourcesHandler = new Resource::StatsHandler(stats.is_open(), *mVFS);
|
||||||
mViewer->addEventHandler(resourceshandler);
|
mViewer->addEventHandler(resourcesHandler);
|
||||||
|
|
||||||
if (stats.is_open())
|
if (stats.is_open())
|
||||||
Resource::CollectStatistics(mViewer);
|
Resource::collectStatistics(*mViewer);
|
||||||
|
|
||||||
// Start the game
|
// Start the game
|
||||||
if (!mSaveGameFile.empty())
|
if (!mSaveGameFile.empty())
|
||||||
|
|
|
@ -463,6 +463,6 @@ namespace MWRender
|
||||||
|
|
||||||
void Groundcover::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
void Groundcover::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
||||||
{
|
{
|
||||||
stats->setAttribute(frameNumber, "Groundcover Chunk", mCache->getCacheSize());
|
Resource::reportStats("Groundcover Chunk", frameNumber, mCache->getStats(), *stats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
#include "landmanager.hpp"
|
#include "landmanager.hpp"
|
||||||
|
|
||||||
#include <osg/Stats>
|
|
||||||
|
|
||||||
#include <components/esm4/loadwrld.hpp>
|
#include <components/esm4/loadwrld.hpp>
|
||||||
#include <components/resource/objectcache.hpp>
|
#include <components/resource/objectcache.hpp>
|
||||||
#include <components/settings/values.hpp>
|
#include <components/settings/values.hpp>
|
||||||
|
@ -53,7 +51,7 @@ namespace MWRender
|
||||||
|
|
||||||
void LandManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
void LandManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
||||||
{
|
{
|
||||||
stats->setAttribute(frameNumber, "Land", mCache->getCacheSize());
|
Resource::reportStats("Land", frameNumber, mCache->getStats(), *stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1013,7 +1013,7 @@ namespace MWRender
|
||||||
|
|
||||||
void ObjectPaging::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
void ObjectPaging::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
||||||
{
|
{
|
||||||
stats->setAttribute(frameNumber, "Object Chunk", mCache->getCacheSize());
|
Resource::reportStats("Object Chunk", frameNumber, mCache->getStats(), *stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
|
#include <osg/Stats>
|
||||||
|
|
||||||
#include <components/debug/debuglog.hpp>
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/esm3/loadcell.hpp>
|
#include <components/esm3/loadcell.hpp>
|
||||||
#include <components/loadinglistener/reporter.hpp>
|
#include <components/loadinglistener/reporter.hpp>
|
||||||
|
@ -276,6 +278,7 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
oldestCell->second.mWorkItem->abort();
|
oldestCell->second.mWorkItem->abort();
|
||||||
mPreloadCells.erase(oldestCell);
|
mPreloadCells.erase(oldestCell);
|
||||||
|
++mEvicted;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
@ -285,7 +288,8 @@ namespace MWWorld
|
||||||
mResourceSystem->getKeyframeManager(), mTerrain, mLandManager, mPreloadInstances));
|
mResourceSystem->getKeyframeManager(), mTerrain, mLandManager, mPreloadInstances));
|
||||||
mWorkQueue->addWorkItem(item);
|
mWorkQueue->addWorkItem(item);
|
||||||
|
|
||||||
mPreloadCells[&cell] = PreloadEntry(timestamp, item);
|
mPreloadCells.emplace(&cell, PreloadEntry(timestamp, item));
|
||||||
|
++mAdded;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CellPreloader::notifyLoaded(CellStore* cell)
|
void CellPreloader::notifyLoaded(CellStore* cell)
|
||||||
|
@ -300,6 +304,7 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
|
|
||||||
mPreloadCells.erase(found);
|
mPreloadCells.erase(found);
|
||||||
|
++mLoaded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,6 +334,7 @@ namespace MWWorld
|
||||||
it->second.mWorkItem = nullptr;
|
it->second.mWorkItem = nullptr;
|
||||||
}
|
}
|
||||||
mPreloadCells.erase(it++);
|
mPreloadCells.erase(it++);
|
||||||
|
++mExpired;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
++it;
|
++it;
|
||||||
|
@ -467,4 +473,12 @@ namespace MWWorld
|
||||||
mPreloadCells.clear();
|
mPreloadCells.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CellPreloader::reportStats(unsigned int frameNumber, osg::Stats& stats) const
|
||||||
|
{
|
||||||
|
stats.setAttribute(frameNumber, "CellPreloader Count", mPreloadCells.size());
|
||||||
|
stats.setAttribute(frameNumber, "CellPreloader Added", mAdded);
|
||||||
|
stats.setAttribute(frameNumber, "CellPreloader Evicted", mEvicted);
|
||||||
|
stats.setAttribute(frameNumber, "CellPreloader Loaded", mLoaded);
|
||||||
|
stats.setAttribute(frameNumber, "CellPreloader Expired", mExpired);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,20 @@
|
||||||
#define OPENMW_MWWORLD_CELLPRELOADER_H
|
#define OPENMW_MWWORLD_CELLPRELOADER_H
|
||||||
|
|
||||||
#include <components/sceneutil/workqueue.hpp>
|
#include <components/sceneutil/workqueue.hpp>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include <osg/Vec3f>
|
#include <osg/Vec3f>
|
||||||
#include <osg/Vec4i>
|
#include <osg/Vec4i>
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace osg
|
||||||
|
{
|
||||||
|
class Stats;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Resource
|
namespace Resource
|
||||||
{
|
{
|
||||||
class ResourceSystem;
|
class ResourceSystem;
|
||||||
|
@ -76,6 +85,8 @@ namespace MWWorld
|
||||||
bool isTerrainLoaded(const CellPreloader::PositionCellGrid& position, double referenceTime) const;
|
bool isTerrainLoaded(const CellPreloader::PositionCellGrid& position, double referenceTime) const;
|
||||||
void setTerrain(Terrain::World* terrain);
|
void setTerrain(Terrain::World* terrain);
|
||||||
|
|
||||||
|
void reportStats(unsigned int frameNumber, osg::Stats& stats) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void clearAllTasks();
|
void clearAllTasks();
|
||||||
|
|
||||||
|
@ -118,6 +129,10 @@ namespace MWWorld
|
||||||
|
|
||||||
std::vector<PositionCellGrid> mLoadedTerrainPositions;
|
std::vector<PositionCellGrid> mLoadedTerrainPositions;
|
||||||
double mLoadedTerrainTimestamp;
|
double mLoadedTerrainTimestamp;
|
||||||
|
std::size_t mEvicted = 0;
|
||||||
|
std::size_t mAdded = 0;
|
||||||
|
std::size_t mExpired = 0;
|
||||||
|
std::size_t mLoaded = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1285,4 +1285,9 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Scene::reportStats(unsigned int frameNumber, osg::Stats& stats) const
|
||||||
|
{
|
||||||
|
mPreloader->reportStats(frameNumber, stats);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
namespace osg
|
namespace osg
|
||||||
{
|
{
|
||||||
class Vec3f;
|
class Vec3f;
|
||||||
|
class Stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
|
@ -203,6 +204,8 @@ namespace MWWorld
|
||||||
|
|
||||||
void testExteriorCells();
|
void testExteriorCells();
|
||||||
void testInteriorCells();
|
void testInteriorCells();
|
||||||
|
|
||||||
|
void reportStats(unsigned int frameNumber, osg::Stats& stats) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3786,6 +3786,7 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
DetourNavigator::reportStats(mNavigator->getStats(), frameNumber, stats);
|
DetourNavigator::reportStats(mNavigator->getStats(), frameNumber, stats);
|
||||||
mPhysics->reportStats(frameNumber, stats);
|
mPhysics->reportStats(frameNumber, stats);
|
||||||
|
mWorldScene->reportStats(frameNumber, stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::updateSkyDate()
|
void World::updateSkyDate()
|
||||||
|
|
|
@ -114,9 +114,11 @@ namespace Resource
|
||||||
|
|
||||||
cache->update(referenceTime, expiryDelay);
|
cache->update(referenceTime, expiryDelay);
|
||||||
ASSERT_THAT(cache->getRefFromObjectCacheOrNone(key), Optional(_));
|
ASSERT_THAT(cache->getRefFromObjectCacheOrNone(key), Optional(_));
|
||||||
|
ASSERT_EQ(cache->getStats().mExpired, 0);
|
||||||
|
|
||||||
cache->update(referenceTime + expiryDelay, expiryDelay);
|
cache->update(referenceTime + expiryDelay, expiryDelay);
|
||||||
EXPECT_EQ(cache->getRefFromObjectCacheOrNone(key), std::nullopt);
|
EXPECT_EQ(cache->getRefFromObjectCacheOrNone(key), std::nullopt);
|
||||||
|
ASSERT_EQ(cache->getStats().mExpired, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ResourceGenericObjectCacheTest, updateShouldKeepExternallyReferencedItems)
|
TEST(ResourceGenericObjectCacheTest, updateShouldKeepExternallyReferencedItems)
|
||||||
|
@ -249,7 +251,7 @@ namespace Resource
|
||||||
EXPECT_THAT(actual, ElementsAre(Pair(1, value1.get()), Pair(2, value2.get()), Pair(3, value3.get())));
|
EXPECT_THAT(actual, ElementsAre(Pair(1, value1.get()), Pair(2, value2.get()), Pair(3, value3.get())));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ResourceGenericObjectCacheTest, getCacheSizeShouldReturnNumberOrAddedItems)
|
TEST(ResourceGenericObjectCacheTest, getStatsShouldReturnNumberOrAddedItems)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
||||||
|
|
||||||
|
@ -258,7 +260,33 @@ namespace Resource
|
||||||
cache->addEntryToObjectCache(13, value1);
|
cache->addEntryToObjectCache(13, value1);
|
||||||
cache->addEntryToObjectCache(42, value2);
|
cache->addEntryToObjectCache(42, value2);
|
||||||
|
|
||||||
EXPECT_EQ(cache->getCacheSize(), 2);
|
const CacheStats stats = cache->getStats();
|
||||||
|
|
||||||
|
EXPECT_EQ(stats.mSize, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ResourceGenericObjectCacheTest, getStatsShouldReturnNumberOrGetsAndHits)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
||||||
|
|
||||||
|
{
|
||||||
|
const CacheStats stats = cache->getStats();
|
||||||
|
|
||||||
|
EXPECT_EQ(stats.mGet, 0);
|
||||||
|
EXPECT_EQ(stats.mHit, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::ref_ptr<Object> value(new Object);
|
||||||
|
cache->addEntryToObjectCache(13, value);
|
||||||
|
cache->getRefFromObjectCache(13);
|
||||||
|
cache->getRefFromObjectCache(42);
|
||||||
|
|
||||||
|
{
|
||||||
|
const CacheStats stats = cache->getStats();
|
||||||
|
|
||||||
|
EXPECT_EQ(stats.mGet, 2);
|
||||||
|
EXPECT_EQ(stats.mHit, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ResourceGenericObjectCacheTest, lowerBoundShouldReturnFirstNotLessThatGivenKey)
|
TEST(ResourceGenericObjectCacheTest, lowerBoundShouldReturnFirstNotLessThatGivenKey)
|
||||||
|
|
|
@ -125,7 +125,7 @@ add_component_dir (vfs
|
||||||
|
|
||||||
add_component_dir (resource
|
add_component_dir (resource
|
||||||
scenemanager keyframemanager imagemanager bulletshapemanager bulletshape niffilemanager objectcache multiobjectcache resourcesystem
|
scenemanager keyframemanager imagemanager bulletshapemanager bulletshape niffilemanager objectcache multiobjectcache resourcesystem
|
||||||
resourcemanager stats animation foreachbulletobject errormarker
|
resourcemanager stats animation foreachbulletobject errormarker cachestats
|
||||||
)
|
)
|
||||||
|
|
||||||
add_component_dir (shader
|
add_component_dir (shader
|
||||||
|
|
|
@ -213,8 +213,8 @@ namespace Resource
|
||||||
|
|
||||||
void BulletShapeManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
void BulletShapeManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
||||||
{
|
{
|
||||||
stats->setAttribute(frameNumber, "Shape", mCache->getCacheSize());
|
Resource::reportStats("Shape", frameNumber, mCache->getStats(), *stats);
|
||||||
stats->setAttribute(frameNumber, "Shape Instance", mInstanceCache->getCacheSize());
|
Resource::reportStats("Shape Instance", frameNumber, mInstanceCache->getStats(), *stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
40
components/resource/cachestats.cpp
Normal file
40
components/resource/cachestats.cpp
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#include "cachestats.hpp"
|
||||||
|
|
||||||
|
#include <osg/Stats>
|
||||||
|
|
||||||
|
namespace Resource
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
std::string makeAttribute(std::string_view prefix, std::string_view suffix)
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
result.reserve(prefix.size() + 1 + suffix.size());
|
||||||
|
result += prefix;
|
||||||
|
result += ' ';
|
||||||
|
result += suffix;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void addCacheStatsAttibutes(std::string_view prefix, std::vector<std::string>& out)
|
||||||
|
{
|
||||||
|
constexpr std::string_view suffixes[] = {
|
||||||
|
"Count",
|
||||||
|
"Get",
|
||||||
|
"Hit",
|
||||||
|
"Expired",
|
||||||
|
};
|
||||||
|
|
||||||
|
for (std::string_view suffix : suffixes)
|
||||||
|
out.push_back(makeAttribute(prefix, suffix));
|
||||||
|
}
|
||||||
|
|
||||||
|
void reportStats(std::string_view prefix, unsigned frameNumber, const CacheStats& src, osg::Stats& dst)
|
||||||
|
{
|
||||||
|
dst.setAttribute(frameNumber, makeAttribute(prefix, "Count"), static_cast<double>(src.mSize));
|
||||||
|
dst.setAttribute(frameNumber, makeAttribute(prefix, "Get"), static_cast<double>(src.mGet));
|
||||||
|
dst.setAttribute(frameNumber, makeAttribute(prefix, "Hit"), static_cast<double>(src.mHit));
|
||||||
|
dst.setAttribute(frameNumber, makeAttribute(prefix, "Expired"), static_cast<double>(src.mExpired));
|
||||||
|
}
|
||||||
|
}
|
28
components/resource/cachestats.hpp
Normal file
28
components/resource/cachestats.hpp
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef OPENMW_COMPONENTS_RESOURCE_CACHESATS
|
||||||
|
#define OPENMW_COMPONENTS_RESOURCE_CACHESATS
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace osg
|
||||||
|
{
|
||||||
|
class Stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Resource
|
||||||
|
{
|
||||||
|
struct CacheStats
|
||||||
|
{
|
||||||
|
std::size_t mSize = 0;
|
||||||
|
std::size_t mGet = 0;
|
||||||
|
std::size_t mHit = 0;
|
||||||
|
std::size_t mExpired = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void addCacheStatsAttibutes(std::string_view prefix, std::vector<std::string>& out);
|
||||||
|
|
||||||
|
void reportStats(std::string_view prefix, unsigned frameNumber, const CacheStats& src, osg::Stats& dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -202,7 +202,7 @@ namespace Resource
|
||||||
|
|
||||||
void ImageManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
void ImageManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
||||||
{
|
{
|
||||||
stats->setAttribute(frameNumber, "Image", mCache->getCacheSize());
|
Resource::reportStats("Image", frameNumber, mCache->getStats(), *stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
|
|
||||||
#include <osg/Stats>
|
|
||||||
#include <osgAnimation/Animation>
|
#include <osgAnimation/Animation>
|
||||||
#include <osgAnimation/BasicAnimationManager>
|
#include <osgAnimation/BasicAnimationManager>
|
||||||
#include <osgAnimation/Channel>
|
#include <osgAnimation/Channel>
|
||||||
|
@ -250,7 +249,7 @@ namespace Resource
|
||||||
|
|
||||||
void KeyframeManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
void KeyframeManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
||||||
{
|
{
|
||||||
stats->setAttribute(frameNumber, "Keyframe", mCache->getCacheSize());
|
Resource::reportStats("Keyframe", frameNumber, mCache->getStats(), *stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ namespace Resource
|
||||||
{
|
{
|
||||||
objectsToRemove.push_back(oitr->second);
|
objectsToRemove.push_back(oitr->second);
|
||||||
_objectCache.erase(oitr++);
|
_objectCache.erase(oitr++);
|
||||||
|
++mExpired;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -57,13 +58,15 @@ namespace Resource
|
||||||
osg::ref_ptr<osg::Object> MultiObjectCache::takeFromObjectCache(const std::string& fileName)
|
osg::ref_ptr<osg::Object> MultiObjectCache::takeFromObjectCache(const std::string& fileName)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_objectCacheMutex);
|
std::lock_guard<std::mutex> lock(_objectCacheMutex);
|
||||||
|
++mGet;
|
||||||
ObjectCacheMap::iterator found = _objectCache.find(fileName);
|
ObjectCacheMap::iterator found = _objectCache.find(fileName);
|
||||||
if (found == _objectCache.end())
|
if (found == _objectCache.end())
|
||||||
return osg::ref_ptr<osg::Object>();
|
return osg::ref_ptr<osg::Object>();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Object> object = found->second;
|
osg::ref_ptr<osg::Object> object = std::move(found->second);
|
||||||
_objectCache.erase(found);
|
_objectCache.erase(found);
|
||||||
|
++mHit;
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,10 +82,15 @@ namespace Resource
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int MultiObjectCache::getCacheSize() const
|
CacheStats MultiObjectCache::getStats() const
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_objectCacheMutex);
|
std::lock_guard<std::mutex> lock(_objectCacheMutex);
|
||||||
return _objectCache.size();
|
return CacheStats{
|
||||||
|
.mSize = _objectCache.size(),
|
||||||
|
.mGet = mGet,
|
||||||
|
.mHit = mHit,
|
||||||
|
.mExpired = mExpired,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#include <osg/Referenced>
|
#include <osg/Referenced>
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
|
|
||||||
|
#include "cachestats.hpp"
|
||||||
|
|
||||||
namespace osg
|
namespace osg
|
||||||
{
|
{
|
||||||
class Object;
|
class Object;
|
||||||
|
@ -37,13 +39,16 @@ namespace Resource
|
||||||
/** call releaseGLObjects on all objects attached to the object cache.*/
|
/** call releaseGLObjects on all objects attached to the object cache.*/
|
||||||
void releaseGLObjects(osg::State* state);
|
void releaseGLObjects(osg::State* state);
|
||||||
|
|
||||||
unsigned int getCacheSize() const;
|
CacheStats getStats() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef std::multimap<std::string, osg::ref_ptr<osg::Object>> ObjectCacheMap;
|
typedef std::multimap<std::string, osg::ref_ptr<osg::Object>> ObjectCacheMap;
|
||||||
|
|
||||||
ObjectCacheMap _objectCache;
|
ObjectCacheMap _objectCache;
|
||||||
mutable std::mutex _objectCacheMutex;
|
mutable std::mutex _objectCacheMutex;
|
||||||
|
std::size_t mGet = 0;
|
||||||
|
std::size_t mHit = 0;
|
||||||
|
std::size_t mExpired = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <osg/Object>
|
#include <osg/Object>
|
||||||
#include <osg/Stats>
|
|
||||||
|
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
|
|
||||||
|
@ -59,7 +58,7 @@ namespace Resource
|
||||||
|
|
||||||
void NifFileManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
void NifFileManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
||||||
{
|
{
|
||||||
stats->setAttribute(frameNumber, "Nif", mCache->getCacheSize());
|
Resource::reportStats("Nif", frameNumber, mCache->getStats(), *stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#ifndef OPENMW_COMPONENTS_RESOURCE_OBJECTCACHE
|
#ifndef OPENMW_COMPONENTS_RESOURCE_OBJECTCACHE
|
||||||
#define OPENMW_COMPONENTS_RESOURCE_OBJECTCACHE
|
#define OPENMW_COMPONENTS_RESOURCE_OBJECTCACHE
|
||||||
|
|
||||||
|
#include "cachestats.hpp"
|
||||||
|
|
||||||
#include <osg/Node>
|
#include <osg/Node>
|
||||||
#include <osg/Referenced>
|
#include <osg/Referenced>
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
|
@ -29,26 +31,28 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace osg
|
namespace osg
|
||||||
{
|
{
|
||||||
class Object;
|
class Object;
|
||||||
class State;
|
class State;
|
||||||
class NodeVisitor;
|
class NodeVisitor;
|
||||||
|
class Stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Resource
|
namespace Resource
|
||||||
{
|
{
|
||||||
|
struct GenericObjectCacheItem
|
||||||
|
{
|
||||||
|
osg::ref_ptr<osg::Object> mValue;
|
||||||
|
double mLastUsage;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename KeyType>
|
template <typename KeyType>
|
||||||
class GenericObjectCache : public osg::Referenced
|
class GenericObjectCache : public osg::Referenced
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GenericObjectCache()
|
|
||||||
: osg::Referenced(true)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update last usage timestamp using referenceTime for each cache time if they are not nullptr and referenced
|
// Update last usage timestamp using referenceTime for each cache time if they are not nullptr and referenced
|
||||||
// from somewhere else. Remove items with last usage > expiryTime. Note: last usage might be updated from other
|
// from somewhere else. Remove items with last usage > expiryTime. Note: last usage might be updated from other
|
||||||
// places so nullptr or not references elsewhere items are not always removed.
|
// places so nullptr or not references elsewhere items are not always removed.
|
||||||
|
@ -64,6 +68,7 @@ namespace Resource
|
||||||
item.mLastUsage = referenceTime;
|
item.mLastUsage = referenceTime;
|
||||||
if (item.mLastUsage > expiryTime)
|
if (item.mLastUsage > expiryTime)
|
||||||
return false;
|
return false;
|
||||||
|
++mExpired;
|
||||||
if (item.mValue != nullptr)
|
if (item.mValue != nullptr)
|
||||||
objectsToRemove.push_back(std::move(item.mValue));
|
objectsToRemove.push_back(std::move(item.mValue));
|
||||||
return true;
|
return true;
|
||||||
|
@ -105,33 +110,28 @@ namespace Resource
|
||||||
osg::ref_ptr<osg::Object> getRefFromObjectCache(const auto& key)
|
osg::ref_ptr<osg::Object> getRefFromObjectCache(const auto& key)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mMutex);
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
const auto itr = mItems.find(key);
|
if (Item* const item = find(key))
|
||||||
if (itr != mItems.end())
|
return item->mValue;
|
||||||
return itr->second.mValue;
|
|
||||||
else
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<osg::ref_ptr<osg::Object>> getRefFromObjectCacheOrNone(const auto& key)
|
std::optional<osg::ref_ptr<osg::Object>> getRefFromObjectCacheOrNone(const auto& key)
|
||||||
{
|
{
|
||||||
const std::lock_guard<std::mutex> lock(mMutex);
|
const std::lock_guard<std::mutex> lock(mMutex);
|
||||||
const auto it = mItems.find(key);
|
if (Item* const item = find(key))
|
||||||
if (it == mItems.end())
|
return item->mValue;
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
return it->second.mValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Check if an object is in the cache, and if it is, update its usage time stamp. */
|
/** Check if an object is in the cache, and if it is, update its usage time stamp. */
|
||||||
bool checkInObjectCache(const auto& key, double timeStamp)
|
bool checkInObjectCache(const auto& key, double timeStamp)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mMutex);
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
const auto itr = mItems.find(key);
|
if (Item* const item = find(key))
|
||||||
if (itr != mItems.end())
|
|
||||||
{
|
{
|
||||||
itr->second.mLastUsage = timeStamp;
|
item->mLastUsage = timeStamp;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,13 +162,6 @@ namespace Resource
|
||||||
f(k, v.mValue.get());
|
f(k, v.mValue.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the number of objects in the cache. */
|
|
||||||
unsigned int getCacheSize() const
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(mMutex);
|
|
||||||
return mItems.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class K>
|
template <class K>
|
||||||
std::optional<std::pair<KeyType, osg::ref_ptr<osg::Object>>> lowerBound(K&& key)
|
std::optional<std::pair<KeyType, osg::ref_ptr<osg::Object>>> lowerBound(K&& key)
|
||||||
{
|
{
|
||||||
|
@ -179,21 +172,36 @@ namespace Resource
|
||||||
return std::pair(it->first, it->second.mValue);
|
return std::pair(it->first, it->second.mValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
CacheStats getStats() const
|
||||||
struct Item
|
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Object> mValue;
|
const std::lock_guard<std::mutex> lock(mMutex);
|
||||||
double mLastUsage;
|
return CacheStats{
|
||||||
|
.mSize = mItems.size(),
|
||||||
|
.mGet = mGet,
|
||||||
|
.mHit = mHit,
|
||||||
|
.mExpired = mExpired,
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
using Item = GenericObjectCacheItem;
|
||||||
|
|
||||||
std::map<KeyType, Item, std::less<>> mItems;
|
std::map<KeyType, Item, std::less<>> mItems;
|
||||||
mutable std::mutex mMutex;
|
mutable std::mutex mMutex;
|
||||||
};
|
std::size_t mGet = 0;
|
||||||
|
std::size_t mHit = 0;
|
||||||
|
std::size_t mExpired = 0;
|
||||||
|
|
||||||
class ObjectCache : public GenericObjectCache<std::string>
|
Item* find(const auto& key)
|
||||||
{
|
{
|
||||||
|
++mGet;
|
||||||
|
const auto it = mItems.find(key);
|
||||||
|
if (it == mItems.end())
|
||||||
|
return nullptr;
|
||||||
|
++mHit;
|
||||||
|
return &it->second;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1125,7 +1125,7 @@ namespace Resource
|
||||||
stats->setAttribute(frameNumber, "StateSet", mSharedStateManager->getNumSharedStateSets());
|
stats->setAttribute(frameNumber, "StateSet", mSharedStateManager->getNumSharedStateSets());
|
||||||
}
|
}
|
||||||
|
|
||||||
stats->setAttribute(frameNumber, "Node", mCache->getCacheSize());
|
Resource::reportStats("Node", frameNumber, mCache->getStats(), *stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::ref_ptr<Shader::ShaderVisitor> SceneManager::createShaderVisitor(const std::string& shaderPrefix)
|
osg::ref_ptr<Shader::ShaderVisitor> SceneManager::createShaderVisitor(const std::string& shaderPrefix)
|
||||||
|
|
|
@ -2,7 +2,11 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <span>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <osg/PolygonMode>
|
#include <osg/PolygonMode>
|
||||||
|
|
||||||
|
@ -16,22 +20,124 @@
|
||||||
|
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
|
|
||||||
|
#include "cachestats.hpp"
|
||||||
|
|
||||||
namespace Resource
|
namespace Resource
|
||||||
{
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
constexpr float statsWidth = 1280.0f;
|
||||||
|
constexpr float statsHeight = 1024.0f;
|
||||||
|
constexpr float characterSize = 17.0f;
|
||||||
|
constexpr float backgroundMargin = 5;
|
||||||
|
constexpr float backgroundSpacing = 3;
|
||||||
|
constexpr float maxStatsHeight = 420.0f;
|
||||||
|
constexpr std::size_t pageSize
|
||||||
|
= static_cast<std::size_t>((maxStatsHeight - 2 * backgroundMargin) / characterSize);
|
||||||
|
constexpr int statsHandlerKey = osgGA::GUIEventAdapter::KEY_F4;
|
||||||
|
const VFS::Path::Normalized fontName("Fonts/DejaVuLGCSansMono.ttf");
|
||||||
|
|
||||||
static bool collectStatRendering = false;
|
bool collectStatRendering = false;
|
||||||
static bool collectStatCameraObjects = false;
|
bool collectStatCameraObjects = false;
|
||||||
static bool collectStatViewerObjects = false;
|
bool collectStatViewerObjects = false;
|
||||||
static bool collectStatResource = false;
|
bool collectStatResource = false;
|
||||||
static bool collectStatGPU = false;
|
bool collectStatGPU = false;
|
||||||
static bool collectStatEvent = false;
|
bool collectStatEvent = false;
|
||||||
static bool collectStatFrameRate = false;
|
bool collectStatFrameRate = false;
|
||||||
static bool collectStatUpdate = false;
|
bool collectStatUpdate = false;
|
||||||
static bool collectStatEngine = false;
|
bool collectStatEngine = false;
|
||||||
|
|
||||||
static const VFS::Path::Normalized sFontName("Fonts/DejaVuLGCSansMono.ttf");
|
std::vector<std::string> generateAllStatNames()
|
||||||
|
{
|
||||||
|
constexpr std::string_view firstPage[] = {
|
||||||
|
"FrameNumber",
|
||||||
|
"",
|
||||||
|
"Compiling",
|
||||||
|
"WorkQueue",
|
||||||
|
"WorkThread",
|
||||||
|
"UnrefQueue",
|
||||||
|
"",
|
||||||
|
"Texture",
|
||||||
|
"StateSet",
|
||||||
|
"Composite",
|
||||||
|
"",
|
||||||
|
"Mechanics Actors",
|
||||||
|
"Mechanics Objects",
|
||||||
|
"",
|
||||||
|
"Physics Actors",
|
||||||
|
"Physics Objects",
|
||||||
|
"Physics Projectiles",
|
||||||
|
"Physics HeightFields",
|
||||||
|
"",
|
||||||
|
"Lua UsedMemory",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
};
|
||||||
|
|
||||||
static void setupStatCollection()
|
constexpr std::string_view caches[] = {
|
||||||
|
"Node",
|
||||||
|
"Shape",
|
||||||
|
"Shape Instance",
|
||||||
|
"Image",
|
||||||
|
"Nif",
|
||||||
|
"Keyframe",
|
||||||
|
"Groundcover Chunk",
|
||||||
|
"Object Chunk",
|
||||||
|
"Terrain Chunk",
|
||||||
|
"Terrain Texture",
|
||||||
|
"Land",
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr std::string_view cellPreloader[] = {
|
||||||
|
"CellPreloader Count",
|
||||||
|
"CellPreloader Added",
|
||||||
|
"CellPreloader Evicted",
|
||||||
|
"CellPreloader Loaded",
|
||||||
|
"CellPreloader Expired",
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr std::string_view navMesh[] = {
|
||||||
|
"NavMesh Jobs",
|
||||||
|
"NavMesh Waiting",
|
||||||
|
"NavMesh Pushed",
|
||||||
|
"NavMesh Processing",
|
||||||
|
"NavMesh DbJobs Write",
|
||||||
|
"NavMesh DbJobs Read",
|
||||||
|
"NavMesh DbCache Get",
|
||||||
|
"NavMesh DbCache Hit",
|
||||||
|
"NavMesh CacheSize",
|
||||||
|
"NavMesh UsedTiles",
|
||||||
|
"NavMesh CachedTiles",
|
||||||
|
"NavMesh Cache Get",
|
||||||
|
"NavMesh Cache Hit",
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<std::string> statNames;
|
||||||
|
|
||||||
|
for (std::string_view name : firstPage)
|
||||||
|
statNames.emplace_back(name);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < std::size(caches); ++i)
|
||||||
|
{
|
||||||
|
Resource::addCacheStatsAttibutes(caches[i], statNames);
|
||||||
|
if ((i + 1) % 5 != 0)
|
||||||
|
statNames.emplace_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::string_view name : cellPreloader)
|
||||||
|
statNames.emplace_back(name);
|
||||||
|
|
||||||
|
statNames.emplace_back();
|
||||||
|
|
||||||
|
for (std::string_view name : navMesh)
|
||||||
|
statNames.emplace_back(name);
|
||||||
|
|
||||||
|
return statNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupStatCollection()
|
||||||
{
|
{
|
||||||
const char* envList = getenv("OPENMW_OSG_STATS_LIST");
|
const char* envList = getenv("OPENMW_OSG_STATS_LIST");
|
||||||
if (envList == nullptr)
|
if (envList == nullptr)
|
||||||
|
@ -82,6 +188,49 @@ namespace Resource
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Geometry> createBackgroundRectangle(
|
||||||
|
const osg::Vec3& pos, const float width, const float height, const osg::Vec4& color)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
|
||||||
|
|
||||||
|
geometry->setUseDisplayList(false);
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::StateSet> stateSet = new osg::StateSet;
|
||||||
|
geometry->setStateSet(stateSet);
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
|
||||||
|
vertices->push_back(osg::Vec3(pos.x(), pos.y(), 0));
|
||||||
|
vertices->push_back(osg::Vec3(pos.x(), pos.y() - height, 0));
|
||||||
|
vertices->push_back(osg::Vec3(pos.x() + width, pos.y() - height, 0));
|
||||||
|
vertices->push_back(osg::Vec3(pos.x() + width, pos.y(), 0));
|
||||||
|
geometry->setVertexArray(vertices);
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
|
||||||
|
colors->push_back(color);
|
||||||
|
geometry->setColorArray(colors, osg::Array::BIND_OVERALL);
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::DrawElementsUShort> base
|
||||||
|
= new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLE_FAN, 0);
|
||||||
|
base->push_back(0);
|
||||||
|
base->push_back(1);
|
||||||
|
base->push_back(2);
|
||||||
|
base->push_back(3);
|
||||||
|
geometry->addPrimitiveSet(base);
|
||||||
|
|
||||||
|
return geometry;
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::ref_ptr<osgText::Font> getMonoFont(const VFS::Manager& vfs)
|
||||||
|
{
|
||||||
|
if (osgDB::Registry::instance()->getReaderWriterForExtension("ttf") && vfs.exists(fontName))
|
||||||
|
{
|
||||||
|
const Files::IStreamPtr streamPtr = vfs.get(fontName);
|
||||||
|
return osgText::readRefFontStream(*streamPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
class SetFontVisitor : public osg::NodeVisitor
|
class SetFontVisitor : public osg::NodeVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -102,59 +251,28 @@ namespace Resource
|
||||||
private:
|
private:
|
||||||
osgText::Font* mFont;
|
osgText::Font* mFont;
|
||||||
};
|
};
|
||||||
|
|
||||||
osg::ref_ptr<osgText::Font> getMonoFont(VFS::Manager* vfs)
|
|
||||||
{
|
|
||||||
if (osgDB::Registry::instance()->getReaderWriterForExtension("ttf") && vfs->exists(sFontName))
|
|
||||||
{
|
|
||||||
Files::IStreamPtr streamPtr = vfs->get(sFontName);
|
|
||||||
return osgText::readRefFontStream(*streamPtr.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
Profiler::Profiler(bool offlineCollect, const VFS::Manager& vfs)
|
||||||
}
|
: mOfflineCollect(offlineCollect)
|
||||||
|
, mTextFont(getMonoFont(vfs))
|
||||||
StatsHandler::StatsHandler(bool offlineCollect, VFS::Manager* vfs)
|
|
||||||
: _key(osgGA::GUIEventAdapter::KEY_F4)
|
|
||||||
, _initialized(false)
|
|
||||||
, _statsType(false)
|
|
||||||
, _offlineCollect(offlineCollect)
|
|
||||||
, _statsWidth(1280.0f)
|
|
||||||
, _statsHeight(1024.0f)
|
|
||||||
, _characterSize(18.0f)
|
|
||||||
{
|
{
|
||||||
_camera = new osg::Camera;
|
_characterSize = characterSize;
|
||||||
_camera->getOrCreateStateSet()->setGlobalDefaults();
|
|
||||||
_camera->setRenderer(new osgViewer::Renderer(_camera.get()));
|
|
||||||
_camera->setProjectionResizePolicy(osg::Camera::FIXED);
|
|
||||||
|
|
||||||
_resourceStatsChildNum = 0;
|
|
||||||
|
|
||||||
_textFont = getMonoFont(vfs);
|
|
||||||
}
|
|
||||||
|
|
||||||
Profiler::Profiler(bool offlineCollect, VFS::Manager* vfs)
|
|
||||||
: _offlineCollect(offlineCollect)
|
|
||||||
, _initFonts(false)
|
|
||||||
{
|
|
||||||
_characterSize = 18;
|
|
||||||
_font.clear();
|
_font.clear();
|
||||||
|
|
||||||
_textFont = getMonoFont(vfs);
|
|
||||||
|
|
||||||
setKeyEventTogglesOnScreenStats(osgGA::GUIEventAdapter::KEY_F3);
|
setKeyEventTogglesOnScreenStats(osgGA::GUIEventAdapter::KEY_F3);
|
||||||
setupStatCollection();
|
setupStatCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Profiler::setUpFonts()
|
void Profiler::setUpFonts()
|
||||||
{
|
{
|
||||||
if (_textFont != nullptr)
|
if (mTextFont != nullptr)
|
||||||
{
|
{
|
||||||
SetFontVisitor visitor(_textFont);
|
SetFontVisitor visitor(mTextFont);
|
||||||
_switch->accept(visitor);
|
_switch->accept(visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
_initFonts = true;
|
mInitFonts = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Profiler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
|
bool Profiler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
|
||||||
|
@ -162,24 +280,45 @@ namespace Resource
|
||||||
osgViewer::ViewerBase* viewer = nullptr;
|
osgViewer::ViewerBase* viewer = nullptr;
|
||||||
|
|
||||||
bool handled = StatsHandler::handle(ea, aa);
|
bool handled = StatsHandler::handle(ea, aa);
|
||||||
if (_initialized && !_initFonts)
|
if (_initialized && !mInitFonts)
|
||||||
setUpFonts();
|
setUpFonts();
|
||||||
|
|
||||||
auto* view = dynamic_cast<osgViewer::View*>(&aa);
|
auto* view = dynamic_cast<osgViewer::View*>(&aa);
|
||||||
if (view)
|
if (view)
|
||||||
viewer = view->getViewerBase();
|
viewer = view->getViewerBase();
|
||||||
|
|
||||||
if (viewer)
|
if (viewer != nullptr)
|
||||||
{
|
{
|
||||||
// Add/remove openmw stats to the osd as necessary
|
// Add/remove openmw stats to the osd as necessary
|
||||||
viewer->getViewerStats()->collectStats("engine", _statsType >= StatsHandler::StatsType::VIEWER_STATS);
|
viewer->getViewerStats()->collectStats("engine", _statsType >= StatsHandler::StatsType::VIEWER_STATS);
|
||||||
|
|
||||||
if (_offlineCollect)
|
if (mOfflineCollect)
|
||||||
CollectStatistics(viewer);
|
collectStatistics(*viewer);
|
||||||
}
|
}
|
||||||
return handled;
|
return handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StatsHandler::StatsHandler(bool offlineCollect, const VFS::Manager& vfs)
|
||||||
|
: mOfflineCollect(offlineCollect)
|
||||||
|
, mSwitch(new osg::Switch)
|
||||||
|
, mCamera(new osg::Camera)
|
||||||
|
, mTextFont(getMonoFont(vfs))
|
||||||
|
, mStatNames(generateAllStatNames())
|
||||||
|
{
|
||||||
|
osg::ref_ptr<osg::StateSet> stateset = mSwitch->getOrCreateStateSet();
|
||||||
|
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||||
|
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||||
|
stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
|
||||||
|
#ifdef OSG_GL1_AVAILABLE
|
||||||
|
stateset->setAttribute(new osg::PolygonMode(), osg::StateAttribute::PROTECTED);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mCamera->getOrCreateStateSet()->setGlobalDefaults();
|
||||||
|
mCamera->setRenderer(new osgViewer::Renderer(mCamera.get()));
|
||||||
|
mCamera->setProjectionResizePolicy(osg::Camera::FIXED);
|
||||||
|
mCamera->addChild(mSwitch);
|
||||||
|
}
|
||||||
|
|
||||||
bool StatsHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
|
bool StatsHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
|
||||||
{
|
{
|
||||||
if (ea.getHandled())
|
if (ea.getHandled())
|
||||||
|
@ -189,18 +328,21 @@ namespace Resource
|
||||||
{
|
{
|
||||||
case (osgGA::GUIEventAdapter::KEYDOWN):
|
case (osgGA::GUIEventAdapter::KEYDOWN):
|
||||||
{
|
{
|
||||||
if (ea.getKey() == _key)
|
if (ea.getKey() == statsHandlerKey)
|
||||||
{
|
{
|
||||||
osgViewer::View* myview = dynamic_cast<osgViewer::View*>(&aa);
|
osgViewer::View* const view = dynamic_cast<osgViewer::View*>(&aa);
|
||||||
if (!myview)
|
if (view == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
osgViewer::ViewerBase* viewer = myview->getViewerBase();
|
osgViewer::ViewerBase* const viewer = view->getViewerBase();
|
||||||
|
|
||||||
toggle(viewer);
|
if (viewer == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (_offlineCollect)
|
toggle(*viewer);
|
||||||
CollectStatistics(viewer);
|
|
||||||
|
if (mOfflineCollect)
|
||||||
|
collectStatistics(*viewer);
|
||||||
|
|
||||||
aa.requestRedraw();
|
aa.requestRedraw();
|
||||||
return true;
|
return true;
|
||||||
|
@ -223,66 +365,69 @@ namespace Resource
|
||||||
if (width <= 0 || height <= 0)
|
if (width <= 0 || height <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_camera->setViewport(0, 0, width, height);
|
mCamera->setViewport(0, 0, width, height);
|
||||||
if (fabs(height * _statsWidth) <= fabs(width * _statsHeight))
|
if (std::abs(height * statsWidth) <= std::abs(width * statsHeight))
|
||||||
{
|
{
|
||||||
_camera->setProjectionMatrix(
|
mCamera->setProjectionMatrix(
|
||||||
osg::Matrix::ortho2D(_statsWidth - width * _statsHeight / height, _statsWidth, 0.0, _statsHeight));
|
osg::Matrix::ortho2D(statsWidth - width * statsHeight / height, statsWidth, 0.0, statsHeight));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_camera->setProjectionMatrix(
|
mCamera->setProjectionMatrix(
|
||||||
osg::Matrix::ortho2D(0.0, _statsWidth, _statsHeight - height * _statsWidth / width, _statsHeight));
|
osg::Matrix::ortho2D(0.0, statsWidth, statsHeight - height * statsWidth / width, statsHeight));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatsHandler::toggle(osgViewer::ViewerBase* viewer)
|
void StatsHandler::toggle(osgViewer::ViewerBase& viewer)
|
||||||
{
|
{
|
||||||
if (!_initialized)
|
if (!mInitialized)
|
||||||
{
|
{
|
||||||
setUpHUDCamera(viewer);
|
setUpHUDCamera(viewer);
|
||||||
setUpScene(viewer);
|
setUpScene(viewer);
|
||||||
|
mInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_statsType = !_statsType;
|
if (mPage == mSwitch->getNumChildren())
|
||||||
|
|
||||||
if (!_statsType)
|
|
||||||
{
|
{
|
||||||
_camera->setNodeMask(0);
|
mPage = 0;
|
||||||
_switch->setAllChildrenOff();
|
|
||||||
|
|
||||||
viewer->getViewerStats()->collectStats("resource", false);
|
mCamera->setNodeMask(0);
|
||||||
|
mSwitch->setAllChildrenOff();
|
||||||
|
|
||||||
|
viewer.getViewerStats()->collectStats("resource", false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_camera->setNodeMask(0xffffffff);
|
mCamera->setNodeMask(0xffffffff);
|
||||||
_switch->setSingleChildOn(_resourceStatsChildNum);
|
mSwitch->setSingleChildOn(mPage);
|
||||||
|
|
||||||
viewer->getViewerStats()->collectStats("resource", true);
|
viewer.getViewerStats()->collectStats("resource", true);
|
||||||
|
|
||||||
|
++mPage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatsHandler::setUpHUDCamera(osgViewer::ViewerBase* viewer)
|
void StatsHandler::setUpHUDCamera(osgViewer::ViewerBase& viewer)
|
||||||
{
|
{
|
||||||
// Try GraphicsWindow first so we're likely to get the main viewer window
|
// Try GraphicsWindow first so we're likely to get the main viewer window
|
||||||
osg::GraphicsContext* context = dynamic_cast<osgViewer::GraphicsWindow*>(_camera->getGraphicsContext());
|
osg::GraphicsContext* context = dynamic_cast<osgViewer::GraphicsWindow*>(mCamera->getGraphicsContext());
|
||||||
|
|
||||||
if (!context)
|
if (!context)
|
||||||
{
|
{
|
||||||
osgViewer::Viewer::Windows windows;
|
osgViewer::Viewer::Windows windows;
|
||||||
viewer->getWindows(windows);
|
viewer.getWindows(windows);
|
||||||
|
|
||||||
if (!windows.empty())
|
if (!windows.empty())
|
||||||
context = windows.front();
|
context = windows.front();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// No GraphicsWindows were found, so let's try to find a GraphicsContext
|
// No GraphicsWindows were found, so let's try to find a GraphicsContext
|
||||||
context = _camera->getGraphicsContext();
|
context = mCamera->getGraphicsContext();
|
||||||
|
|
||||||
if (!context)
|
if (!context)
|
||||||
{
|
{
|
||||||
osgViewer::Viewer::Contexts contexts;
|
osgViewer::Viewer::Contexts contexts;
|
||||||
viewer->getContexts(contexts);
|
viewer.getContexts(contexts);
|
||||||
|
|
||||||
if (contexts.empty())
|
if (contexts.empty())
|
||||||
return;
|
return;
|
||||||
|
@ -292,60 +437,27 @@ namespace Resource
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_camera->setGraphicsContext(context);
|
mCamera->setGraphicsContext(context);
|
||||||
|
|
||||||
_camera->setRenderOrder(osg::Camera::POST_RENDER, 11);
|
mCamera->setRenderOrder(osg::Camera::POST_RENDER, 11);
|
||||||
|
|
||||||
_camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
|
mCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
|
||||||
_camera->setViewMatrix(osg::Matrix::identity());
|
mCamera->setViewMatrix(osg::Matrix::identity());
|
||||||
setWindowSize(context->getTraits()->width, context->getTraits()->height);
|
setWindowSize(context->getTraits()->width, context->getTraits()->height);
|
||||||
|
|
||||||
// only clear the depth buffer
|
// only clear the depth buffer
|
||||||
_camera->setClearMask(0);
|
mCamera->setClearMask(0);
|
||||||
_camera->setAllowEventFocus(false);
|
mCamera->setAllowEventFocus(false);
|
||||||
|
|
||||||
_camera->setRenderer(new osgViewer::Renderer(_camera.get()));
|
mCamera->setRenderer(new osgViewer::Renderer(mCamera.get()));
|
||||||
|
|
||||||
_initialized = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::Geometry* createBackgroundRectangle(
|
namespace
|
||||||
const osg::Vec3& pos, const float width, const float height, osg::Vec4& color)
|
|
||||||
{
|
{
|
||||||
osg::StateSet* ss = new osg::StateSet;
|
|
||||||
|
|
||||||
osg::Geometry* geometry = new osg::Geometry;
|
|
||||||
|
|
||||||
geometry->setUseDisplayList(false);
|
|
||||||
geometry->setStateSet(ss);
|
|
||||||
|
|
||||||
osg::Vec3Array* vertices = new osg::Vec3Array;
|
|
||||||
geometry->setVertexArray(vertices);
|
|
||||||
|
|
||||||
vertices->push_back(osg::Vec3(pos.x(), pos.y(), 0));
|
|
||||||
vertices->push_back(osg::Vec3(pos.x(), pos.y() - height, 0));
|
|
||||||
vertices->push_back(osg::Vec3(pos.x() + width, pos.y() - height, 0));
|
|
||||||
vertices->push_back(osg::Vec3(pos.x() + width, pos.y(), 0));
|
|
||||||
|
|
||||||
osg::Vec4Array* colors = new osg::Vec4Array;
|
|
||||||
colors->push_back(color);
|
|
||||||
geometry->setColorArray(colors, osg::Array::BIND_OVERALL);
|
|
||||||
|
|
||||||
osg::DrawElementsUShort* base = new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLE_FAN, 0);
|
|
||||||
base->push_back(0);
|
|
||||||
base->push_back(1);
|
|
||||||
base->push_back(2);
|
|
||||||
base->push_back(3);
|
|
||||||
|
|
||||||
geometry->addPrimitiveSet(base);
|
|
||||||
|
|
||||||
return geometry;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ResourceStatsTextDrawCallback : public osg::Drawable::DrawCallback
|
class ResourceStatsTextDrawCallback : public osg::Drawable::DrawCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ResourceStatsTextDrawCallback(osg::Stats* stats, const std::vector<std::string>& statNames)
|
explicit ResourceStatsTextDrawCallback(osg::Stats* stats, std::span<const std::string> statNames)
|
||||||
: mStats(stats)
|
: mStats(stats)
|
||||||
, mStatNames(statNames)
|
, mStatNames(statNames)
|
||||||
{
|
{
|
||||||
|
@ -353,7 +465,7 @@ namespace Resource
|
||||||
|
|
||||||
void drawImplementation(osg::RenderInfo& renderInfo, const osg::Drawable* drawable) const override
|
void drawImplementation(osg::RenderInfo& renderInfo, const osg::Drawable* drawable) const override
|
||||||
{
|
{
|
||||||
if (!mStats)
|
if (mStats == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
osgText::Text* text = (osgText::Text*)(drawable);
|
osgText::Text* text = (osgText::Text*)(drawable);
|
||||||
|
@ -366,9 +478,9 @@ namespace Resource
|
||||||
viewStr.setf(std::ios::fixed);
|
viewStr.setf(std::ios::fixed);
|
||||||
viewStr.precision(0);
|
viewStr.precision(0);
|
||||||
|
|
||||||
unsigned int frameNumber = renderInfo.getState()->getFrameStamp()->getFrameNumber() - 1;
|
const unsigned int frameNumber = renderInfo.getState()->getFrameStamp()->getFrameNumber() - 1;
|
||||||
|
|
||||||
for (const auto& statName : mStatNames.get())
|
for (const std::string& statName : mStatNames)
|
||||||
{
|
{
|
||||||
if (statName.empty())
|
if (statName.empty())
|
||||||
viewStr << std::endl;
|
viewStr << std::endl;
|
||||||
|
@ -387,146 +499,89 @@ namespace Resource
|
||||||
text->drawImplementation(renderInfo);
|
text->drawImplementation(renderInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
osg::ref_ptr<osg::Stats> mStats;
|
osg::ref_ptr<osg::Stats> mStats;
|
||||||
std::reference_wrapper<const std::vector<std::string>> mStatNames;
|
std::span<const std::string> mStatNames;
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
void StatsHandler::setUpScene(osgViewer::ViewerBase* viewer)
|
void StatsHandler::setUpScene(osgViewer::ViewerBase& viewer)
|
||||||
{
|
{
|
||||||
_switch = new osg::Switch;
|
const osg::Vec4 backgroundColor(0.0, 0.0, 0.0f, 0.3);
|
||||||
|
const osg::Vec4 staticTextColor(1.0, 1.0, 0.0f, 1.0);
|
||||||
|
const osg::Vec4 dynamicTextColor(1.0, 1.0, 1.0f, 1.0);
|
||||||
|
|
||||||
_camera->addChild(_switch);
|
const auto longest = std::max_element(mStatNames.begin(), mStatNames.end(),
|
||||||
|
|
||||||
osg::StateSet* stateset = _switch->getOrCreateStateSet();
|
|
||||||
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
|
||||||
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
|
|
||||||
stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
|
|
||||||
#ifdef OSG_GL1_AVAILABLE
|
|
||||||
stateset->setAttribute(new osg::PolygonMode(), osg::StateAttribute::PROTECTED);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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);
|
|
||||||
float backgroundMargin = 5;
|
|
||||||
float backgroundSpacing = 3;
|
|
||||||
|
|
||||||
// resource stats
|
|
||||||
{
|
|
||||||
osg::Group* group = new osg::Group;
|
|
||||||
group->setCullingActive(false);
|
|
||||||
_resourceStatsChildNum = _switch->getNumChildren();
|
|
||||||
_switch->addChild(group, false);
|
|
||||||
|
|
||||||
static const std::vector<std::string> statNames({
|
|
||||||
"FrameNumber",
|
|
||||||
"",
|
|
||||||
"Compiling",
|
|
||||||
"WorkQueue",
|
|
||||||
"WorkThread",
|
|
||||||
"UnrefQueue",
|
|
||||||
"",
|
|
||||||
"Texture",
|
|
||||||
"StateSet",
|
|
||||||
"Node",
|
|
||||||
"Shape",
|
|
||||||
"Shape Instance",
|
|
||||||
"Image",
|
|
||||||
"Nif",
|
|
||||||
"Keyframe",
|
|
||||||
"",
|
|
||||||
"Groundcover Chunk",
|
|
||||||
"Object Chunk",
|
|
||||||
"Terrain Chunk",
|
|
||||||
"Terrain Texture",
|
|
||||||
"Land",
|
|
||||||
"Composite",
|
|
||||||
"",
|
|
||||||
"NavMesh Jobs",
|
|
||||||
"NavMesh Waiting",
|
|
||||||
"NavMesh Pushed",
|
|
||||||
"NavMesh Processing",
|
|
||||||
"NavMesh DbJobs Write",
|
|
||||||
"NavMesh DbJobs Read",
|
|
||||||
"NavMesh DbCache Get",
|
|
||||||
"NavMesh DbCache Hit",
|
|
||||||
"NavMesh CacheSize",
|
|
||||||
"NavMesh UsedTiles",
|
|
||||||
"NavMesh CachedTiles",
|
|
||||||
"NavMesh Cache Get",
|
|
||||||
"NavMesh Cache Hit",
|
|
||||||
"",
|
|
||||||
"Mechanics Actors",
|
|
||||||
"Mechanics Objects",
|
|
||||||
"",
|
|
||||||
"Physics Actors",
|
|
||||||
"Physics Objects",
|
|
||||||
"Physics Projectiles",
|
|
||||||
"Physics HeightFields",
|
|
||||||
"",
|
|
||||||
"Lua UsedMemory",
|
|
||||||
});
|
|
||||||
|
|
||||||
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 std::string& lhs, const std::string& rhs) { return lhs.size() < rhs.size(); });
|
||||||
const float statNamesWidth = 13 * _characterSize + 2 * backgroundMargin;
|
const std::size_t longestSize = longest->size();
|
||||||
const float statTextWidth = 7 * _characterSize + 2 * backgroundMargin;
|
const float statNamesWidth = longestSize * characterSize * 0.6 + 2 * backgroundMargin;
|
||||||
const float statHeight = statNames.size() * _characterSize + 2 * backgroundMargin;
|
const float statTextWidth = 7 * characterSize + 2 * backgroundMargin;
|
||||||
osg::Vec3 pos(_statsWidth - statNamesWidth - backgroundSpacing - statTextWidth, statHeight, 0.0f);
|
const float statHeight = pageSize * characterSize + 2 * backgroundMargin;
|
||||||
|
const float width = statNamesWidth + backgroundSpacing + statTextWidth;
|
||||||
|
|
||||||
|
for (std::size_t offset = 0; offset < mStatNames.size(); offset += pageSize)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<osg::Group> group = new osg::Group;
|
||||||
|
|
||||||
|
group->setCullingActive(false);
|
||||||
|
|
||||||
|
const std::size_t count = std::min(mStatNames.size() - offset, pageSize);
|
||||||
|
std::span<const std::string> currentStatNames(mStatNames.data() + offset, count);
|
||||||
|
osg::Vec3 pos(statsWidth - width, statHeight - characterSize, 0.0f);
|
||||||
|
|
||||||
group->addChild(
|
group->addChild(
|
||||||
createBackgroundRectangle(pos + osg::Vec3(-backgroundMargin, _characterSize + backgroundMargin, 0),
|
createBackgroundRectangle(pos + osg::Vec3(-backgroundMargin, backgroundMargin + characterSize, 0),
|
||||||
statNamesWidth, statHeight, backgroundColor));
|
statNamesWidth, statHeight, backgroundColor));
|
||||||
|
|
||||||
osg::ref_ptr<osgText::Text> staticText = new osgText::Text;
|
osg::ref_ptr<osgText::Text> staticText = new osgText::Text;
|
||||||
group->addChild(staticText.get());
|
group->addChild(staticText.get());
|
||||||
staticText->setColor(staticTextColor);
|
staticText->setColor(staticTextColor);
|
||||||
staticText->setCharacterSize(_characterSize);
|
staticText->setCharacterSize(characterSize);
|
||||||
staticText->setPosition(pos);
|
staticText->setPosition(pos);
|
||||||
|
|
||||||
std::ostringstream viewStr;
|
std::ostringstream viewStr;
|
||||||
viewStr.clear();
|
viewStr.clear();
|
||||||
viewStr.setf(std::ios::left, std::ios::adjustfield);
|
viewStr.setf(std::ios::left, std::ios::adjustfield);
|
||||||
viewStr.width(longest->size());
|
viewStr.width(longestSize);
|
||||||
for (const auto& statName : statNames)
|
for (const std::string& statName : currentStatNames)
|
||||||
{
|
|
||||||
viewStr << statName << std::endl;
|
viewStr << statName << std::endl;
|
||||||
}
|
|
||||||
|
|
||||||
staticText->setText(viewStr.str());
|
staticText->setText(viewStr.str());
|
||||||
|
|
||||||
pos.x() += statNamesWidth + backgroundSpacing;
|
pos.x() += statNamesWidth + backgroundSpacing;
|
||||||
|
|
||||||
group->addChild(
|
group->addChild(
|
||||||
createBackgroundRectangle(pos + osg::Vec3(-backgroundMargin, _characterSize + backgroundMargin, 0),
|
createBackgroundRectangle(pos + osg::Vec3(-backgroundMargin, backgroundMargin + characterSize, 0),
|
||||||
statTextWidth, statHeight, backgroundColor));
|
statTextWidth, statHeight, backgroundColor));
|
||||||
|
|
||||||
osg::ref_ptr<osgText::Text> statsText = new osgText::Text;
|
osg::ref_ptr<osgText::Text> statsText = new osgText::Text;
|
||||||
group->addChild(statsText.get());
|
group->addChild(statsText.get());
|
||||||
|
|
||||||
statsText->setColor(dynamicTextColor);
|
statsText->setColor(dynamicTextColor);
|
||||||
statsText->setCharacterSize(_characterSize);
|
statsText->setCharacterSize(characterSize);
|
||||||
statsText->setPosition(pos);
|
statsText->setPosition(pos);
|
||||||
statsText->setText("");
|
statsText->setText("");
|
||||||
statsText->setDrawCallback(new ResourceStatsTextDrawCallback(viewer->getViewerStats(), statNames));
|
statsText->setDrawCallback(new ResourceStatsTextDrawCallback(viewer.getViewerStats(), currentStatNames));
|
||||||
|
|
||||||
if (_textFont)
|
if (mTextFont != nullptr)
|
||||||
{
|
{
|
||||||
staticText->setFont(_textFont);
|
staticText->setFont(mTextFont);
|
||||||
statsText->setFont(_textFont);
|
statsText->setFont(mTextFont);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mSwitch->addChild(group, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatsHandler::getUsage(osg::ApplicationUsage& usage) const
|
void StatsHandler::getUsage(osg::ApplicationUsage& usage) const
|
||||||
{
|
{
|
||||||
usage.addKeyboardMouseBinding(_key, "On screen resource usage stats.");
|
usage.addKeyboardMouseBinding(statsHandlerKey, "On screen resource usage stats.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectStatistics(osgViewer::ViewerBase* viewer)
|
void collectStatistics(osgViewer::ViewerBase& viewer)
|
||||||
{
|
{
|
||||||
osgViewer::Viewer::Cameras cameras;
|
osgViewer::Viewer::Cameras cameras;
|
||||||
viewer->getCameras(cameras);
|
viewer.getCameras(cameras);
|
||||||
for (auto* camera : cameras)
|
for (auto* camera : cameras)
|
||||||
{
|
{
|
||||||
if (collectStatGPU)
|
if (collectStatGPU)
|
||||||
|
@ -537,17 +592,16 @@ namespace Resource
|
||||||
camera->getStats()->collectStats("scene", true);
|
camera->getStats()->collectStats("scene", true);
|
||||||
}
|
}
|
||||||
if (collectStatEvent)
|
if (collectStatEvent)
|
||||||
viewer->getViewerStats()->collectStats("event", true);
|
viewer.getViewerStats()->collectStats("event", true);
|
||||||
if (collectStatFrameRate)
|
if (collectStatFrameRate)
|
||||||
viewer->getViewerStats()->collectStats("frame_rate", true);
|
viewer.getViewerStats()->collectStats("frame_rate", true);
|
||||||
if (collectStatUpdate)
|
if (collectStatUpdate)
|
||||||
viewer->getViewerStats()->collectStats("update", true);
|
viewer.getViewerStats()->collectStats("update", true);
|
||||||
if (collectStatResource)
|
if (collectStatResource)
|
||||||
viewer->getViewerStats()->collectStats("resource", true);
|
viewer.getViewerStats()->collectStats("resource", true);
|
||||||
if (collectStatViewerObjects)
|
if (collectStatViewerObjects)
|
||||||
viewer->getViewerStats()->collectStats("scene", true);
|
viewer.getViewerStats()->collectStats("scene", true);
|
||||||
if (collectStatEngine)
|
if (collectStatEngine)
|
||||||
viewer->getViewerStats()->collectStats("engine", true);
|
viewer.getViewerStats()->collectStats("engine", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,57 +28,47 @@ namespace Resource
|
||||||
class Profiler : public osgViewer::StatsHandler
|
class Profiler : public osgViewer::StatsHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Profiler(bool offlineCollect, VFS::Manager* vfs);
|
explicit Profiler(bool offlineCollect, const VFS::Manager& vfs);
|
||||||
|
|
||||||
bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) override;
|
bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setUpFonts();
|
void setUpFonts();
|
||||||
|
|
||||||
bool _offlineCollect;
|
bool mInitFonts = false;
|
||||||
bool _initFonts;
|
bool mOfflineCollect;
|
||||||
osg::ref_ptr<osgText::Font> _textFont;
|
osg::ref_ptr<osgText::Font> mTextFont;
|
||||||
};
|
};
|
||||||
|
|
||||||
class StatsHandler : public osgGA::GUIEventHandler
|
class StatsHandler : public osgGA::GUIEventHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
StatsHandler(bool offlineCollect, VFS::Manager* vfs);
|
explicit StatsHandler(bool offlineCollect, const VFS::Manager& vfs);
|
||||||
|
|
||||||
void setKey(int key) { _key = key; }
|
|
||||||
int getKey() const { return _key; }
|
|
||||||
|
|
||||||
bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) override;
|
bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) override;
|
||||||
|
|
||||||
void setWindowSize(int w, int h);
|
|
||||||
|
|
||||||
void toggle(osgViewer::ViewerBase* viewer);
|
|
||||||
|
|
||||||
void setUpHUDCamera(osgViewer::ViewerBase* viewer);
|
|
||||||
void setUpScene(osgViewer::ViewerBase* viewer);
|
|
||||||
|
|
||||||
/** Get the keyboard and mouse usage of this manipulator.*/
|
/** Get the keyboard and mouse usage of this manipulator.*/
|
||||||
void getUsage(osg::ApplicationUsage& usage) const override;
|
void getUsage(osg::ApplicationUsage& usage) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
osg::ref_ptr<osg::Switch> _switch;
|
unsigned mPage = 0;
|
||||||
int _key;
|
bool mInitialized = false;
|
||||||
osg::ref_ptr<osg::Camera> _camera;
|
bool mOfflineCollect;
|
||||||
bool _initialized;
|
osg::ref_ptr<osg::Switch> mSwitch;
|
||||||
bool _statsType;
|
osg::ref_ptr<osg::Camera> mCamera;
|
||||||
bool _offlineCollect;
|
osg::ref_ptr<osgText::Font> mTextFont;
|
||||||
|
std::vector<std::string> mStatNames;
|
||||||
|
|
||||||
float _statsWidth;
|
void setWindowSize(int w, int h);
|
||||||
float _statsHeight;
|
|
||||||
|
|
||||||
float _characterSize;
|
void toggle(osgViewer::ViewerBase& viewer);
|
||||||
|
|
||||||
int _resourceStatsChildNum;
|
void setUpHUDCamera(osgViewer::ViewerBase& viewer);
|
||||||
|
|
||||||
osg::ref_ptr<osgText::Font> _textFont;
|
void setUpScene(osgViewer::ViewerBase& viewer);
|
||||||
};
|
};
|
||||||
|
|
||||||
void CollectStatistics(osgViewer::ViewerBase* viewer);
|
void collectStatistics(osgViewer::ViewerBase& viewer);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -63,7 +63,7 @@ namespace Terrain
|
||||||
|
|
||||||
void ChunkManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
void ChunkManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
||||||
{
|
{
|
||||||
stats->setAttribute(frameNumber, "Terrain Chunk", mCache->getCacheSize());
|
Resource::reportStats("Terrain Chunk", frameNumber, mCache->getStats(), *stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChunkManager::clearCache()
|
void ChunkManager::clearCache()
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include "texturemanager.hpp"
|
#include "texturemanager.hpp"
|
||||||
|
|
||||||
#include <osg/Stats>
|
|
||||||
#include <osg/Texture2D>
|
#include <osg/Texture2D>
|
||||||
|
|
||||||
#include <components/resource/imagemanager.hpp>
|
#include <components/resource/imagemanager.hpp>
|
||||||
|
@ -56,7 +55,7 @@ namespace Terrain
|
||||||
|
|
||||||
void TextureManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
void TextureManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
||||||
{
|
{
|
||||||
stats->setAttribute(frameNumber, "Terrain Texture", mCache->getCacheSize());
|
Resource::reportStats("Terrain Texture", frameNumber, mCache->getStats(), *stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue