diff --git a/include/osgDB/DatabasePager b/include/osgDB/DatabasePager index b3d40c764..157b729ba 100644 --- a/include/osgDB/DatabasePager +++ b/include/osgDB/DatabasePager @@ -219,12 +219,23 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl } + /** Add a graphics context that should be used to compile/delete OpenGL objects.*/ + void addCompileGraphicsContext(osg::GraphicsContext* gc); + + /** Removed a graphics context that should be used to compile/delete OpenGL objects.*/ + void removeCompileGraphicsContext(osg::GraphicsContext* gc); + + /** Turn the compilation of rendering objects for specfied graphics context on (true) or off(false). */ void setCompileGLObjectsForContextID(unsigned int contextID, bool on); /** Get whether the compilation of rendering objects for specfied graphics context on (true) or off(false). */ bool getCompileGLObjectsForContextID(unsigned int contextID); + + /** Rerturn true if an external draw thread should call compileGLObjects(..) or not.*/ + bool requiresExternalCompileGLObjects(unsigned int contextID) const; + /** Return true if there are pending compile operations that are required. * If requiresCompileGLObjects() return true the application should call compileGLObjects() .*/ bool requiresCompileGLObjects() const; @@ -234,6 +245,11 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl * Note, must only be called from a valid graphics context. */ virtual void compileGLObjects(osg::State& state,double& availableTime); + /** Compile the rendering objects (display lists,texture objects, VBO's) on loaded subgraph. + * note, should only be called from the draw thread. + * Note, must only be called from a valid graphics context. */ + virtual void compileAllGLObjects(osg::State& state); + /** Report how many items are in the _fileRequestList queue */ unsigned int getFileRequestListSize() const { return _fileRequestList.size(); } @@ -241,12 +257,13 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl unsigned int getDataToCompileListSize() const { return _dataToCompileList.size(); } - typedef std::list< osg::ref_ptr > PagedLODList; - typedef std::set< osg::ref_ptr > StateSetList; - typedef std::vector< osg::ref_ptr > DrawableList; - typedef std::pair DataToCompile; - typedef std::map< unsigned int, DataToCompile > DataToCompileMap; - typedef std::set ActiveGraphicsContexts; + typedef std::list< osg::ref_ptr > PagedLODList; + typedef std::set< osg::ref_ptr > StateSetList; + typedef std::vector< osg::ref_ptr > DrawableList; + typedef std::pair DataToCompile; + typedef std::map< unsigned int, DataToCompile > DataToCompileMap; + typedef std::set ActiveGraphicsContexts; + typedef std::vector< osg::observer_ptr > CompileGraphicsContexts; protected: @@ -358,11 +375,21 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl double _expiryDelay; ActiveGraphicsContexts _activeGraphicsContexts; + CompileGraphicsContexts _compileGraphicsContexts; bool _doPreCompile; double _targetFrameRate; double _minimumTimeAvailableForGLCompileAndDeletePerFrame; unsigned int _maximumNumOfObjectsToCompilePerFrame; + + struct CompileOperation : public osg::Operation + { + CompileOperation(DatabasePager* databasePager); + + virtual void operator () (osg::Object* object); + + osg::observer_ptr _databasePager; + }; }; } diff --git a/src/osgDB/DatabasePager.cpp b/src/osgDB/DatabasePager.cpp index fad0f0ddc..a90af31e7 100644 --- a/src/osgDB/DatabasePager.cpp +++ b/src/osgDB/DatabasePager.cpp @@ -455,14 +455,14 @@ void DatabasePager::run() do { - + _databasePagerThreadBlock->block(); if (_useFrameBlock) { _frameBlock->block(); } - + // // delete any children if required. // @@ -508,7 +508,7 @@ void DatabasePager::run() // load the data, note safe to write to the databaseRequest since once // it is created this thread is the only one to write to the _loadedModel pointer. - // osg::notify(osg::NOTICE)<<"In DatabasePager thread readNodeFile("<_fileName<<")"<_fileName<<")"<tick(); @@ -567,32 +567,59 @@ void DatabasePager::run() } // move the databaseRequest from the front of the fileRequest to the end of - // dataLoad list. - - OpenThreads::ScopedLock lock(_fileRequestListMutex); - - DatabaseRequestList::iterator itr = std::find(_fileRequestList.begin(),_fileRequestList.end(),databaseRequest); - if (itr != _fileRequestList.end()) + // dataToCompile or dataToMerge lists. { - if (databaseRequest->_loadedModel.valid()) + OpenThreads::ScopedLock lock(_fileRequestListMutex); + + DatabaseRequestList::iterator itr = std::find(_fileRequestList.begin(),_fileRequestList.end(),databaseRequest); + if (itr != _fileRequestList.end()) { - if (loadedObjectsNeedToBeCompiled) + if (databaseRequest->_loadedModel.valid()) { - OpenThreads::ScopedLock lock(_dataToCompileListMutex); - _dataToCompileList.push_back(databaseRequest); - } - else - { - OpenThreads::ScopedLock lock(_dataToMergeListMutex); - _dataToMergeList.push_back(databaseRequest); - } - } - - _fileRequestList.erase(itr); + if (loadedObjectsNeedToBeCompiled) + { + OpenThreads::ScopedLock lock(_dataToCompileListMutex); + _dataToCompileList.push_back(databaseRequest); + } + else + { + OpenThreads::ScopedLock lock(_dataToMergeListMutex); + _dataToMergeList.push_back(databaseRequest); + } + } + + _fileRequestList.erase(itr); + } + + updateDatabasePagerThreadBlock(); } - - updateDatabasePagerThreadBlock(); - + + if (loadedObjectsNeedToBeCompiled && !_compileGraphicsContexts.empty()) + { + for(CompileGraphicsContexts::iterator citr = _compileGraphicsContexts.begin(); + citr != _compileGraphicsContexts.end(); + ++citr) + { + osg::GraphicsContext* gc = citr->get(); + if (gc) + { + osg::OperationsThread* gt = gc->getGraphicsThread(); + if (gt) gt->add(new DatabasePager::CompileOperation(this)); + else + { + gc->makeCurrent(); + + // osg::notify(osg::NOTICE)<<"Database pager thread compiling"<getState())); + + gc->releaseContext(); + } + } + } + // osg::notify(osg::NOTICE)<<"Done compiling in paging thread"<getState()->getContextID(),true); +} + +void DatabasePager::removeCompileGraphicsContext(osg::GraphicsContext* gc) +{ + for(CompileGraphicsContexts::iterator itr = _compileGraphicsContexts.begin(); + itr != _compileGraphicsContexts.end(); + ++itr) + { + if (*itr == gc) + { + _compileGraphicsContexts.erase(itr); + return; + } + } +} + void DatabasePager::setCompileGLObjectsForContextID(unsigned int contextID, bool on) { if (on) @@ -874,9 +932,48 @@ bool DatabasePager::getCompileGLObjectsForContextID(unsigned int contextID) } +DatabasePager::CompileOperation::CompileOperation(osgDB::DatabasePager* databasePager): + osg::Operation("DatabasePager::CompileOperation",false), + _databasePager(databasePager) +{ +} + +void DatabasePager::CompileOperation::operator () (osg::Object* object) +{ + osg::GraphicsContext* context = dynamic_cast(object); + if (!context) return; + + // osg::notify(osg::NOTICE)<<"Background thread compiling"<compileAllGLObjects(*(context->getState())); + +} + +bool DatabasePager::requiresExternalCompileGLObjects(unsigned int contextID) const +{ + if (_activeGraphicsContexts.count(contextID)==0) return false; + + for(CompileGraphicsContexts::const_iterator citr = _compileGraphicsContexts.begin(); + citr != _compileGraphicsContexts.end(); + ++citr) + { + const osg::GraphicsContext* gc = citr->get(); + if (gc && gc->getState()->getContextID()==contextID) return false; + } + + return true; +} + +void DatabasePager::compileAllGLObjects(osg::State& state) +{ + double availableTime = DBL_MAX; + compileGLObjects(state, availableTime); +} + void DatabasePager::compileGLObjects(osg::State& state, double& availableTime) { -// osg::notify(osg::NOTICE)<<"DatabasePager::compileGLObjects "<<_frameNumber<_dataToCompileMap; DataToCompile& dtc = dcm[state.getContextID()]; @@ -973,14 +1070,14 @@ void DatabasePager::compileGLObjects(osg::State& state, double& availableTime) sslist.erase(sslist.begin(),itr); } - if (!dtc.second.empty() && (elapsedTime+estimatedDrawableDuration) lock(_dataToCompileListMutex); @@ -1035,7 +1134,7 @@ void DatabasePager::compileGLObjects(osg::State& state, double& availableTime) } else { - //osg::notify(osg::INFO)<<"Not all compiled"<cull(); _sceneView->draw(); - if (_databasePager.valid()) + double availableTime = 0.004; // 4 ms + + if (_databasePager.valid() && _databasePager->requiresExternalCompileGLObjects(_sceneView->getState()->getContextID())) { - double availableTime = 0.004; // 4 ms _databasePager->compileGLObjects(*(_sceneView->getState()), availableTime); - _sceneView->flushDeletedGLObjects(availableTime); } + + _sceneView->flushDeletedGLObjects(availableTime); } osg::observer_ptr _sceneView; diff --git a/src/osgViewer/Viewer.cpp b/src/osgViewer/Viewer.cpp index be35755fa..8ed1b4f4b 100644 --- a/src/osgViewer/Viewer.cpp +++ b/src/osgViewer/Viewer.cpp @@ -198,9 +198,9 @@ struct ViewerRenderingOperation : public osg::Operation, public ViewerQuerySuppo _sceneView->draw(); double availableTime = 0.004; // 4 ms - if (_databasePager.valid()) + if (_databasePager.valid() && _databasePager->requiresExternalCompileGLObjects(_sceneView->getState()->getContextID())) { - _databasePager->compileGLObjects(*(_sceneView->getState()), availableTime); + _databasePager->compileGLObjects(*(_sceneView->getState()), availableTime); } _sceneView->flushDeletedGLObjects(availableTime); @@ -422,7 +422,7 @@ struct ViewerDoubleBufferedRenderingOperation : public osg::Operation, public Vi sceneView->draw(); double availableTime = 0.004; // 4 ms - if (_databasePager.valid()) + if (_databasePager.valid() && _databasePager->requiresExternalCompileGLObjects(sceneView->getState()->getContextID())) { _databasePager->compileGLObjects(*(sceneView->getState()), availableTime); } @@ -511,7 +511,7 @@ struct ViewerDoubleBufferedRenderingOperation : public osg::Operation, public Vi sceneView->draw(); double availableTime = 0.004; // 4 ms - if (_databasePager.valid()) + if (_databasePager.valid() && _databasePager->requiresExternalCompileGLObjects(sceneView->getState()->getContextID())) { _databasePager->compileGLObjects(*(sceneView->getState()), availableTime); } @@ -1559,6 +1559,7 @@ void Viewer::setUpRenderingSupport() osg::GraphicsContext* gc = *gcitr; osg::GraphicsContext::Cameras& cameras = gc->getCameras(); osg::State* state = gc->getState(); + if (dp) dp->setCompileGLObjectsForContextID(state->getContextID(), true); for(osg::GraphicsContext::Cameras::iterator citr = cameras.begin();