Further work on IncrementalCompileOperation

This commit is contained in:
Robert Osfield 2009-03-09 14:56:20 +00:00
parent 73c2615d17
commit 173357252b
2 changed files with 245 additions and 35 deletions

View File

@ -153,20 +153,20 @@ class OSGUTIL_EXPORT IncrementalCompileOperation : public osg::GraphicsOperation
struct CompileData : public osg::Referenced struct CompileData : public osg::Referenced
{ {
typedef std::list< osg::ref_ptr<osg::Texture> > Textures;
typedef std::list< osg::ref_ptr<osg::Drawable> > Drawables; typedef std::list< osg::ref_ptr<osg::Drawable> > Drawables;
typedef std::list< osg::ref_ptr<osg::Texture> > Textures;
typedef std::list< osg::ref_ptr<osg::Program> > Programs; typedef std::list< osg::ref_ptr<osg::Program> > Programs;
bool empty() const { return _textures.empty() && _drawables.empty() && _programs.empty(); } bool empty() const { return _drawables.empty() && _textures.empty() && _programs.empty(); }
Textures _textures;
Drawables _drawables; Drawables _drawables;
Textures _textures;
Programs _programs; Programs _programs;
}; };
class CompileSet; class CompileSet;
typedef std::set<osg::GraphicsContext*> ContextSet; typedef std::set<osg::GraphicsContext*> ContextSet;
typedef std::map<osg::GraphicsContext*, osg::ref_ptr<CompileData> > CompileMap; typedef std::map<osg::GraphicsContext*, CompileData > CompileMap;
struct CompileCompletedCallback : public osg::Referenced struct CompileCompletedCallback : public osg::Referenced
{ {
@ -187,7 +187,18 @@ class OSGUTIL_EXPORT IncrementalCompileOperation : public osg::GraphicsOperation
_attachmentPoint(attachmentPoint), _attachmentPoint(attachmentPoint),
_subgraphToCompile(subgraphToCompile) {} _subgraphToCompile(subgraphToCompile) {}
void buildCompileMap(ContextSet& context); void buildCompileMap(ContextSet& context, GLObjectsVisitor::Mode mode=GLObjectsVisitor::COMPILE_DISPLAY_LISTS|GLObjectsVisitor::COMPILE_STATE_ATTRIBUTES);
bool compileCompleted() const
{
for(CompileMap::const_iterator itr = _compileMap.begin();
itr != _compileMap.end();
++itr)
{
if (!(itr->second.empty())) return false;
}
return true;
}
osg::ref_ptr<osg::Group> _attachmentPoint; osg::ref_ptr<osg::Group> _attachmentPoint;
osg::ref_ptr<osg::Node> _subgraphToCompile; osg::ref_ptr<osg::Node> _subgraphToCompile;
@ -222,6 +233,9 @@ class OSGUTIL_EXPORT IncrementalCompileOperation : public osg::GraphicsOperation
virtual ~IncrementalCompileOperation(); virtual ~IncrementalCompileOperation();
// forward declare to keep within class namespace
class CollectStateToCompile;
OpenThreads::Mutex _toCompileMutex; OpenThreads::Mutex _toCompileMutex;
CompileSets _toCompile; CompileSets _toCompile;

View File

@ -11,13 +11,17 @@
* OpenSceneGraph Public License for more details. * OpenSceneGraph Public License for more details.
*/ */
#include <osgUtil/GLObjectsVisitor> #include <osgUtil/GLObjectsVisitor>
#include <osg/Drawable> #include <osg/Drawable>
#include <osg/Notify> #include <osg/Notify>
#include <osg/Timer>
#include <OpenThreads/ScopedLock> #include <OpenThreads/ScopedLock>
using namespace osg; #include <algorithm>
using namespace osgUtil;
namespace osgUtil
{
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// //
@ -51,7 +55,7 @@ void GLObjectsVisitor::apply(osg::Geode& node)
for(unsigned int i=0;i<node.getNumDrawables();++i) for(unsigned int i=0;i<node.getNumDrawables();++i)
{ {
Drawable* drawable = node.getDrawable(i); osg::Drawable* drawable = node.getDrawable(i);
if (drawable) if (drawable)
{ {
apply(*drawable); apply(*drawable);
@ -133,7 +137,7 @@ void GLObjectsVisitor::apply(osg::StateSet& stateset)
} }
else if(_renderInfo.getState()->getLastAppliedProgramObject()){ else if(_renderInfo.getState()->getLastAppliedProgramObject()){
GL2Extensions* extensions = GL2Extensions::Get(_renderInfo.getState()->getContextID(), true); osg::GL2Extensions* extensions = osg::GL2Extensions::Get(_renderInfo.getState()->getContextID(), true);
extensions->glUseProgram(0); extensions->glUseProgram(0);
_renderInfo.getState()->setLastAppliedProgramObject(0); _renderInfo.getState()->setLastAppliedProgramObject(0);
} }
@ -275,7 +279,7 @@ void IncrementalCompileOperation::add(CompileSet* compileSet, bool callBuildComp
void IncrementalCompileOperation::mergeCompiledSubgraphs() void IncrementalCompileOperation::mergeCompiledSubgraphs()
{ {
osg::notify(osg::NOTICE)<<"IncrementalCompileOperation::mergeCompiledSubgraphs()"<<std::endl; // osg::notify(osg::NOTICE)<<"IncrementalCompileOperation::mergeCompiledSubgraphs()"<<std::endl;
OpenThreads::ScopedLock<OpenThreads::Mutex> compilded_lock(_compiledMutex); OpenThreads::ScopedLock<OpenThreads::Mutex> compilded_lock(_compiledMutex);
@ -293,38 +297,234 @@ void IncrementalCompileOperation::mergeCompiledSubgraphs()
_compiled.clear(); _compiled.clear();
} }
void IncrementalCompileOperation::CompileSet::buildCompileMap(ContextSet& context) class IncrementalCompileOperation::CollectStateToCompile : public osg::NodeVisitor
{ {
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)
{
if (node.getStateSet())
{
apply(*(node.getStateSet()));
}
traverse(node);
}
void apply(osg::Geode& node)
{
if (node.getStateSet())
{
apply(*(node.getStateSet()));
}
for(unsigned int i=0;i<node.getNumDrawables();++i)
{
osg::Drawable* drawable = node.getDrawable(i);
if (drawable)
{
apply(*drawable);
if (drawable->getStateSet())
{
apply(*(drawable->getStateSet()));
}
}
}
}
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)
{
_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 IncrementalCompileOperation::CompileSet::buildCompileMap(ContextSet& contexts, GLObjectsVisitor::Mode mode)
{
if (contexts.empty() || !_subgraphToCompile) return;
CollectStateToCompile cstc(mode);
_subgraphToCompile->accept(cstc);
if (cstc._textures.empty() && cstc._programs.empty() && cstc._drawables.empty()) return;
for(ContextSet::iterator itr = contexts.begin();
itr != contexts.end();
++itr)
{
CompileData& cd = _compileMap[*itr];
std::copy(cstc._textures.begin(), cstc._textures.end(), std::back_inserter<CompileData::Textures>(cd._textures));
std::copy(cstc._programs.begin(), cstc._programs.end(), std::back_inserter<CompileData::Programs>(cd._programs));
std::copy(cstc._drawables.begin(), cstc._drawables.end(), std::back_inserter<CompileData::Drawables>(cd._drawables));
}
} }
void IncrementalCompileOperation::operator () (osg::GraphicsContext* context) void IncrementalCompileOperation::operator () (osg::GraphicsContext* context)
{ {
osg::notify(osg::NOTICE)<<"IncrementalCompileOperation::operator () ("<<context<<")"<<std::endl; // osg::notify(osg::NOTICE)<<"IncrementalCompileOperation::operator () ("<<context<<")"<<std::endl;
osg::RenderInfo renderInfo;
renderInfo.setState(context->getState());
CompileSets toCompileCopy;
{
OpenThreads::ScopedLock<OpenThreads::Mutex> toCompile_lock(_toCompileMutex); OpenThreads::ScopedLock<OpenThreads::Mutex> toCompile_lock(_toCompileMutex);
for(CompileSets::iterator itr = _toCompile.begin(); std::copy(_toCompile.begin(),_toCompile.end(),std::back_inserter<CompileSets>(toCompileCopy));
itr != _toCompile.end(); }
)
for(CompileSets::iterator itr = toCompileCopy.begin();
itr != toCompileCopy.end();
++itr)
{ {
CompileSet* cs = itr->get(); CompileSet* cs = itr->get();
CompileMap& cm = cs->_compileMap; CompileMap& cm = cs->_compileMap;
CompileData* cd = cm[context].get(); CompileData& cd = cm[context];
if (cd) if (!cd.empty())
{ {
// compile textures osg::notify(osg::NOTICE)<<"cd._drawables.size()="<<cd._drawables.size()<<std::endl;
cd->_textures.clear(); osg::notify(osg::NOTICE)<<"cd._textures.size()="<<cd._textures.size()<<std::endl;
osg::notify(osg::NOTICE)<<"cd._programs.size()="<<cd._programs.size()<<std::endl;
// compile drawables osg::Timer_t startTick = osg::Timer::instance()->tick();
cd->_drawables.clear(); double maxTimeAvailable = 0.001;
// compile programs while(!cd._drawables.empty() &&
cd->_programs.clear(); osg::Timer::instance()->delta_s(startTick, osg::Timer::instance()->tick()) < maxTimeAvailable)
{
cd._drawables.back()->compileGLObjects(renderInfo);
cd._drawables.pop_back();
} }
if (!cd || cd->empty()) while(!cd._textures.empty() &&
osg::Timer::instance()->delta_s(startTick, osg::Timer::instance()->tick()) < maxTimeAvailable)
{ {
if (cs->_compileCompletedCallback.valid()) cd._textures.back()->apply(*renderInfo.getState());
cd._textures.pop_back();
}
if (!cd._programs.empty())
{
// compile programs
while(!cd._programs.empty() &&
osg::Timer::instance()->delta_s(startTick, osg::Timer::instance()->tick()) < maxTimeAvailable)
{
cd._programs.back()->apply(*renderInfo.getState());
cd._programs.pop_back();
}
// switch off Program,
osg::GL2Extensions* extensions = osg::GL2Extensions::Get(renderInfo.getState()->getContextID(), true);
extensions->glUseProgram(0);
renderInfo.getState()->setLastAppliedProgramObject(0);
}
}
if (cd.empty())
{
bool csCompleted = false;
{
OpenThreads::ScopedLock<OpenThreads::Mutex> toCompile_lock(_toCompileMutex);
if (cs->compileCompleted())
{
CompileSets::iterator cs_itr = std::find(_toCompile.begin(), _toCompile.end(), *itr);
if (cs_itr != _toCompile.end())
{
osg::notify(osg::NOTICE)<<"Erasing from list"<<std::endl;
// remove from the _toCompile list, note cs won't be deleted here as the tempoary
// toCompile_Copy list will retain a reference.
_toCompile.erase(cs_itr);
// signal that we need to do clean up operations/pass cs on to _compile list.
csCompleted = true;
}
}
}
if (csCompleted && cs->_compileCompletedCallback.valid())
{ {
if (cs->_compileCompletedCallback->compileCompleted(cs)) if (cs->_compileCompletedCallback->compileCompleted(cs))
{ {
@ -337,12 +537,8 @@ void IncrementalCompileOperation::operator () (osg::GraphicsContext* context)
} }
} }
// remove from toCompileSet;
itr = _toCompile.erase(itr);
}
else
{
++itr;
} }
} }
} }
} // end of namespace osgUtil