From 42eb39ef372b4a2eb7da09900377e3dbfba6c277 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Sun, 12 Oct 2003 12:13:58 +0000 Subject: [PATCH] Improvements to the DatabasePager --- include/osgDB/DatabasePager | 47 ++++++---- src/osgDB/DatabasePager.cpp | 167 +++++++++++++++++++++++++----------- src/osgProducer/Viewer.cpp | 31 ++++++- 3 files changed, 177 insertions(+), 68 deletions(-) diff --git a/include/osgDB/DatabasePager b/include/osgDB/DatabasePager index 125eea329..496e41491 100644 --- a/include/osgDB/DatabasePager +++ b/include/osgDB/DatabasePager @@ -22,6 +22,8 @@ #include #include +#include + #include #include @@ -43,6 +45,15 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl /** run does the database paging.*/ virtual void run(); + + /** Signal the database thread that the update, cull and draw has begun for a new frame. + * Note, this is called by the application so that the database pager can go to sleep while the CPU is busy on the main rendering threads. */ + void signalBeginFrame(const osg::FrameStamp* framestamp); + + /** Signal the database thread that the update, cull and draw dispatch has completed. + * Note, this is called by the application so that the database pager can go to wake back up now the main rendering threads are iddle waiting for the next frame.*/ + void signalEndFrame(); + /** Add the loaded data to the scene graph.*/ void addLoadedDataToSceneGraph(double timeStamp); @@ -121,8 +132,10 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl {} std::string _fileName; + int _frameNumberFirstRequest; double _timestampFirstRequest; float _priorityFirstRequest; + int _frameNumberLastRequest; double _timestampLastRequest; float _priorityLastRequest; unsigned int _numOfRequests; @@ -138,25 +151,29 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl virtual ~DatabasePager(); - DatabaseRequestList _fileRequestList; - OpenThreads::Mutex _fileRequestListMutex; - - DatabaseRequestList _dataToCompileList; - OpenThreads::Mutex _dataToCompileListMutex; - - bool _deleteRemovedSubgraphsInDatabaseThread; - osg::NodeList _childrenToDeleteList; - OpenThreads::Mutex _childrenToDeleteListMutex; + osg::ref_ptr _frameBlock; + int _frameNumber; - DatabaseRequestList _dataToMergeList; - OpenThreads::Mutex _dataToMergeListMutex; + DatabaseRequestList _fileRequestList; + OpenThreads::Mutex _fileRequestListMutex; + osg::ref_ptr _fileRequestListEmptyBlock; + DatabaseRequestList _dataToCompileList; + OpenThreads::Mutex _dataToCompileListMutex; - PagedLODList _pagedLODList; - - double _expiryDelay; + bool _deleteRemovedSubgraphsInDatabaseThread; + osg::NodeList _childrenToDeleteList; + OpenThreads::Mutex _childrenToDeleteListMutex; - ActiveGraphicsContexts _activeGraphicsContexts; + DatabaseRequestList _dataToMergeList; + OpenThreads::Mutex _dataToMergeListMutex; + + + PagedLODList _pagedLODList; + + double _expiryDelay; + + ActiveGraphicsContexts _activeGraphicsContexts; }; diff --git a/src/osgDB/DatabasePager.cpp b/src/osgDB/DatabasePager.cpp index 5532cbec7..4c34f8a7a 100644 --- a/src/osgDB/DatabasePager.cpp +++ b/src/osgDB/DatabasePager.cpp @@ -19,6 +19,10 @@ DatabasePager::DatabasePager() { //osg::notify(osg::INFO)<<"Constructing DatabasePager()"<getReferenceTime():0.0; + int frameNumber = framestamp?framestamp->getFrameNumber():_frameNumber; // search to see if filename already exist in the file loaded list. bool foundEntry = false; @@ -60,6 +65,7 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou if ((*litr)->_fileName==fileName) { foundEntry = true; + (*litr)->_frameNumberLastRequest = frameNumber; (*litr)->_timestampLastRequest = timestamp; (*litr)->_priorityLastRequest = priority; ++((*litr)->_numOfRequests); @@ -79,6 +85,7 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou if ((*litr)->_fileName==fileName) { foundEntry = true; + (*litr)->_frameNumberLastRequest = frameNumber; (*litr)->_timestampLastRequest = timestamp; (*litr)->_priorityLastRequest = priority; ++((*litr)->_numOfRequests); @@ -104,21 +111,28 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou foundEntry = true; (*ritr)->_timestampLastRequest = timestamp; (*ritr)->_priorityLastRequest = priority; + (*ritr)->_frameNumberLastRequest = frameNumber; ++((*ritr)->_numOfRequests); } } if (!foundEntry) { + osg::notify(osg::INFO)<<"In DatabasePager::fileRquest("< databaseRequest = new DatabaseRequest; databaseRequest->_fileName = fileName; + databaseRequest->_frameNumberFirstRequest = frameNumber; databaseRequest->_timestampFirstRequest = timestamp; databaseRequest->_priorityFirstRequest = priority; + databaseRequest->_frameNumberLastRequest = frameNumber; databaseRequest->_timestampLastRequest = timestamp; databaseRequest->_priorityLastRequest = priority; databaseRequest->_groupForAddingLoadedSubgraph = group; + if (_fileRequestList.empty()) _fileRequestListEmptyBlock->release(); + _fileRequestList.push_back(databaseRequest); } @@ -144,6 +158,23 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou } } +void DatabasePager::signalBeginFrame(const osg::FrameStamp* framestamp) +{ + if (framestamp) + { + osg::notify(osg::INFO) << "signalBeginFrame "<getFrameNumber()<<">>>>>>>>>>>>>>>>"<getFrameNumber(); + } else osg::notify(osg::INFO) << "signalBeginFrame >>>>>>>>>>>>>>>>"<reset(); +} + +void DatabasePager::signalEndFrame() +{ + osg::notify(osg::INFO) << "signalEndFrame <<<<<<<<<<<<<<<<<<<< "<release(); +} + class FindCompileableRenderingObjectsVisitor : public osg::NodeVisitor { public: @@ -232,6 +263,17 @@ void DatabasePager::run() do { + //std::cout<<"In run loop"<tick(); + _fileRequestListEmptyBlock->block(); + osg::Timer_t t2 = osg::Timer::instance()->tick(); + _frameBlock->block(); + osg::Timer_t t3 = osg::Timer::instance()->tick(); + + //std::cout<<"Time in _fileRequestListEmptyBlock block()"<delta_m(t1,t2)<delta_m(t2,t3)<_loadedModel = osgDB::readNodeFile(databaseRequest->_fileName); - - bool loadedObjectsNeedToBeCompiled = false; - - if (databaseRequest->_loadedModel.valid() && !_activeGraphicsContexts.empty()) + // check if databaseRequest is still relevant + if (_frameNumber-databaseRequest->_frameNumberLastRequest<=1) { - // force a compute of the loaded model's bounding volume, so that when the subgraph - // merged with the main scene graph and large computeBound() isn't incurred. - databaseRequest->_loadedModel->getBound(); - - - 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()) + + // 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::INFO)<<"In DatabasePager thread readNodeFile("<_fileName<<")"<tick(); + databaseRequest->_loadedModel = osgDB::readNodeFile(databaseRequest->_fileName); + osg::notify(osg::INFO)<<" node read"<delta_m(before,osg::Timer::instance()->tick())<_loadedModel.valid() && !_activeGraphicsContexts.empty()) { - loadedObjectsNeedToBeCompiled = true; - - // copy the objects to compile list to the other graphics context list. - for(; - itr != _activeGraphicsContexts.end(); - ++itr) + // force a compute of the loaded model's bounding volume, so that when the subgraph + // merged with the main scene graph and large computeBound() isn't incurred. + databaseRequest->_loadedModel->getBound(); + + + 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()) { - databaseRequest->_dataToCompileMap[*itr] = dtc; + 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(); + // move the databaseRequest from the front of the fileRequest to the end of + // dataLoad list. + _fileRequestListMutex.lock(); - if (databaseRequest->_loadedModel.valid()) - { - if (loadedObjectsNeedToBeCompiled) + if (databaseRequest->_loadedModel.valid()) { - _dataToCompileListMutex.lock(); - _dataToCompileList.push_back(databaseRequest); - _dataToCompileListMutex.unlock(); - } - else - { - _dataToMergeListMutex.lock(); - _dataToMergeList.push_back(databaseRequest); - _dataToMergeListMutex.unlock(); - } - } + if (loadedObjectsNeedToBeCompiled) + { + _dataToCompileListMutex.lock(); + _dataToCompileList.push_back(databaseRequest); + _dataToCompileListMutex.unlock(); + } + else + { + _dataToMergeListMutex.lock(); + _dataToMergeList.push_back(databaseRequest); + _dataToMergeListMutex.unlock(); + } + } - _fileRequestList.erase(_fileRequestList.begin()); + _fileRequestList.erase(_fileRequestList.begin()); - _fileRequestListMutex.unlock(); + if (_fileRequestList.empty()) _fileRequestListEmptyBlock->reset(); + _fileRequestListMutex.unlock(); + } + else + { + //std::cout<<"frame number delta for "<_fileName<<" "<<_frameNumber-databaseRequest->_frameNumberLastRequest<reset(); + + _fileRequestListMutex.unlock(); + } } // go to sleep till our the next time our thread gets scheduled. - YieldCurrentThread(); + //YieldCurrentThread(); + + //std::cout<<"At end of loop"<signalBeginFrame(sh.getSceneView()->getState()->getFrameStamp()); + + sh.cullImplementation(camera); + + } + + osg::ref_ptr _databasePager; +}; + class DatabasePagerCompileCallback : public OsgSceneHandler::Callback { public: @@ -328,9 +348,12 @@ public: sh.drawImplementation(camera); - double availableTime = 0.005; // 5 ms + double availableTime = 0.0025; // 5 ms _databasePager->compileRenderingObjects(*(sh.getSceneView()->getState()),availableTime); + + _databasePager->signalEndFrame(); + } osg::ref_ptr _databasePager; @@ -357,6 +380,8 @@ bool Viewer::realize() // pass the database pager to the cull visitor so node can send requests to the pager. (*p)->getSceneView()->getCullVisitor()->setDatabaseRequestHandler(_databasePager.get()); + (*p)->setCullCallback(new DatabasePagerStartCullCallback(_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())); @@ -418,6 +443,9 @@ void Viewer::update() if (_databasePager.valid()) { + + //_databasePager->signalBeginFrame(_frameStamp.get()); + // removed any children PagedLOD children that havn't been visited in the cull traversal recently. _databasePager->removeExpiredSubgraphs(_frameStamp->getReferenceTime()); @@ -460,6 +488,7 @@ void Viewer::frame() } OsgCameraGroup::frame(); + } bool Viewer::computePixelCoords(float x,float y,unsigned int cameraNum,float& pixel_x,float& pixel_y)