From c5c7a1b2baa155e020d6fbdf01287a5ebfc8e5a6 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 10 Jul 2003 11:10:39 +0000 Subject: [PATCH] Updates to the DatabasePager code to include support for compiling texture objects and display lists before merging loaded subgraphs with the main scene graph. --- include/osgProducer/DatabasePager | 18 ++- src/osgProducer/DatabasePager.cpp | 210 +++++++++++++++++++++++++++--- src/osgProducer/Viewer.cpp | 10 +- 3 files changed, 214 insertions(+), 24 deletions(-) diff --git a/include/osgProducer/DatabasePager b/include/osgProducer/DatabasePager index 4d4f95612..df625c4d7 100644 --- a/include/osgProducer/DatabasePager +++ b/include/osgProducer/DatabasePager @@ -25,6 +25,7 @@ #include #include +#include namespace osgProducer { @@ -73,6 +74,12 @@ class OSGPRODUCER_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseReques void removeExpiredSubgraphs(double currentFrameTime); + /** Turn the compilation of rendering objects for specfied graphics context on (true) or off(false).*/ + void setCompileRenderingObjectsForContexID(unsigned int contextID, bool on); + + /** Get whether the compilation of rendering objects for specfied graphics context on (true) or off(false).*/ + bool getCompileRenderingObjectsForContexID(unsigned int contextID); + /* Set the maximum amount of time available for compile rendering objects. */ void setMaximumTimeForCompilingRenderingObjects(double time) { _maximumTimeForCompiling = time; } @@ -89,7 +96,7 @@ class OSGPRODUCER_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseReques virtual ~DatabasePager() {} // make friends with helper classes defined in DatabasePager.cpp. - class FindRenderingObjectsVisitor; + class FindCompileableRenderingObjectsVisitor; class FindPagedLODsVisitor; typedef std::vector< osg::ref_ptr > PagedLODList; @@ -99,6 +106,8 @@ class OSGPRODUCER_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseReques typedef std::pair DataToCompile; typedef std::map< unsigned int, DataToCompile > DataToCompileMap; + typedef std::set ActiveGraphicsContexts; + struct DatabaseRequest : public osg::Referenced { DatabaseRequest(): @@ -118,15 +127,15 @@ class OSGPRODUCER_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseReques DatabaseRequestList _fileRequestList; Producer::Mutex _fileRequestListMutex; - DatabaseRequestList _dataLoadedList; - Producer::Mutex _dataLoadedListMutex; + DatabaseRequestList _dataToCompileList; + Producer::Mutex _dataToCompileListMutex; bool _deleteRemovedSubgraphsInDatabaseThread; osg::NodeList _childrenToDeleteList; Producer::Mutex _childrenToDeleteListMutex; DatabaseRequestList _dataToMergeList; - Producer::Mutex _dataToMergeMutex; + Producer::Mutex _dataToMergeListMutex; PagedLODList _pagedLODList; @@ -134,6 +143,7 @@ class OSGPRODUCER_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseReques double _expiryDelay; double _maximumTimeForCompiling; + ActiveGraphicsContexts _activeGraphicsContexts; }; diff --git a/src/osgProducer/DatabasePager.cpp b/src/osgProducer/DatabasePager.cpp index ce8e8e159..660fe7c6c 100644 --- a/src/osgProducer/DatabasePager.cpp +++ b/src/osgProducer/DatabasePager.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #ifdef WIN32 #include @@ -27,10 +28,10 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou // search to see if filename already exist in the file loaded list. bool foundEntry = false; - _dataLoadedListMutex.lock(); + _dataToCompileListMutex.lock(); - for(DatabaseRequestList::iterator litr = _dataLoadedList.begin(); - litr != _dataLoadedList.end() && !foundEntry; + for(DatabaseRequestList::iterator litr = _dataToCompileList.begin(); + litr != _dataToCompileList.end() && !foundEntry; ++litr) { if ((*litr)->_fileName==fileName) @@ -40,7 +41,7 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou } } - _dataLoadedListMutex.unlock(); + _dataToCompileListMutex.unlock(); if (!foundEntry) { @@ -80,10 +81,10 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou } } -class DatabasePager::FindRenderingObjectsVisitor : public osg::NodeVisitor +class DatabasePager::FindCompileableRenderingObjectsVisitor : public osg::NodeVisitor { public: - FindRenderingObjectsVisitor(DatabasePager::DataToCompile& dataToCompile): + FindCompileableRenderingObjectsVisitor(DatabasePager::DataToCompile& dataToCompile): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), _dataToCompile(dataToCompile) { @@ -112,7 +113,23 @@ public: { if (stateset) { - _dataToCompile.first.push_back(stateset); + // search for the existance of any texture object attributes + bool foundTextureState = false; + osg::StateSet::TextureAttributeList& tal = stateset->getTextureAttributeList(); + for(osg::StateSet::TextureAttributeList::iterator itr=tal.begin(); + itr!=tal.end() && !foundTextureState; + ++itr) + { + osg::StateSet::AttributeList& al = *itr; + if (al.count(osg::StateAttribute::TEXTURE)==1) foundTextureState = true; + } + + // if texture object attributes exist add the state to the list for later compilation. + if (foundTextureState) + { + //std::cout<<"Found compilable texture state"<getUseDisplayList() || drawable->getUseVertexBufferObjects()) { + //std::cout<<"Found compilable drawable"<_loadedModel = osgDB::readNodeFile(databaseRequest->_fileName); + bool loadedObjectsNeedToBeCompiled = false; + + if (databaseRequest->_loadedModel.valid() && !_activeGraphicsContexts.empty()) + { + ActiveGraphicsContexts::iterator itr = _activeGraphicsContexts.begin(); + + DataToCompile& dtc = databaseRequest->_dataToCompileMap[*itr]; + ++itr; + + // find all the compileable rendering objects + FindCompileableRenderingObjectsVisitor frov(dtc); + databaseRequest->_loadedModel->accept(frov); + + if (!dtc.first.empty() || !dtc.second.empty()) + { + loadedObjectsNeedToBeCompiled = true; + + // copy the objects to compile list to the other graphics context list. + for(; + itr != _activeGraphicsContexts.end(); + ++itr) + { + databaseRequest->_dataToCompileMap[*itr] = dtc; + } + } + } + + + // move the databaseRequest from the front of the fileRequest to the end of + // dataLoad list. _fileRequestListMutex.lock(); + + if (databaseRequest->_loadedModel.valid()) + { + if (loadedObjectsNeedToBeCompiled) + { + _dataToCompileListMutex.lock(); + _dataToCompileList.push_back(databaseRequest); + _dataToCompileListMutex.unlock(); + } + else + { + _dataToMergeListMutex.lock(); + _dataToMergeList.push_back(databaseRequest); + _dataToMergeListMutex.unlock(); + } + } + _fileRequestList.erase(_fileRequestList.begin()); + _fileRequestListMutex.unlock(); - if (databaseRequest->_loadedModel.valid()) - { - _dataLoadedListMutex.lock(); - _dataLoadedList.push_back(databaseRequest); + - _dataLoadedListMutex.unlock(); - } } // hack hack hack... sleep for 1ms so we give other threads a chance.. @@ -196,10 +257,10 @@ void DatabasePager::addLoadedDataToSceneGraph() { DatabaseRequestList localFileLoadedList; - // get the dat for the _dataLoadedList, leaving it empty via a std::vector<>.swap. - _dataLoadedListMutex.lock(); - localFileLoadedList.swap(_dataLoadedList); - _dataLoadedListMutex.unlock(); + // get the dat for the _dataToCompileList, leaving it empty via a std::vector<>.swap. + _dataToMergeListMutex.lock(); + localFileLoadedList.swap(_dataToMergeList); + _dataToMergeListMutex.unlock(); // add the loaded data into the scene graph. for(DatabaseRequestList::iterator itr=localFileLoadedList.begin(); @@ -284,8 +345,119 @@ void DatabasePager::registerPagedLODs(osg::Node* subgraph) if (subgraph) subgraph->accept(fplv); } -void DatabasePager::compileRenderingObjects(osg::State& state) +void DatabasePager::setCompileRenderingObjectsForContexID(unsigned int contextID, bool on) { -// std::cout<<"Compiling rendering objects"< databaseRequest; + + // get the first compileable entry. + _dataToCompileListMutex.lock(); + if (!_dataToCompileList.empty()) databaseRequest = _dataToCompileList.front(); + _dataToCompileListMutex.unlock(); + + // while there are valid databaseRequest's in the to compile list and there is + // sufficient time left compile each databaseRequest's stateset and drawables. + while (databaseRequest.valid() && elapsedTime<_maximumTimeForCompiling) + { + DataToCompileMap& dcm = databaseRequest->_dataToCompileMap; + DataToCompile& dtc = dcm[state.getContextID()]; + if (!dtc.first.empty() && elapsedTime<_maximumTimeForCompiling) + { + // we have StateSet's to compile + StateSetList& sslist = dtc.first; + //std::cout<<"Compiling statesets"<compile(state); + elapsedTime = timer.delta_s(start_tick,timer.tick()); + } + // remove the compiled stateset from the list. + sslist.erase(sslist.begin(),itr); + } + if (!dtc.second.empty() && elapsedTime<_maximumTimeForCompiling) + { + // we have Drawable's to compile + //std::cout<<"Compiling drawables"<compile(state); + elapsedTime = timer.delta_s(start_tick,timer.tick()); + } + // remove the compiled drawables from the list. + dwlist.erase(dwlist.begin(),itr); + } + + //std::cout<<"Checking if compiled"<second.first.empty())) allCompiled=false; + if (!(itr->second.second.empty())) allCompiled=false; + } + + + if (allCompiled) + { + //std::cout<<"All compiled"<compileRenderingObjects(*(sh.getSceneView()->getState())); sh.drawImplementation(camera); + + _databasePager->compileRenderingObjects(*(sh.getSceneView()->getState())); } osg::ref_ptr _databasePager; @@ -330,8 +331,15 @@ bool Viewer::realize() p!=_shvec.end(); ++p) { + // pass the database pager to the cull visitor so node can send requests to the pager. (*p)->getSceneView()->getCullVisitor()->setDatabaseRequestHandler(_databasePager.get()); + + // set up a draw callback to pre compile any rendering object of database has loaded, + // but not yet merged with the main scene graph. (*p)->setDrawCallback(new DatabasePagerCompileCallback(_databasePager.get())); + + // tell the database pager which graphic context the compile of rendering objexts is needed. + _databasePager->setCompileRenderingObjectsForContexID((*p)->getSceneView()->getState()->getContextID(),true); } }