From ea5ca995e3f1a73ffb90c2f7f60e3f1986539d33 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 17 Jul 2007 16:18:13 +0000 Subject: [PATCH] Merged the new master operation/operation thread code with older standard terrain set up code. --- examples/osgterrain/osgterrain.cpp | 315 ++++++++++++++--------------- 1 file changed, 148 insertions(+), 167 deletions(-) diff --git a/examples/osgterrain/osgterrain.cpp b/examples/osgterrain/osgterrain.cpp index 38e8f9b53..84ec45f46 100644 --- a/examples/osgterrain/osgterrain.cpp +++ b/examples/osgterrain/osgterrain.cpp @@ -126,9 +126,12 @@ public: Files files; readMasterFile(files); + // osg::notify(osg::NOTICE)<<"void operator () files.size()="< lock(_mutex); @@ -150,51 +153,90 @@ public: } } - if (newFiles.empty()) - // first load the files. + // first load the new files. FilenameNodeMap nodesToAdd; - for(Files::iterator nitr = newFiles.begin(); - nitr != newFiles.end(); - ++nitr) + if (!newFiles.empty()) { - osg::ref_ptr loadedModel = osgDB::readNodeFile(*nitr); - - if (loadedModel.get()) + + typedef std::vector< osg::ref_ptr > GraphicsThreads; + GraphicsThreads threads; + + for(unsigned int i=0; i<= osg::GraphicsContext::getMaxContextID(); ++i) { - osg::notify(osg::NOTICE)<<"Loadinged file "<<*nitr<getGraphicsThread() : 0; + if (gt) threads.push_back(gt); + } - nodesToAdd[*nitr] = loadedModel; - osg::ref_ptr compileOperation = new osgUtil::GLObjectsOperation(loadedModel.get()); + bool requiresBarrier = false; + + for(Files::iterator nitr = newFiles.begin(); + nitr != newFiles.end(); + ++nitr) + { + osg::ref_ptr loadedModel = osgDB::readNodeFile(*nitr); -#if 1 - for(unsigned int i=0; i<= osg::GraphicsContext::getMaxContextID(); ++i) + if (loadedModel.get()) { - osg::GraphicsContext* gc = osg::GraphicsContext::getCompileContext(i); - osg::GraphicsThread* gt = gc ? gc->getGraphicsThread() : 0; - if (gt) + nodesToAdd[*nitr] = loadedModel; + + osg::ref_ptr compileOperation = new osgUtil::GLObjectsOperation(loadedModel.get()); + + for(GraphicsThreads::iterator gitr = threads.begin(); + gitr != threads.end(); + ++gitr) { - osg::notify(osg::NOTICE)<<"Adding compile op. to compile context "<add( compileOperation.get() ); + (*gitr)->add( compileOperation.get() ); + requiresBarrier = true; } } -#endif + } + + if (requiresBarrier) + { + _barrier = new osg::BarrierOperation(threads.size()+1); + _barrier->setKeep(false); + + for(GraphicsThreads::iterator gitr = threads.begin(); + gitr != threads.end(); + ++gitr) + { + (*gitr)->add(_barrier.get()); + } + + // wait for the graphics threads to complete. + _barrier->block(); } } - - // swap the data. + + bool requiresBlock = false; + + // pass the locally peppared data to MasterOperations shared data + // so that updated thread can merge these changes with the main scene + // graph. This merge is carried out via the update(..) method. + if (!removedFiles.empty() || !nodesToAdd.empty()) { OpenThreads::ScopedLock lock(_mutex); _nodesToRemove.swap(removedFiles); _nodesToAdd.swap(nodesToAdd); + requiresBlock = true; } // now block so we don't try to load anything till the new data has been merged // otherwise _existingFilenameNodeMap will get out of sync. - _updatesMergedBlock.block(); + if (requiresBlock) + { + _updatesMergedBlock.block(); + } + else + { + OpenThreads::Thread::YieldCurrentThread(); + } } + // merge the changes with the main scene graph. void update(osg::Group* scene) { OpenThreads::ScopedLock lock(_mutex); @@ -235,20 +277,23 @@ public: } + // add release implementation so that any thread cancellation can + // work even when blocks and barriers are used. virtual void release() { _updatesMergedBlock.release(); + if (_barrier.valid()) _barrier.release(); } - std::string _filename; - - OpenThreads::Mutex _mutex; - FilenameNodeMap _existingFilenameNodeMap; - Files _nodesToRemove; - FilenameNodeMap _nodesToAdd; - OpenThreads::Block _updatesMergedBlock; + std::string _filename; + OpenThreads::Mutex _mutex; + FilenameNodeMap _existingFilenameNodeMap; + Files _nodesToRemove; + FilenameNodeMap _nodesToAdd; + OpenThreads::Block _updatesMergedBlock; + osg::ref_ptr _barrier; }; class FilterHandler : public osgGA::GUIEventHandler @@ -364,11 +409,8 @@ public: protected: osg::observer_ptr _layer; - }; -#if 1 - int main(int argc, char** argv) { osg::ArgumentParser arguments(&argc, argv); @@ -432,62 +474,6 @@ int main(int argc, char** argv) masterOperation = new MasterOperation(masterFilename); } - osg::ref_ptr scene = new osg::Group; - - osg::ref_ptr loadedModel = osgDB::readNodeFiles(arguments); - if (!masterOperation && !loadedModel) return 0; - - if (masterOperation.valid()) masterOperation->open(scene.get()); - if (loadedModel.valid()) scene->addChild(loadedModel.get()); - - viewer.setSceneData(scene.get()); - - viewer.realize(); - - osg::ref_ptr operationThread; - if (masterOperation.valid()) - { - operationThread = new osg::OperationThread; - operationThread->startThread(); - operationThread->add(masterOperation.get()); - } - - if (createBackgroundContextForCompiling) - { - - int numProcessors = OpenThreads::GetNumberOfProcessors(); - int processNum = 0; - - for(unsigned int i=0; i<= osg::GraphicsContext::getMaxContextID(); ++i) - { - osg::GraphicsContext* gc = osg::GraphicsContext::getOrCreateCompileContext(i); - - if (gc && createBackgroundThreadsForCompiling) - { - gc->createGraphicsThread(); - gc->getGraphicsThread()->setProcessorAffinity(processNum % numProcessors); - gc->getGraphicsThread()->startThread(); - - ++processNum; - } - } - } - - while (!viewer.done()) - { - viewer.advance(); - viewer.eventTraversal(); - viewer.updateTraversal(); - - if (masterOperation.valid()) masterOperation->update(scene.get()); - - viewer.frame(); - } - - // kill the operation thread - operationThread = 0; - - return 0; osg::ref_ptr terrain = new osgTerrain::TerrainNode; osg::ref_ptr locator = new osgTerrain::EllipsoidLocator(-osg::PI, -osg::PI*0.5, 2.0*osg::PI, osg::PI, 0.0); @@ -503,7 +489,6 @@ int main(int argc, char** argv) float scale = 1.0f; float offset = 0.0f; - int pos = 1; while(pos geometryTechnique = new osgTerrain::GeometryTechnique; - - terrain->setTerrainTechnique(geometryTechnique.get()); - - viewer.addEventHandler(new FilterHandler(geometryTechnique.get())); - - viewer.addEventHandler(new LayerHandler(lastAppliedLayer.get())); + osg::ref_ptr scene = new osg::Group; - if (!terrain) return 0; - - // return 0; - - // add a viewport to the viewer and attach the scene graph. - viewer.setSceneData(terrain.get()); - - return viewer.run(); -} - -#else - -#include -#include - -struct MyOperation : public osg::Operation -{ - - MyOperation(const std::string& str, bool keep, double number): - osg::Operation(str,keep), - _number(number) {} - - virtual void operator () (osg::Object* object) + if (terrain.valid() && (terrain->getElevationLayer() || terrain->getColorLayer(0))) { - OpenThreads::ScopedLock lock(_mutex); + osg::notify(osg::NOTICE)<<"Terrain created"<addChild(terrain.get()); + + osg::ref_ptr geometryTechnique = new osgTerrain::GeometryTechnique; + terrain->setTerrainTechnique(geometryTechnique.get()); + viewer.addEventHandler(new FilterHandler(geometryTechnique.get())); + viewer.addEventHandler(new LayerHandler(lastAppliedLayer.get())); + } + + if (masterOperation.valid()) + { + osg::notify(osg::NOTICE)<<"Master operation created"<open(scene.get()); + } + + if (scene->getNumChildren()==0) + { + osg::notify(osg::NOTICE)<<"No model created, please specify terrain or master file on command line."< operationThread; + if (masterOperation.valid()) + { + operationThread = new osg::OperationThread; + operationThread->startThread(); + operationThread->add(masterOperation.get()); + } + + // realize the graphics windows. + viewer.realize(); + + // set up any compile contexts that are required. + if (createBackgroundContextForCompiling) + { + + int numProcessors = OpenThreads::GetNumberOfProcessors(); + int processNum = 0; + + for(unsigned int i=0; i<= osg::GraphicsContext::getMaxContextID(); ++i) + { + osg::GraphicsContext* gc = osg::GraphicsContext::getOrCreateCompileContext(i); + + if (gc && createBackgroundThreadsForCompiling) + { + gc->createGraphicsThread(); + gc->getGraphicsThread()->setProcessorAffinity(processNum % numProcessors); + gc->getGraphicsThread()->startThread(); + + ++processNum; + } + } + } + + + // run main loop, with syncing with masterOperation + while (!viewer.done()) + { + viewer.advance(); + viewer.eventTraversal(); + viewer.updateTraversal(); - osg::notify(osg::NOTICE)<add(new MyOperation("two ",true, 0.0)); - - { - typedef std::list< osg::ref_ptr > Threads; - Threads threads; - - unsigned int numberThreads = 2; - while (arguments.read("--threads",numberThreads)) {} - - for(unsigned int i=0; i thread = new osg::OperationsThread; - thread->setOperationQueue(operations.get()); - threads.push_back(thread.get()); - thread->startThread(); - } - - while(!operations->empty()) - { - osg::notify(osg::NOTICE)<<"Main loop"< operation = operations->getNextOperation(); - if (operation.valid()) (*operation)(0); - } - - osg::notify(osg::NOTICE)<<"Completed main loop ******************************* "<