forked from teamnwah/openmw-tes3coop
Add resource statistics panel opened with F4
This commit is contained in:
parent
b40ca9b60a
commit
8f79fa3d72
32 changed files with 549 additions and 11 deletions
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <components/resource/resourcesystem.hpp>
|
||||
#include <components/resource/scenemanager.hpp>
|
||||
#include <components/resource/stats.hpp>
|
||||
|
||||
#include <components/compiler/extensions0.hpp>
|
||||
|
||||
|
@ -169,7 +170,7 @@ void OMW::Engine::frame(float frametime)
|
|||
mEnvironment.getWindowManager()->update();
|
||||
}
|
||||
|
||||
int frameNumber = mViewer->getFrameStamp()->getFrameNumber();
|
||||
unsigned int frameNumber = mViewer->getFrameStamp()->getFrameNumber();
|
||||
osg::Stats* stats = mViewer->getViewerStats();
|
||||
stats->setAttribute(frameNumber, "script_time_begin", osg::Timer::instance()->delta_s(mStartTick, beforeScriptTick));
|
||||
stats->setAttribute(frameNumber, "script_time_taken", osg::Timer::instance()->delta_s(beforeScriptTick, afterScriptTick));
|
||||
|
@ -183,6 +184,14 @@ void OMW::Engine::frame(float frametime)
|
|||
stats->setAttribute(frameNumber, "physics_time_taken", osg::Timer::instance()->delta_s(beforePhysicsTick, afterPhysicsTick));
|
||||
stats->setAttribute(frameNumber, "physics_time_end", osg::Timer::instance()->delta_s(mStartTick, afterPhysicsTick));
|
||||
|
||||
if (stats->collectStats("resource"))
|
||||
{
|
||||
mResourceSystem->reportStats(frameNumber, stats);
|
||||
|
||||
stats->setAttribute(frameNumber, "WorkQueue", mWorkQueue->getNumItems());
|
||||
stats->setAttribute(frameNumber, "WorkThread", mWorkQueue->getNumActiveThreads());
|
||||
}
|
||||
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
@ -635,6 +644,8 @@ void OMW::Engine::go()
|
|||
|
||||
mViewer->addEventHandler(statshandler);
|
||||
|
||||
mViewer->addEventHandler(new Resource::StatsHandler);
|
||||
|
||||
Settings::Manager settings;
|
||||
std::string settingspath;
|
||||
|
||||
|
|
|
@ -475,6 +475,8 @@ namespace MWRender
|
|||
|
||||
void RenderingManager::update(float dt, bool paused)
|
||||
{
|
||||
reportStats();
|
||||
|
||||
mUnrefQueue->flush(mWorkQueue.get());
|
||||
|
||||
if (!paused)
|
||||
|
@ -901,6 +903,18 @@ namespace MWRender
|
|||
mStateUpdater->setFogColor(color);
|
||||
}
|
||||
|
||||
void RenderingManager::reportStats()
|
||||
{
|
||||
osg::Stats* stats = mViewer->getViewerStats();
|
||||
unsigned int frameNumber = mViewer->getFrameStamp()->getFrameNumber();
|
||||
if (stats->collectStats("resource"))
|
||||
{
|
||||
stats->setAttribute(frameNumber, "UnrefQueue", mUnrefQueue->getNumItems());
|
||||
|
||||
mTerrain->reportStats(frameNumber, stats);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingManager::processChangedSettings(const Settings::CategorySettingVector &changed)
|
||||
{
|
||||
for (Settings::CategorySettingVector::const_iterator it = changed.begin(); it != changed.end(); ++it)
|
||||
|
|
|
@ -196,6 +196,8 @@ namespace MWRender
|
|||
void updateAmbient();
|
||||
void setFogColor(const osg::Vec4f& color);
|
||||
|
||||
void reportStats();
|
||||
|
||||
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
||||
osg::ref_ptr<osg::Group> mRootNode;
|
||||
osg::ref_ptr<osg::Group> mSceneRoot;
|
||||
|
|
|
@ -41,7 +41,7 @@ add_component_dir (vfs
|
|||
)
|
||||
|
||||
add_component_dir (resource
|
||||
scenemanager keyframemanager imagemanager bulletshapemanager bulletshape niffilemanager objectcache multiobjectcache resourcesystem resourcemanager
|
||||
scenemanager keyframemanager imagemanager bulletshapemanager bulletshape niffilemanager objectcache multiobjectcache resourcesystem resourcemanager stats
|
||||
)
|
||||
|
||||
add_component_dir (shader
|
||||
|
@ -202,6 +202,7 @@ target_link_libraries(components
|
|||
${OSGUTIL_LIBRARIES}
|
||||
${OSGDB_LIBRARIES}
|
||||
${OSGVIEWER_LIBRARIES}
|
||||
${OSGTEXT_LIBRARIES}
|
||||
${OSGGA_LIBRARIES}
|
||||
${OSGFX_LIBRARIES}
|
||||
${OSGANIMATION_LIBRARIES}
|
||||
|
|
|
@ -185,4 +185,10 @@ void BulletShapeManager::updateCache(double referenceTime)
|
|||
mInstanceCache->removeUnreferencedObjectsInCache();
|
||||
}
|
||||
|
||||
void BulletShapeManager::reportStats(unsigned int frameNumber, osg::Stats *stats)
|
||||
{
|
||||
stats->setAttribute(frameNumber, "Shape", mCache->getCacheSize());
|
||||
stats->setAttribute(frameNumber, "Shape Instance", mInstanceCache->getCacheSize());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ namespace Resource
|
|||
/// @see ResourceManager::updateCache
|
||||
virtual void updateCache(double referenceTime);
|
||||
|
||||
void reportStats(unsigned int frameNumber, osg::Stats *stats);
|
||||
|
||||
private:
|
||||
osg::ref_ptr<BulletShapeInstance> createInstance(const std::string& name);
|
||||
|
||||
|
|
|
@ -141,4 +141,9 @@ namespace Resource
|
|||
return mWarningImage;
|
||||
}
|
||||
|
||||
void ImageManager::reportStats(unsigned int frameNumber, osg::Stats *stats)
|
||||
{
|
||||
stats->setAttribute(frameNumber, "Image", mCache->getCacheSize());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,6 +32,8 @@ namespace Resource
|
|||
|
||||
osg::Image* getWarningImage();
|
||||
|
||||
void reportStats(unsigned int frameNumber, osg::Stats* stats);
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osg::Image> mWarningImage;
|
||||
osg::ref_ptr<osgDB::Options> mOptions;
|
||||
|
|
|
@ -34,6 +34,11 @@ namespace Resource
|
|||
}
|
||||
}
|
||||
|
||||
void KeyframeManager::reportStats(unsigned int frameNumber, osg::Stats *stats)
|
||||
{
|
||||
stats->setAttribute(frameNumber, "Keyframe", mCache->getCacheSize());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@ namespace Resource
|
|||
/// Retrieve a read-only keyframe resource by name (case-insensitive).
|
||||
/// @note Throws an exception if the resource is not found.
|
||||
osg::ref_ptr<const NifOsg::KeyframeHolder> get(const std::string& name);
|
||||
|
||||
void reportStats(unsigned int frameNumber, osg::Stats* stats);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -76,4 +76,10 @@ namespace Resource
|
|||
}
|
||||
}
|
||||
|
||||
unsigned int MultiObjectCache::getCacheSize() const
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
|
||||
return _objectCache.size();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -33,12 +33,14 @@ namespace Resource
|
|||
/** call releaseGLObjects on all objects attached to the object cache.*/
|
||||
void releaseGLObjects(osg::State* state);
|
||||
|
||||
unsigned int getCacheSize() const;
|
||||
|
||||
protected:
|
||||
|
||||
typedef std::multimap<std::string, osg::ref_ptr<osg::Object> > ObjectCacheMap;
|
||||
|
||||
ObjectCacheMap _objectCache;
|
||||
OpenThreads::Mutex _objectCacheMutex;
|
||||
mutable OpenThreads::Mutex _objectCacheMutex;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "niffilemanager.hpp"
|
||||
|
||||
#include <osg/Object>
|
||||
#include <osg/Stats>
|
||||
|
||||
#include <components/vfs/manager.hpp>
|
||||
|
||||
|
@ -55,4 +56,9 @@ namespace Resource
|
|||
}
|
||||
}
|
||||
|
||||
void NifFileManager::reportStats(unsigned int frameNumber, osg::Stats *stats)
|
||||
{
|
||||
stats->setAttribute(frameNumber, "Nif", mCache->getCacheSize());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@ namespace Resource
|
|||
/// @note For performance reasons the NifFileManager does not handle case folding, needs
|
||||
/// to be done in advance by other managers accessing the NifFileManager.
|
||||
Nif::NIFFilePtr get(const std::string& name);
|
||||
|
||||
void reportStats(unsigned int frameNumber, osg::Stats *stats);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -150,4 +150,10 @@ void ObjectCache::accept(osg::NodeVisitor &nv)
|
|||
}
|
||||
}
|
||||
|
||||
unsigned int ObjectCache::getCacheSize() const
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
|
||||
return _objectCache.size();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -73,6 +73,9 @@ class ObjectCache : public osg::Referenced
|
|||
/** call node->accept(nv); for all nodes in the objectCache. */
|
||||
void accept(osg::NodeVisitor& nv);
|
||||
|
||||
/** Get the number of objects in the cache. */
|
||||
unsigned int getCacheSize() const;
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~ObjectCache();
|
||||
|
@ -81,7 +84,7 @@ class ObjectCache : public osg::Referenced
|
|||
typedef std::map<std::string, ObjectTimeStampPair > ObjectCacheMap;
|
||||
|
||||
ObjectCacheMap _objectCache;
|
||||
OpenThreads::Mutex _objectCacheMutex;
|
||||
mutable OpenThreads::Mutex _objectCacheMutex;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -8,6 +8,11 @@ namespace VFS
|
|||
class Manager;
|
||||
}
|
||||
|
||||
namespace osg
|
||||
{
|
||||
class Stats;
|
||||
}
|
||||
|
||||
namespace Resource
|
||||
{
|
||||
class ObjectCache;
|
||||
|
@ -28,6 +33,8 @@ namespace Resource
|
|||
|
||||
const VFS::Manager* getVFS() const;
|
||||
|
||||
virtual void reportStats(unsigned int frameNumber, osg::Stats* stats) {}
|
||||
|
||||
protected:
|
||||
const VFS::Manager* mVFS;
|
||||
osg::ref_ptr<Resource::ObjectCache> mCache;
|
||||
|
|
|
@ -85,4 +85,10 @@ namespace Resource
|
|||
return mVFS;
|
||||
}
|
||||
|
||||
void ResourceSystem::reportStats(unsigned int frameNumber, osg::Stats *stats)
|
||||
{
|
||||
for (std::vector<ResourceManager*>::iterator it = mResourceManagers.begin(); it != mResourceManagers.end(); ++it)
|
||||
(*it)->reportStats(frameNumber, stats);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,6 +9,11 @@ namespace VFS
|
|||
class Manager;
|
||||
}
|
||||
|
||||
namespace osg
|
||||
{
|
||||
class Stats;
|
||||
}
|
||||
|
||||
namespace Resource
|
||||
{
|
||||
|
||||
|
@ -49,6 +54,8 @@ namespace Resource
|
|||
/// @note May be called from any thread.
|
||||
const VFS::Manager* getVFS() const;
|
||||
|
||||
void reportStats(unsigned int frameNumber, osg::Stats* stats);
|
||||
|
||||
private:
|
||||
std::auto_ptr<SceneManager> mSceneManager;
|
||||
std::auto_ptr<ImageManager> mImageManager;
|
||||
|
|
|
@ -585,4 +585,15 @@ namespace Resource
|
|||
mInstanceCache->removeUnreferencedObjectsInCache();
|
||||
}
|
||||
|
||||
void SceneManager::reportStats(unsigned int frameNumber, osg::Stats *stats)
|
||||
{
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*mIncrementalCompileOperation->getToCompiledMutex());
|
||||
stats->setAttribute(frameNumber, "Compiling", mIncrementalCompileOperation->getToCompile().size());
|
||||
}
|
||||
|
||||
stats->setAttribute(frameNumber, "Node", mCache->getCacheSize());
|
||||
stats->setAttribute(frameNumber, "Node Instance", mInstanceCache->getCacheSize());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -139,6 +139,8 @@ namespace Resource
|
|||
/// @see ResourceManager::updateCache
|
||||
virtual void updateCache(double referenceTime);
|
||||
|
||||
virtual void reportStats(unsigned int frameNumber, osg::Stats* stats);
|
||||
|
||||
private:
|
||||
|
||||
osg::ref_ptr<osg::Node> createInstance(const std::string& name);
|
||||
|
|
316
components/resource/stats.cpp
Normal file
316
components/resource/stats.cpp
Normal file
|
@ -0,0 +1,316 @@
|
|||
#include "stats.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
#include <osg/PolygonMode>
|
||||
|
||||
#include <osgText/Text>
|
||||
|
||||
#include <osgViewer/Viewer>
|
||||
#include <osgViewer/Renderer>
|
||||
|
||||
namespace Resource
|
||||
{
|
||||
|
||||
StatsHandler::StatsHandler():
|
||||
_key(osgGA::GUIEventAdapter::KEY_F4),
|
||||
_initialized(false),
|
||||
_statsType(false),
|
||||
_statsWidth(1280.0f),
|
||||
_statsHeight(1024.0f),
|
||||
_font("fonts/arial.ttf"),
|
||||
_characterSize(20.0f)
|
||||
{
|
||||
_camera = new osg::Camera;
|
||||
_camera->getOrCreateStateSet()->setGlobalDefaults();
|
||||
_camera->setRenderer(new osgViewer::Renderer(_camera.get()));
|
||||
_camera->setProjectionResizePolicy(osg::Camera::FIXED);
|
||||
|
||||
_resourceStatsChildNum = 0;
|
||||
}
|
||||
|
||||
bool StatsHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa)
|
||||
{
|
||||
if (ea.getHandled()) return false;
|
||||
|
||||
switch(ea.getEventType())
|
||||
{
|
||||
case(osgGA::GUIEventAdapter::KEYDOWN):
|
||||
{
|
||||
if (ea.getKey()== _key)
|
||||
{
|
||||
osgViewer::View* myview = dynamic_cast<osgViewer::View*>(&aa);
|
||||
if (!myview) return false;
|
||||
|
||||
osgViewer::ViewerBase* viewer = myview->getViewerBase();
|
||||
|
||||
toggle(viewer);
|
||||
|
||||
aa.requestRedraw();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case osgGA::GUIEventAdapter::RESIZE:
|
||||
{
|
||||
setWindowSize(ea.getWindowWidth(), ea.getWindowHeight());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void StatsHandler::setWindowSize(int width, int height)
|
||||
{
|
||||
if (width <= 0 || height <= 0)
|
||||
return;
|
||||
|
||||
_camera->setViewport(0, 0, width, height);
|
||||
if (fabs(height*_statsWidth) <= fabs(width*_statsHeight))
|
||||
{
|
||||
_camera->setProjectionMatrix(osg::Matrix::ortho2D(_statsWidth - width*_statsHeight/height, _statsWidth,0.0,_statsHeight));
|
||||
}
|
||||
else
|
||||
{
|
||||
_camera->setProjectionMatrix(osg::Matrix::ortho2D(0.0,_statsWidth,_statsHeight-height*_statsWidth/width,_statsHeight));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void StatsHandler::toggle(osgViewer::ViewerBase *viewer)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
setUpHUDCamera(viewer);
|
||||
setUpScene(viewer);
|
||||
}
|
||||
|
||||
_statsType = !_statsType;
|
||||
|
||||
if (!_statsType)
|
||||
{
|
||||
_camera->setNodeMask(0);
|
||||
_switch->setAllChildrenOff();
|
||||
|
||||
viewer->getViewerStats()->collectStats("resource", false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_camera->setNodeMask(0xffffffff);
|
||||
_switch->setSingleChildOn(_resourceStatsChildNum);
|
||||
|
||||
viewer->getViewerStats()->collectStats("resource", true);
|
||||
}
|
||||
}
|
||||
|
||||
void StatsHandler::setUpHUDCamera(osgViewer::ViewerBase* viewer)
|
||||
{
|
||||
// Try GraphicsWindow first so we're likely to get the main viewer window
|
||||
osg::GraphicsContext* context = dynamic_cast<osgViewer::GraphicsWindow*>(_camera->getGraphicsContext());
|
||||
|
||||
if (!context)
|
||||
{
|
||||
osgViewer::Viewer::Windows windows;
|
||||
viewer->getWindows(windows);
|
||||
|
||||
if (!windows.empty()) context = windows.front();
|
||||
else
|
||||
{
|
||||
// No GraphicsWindows were found, so let's try to find a GraphicsContext
|
||||
context = _camera->getGraphicsContext();
|
||||
|
||||
if (!context)
|
||||
{
|
||||
osgViewer::Viewer::Contexts contexts;
|
||||
viewer->getContexts(contexts);
|
||||
|
||||
if (contexts.empty()) return;
|
||||
|
||||
context = contexts.front();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_camera->setGraphicsContext(context);
|
||||
|
||||
_camera->setRenderOrder(osg::Camera::POST_RENDER, 11);
|
||||
|
||||
_camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
|
||||
_camera->setViewMatrix(osg::Matrix::identity());
|
||||
setWindowSize(context->getTraits()->width, context->getTraits()->height);
|
||||
|
||||
// only clear the depth buffer
|
||||
_camera->setClearMask(0);
|
||||
_camera->setAllowEventFocus(false);
|
||||
|
||||
_camera->setRenderer(new osgViewer::Renderer(_camera.get()));
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
osg::Geometry* createBackgroundRectangle(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
|
||||
{
|
||||
public:
|
||||
ResourceStatsTextDrawCallback(osg::Stats* stats, const std::vector<std::string>& statNames)
|
||||
: _stats(stats)
|
||||
, _statNames(statNames)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const
|
||||
{
|
||||
if (!_stats) return;
|
||||
|
||||
osgText::Text* text = (osgText::Text*)(drawable);
|
||||
|
||||
std::ostringstream viewStr;
|
||||
viewStr.setf(std::ios::left, std::ios::adjustfield);
|
||||
viewStr.width(14);
|
||||
// Used fixed formatting, as scientific will switch to "...e+.." notation for
|
||||
// large numbers of vertices/drawables/etc.
|
||||
viewStr.setf(std::ios::fixed);
|
||||
viewStr.precision(0);
|
||||
|
||||
unsigned int frameNumber = renderInfo.getState()->getFrameStamp()->getFrameNumber()-1;
|
||||
|
||||
for (std::vector<std::string>::const_iterator it = _statNames.begin(); it != _statNames.end(); ++it)
|
||||
{
|
||||
if (it->empty())
|
||||
viewStr << std::endl;
|
||||
else
|
||||
{
|
||||
double value = 0.0;
|
||||
if (_stats->getAttribute(frameNumber, *it, value))
|
||||
viewStr << std::setw(8) << value << std::endl;
|
||||
else
|
||||
viewStr << std::setw(8) << "." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
text->setText(viewStr.str());
|
||||
|
||||
text->drawImplementation(renderInfo);
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Stats> _stats;
|
||||
std::vector<std::string> _statNames;
|
||||
};
|
||||
|
||||
void StatsHandler::setUpScene(osgViewer::ViewerBase *viewer)
|
||||
{
|
||||
_switch = new osg::Switch;
|
||||
|
||||
_camera->addChild(_switch);
|
||||
|
||||
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::Vec3 pos(_statsWidth-300.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);
|
||||
float backgroundMargin = 5;
|
||||
float backgroundSpacing = 3;
|
||||
|
||||
// resource stats
|
||||
{
|
||||
osg::Group* group = new osg::Group;
|
||||
group->setCullingActive(false);
|
||||
_resourceStatsChildNum = _switch->getNumChildren();
|
||||
_switch->addChild(group, false);
|
||||
|
||||
const char* statNames[] = {"Compiling", "WorkQueue", "WorkThread", "", "Node", "Node Instance", "Shape", "Shape Instance", "Image", "Nif", "Keyframe", "Terrain Cell", "Terrain Texture", "", "UnrefQueue"};
|
||||
|
||||
int numLines = sizeof(statNames) / sizeof(statNames[0]);
|
||||
|
||||
group->addChild(createBackgroundRectangle(pos + osg::Vec3(-backgroundMargin, _characterSize + backgroundMargin, 0),
|
||||
10 * _characterSize + 2 * backgroundMargin,
|
||||
numLines * _characterSize + 2 * backgroundMargin,
|
||||
backgroundColor));
|
||||
|
||||
osg::ref_ptr<osgText::Text> staticText = new osgText::Text;
|
||||
group->addChild( staticText.get() );
|
||||
staticText->setColor(staticTextColor);
|
||||
staticText->setFont(_font);
|
||||
staticText->setCharacterSize(_characterSize);
|
||||
staticText->setPosition(pos);
|
||||
|
||||
std::ostringstream viewStr;
|
||||
viewStr.clear();
|
||||
viewStr.setf(std::ios::left, std::ios::adjustfield);
|
||||
viewStr.width(14);
|
||||
for (size_t i = 0; i<sizeof(statNames)/sizeof(statNames[0]); ++i)
|
||||
{
|
||||
viewStr << statNames[i] << std::endl;
|
||||
}
|
||||
|
||||
staticText->setText(viewStr.str());
|
||||
|
||||
pos.x() += 10 * _characterSize + 2 * backgroundMargin + backgroundSpacing;
|
||||
|
||||
group->addChild(createBackgroundRectangle(pos + osg::Vec3(-backgroundMargin, _characterSize + backgroundMargin, 0),
|
||||
5 * _characterSize + 2 * backgroundMargin,
|
||||
numLines * _characterSize + 2 * backgroundMargin,
|
||||
backgroundColor));
|
||||
|
||||
osg::ref_ptr<osgText::Text> statsText = new osgText::Text;
|
||||
group->addChild( statsText.get() );
|
||||
|
||||
statsText->setColor(dynamicTextColor);
|
||||
statsText->setFont(_font);
|
||||
statsText->setCharacterSize(_characterSize);
|
||||
statsText->setPosition(pos);
|
||||
statsText->setText("");
|
||||
statsText->setDrawCallback(new ResourceStatsTextDrawCallback(viewer->getViewerStats(), std::vector<std::string>(statNames, statNames + numLines)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void StatsHandler::getUsage(osg::ApplicationUsage &usage) const
|
||||
{
|
||||
usage.addKeyboardMouseBinding(_key, "On screen resource usage stats.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
59
components/resource/stats.hpp
Normal file
59
components/resource/stats.hpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
#ifndef OPENMW_COMPONENTS_RESOURCE_STATS_H
|
||||
#define OPENMW_COMPONENTS_RESOURCE_STATS_H
|
||||
|
||||
#include <osgGA/GUIEventHandler>
|
||||
|
||||
namespace osgViewer
|
||||
{
|
||||
class ViewerBase;
|
||||
}
|
||||
|
||||
namespace osg
|
||||
{
|
||||
class Switch;
|
||||
}
|
||||
|
||||
namespace Resource
|
||||
{
|
||||
|
||||
class StatsHandler : public osgGA::GUIEventHandler
|
||||
{
|
||||
public:
|
||||
StatsHandler();
|
||||
|
||||
void setKey(int key) { _key = key; }
|
||||
int getKey() const { return _key; }
|
||||
|
||||
bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
|
||||
|
||||
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.*/
|
||||
virtual void getUsage(osg::ApplicationUsage& usage) const;
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osg::Switch> _switch;
|
||||
int _key;
|
||||
osg::ref_ptr<osg::Camera> _camera;
|
||||
bool _initialized;
|
||||
bool _statsType;
|
||||
|
||||
float _statsWidth;
|
||||
float _statsHeight;
|
||||
|
||||
std::string _font;
|
||||
float _leftPos;
|
||||
float _characterSize;
|
||||
|
||||
int _resourceStatsChildNum;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -44,4 +44,9 @@ namespace SceneUtil
|
|||
mWorkItem = new UnrefWorkItem;
|
||||
}
|
||||
|
||||
unsigned int UnrefQueue::getNumItems() const
|
||||
{
|
||||
return mWorkItem->mObjects.size();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ namespace SceneUtil
|
|||
/// Call from the main thread.
|
||||
void flush(SceneUtil::WorkQueue* workQueue);
|
||||
|
||||
unsigned int getNumItems() const;
|
||||
|
||||
private:
|
||||
osg::ref_ptr<UnrefWorkItem> mWorkItem;
|
||||
};
|
||||
|
|
|
@ -100,6 +100,23 @@ osg::ref_ptr<WorkItem> WorkQueue::removeWorkItem()
|
|||
return NULL;
|
||||
}
|
||||
|
||||
unsigned int WorkQueue::getNumItems() const
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mMutex);
|
||||
return mQueue.size();
|
||||
}
|
||||
|
||||
unsigned int WorkQueue::getNumActiveThreads() const
|
||||
{
|
||||
unsigned int count = 0;
|
||||
for (unsigned int i=0; i<mThreads.size(); ++i)
|
||||
{
|
||||
if (mThreads[i]->isActive())
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
WorkThread::WorkThread(WorkQueue *workQueue)
|
||||
: mWorkQueue(workQueue)
|
||||
{
|
||||
|
@ -112,9 +129,16 @@ void WorkThread::run()
|
|||
osg::ref_ptr<WorkItem> item = mWorkQueue->removeWorkItem();
|
||||
if (!item)
|
||||
return;
|
||||
mActive = true;
|
||||
item->doWork();
|
||||
item->signalDone();
|
||||
mActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool WorkThread::isActive() const
|
||||
{
|
||||
return mActive;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -61,11 +61,15 @@ namespace SceneUtil
|
|||
/// @par Used internally by the WorkThread.
|
||||
osg::ref_ptr<WorkItem> removeWorkItem();
|
||||
|
||||
unsigned int getNumItems() const;
|
||||
|
||||
unsigned int getNumActiveThreads() const;
|
||||
|
||||
private:
|
||||
bool mIsReleased;
|
||||
std::deque<osg::ref_ptr<WorkItem> > mQueue;
|
||||
|
||||
OpenThreads::Mutex mMutex;
|
||||
mutable OpenThreads::Mutex mMutex;
|
||||
OpenThreads::Condition mCondition;
|
||||
|
||||
std::vector<WorkThread*> mThreads;
|
||||
|
@ -79,8 +83,11 @@ namespace SceneUtil
|
|||
|
||||
virtual void run();
|
||||
|
||||
bool isActive() const;
|
||||
|
||||
private:
|
||||
WorkQueue* mWorkQueue;
|
||||
volatile bool mActive;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -89,18 +89,16 @@ InputWrapper::InputWrapper(SDL_Window* window, osg::ref_ptr<osgViewer::Viewer> v
|
|||
if (!evt.key.repeat)
|
||||
mKeyboardListener->keyPressed(evt.key);
|
||||
|
||||
// temporary for the stats viewer
|
||||
if (evt.key.keysym.sym == SDLK_F3)
|
||||
mViewer->getEventQueue()->keyPress(osgGA::GUIEventAdapter::KEY_F3);
|
||||
if (evt.key.keysym.sym >= SDLK_F1 && evt.key.keysym.sym <= SDLK_F12)
|
||||
mViewer->getEventQueue()->keyPress(osgGA::GUIEventAdapter::KEY_F1 + (evt.key.keysym.sym - SDLK_F1));
|
||||
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
if (!evt.key.repeat)
|
||||
mKeyboardListener->keyReleased(evt.key);
|
||||
|
||||
// temporary for the stats viewer
|
||||
if (evt.key.keysym.sym == SDLK_F3)
|
||||
mViewer->getEventQueue()->keyRelease(osgGA::GUIEventAdapter::KEY_F3);
|
||||
if (evt.key.keysym.sym >= SDLK_F1 && evt.key.keysym.sym <= SDLK_F12)
|
||||
mViewer->getEventQueue()->keyRelease(osgGA::GUIEventAdapter::KEY_F1 + (evt.key.keysym.sym - SDLK_F1));
|
||||
|
||||
break;
|
||||
case SDL_TEXTEDITING:
|
||||
|
|
|
@ -314,4 +314,16 @@ void TerrainGrid::updateTextureFiltering()
|
|||
mResourceSystem->getSceneManager()->applyFilterSettings(it->second);
|
||||
}
|
||||
|
||||
void TerrainGrid::reportStats(unsigned int frameNumber, osg::Stats *stats)
|
||||
{
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mGridCacheMutex);
|
||||
stats->setAttribute(frameNumber, "Terrain Cell", mGridCache.size());
|
||||
}
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mTextureCacheMutex);
|
||||
stats->setAttribute(frameNumber, "Terrain Texture", mTextureCache.size());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -49,6 +49,8 @@ namespace Terrain
|
|||
/// @note Thread safe.
|
||||
void updateTextureFiltering();
|
||||
|
||||
void reportStats(unsigned int frameNumber, osg::Stats *stats);
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osg::Node> buildTerrain (osg::Group* parent, float chunkSize, const osg::Vec2f& chunkCenter);
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
namespace osg
|
||||
{
|
||||
class Group;
|
||||
class Stats;
|
||||
}
|
||||
|
||||
namespace osgUtil
|
||||
|
@ -43,6 +44,8 @@ namespace Terrain
|
|||
|
||||
virtual void updateCache() {}
|
||||
|
||||
virtual void reportStats(unsigned int frameNumber, osg::Stats* stats) {}
|
||||
|
||||
float getHeightAt (const osg::Vec3f& worldPos);
|
||||
|
||||
virtual osg::ref_ptr<osg::Node> cacheCell(int x, int y) {return NULL;}
|
||||
|
|
|
@ -26,6 +26,8 @@ preload enabled
|
|||
|
||||
Controls whether textures and objects will be pre-loaded in background threads. This setting being enabled should result in a reduced amount of loading screens, no impact on frame rate and a varying amount of additional RAM usage, depending on how the preloader was configured (see the below settings). The default preloading settings with vanilla game files should only use negligible amounts of RAM, however, when using high-res texture and model replacers it may be necessary to tweak these settings to prevent the game from running out of memory.
|
||||
|
||||
The effects of (pre-)loading can be observed on the in-game statistics panel brought up with the 'F4' key.
|
||||
|
||||
All settings starting with 'preload' in this section will have no effect if preloading is disabled, and can only be configured by editing the settings configuration file.
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue