Implemented better coupling of DatabasePager and IcrementalCompileOperation,

removing functional duplication and opening the door to dynamic enabling/disabling
of pre compile based on load.
This commit is contained in:
Robert Osfield
2011-01-17 17:17:19 +00:00
parent 45bd464942
commit 11cd5a89ed
3 changed files with 211 additions and 221 deletions

View File

@@ -20,6 +20,35 @@
namespace osgUtil {
class OSGUTIL_EXPORT StateToCompile : public osg::NodeVisitor
{
public:
StateToCompile(GLObjectsVisitor::Mode mode);
typedef std::set<osg::Drawable*> DrawableSet;
typedef std::set<osg::StateSet*> StateSetSet;
typedef std::set<osg::Texture*> TextureSet;
typedef std::set<osg::Program*> ProgramSet;
DrawableSet _drawablesHandled;
StateSetSet _statesetsHandled;
GLObjectsVisitor::Mode _mode;
DrawableSet _drawables;
TextureSet _textures;
ProgramSet _programs;
bool empty() const { return _textures.empty() && _programs.empty() && _drawables.empty(); }
virtual void apply(osg::Node& node);
virtual void apply(osg::Geode& node);
virtual void apply(osg::Drawable& drawable);
virtual void apply(osg::StateSet& stateset);
virtual void apply(osg::Texture& texture);
};
class OSGUTIL_EXPORT CompileStats : public osg::Referenced
{
public:
@@ -93,7 +122,12 @@ class OSGUTIL_EXPORT IncrementalCompileOperation : public osg::GraphicsOperation
public:
IncrementalCompileOperation();
/** Return true if the IncrementCompileOperation is active.*/
bool isActive() const { return !_contexts.empty(); }
bool requiresCompile(StateToCompile& stateToCompile);
/** Set the target frame rate that the IncrementalCompileOperation should assume.
* Typically one would set this to the value refresh rate of your display system i.e. 60Hz.
* Default value is 100.
@@ -163,6 +197,10 @@ class OSGUTIL_EXPORT IncrementalCompileOperation : public osg::GraphicsOperation
void addGraphicsContext(osg::GraphicsContext* gc);
void removeGraphicsContext(osg::GraphicsContext* gc);
typedef std::set<osg::GraphicsContext*> ContextSet;
ContextSet& getContextSet() { return _contexts; }
const ContextSet& getContextSet() const { return _contexts; }
/** Merge subgraphs that have been compiled.*/
void mergeCompiledSubgraphs();
@@ -235,7 +273,6 @@ class OSGUTIL_EXPORT IncrementalCompileOperation : public osg::GraphicsOperation
class CompileSet;
typedef std::set<osg::GraphicsContext*> ContextSet;
struct CompileCompletedCallback : public virtual osg::Referenced
{
@@ -256,7 +293,8 @@ class OSGUTIL_EXPORT IncrementalCompileOperation : public osg::GraphicsOperation
_attachmentPoint(attachmentPoint),
_subgraphToCompile(subgraphToCompile) {}
void buildCompileMap(ContextSet& context, GLObjectsVisitor::Mode mode=GLObjectsVisitor::COMPILE_DISPLAY_LISTS|GLObjectsVisitor::COMPILE_STATE_ATTRIBUTES);
void buildCompileMap(ContextSet& contexts, StateToCompile& stateToCompile);
void buildCompileMap(ContextSet& contexts, GLObjectsVisitor::Mode mode=GLObjectsVisitor::COMPILE_DISPLAY_LISTS|GLObjectsVisitor::COMPILE_STATE_ATTRIBUTES);
bool compile(CompileInfo& compileInfo);
@@ -299,8 +337,6 @@ class OSGUTIL_EXPORT IncrementalCompileOperation : public osg::GraphicsOperation
virtual ~IncrementalCompileOperation();
// forward declare to keep within class namespace
class CollectStateToCompile;
double _targetFrameRate;
double _minimumTimeAvailableForGLCompileAndDeletePerFrame;

View File

@@ -290,18 +290,38 @@ public:
//
// FindCompileableGLObjectsVisitor
//
class DatabasePager::FindCompileableGLObjectsVisitor : public osg::NodeVisitor
class DatabasePager::FindCompileableGLObjectsVisitor : public osgUtil::StateToCompile
{
public:
FindCompileableGLObjectsVisitor(bool changeAutoUnRef, bool valueAutoUnRef,
bool changeAnisotropy, float valueAnisotropy,
DatabasePager::DrawablePolicy drawablePolicy,
const DatabasePager* pager):
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
_changeAutoUnRef(changeAutoUnRef), _valueAutoUnRef(valueAutoUnRef),
_changeAnisotropy(changeAnisotropy), _valueAnisotropy(valueAnisotropy),
_drawablePolicy(drawablePolicy), _pager(pager)
FindCompileableGLObjectsVisitor(const DatabasePager* pager):
osgUtil::StateToCompile(osgUtil::GLObjectsVisitor::COMPILE_DISPLAY_LISTS|osgUtil::GLObjectsVisitor::COMPILE_STATE_ATTRIBUTES),
_pager(pager),
_changeAutoUnRef(false), _valueAutoUnRef(false),
_changeAnisotropy(false), _valueAnisotropy(1.0)
{
_changeAutoUnRef = _pager->_changeAutoUnRef;
_valueAutoUnRef = _pager->_valueAutoUnRef;
_changeAnisotropy = _pager->_changeAnisotropy;
_valueAnisotropy = _pager->_valueAnisotropy;
switch(_pager->_drawablePolicy)
{
case DatabasePager::DO_NOT_MODIFY_DRAWABLE_SETTINGS:
// do nothing, leave settings as they came in from loaded database.
// OSG_NOTICE<<"DO_NOT_MODIFY_DRAWABLE_SETTINGS"<<std::endl;
break;
case DatabasePager::USE_DISPLAY_LISTS:
_mode = _mode | osgUtil::GLObjectsVisitor::SWITCH_ON_DISPLAY_LISTS;
break;
case DatabasePager::USE_VERTEX_BUFFER_OBJECTS:
_mode = _mode | osgUtil::GLObjectsVisitor::SWITCH_ON_VERTEX_BUFFER_OBJECTS;
break;
case DatabasePager::USE_VERTEX_ARRAYS:
_mode = _mode & ~osgUtil::GLObjectsVisitor::SWITCH_ON_DISPLAY_LISTS;
_mode = _mode & ~osgUtil::GLObjectsVisitor::SWITCH_ON_VERTEX_BUFFER_OBJECTS;
break;
}
if (osgDB::Registry::instance()->getBuildKdTreesHint()==osgDB::Options::BUILD_KDTREES &&
osgDB::Registry::instance()->getKdTreeBuilder())
{
@@ -311,25 +331,11 @@ public:
META_NodeVisitor("osgDB","FindCompileableGLObjectsVisitor")
bool requiresCompilation() const { return true; }
virtual void apply(osg::Node& node)
{
apply(node.getStateSet());
traverse(node);
}
bool requiresCompilation() const { return !empty(); }
virtual void apply(osg::Geode& geode)
{
apply(geode.getStateSet());
for(unsigned int i=0;i<geode.getNumDrawables();++i)
{
apply(geode.getDrawable(i));
}
traverse(geode);
StateToCompile::apply(geode);
if (_kdTreeBuilder.valid())
{
@@ -337,75 +343,26 @@ public:
}
}
inline void apply(osg::StateSet* stateset)
void apply(osg::Texture& texture)
{
if (stateset)
{
// search for the existance of any texture object
// attributes
// if texture object attributes exist and need to be
// compiled, add the state to the list for later
// compilation.
for(unsigned int i=0;i<stateset->getTextureAttributeList().size();++i)
{
osg::Texture* texture = dynamic_cast<osg::Texture*>(stateset->getTextureAttribute(i,osg::StateAttribute::TEXTURE));
// Has this texture already been encountered?
if (texture && !_textureSet.count(texture))
{
_textureSet.insert(texture);
if (_changeAutoUnRef) texture->setUnRefImageDataAfterApply(_valueAutoUnRef);
if ((_changeAnisotropy
&& texture->getMaxAnisotropy() != _valueAnisotropy))
{
if (_changeAnisotropy)
texture->setMaxAnisotropy(_valueAnisotropy);
}
}
}
StateToCompile::apply(texture);
if (_changeAutoUnRef)
{
texture.setUnRefImageDataAfterApply(_valueAutoUnRef);
}
if ((_changeAnisotropy && texture.getMaxAnisotropy() != _valueAnisotropy))
{
texture.setMaxAnisotropy(_valueAnisotropy);
}
}
inline void apply(osg::Drawable* drawable)
{
if (_drawableSet.count(drawable))
return;
_drawableSet.insert(drawable);
apply(drawable->getStateSet());
switch(_drawablePolicy)
{
case DatabasePager::DO_NOT_MODIFY_DRAWABLE_SETTINGS:
// do nothing, leave settings as they came in from loaded database.
// OSG_NOTICE<<"DO_NOT_MODIFY_DRAWABLE_SETTINGS"<<std::endl;
break;
case DatabasePager::USE_DISPLAY_LISTS:
drawable->setUseDisplayList(true);
drawable->setUseVertexBufferObjects(false);
break;
case DatabasePager::USE_VERTEX_BUFFER_OBJECTS:
drawable->setUseDisplayList(true);
drawable->setUseVertexBufferObjects(true);
// OSG_NOTICE<<"USE_VERTEX_BUFFER_OBJECTS"<<std::endl;
break;
case DatabasePager::USE_VERTEX_ARRAYS:
drawable->setUseDisplayList(false);
drawable->setUseVertexBufferObjects(false);
// OSG_NOTICE<<"USE_VERTEX_ARRAYS"<<std::endl;
break;
}
}
const DatabasePager* _pager;
bool _changeAutoUnRef;
bool _valueAutoUnRef;
bool _changeAnisotropy;
float _valueAnisotropy;
DatabasePager::DrawablePolicy _drawablePolicy;
const DatabasePager* _pager;
std::set<osg::ref_ptr<osg::Texture> > _textureSet;
std::set<osg::ref_ptr<osg::Drawable> > _drawableSet;
osg::ref_ptr<osg::KdTreeBuilder> _kdTreeBuilder;
protected:
@@ -918,24 +875,24 @@ void DatabasePager::DatabaseThread::run()
loadedModel->getBound();
// find all the compileable rendering objects
DatabasePager::FindCompileableGLObjectsVisitor frov(_pager->_changeAutoUnRef, _pager->_valueAutoUnRef,
_pager->_changeAnisotropy, _pager->_valueAnisotropy,
_pager->_drawablePolicy,
_pager);
DatabasePager::FindCompileableGLObjectsVisitor stateToCompile(_pager);
loadedModel->accept(stateToCompile);
loadedModel->accept(frov);
bool loadedObjectsNeedToBeCompiled = (_pager->_doPreCompile && frov.requiresCompilation() && _pager->_incrementalCompileOperation.valid());
bool loadedObjectsNeedToBeCompiled = _pager->_doPreCompile &&
_pager->_incrementalCompileOperation.valid() &&
_pager->_incrementalCompileOperation->requiresCompile(stateToCompile);
// move the databaseRequest from the front of the fileRequest to the end of
// dataToCompile or dataToMerge lists.
osgUtil::IncrementalCompileOperation::CompileSet* compileSet = 0;
osg::ref_ptr<osgUtil::IncrementalCompileOperation::CompileSet> compileSet = 0;
if (loadedObjectsNeedToBeCompiled)
{
// OSG_NOTICE<<"Using IncrementalCompileOperation"<<std::endl;
compileSet = new osgUtil::IncrementalCompileOperation::CompileSet(loadedModel.get());
compileSet->buildCompileMap(_pager->_incrementalCompileOperation->getContextSet(), stateToCompile);
compileSet->_compileCompletedCallback = new DatabasePagerCompileCompletedCallback(_pager, databaseRequest.get());
_pager->_incrementalCompileOperation->add(compileSet, false);
}
{
OpenThreads::ScopedLock<OpenThreads::Mutex> drLock(_pager->_dr_mutex);
@@ -948,7 +905,6 @@ void DatabasePager::DatabaseThread::run()
// addLoadedDataToSceneGraph.
if (loadedObjectsNeedToBeCompiled)
{
_pager->_incrementalCompileOperation->add(compileSet);
OpenThreads::ScopedLock<OpenThreads::Mutex> listLock(
_pager->_dataToCompileList->_requestMutex);
_pager->_dataToCompileList->addNoLock(databaseRequest.get());
@@ -1054,7 +1010,7 @@ DatabasePager::DatabasePager()
}
_doPreCompile = false;
_doPreCompile = true;
if( (ptr = getenv("OSG_DO_PRE_COMPILE")) != 0)
{
_doPreCompile = strcmp(ptr,"yes")==0 || strcmp(ptr,"YES")==0 ||
@@ -1064,12 +1020,6 @@ DatabasePager::DatabasePager()
// initialize the stats variables
resetStats();
// make sure a SharedStateManager exists.
//osgDB::Registry::instance()->getOrCreateSharedStateManager();
//if (osgDB::Registry::instance()->getSharedStateManager())
//osgDB::Registry::instance()->setUseObjectCacheHint(true);
_fileRequestQueue = new ReadQueue(this,"fileRequestQueue");
_httpRequestQueue = new ReadQueue(this,"httpRequestQueue");

View File

@@ -51,125 +51,117 @@ static osg::ApplicationUsageProxy UCO_e2(osg::ApplicationUsage::ENVIRONMENTAL_VA
//
// CollectStateToCompile
//
class IncrementalCompileOperation::CollectStateToCompile : public osg::NodeVisitor
StateToCompile::StateToCompile(GLObjectsVisitor::Mode mode):
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
_mode(mode)
{
public:
}
CollectStateToCompile(GLObjectsVisitor::Mode mode):
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
_mode(mode) {}
GLObjectsVisitor::Mode _mode;
typedef std::set<osg::Drawable*> DrawableSet;
typedef std::set<osg::StateSet*> StateSetSet;
typedef std::set<osg::Texture*> TextureSet;
typedef std::set<osg::Program*> ProgramSet;
DrawableSet _drawablesHandled;
StateSetSet _statesetsHandled;
DrawableSet _drawables;
TextureSet _textures;
ProgramSet _programs;
void apply(osg::Node& node)
void StateToCompile::apply(osg::Node& node)
{
if (node.getStateSet())
{
if (node.getStateSet())
{
apply(*(node.getStateSet()));
}
traverse(node);
apply(*(node.getStateSet()));
}
void apply(osg::Geode& node)
traverse(node);
}
void StateToCompile::apply(osg::Geode& node)
{
if (node.getStateSet())
{
if (node.getStateSet())
apply(*(node.getStateSet()));
}
for(unsigned int i=0;i<node.getNumDrawables();++i)
{
osg::Drawable* drawable = node.getDrawable(i);
if (drawable)
{
apply(*(node.getStateSet()));
apply(*drawable);
if (drawable->getStateSet())
{
apply(*(drawable->getStateSet()));
}
}
}
}
void StateToCompile::apply(osg::Drawable& drawable)
{
if (_drawablesHandled.count(&drawable)!=0) return;
_drawablesHandled.insert(&drawable);
if (_mode&GLObjectsVisitor::SWITCH_OFF_DISPLAY_LISTS)
{
drawable.setUseDisplayList(false);
}
if (_mode&GLObjectsVisitor::SWITCH_ON_DISPLAY_LISTS)
{
drawable.setUseDisplayList(true);
}
if (_mode&GLObjectsVisitor::SWITCH_ON_VERTEX_BUFFER_OBJECTS)
{
drawable.setUseVertexBufferObjects(true);
}
if (_mode&GLObjectsVisitor::SWITCH_OFF_VERTEX_BUFFER_OBJECTS)
{
drawable.setUseVertexBufferObjects(false);
}
if (_mode&GLObjectsVisitor::COMPILE_DISPLAY_LISTS &&
(drawable.getUseDisplayList() || drawable.getUseVertexBufferObjects()))
{
_drawables.insert(&drawable);
}
}
void StateToCompile::apply(osg::StateSet& stateset)
{
if (_statesetsHandled.count(&stateset)!=0) return;
_statesetsHandled.insert(&stateset);
if (_mode & GLObjectsVisitor::COMPILE_STATE_ATTRIBUTES)
{
osg::Program* program = dynamic_cast<osg::Program*>(stateset.getAttribute(osg::StateAttribute::PROGRAM));
if (program)
{
_programs.insert(program);
}
for(unsigned int i=0;i<node.getNumDrawables();++i)
osg::StateSet::TextureAttributeList& tal = stateset.getTextureAttributeList();
for(osg::StateSet::TextureAttributeList::iterator itr = tal.begin();
itr != tal.end();
++itr)
{
osg::Drawable* drawable = node.getDrawable(i);
if (drawable)
osg::StateSet::AttributeList& al = *itr;
osg::StateAttribute::TypeMemberPair tmp(osg::StateAttribute::TEXTURE,0);
osg::StateSet::AttributeList::iterator texItr = al.find(tmp);
if (texItr != al.end())
{
apply(*drawable);
if (drawable->getStateSet())
osg::Texture* texture = dynamic_cast<osg::Texture*>(texItr->second.first.get());
if (texture)
{
apply(*(drawable->getStateSet()));
if (_textures.count(texture)==0)
{
apply(*texture);
}
}
}
}
}
}
void apply(osg::Drawable& drawable)
{
if (_drawablesHandled.count(&drawable)!=0) return;
_drawablesHandled.insert(&drawable);
if (_mode&GLObjectsVisitor::SWITCH_OFF_DISPLAY_LISTS)
{
drawable.setUseDisplayList(false);
}
if (_mode&GLObjectsVisitor::SWITCH_ON_DISPLAY_LISTS)
{
drawable.setUseDisplayList(true);
}
if (_mode&GLObjectsVisitor::SWITCH_ON_VERTEX_BUFFER_OBJECTS)
{
drawable.setUseVertexBufferObjects(true);
}
if (_mode&GLObjectsVisitor::SWITCH_OFF_VERTEX_BUFFER_OBJECTS)
{
drawable.setUseVertexBufferObjects(false);
}
if (_mode&GLObjectsVisitor::COMPILE_DISPLAY_LISTS &&
(drawable.getUseDisplayList() || drawable.getUseVertexBufferObjects()))
{
_drawables.insert(&drawable);
}
}
void apply(osg::StateSet& stateset)
{
if (_statesetsHandled.count(&stateset)!=0) return;
_statesetsHandled.insert(&stateset);
if (_mode & GLObjectsVisitor::COMPILE_STATE_ATTRIBUTES)
{
osg::Program* program = dynamic_cast<osg::Program*>(stateset.getAttribute(osg::StateAttribute::PROGRAM));
if (program)
{
_programs.insert(program);
}
osg::StateSet::TextureAttributeList& tal = stateset.getTextureAttributeList();
for(osg::StateSet::TextureAttributeList::iterator itr = tal.begin();
itr != tal.end();
++itr)
{
osg::StateSet::AttributeList& al = *itr;
osg::StateAttribute::TypeMemberPair tmp(osg::StateAttribute::TEXTURE,0);
osg::StateSet::AttributeList::iterator texItr = al.find(tmp);
if (texItr != al.end())
{
osg::Texture* texture = dynamic_cast<osg::Texture*>(texItr->second.first.get());
if (texture) _textures.insert(texture);
}
}
}
}
};
void StateToCompile::apply(osg::Texture& texture)
{
_textures.insert(&texture);
}
/////////////////////////////////////////////////////////////////
//
@@ -391,14 +383,11 @@ bool IncrementalCompileOperation::CompileList::compile(CompileInfo& compileInfo)
//
// CompileSet
//
void IncrementalCompileOperation::CompileSet::buildCompileMap(ContextSet& contexts, GLObjectsVisitor::Mode mode)
void IncrementalCompileOperation::CompileSet::buildCompileMap(ContextSet& contexts, StateToCompile& stc)
{
if (contexts.empty() || !_subgraphToCompile) return;
if (contexts.empty() || stc.empty()) return;
CollectStateToCompile cstc(mode);
_subgraphToCompile->accept(cstc);
if (cstc._textures.empty() && cstc._programs.empty() && cstc._drawables.empty()) return;
if (stc.empty()) return;
for(ContextSet::iterator itr = contexts.begin();
itr != contexts.end();
@@ -406,24 +395,24 @@ void IncrementalCompileOperation::CompileSet::buildCompileMap(ContextSet& contex
{
// increment the number of compile lists that will need to compile
++_numberCompileListsToCompile;
CompileList& cl = _compileMap[*itr];
for(CollectStateToCompile::DrawableSet::iterator ditr = cstc._drawables.begin();
ditr != cstc._drawables.end();
for(StateToCompile::DrawableSet::iterator ditr = stc._drawables.begin();
ditr != stc._drawables.end();
++ditr)
{
cl.add(*ditr);
}
for(CollectStateToCompile::TextureSet::iterator titr = cstc._textures.begin();
titr != cstc._textures.end();
for(StateToCompile::TextureSet::iterator titr = stc._textures.begin();
titr != stc._textures.end();
++titr)
{
cl.add(*titr);
}
for(CollectStateToCompile::ProgramSet::iterator pitr = cstc._programs.begin();
pitr != cstc._programs.end();
for(StateToCompile::ProgramSet::iterator pitr = stc._programs.begin();
pitr != stc._programs.end();
++pitr)
{
cl.add(*pitr);
@@ -431,6 +420,16 @@ void IncrementalCompileOperation::CompileSet::buildCompileMap(ContextSet& contex
}
}
void IncrementalCompileOperation::CompileSet::buildCompileMap(ContextSet& contexts, GLObjectsVisitor::Mode mode)
{
if (contexts.empty() || !_subgraphToCompile) return;
StateToCompile stc(mode);
_subgraphToCompile->accept(stc);
buildCompileMap(contexts, stc);
}
bool IncrementalCompileOperation::CompileSet::compile(CompileInfo& compileInfo)
{
CompileList& compileList = _compileMap[compileInfo.getState()->getGraphicsContext()];
@@ -545,6 +544,11 @@ void IncrementalCompileOperation::removeGraphicsContext(osg::GraphicsContext* gc
}
}
bool IncrementalCompileOperation::requiresCompile(StateToCompile& stateToCompile)
{
return isActive() && !stateToCompile.empty();
}
void IncrementalCompileOperation::add(osg::Node* subgraphToCompile)
{
OSG_INFO<<"IncrementalCompileOperation::add("<<subgraphToCompile<<")"<<std::endl;