Preliminary work on general purpose incremental compile support in osgViewer.

This commit is contained in:
Robert Osfield
2009-03-08 12:00:36 +00:00
parent 43a081ee98
commit 7473b06275
8 changed files with 405 additions and 74 deletions

View File

@@ -57,16 +57,35 @@
typedef std::vector< osg::ref_ptr<osg::GraphicsThread> > GraphicsThreads;
struct ReleaseBlockOnCompileCompleted : public osgUtil::IncrementalCompileOperation::CompileCompletedCallback
{
ReleaseBlockOnCompileCompleted(osg::RefBlockCount* block):
_block(block) {}
virtual bool compileCompleted(osgUtil::IncrementalCompileOperation::CompileSet* compileSet)
{
if (_block.valid()) _block->completed();
// tell IncrementalCompileOperation that it's now safe to remove the compileSet
osg::notify(osg::NOTICE)<<"compileCompleted("<<compileSet<<")"<<std::endl;
return true;
}
osg::ref_ptr<osg::RefBlockCount> _block;
};
class LoadAndCompileOperation : public osg::Operation
{
public:
LoadAndCompileOperation(const std::string& filename, GraphicsThreads& graphicsThreads, osg::RefBlockCount* block):
LoadAndCompileOperation(const std::string& filename, osgUtil::IncrementalCompileOperation* ico , osg::RefBlockCount* block):
Operation("Load and compile Operation", false),
_filename(filename),
_graphicsThreads(graphicsThreads),
_incrementalCompileOperation(ico),
_block(block) {}
virtual void operator () (osg::Object* object)
@@ -74,28 +93,28 @@ public:
// osg::notify(osg::NOTICE)<<"LoadAndCompileOperation "<<_filename<<std::endl;
_loadedModel = osgDB::readNodeFile(_filename);
if (_loadedModel.valid() && !_graphicsThreads.empty())
{
osg::ref_ptr<osgUtil::GLObjectsOperation> compileOperation = new osgUtil::GLObjectsOperation(_loadedModel.get());
for(GraphicsThreads::iterator gitr = _graphicsThreads.begin();
gitr != _graphicsThreads.end();
++gitr)
{
(*gitr)->add( compileOperation.get() );
// requiresBarrier = true;
}
}
if (_block.valid()) _block->completed();
if (_loadedModel.valid() && _incrementalCompileOperation.valid())
{
osg::ref_ptr<osgUtil::IncrementalCompileOperation::CompileSet> compileSet =
new osgUtil::IncrementalCompileOperation::CompileSet(_loadedModel);
compileSet->_compileCompletedCallback = new ReleaseBlockOnCompileCompleted(_block.get());
_incrementalCompileOperation->add(compileSet.get());
}
else
{
if (_block.valid()) _block->completed();
}
// osg::notify(osg::NOTICE)<<"done LoadAndCompileOperation "<<_filename<<std::endl;
}
std::string _filename;
GraphicsThreads _graphicsThreads;
osg::ref_ptr<osg::Node> _loadedModel;
osg::ref_ptr<osg::RefBlockCount> _block;
std::string _filename;
osg::ref_ptr<osg::Node> _loadedModel;
osg::ref_ptr<osgUtil::IncrementalCompileOperation> _incrementalCompileOperation;
osg::ref_ptr<osg::RefBlockCount> _block;
};
@@ -108,9 +127,10 @@ public:
typedef std::vector< osg::ref_ptr<osg::Node> > Nodes;
MasterOperation(const std::string& filename):
MasterOperation(const std::string& filename, osgUtil::IncrementalCompileOperation* ico):
Operation("Master reading operation",true),
_filename(filename)
_filename(filename),
_incrementalCompileOperation(ico)
{
}
@@ -256,9 +276,6 @@ public:
if (gt) threads.push_back(gt);
}
bool requiresBarrier = false;
if (_operationQueue.valid())
{
// osg::notify(osg::NOTICE)<<"Using OperationQueue"<<std::endl;
@@ -276,7 +293,7 @@ public:
{
// osg::notify(osg::NOTICE)<<"Adding LoadAndCompileOperation "<<*nitr<<std::endl;
osg::ref_ptr<LoadAndCompileOperation> loadAndCompile = new LoadAndCompileOperation( *nitr, threads, _endOfLoadBlock.get() );
osg::ref_ptr<LoadAndCompileOperation> loadAndCompile = new LoadAndCompileOperation( *nitr, _incrementalCompileOperation.get(), _endOfLoadBlock.get() );
loadAndCompileList.push_back(loadAndCompile);
_operationQueue->add( loadAndCompile.get() );
}
@@ -300,7 +317,6 @@ public:
if ((*litr)->_loadedModel.valid())
{
nodesToAdd[(*litr)->_filename] = (*litr)->_loadedModel;
requiresBarrier = true;
}
}
@@ -308,6 +324,11 @@ public:
else
{
_endOfLoadBlock = new osg::RefBlockCount(newFiles.size());
_endOfLoadBlock->reset();
for(Files::iterator nitr = newFiles.begin();
nitr != newFiles.end();
++nitr)
@@ -318,38 +339,30 @@ public:
{
nodesToAdd[*nitr] = loadedModel;
osg::ref_ptr<osgUtil::GLObjectsOperation> compileOperation = new osgUtil::GLObjectsOperation(loadedModel.get());
for(GraphicsThreads::iterator gitr = threads.begin();
gitr != threads.end();
++gitr)
if (_incrementalCompileOperation.valid())
{
(*gitr)->add( compileOperation.get() );
requiresBarrier = true;
osg::ref_ptr<osgUtil::IncrementalCompileOperation::CompileSet> compileSet =
new osgUtil::IncrementalCompileOperation::CompileSet(loadedModel.get());
compileSet->_compileCompletedCallback = new ReleaseBlockOnCompileCompleted(_endOfLoadBlock.get());
_incrementalCompileOperation->add(compileSet.get());
}
else
{
_endOfLoadBlock->completed();
}
}
else
{
_endOfLoadBlock->completed();
}
}
_endOfLoadBlock->block();
}
if (requiresBarrier)
{
_endOfCompilebarrier = new osg::BarrierOperation(threads.size()+1);
_endOfCompilebarrier->setKeep(false);
for(GraphicsThreads::iterator gitr = threads.begin();
gitr != threads.end();
++gitr)
{
(*gitr)->add(_endOfCompilebarrier.get());
}
// osg::notify(osg::NOTICE)<<"Waiting for Compile to complete"<<std::endl;
// wait for the graphics threads to complete.
_endOfCompilebarrier->block();
// osg::notify(osg::NOTICE)<<"done ... Waiting for Compile to complete"<<std::endl;
}
}
bool requiresBlock = false;
@@ -454,6 +467,7 @@ public:
FilenameNodeMap _nodesToAdd;
OpenThreads::Block _updatesMergedBlock;
osg::ref_ptr<osgUtil::IncrementalCompileOperation> _incrementalCompileOperation;
osg::ref_ptr<osg::BarrierOperation> _endOfCompilebarrier;
osg::ref_ptr<osg::RefBlockCount> _endOfLoadBlock;
@@ -618,6 +632,9 @@ int main(int argc, char** argv)
// add the record camera path handler
viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);
// attach an IncrementaCompileOperation to allow the master loading
// to be handled with an incremental compile to avoid frame drops when large objects are added.
viewer.setIncrementalCompileOperation(new osgUtil::IncrementalCompileOperation());
double x = 0.0;
double y = 0.0;
@@ -631,7 +648,7 @@ int main(int argc, char** argv)
std::string masterFilename;
while(arguments.read("-m",masterFilename))
{
masterOperation = new MasterOperation(masterFilename);
masterOperation = new MasterOperation(masterFilename, viewer.getIncrementalCompileOperation());
}

View File

@@ -123,13 +123,117 @@ class OSGUTIL_EXPORT GLObjectsOperation : public osg::GraphicsOperation
GLObjectsOperation(osg::Node* subgraph, GLObjectsVisitor::Mode mode = GLObjectsVisitor::COMPILE_DISPLAY_LISTS|GLObjectsVisitor::COMPILE_STATE_ATTRIBUTES|GLObjectsVisitor::CHECK_BLACK_LISTED_MODES);
virtual void operator () (osg::GraphicsContext* context);
protected:
osg::ref_ptr<osg::Node> _subgraph;
GLObjectsVisitor::Mode _mode;
};
class OSGUTIL_EXPORT IncrementalCompileOperation : public osg::GraphicsOperation
{
public:
IncrementalCompileOperation();
typedef std::vector<osg::GraphicsContext*> Contexts;
void assignContexts(Contexts& contexts);
void removeContexts(Contexts& contexts);
void addGraphicsContext(osg::GraphicsContext* gc);
void removeGraphicsContext(osg::GraphicsContext* gc);
/** Merge subgraphs that have been compiled.*/
void mergeCompiledSubgraphs();
virtual void operator () (osg::GraphicsContext* context);
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::Program> > Programs;
bool empty() const { return _textures.empty() && _drawables.empty() && _programs.empty(); }
Textures _textures;
Drawables _drawables;
Programs _programs;
};
class CompileSet;
typedef std::set<osg::GraphicsContext*> ContextSet;
typedef std::map<osg::GraphicsContext*, osg::ref_ptr<CompileData> > CompileMap;
struct CompileCompletedCallback : public osg::Referenced
{
virtual bool compileCompleted(CompileSet* compileSet) = 0;
};
class CompileSet : public osg::Referenced
{
public:
CompileSet() {}
CompileSet(osg::Node*subgraphToCompile):
_subgraphToCompile(subgraphToCompile) {}
CompileSet(osg::Group* attachmentPoint, osg::Node*subgraphToCompile):
_attachmentPoint(attachmentPoint),
_subgraphToCompile(subgraphToCompile) {}
void buildCompileMap(ContextSet& context);
osg::ref_ptr<osg::Group> _attachmentPoint;
osg::ref_ptr<osg::Node> _subgraphToCompile;
osg::ref_ptr<CompileCompletedCallback> _compileCompletedCallback;
CompileMap _compileMap;
// protected:
virtual ~CompileSet() {}
};
typedef std::list< osg::ref_ptr<CompileSet> > CompileSets;
/** Add a subgraph to be compiled.*/
void add(osg::Node* subgraphToCompile);
/** Add a subgraph to be compiled and add automatically to attachPoint on call to mergeCompiledSubgraphs.*/
void add(osg::Group* attachmentPoint, osg::Node* subgraphToCompile);
/** Add a CompileSet to be compiled.*/
void add(CompileSet* compileSet, bool callBuildCompileMap=true);
OpenThreads::Mutex& getToCompiledMutex() { return _toCompileMutex; }
CompileSets& getToCompile() { return _compiled; }
OpenThreads::Mutex& getCompiledMutex() { return _compiledMutex; }
CompileSets& getCompiled() { return _compiled; }
protected:
virtual ~IncrementalCompileOperation();
OpenThreads::Mutex _toCompileMutex;
CompileSets _toCompile;
OpenThreads::Mutex _compiledMutex;
CompileSets _compiled;
ContextSet _contexts;
};
}
#endif

View File

@@ -17,6 +17,7 @@
#include <osg/Stats>
#include <osgUtil/UpdateVisitor>
#include <osgUtil/GLObjectsVisitor>
#include <osgGA/MatrixManipulator>
#include <osgGA/EventVisitor>
@@ -184,6 +185,15 @@ class OSGVIEWER_EXPORT ViewerBase : public virtual osg::Object
/** Get the graphics operation to call on realization of the viewers graphics windows.*/
osg::Operation* getRealizeOperation() { return _realizeOperation.get(); }
/** Set the incremental compile operation.
* Used to manage the OpenGL object compilation and merging of subgraphs in a way that avoids overloading
* the rendering of frame with too many new objects in one frame. */
void setIncrementalCompileOperation(osgUtil::IncrementalCompileOperation* ico);
/** Get the incremental compile operation. */
osgUtil::IncrementalCompileOperation* getIncrementalCompileOperation() { return _incrementalCompileOperation.get(); }
/** Check to see if windows are still open, if not set viewer done to true. */
@@ -260,29 +270,30 @@ class OSGVIEWER_EXPORT ViewerBase : public virtual osg::Object
virtual void viewerInit() = 0;
bool _firstFrame;
bool _done;
int _keyEventSetsDone;
bool _quitEventSetsDone;
bool _releaseContextAtEndOfFrameHint;
bool _firstFrame;
bool _done;
int _keyEventSetsDone;
bool _quitEventSetsDone;
bool _releaseContextAtEndOfFrameHint;
ThreadingModel _threadingModel;
bool _threadsRunning;
ThreadingModel _threadingModel;
bool _threadsRunning;
BarrierPosition _endBarrierPosition;
BarrierPosition _endBarrierPosition;
osg::ref_ptr<osg::BarrierOperation> _startRenderingBarrier;
osg::ref_ptr<osg::BarrierOperation> _endRenderingDispatchBarrier;
osg::ref_ptr<osg::EndOfDynamicDrawBlock> _endDynamicDrawBlock;
osg::ref_ptr<osg::BarrierOperation> _startRenderingBarrier;
osg::ref_ptr<osg::BarrierOperation> _endRenderingDispatchBarrier;
osg::ref_ptr<osg::EndOfDynamicDrawBlock> _endDynamicDrawBlock;
osg::ref_ptr<osgGA::EventVisitor> _eventVisitor;
osg::ref_ptr<osgGA::EventVisitor> _eventVisitor;
osg::ref_ptr<osg::OperationQueue> _updateOperations;
osg::ref_ptr<osgUtil::UpdateVisitor> _updateVisitor;
osg::ref_ptr<osg::OperationQueue> _updateOperations;
osg::ref_ptr<osgUtil::UpdateVisitor> _updateVisitor;
osg::ref_ptr<osg::Operation> _realizeOperation;
osg::ref_ptr<osg::Operation> _realizeOperation;
osg::ref_ptr<osgUtil::IncrementalCompileOperation> _incrementalCompileOperation;
osg::observer_ptr<osg::GraphicsContext> _currentContext;
osg::observer_ptr<osg::GraphicsContext> _currentContext;
};
}

View File

@@ -317,7 +317,7 @@ GraphicsContext::GraphicsContexts GraphicsContext::getRegisteredGraphicsContexts
GraphicsContext* GraphicsContext::getOrCreateCompileContext(unsigned int contextID)
{
osg::notify(osg::INFO)<<"GraphicsContext::createCompileContext."<<std::endl;
osg::notify(osg::NOTICE)<<"GraphicsContext::createCompileContext."<<std::endl;
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
@@ -349,7 +349,7 @@ GraphicsContext* GraphicsContext::getOrCreateCompileContext(unsigned int context
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
s_contextIDMap[contextID]._compileContext = gc;
osg::notify(osg::INFO)<<" succeeded GraphicsContext::createCompileContext."<<std::endl;
osg::notify(osg::NOTICE)<<" succeeded GraphicsContext::createCompileContext."<<std::endl;
return gc.release();
}
else

View File

@@ -13,10 +13,16 @@
#include <osgUtil/GLObjectsVisitor>
#include <osg/Drawable>
#include <osg/Notify>
#include <OpenThreads/ScopedLock>
using namespace osg;
using namespace osgUtil;
/////////////////////////////////////////////////////////////////
//
// GLObjectsVisitor
//
GLObjectsVisitor::GLObjectsVisitor(Mode mode)
{
setTraversalMode(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN);
@@ -145,6 +151,11 @@ void GLObjectsVisitor::apply(osg::StateSet& stateset)
}
}
/////////////////////////////////////////////////////////////////
//
// GLObjectsVisitor
//
GLObjectsOperation::GLObjectsOperation(GLObjectsVisitor::Mode mode):
osg::GraphicsOperation("GLObjectOperation",false),
_mode(mode)
@@ -182,3 +193,156 @@ void GLObjectsOperation::operator () (osg::GraphicsContext* context)
}
// osg::notify(osg::NOTICE)<<"GLObjectsOperation::after >>>>>>>>>>> "<<std::endl;
}
/////////////////////////////////////////////////////////////////
//
// IncrementalCompileOperation
//
IncrementalCompileOperation::IncrementalCompileOperation():
osg::GraphicsOperation("IncrementalCompileOperation",true)
{
}
IncrementalCompileOperation::~IncrementalCompileOperation()
{
}
void IncrementalCompileOperation::assignContexts(Contexts& contexts)
{
for(Contexts::iterator itr = contexts.begin();
itr != contexts.end();
++itr)
{
osg::GraphicsContext* gc = *itr;
addGraphicsContext(gc);
}
}
void IncrementalCompileOperation::removeContexts(Contexts& contexts)
{
for(Contexts::iterator itr = contexts.begin();
itr != contexts.end();
++itr)
{
osg::GraphicsContext* gc = *itr;
removeGraphicsContext(gc);
}
}
void IncrementalCompileOperation::addGraphicsContext(osg::GraphicsContext* gc)
{
if (_contexts.count(gc)==0)
{
gc->add(this);
_contexts.insert(gc);
}
}
void IncrementalCompileOperation::removeGraphicsContext(osg::GraphicsContext* gc)
{
if (_contexts.count(gc)!=0)
{
gc->remove(this);
_contexts.erase(gc);
}
}
void IncrementalCompileOperation::add(osg::Node* subgraphToCompile)
{
osg::notify(osg::NOTICE)<<"IncrementalCompileOperation::add("<<subgraphToCompile<<")"<<std::endl;
add(new CompileSet(subgraphToCompile));
}
void IncrementalCompileOperation::add(osg::Group* attachmentPoint, osg::Node* subgraphToCompile)
{
osg::notify(osg::NOTICE)<<"IncrementalCompileOperation::add("<<attachmentPoint<<", "<<subgraphToCompile<<")"<<std::endl;
add(new CompileSet(attachmentPoint, subgraphToCompile));
}
void IncrementalCompileOperation::add(CompileSet* compileSet, bool callBuildCompileMap)
{
if (!compileSet) return;
if (callBuildCompileMap) compileSet->buildCompileMap(_contexts);
osg::notify(osg::NOTICE)<<"IncrementalCompileOperation::add(CompileSet = "<<compileSet<<", "<<", "<<callBuildCompileMap<<")"<<std::endl;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_toCompileMutex);
_toCompile.push_back(compileSet);
}
void IncrementalCompileOperation::mergeCompiledSubgraphs()
{
osg::notify(osg::NOTICE)<<"IncrementalCompileOperation::mergeCompiledSubgraphs()"<<std::endl;
OpenThreads::ScopedLock<OpenThreads::Mutex> compilded_lock(_compiledMutex);
for(CompileSets::iterator itr = _compiled.begin();
itr != _compiled.end();
++itr)
{
CompileSet* cs = itr->get();
if (cs->_attachmentPoint.valid())
{
cs->_attachmentPoint->addChild(cs->_subgraphToCompile.get());
}
}
_compiled.clear();
}
void IncrementalCompileOperation::CompileSet::buildCompileMap(ContextSet& context)
{
}
void IncrementalCompileOperation::operator () (osg::GraphicsContext* context)
{
osg::notify(osg::NOTICE)<<"IncrementalCompileOperation::operator () ("<<context<<")"<<std::endl;
OpenThreads::ScopedLock<OpenThreads::Mutex> toCompile_lock(_toCompileMutex);
for(CompileSets::iterator itr = _toCompile.begin();
itr != _toCompile.end();
)
{
CompileSet* cs = itr->get();
CompileMap& cm = cs->_compileMap;
CompileData* cd = cm[context].get();
if (cd)
{
// compile textures
cd->_textures.clear();
// compile drawables
cd->_drawables.clear();
// compile programs
cd->_programs.clear();
}
if (!cd || cd->empty())
{
if (cs->_compileCompletedCallback.valid())
{
if (cs->_compileCompletedCallback->compileCompleted(cs))
{
// callback will handle merging of subgraph so no need to place CompileSet in merge.
}
else
{
OpenThreads::ScopedLock<OpenThreads::Mutex> compilded_lock(_compiledMutex);
_compiled.push_back(cs);
}
}
// remove from toCompileSet;
itr = _toCompile.erase(itr);
}
else
{
++itr;
}
}
}

View File

@@ -497,6 +497,10 @@ void CompositeViewer::realize()
}
}
// attach contexts to _incrementalCompileOperation if attached.
if (_incrementalCompileOperation) _incrementalCompileOperation->assignContexts(contexts);
bool grabFocus = true;
if (grabFocus)
{
@@ -994,6 +998,12 @@ void CompositeViewer::updateTraversal()
}
if (_incrementalCompileOperation.valid())
{
// merge subgraphs that have been compiled by the incremental compiler operation.
_incrementalCompileOperation->mergeCompiledSubgraphs();
}
if (_updateOperations.valid())
{
_updateOperations->runOperations(this);

View File

@@ -448,7 +448,10 @@ void Viewer::realize()
gc->releaseContext();
}
}
// attach contexts to _incrementalCompileOperation if attached.
if (_incrementalCompileOperation) _incrementalCompileOperation->assignContexts(contexts);
bool grabFocus = true;
if (grabFocus)
{
@@ -898,6 +901,13 @@ void Viewer::updateTraversal()
{
_updateOperations->runOperations(this);
}
if (_incrementalCompileOperation.valid())
{
// merge subgraphs that have been compiled by the incremental compiler operation.
_incrementalCompileOperation->mergeCompiledSubgraphs();
}
{
// call any camera update callbacks, but only traverse that callback, don't traverse its subgraph

View File

@@ -375,7 +375,7 @@ void ViewerBase::startThreading()
if (!gc->isRealized())
{
osg::notify(osg::INFO)<<"ViewerBase::startThreading() : Realizng window "<<gc<<std::endl;
osg::notify(osg::INFO)<<"ViewerBase::startThreading() : Realizing window "<<gc<<std::endl;
gc->realize();
}
@@ -551,6 +551,21 @@ void ViewerBase::removeUpdateOperation(osg::Operation* operation)
}
}
void ViewerBase::setIncrementalCompileOperation(osgUtil::IncrementalCompileOperation* ico)
{
if (_incrementalCompileOperation == ico) return;
Contexts contexts;
getContexts(contexts, false);
if (_incrementalCompileOperation.valid()) _incrementalCompileOperation->removeContexts(contexts);
// assign new operation
_incrementalCompileOperation = ico;
if (_incrementalCompileOperation) _incrementalCompileOperation->assignContexts(contexts);
}
int ViewerBase::run()
{
if (!isRealized())