Improvements to the DatabasePager
This commit is contained in:
@@ -22,6 +22,8 @@
|
||||
#include <OpenThreads/Thread>
|
||||
#include <OpenThreads/Mutex>
|
||||
|
||||
#include <Producer/Block>
|
||||
|
||||
#include <osgDB/Export>
|
||||
|
||||
#include <map>
|
||||
@@ -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<Producer::Block> _frameBlock;
|
||||
int _frameNumber;
|
||||
|
||||
DatabaseRequestList _dataToMergeList;
|
||||
OpenThreads::Mutex _dataToMergeListMutex;
|
||||
DatabaseRequestList _fileRequestList;
|
||||
OpenThreads::Mutex _fileRequestListMutex;
|
||||
osg::ref_ptr<Producer::Block> _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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -19,6 +19,10 @@ DatabasePager::DatabasePager()
|
||||
{
|
||||
//osg::notify(osg::INFO)<<"Constructing DatabasePager()"<<std::endl;
|
||||
|
||||
_frameNumber = 0;
|
||||
_frameBlock = new Producer::Block;
|
||||
_fileRequestListEmptyBlock = new Producer::Block;
|
||||
|
||||
_deleteRemovedSubgraphsInDatabaseThread = true;
|
||||
|
||||
_expiryDelay = 1.0;
|
||||
@@ -47,6 +51,7 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou
|
||||
{
|
||||
|
||||
double timestamp = framestamp?framestamp->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("<<fileName<<")"<<std::endl;
|
||||
|
||||
osg::ref_ptr<DatabaseRequest> 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 "<<framestamp->getFrameNumber()<<">>>>>>>>>>>>>>>>"<<std::endl;
|
||||
_frameNumber = framestamp->getFrameNumber();
|
||||
} else osg::notify(osg::INFO) << "signalBeginFrame >>>>>>>>>>>>>>>>"<<std::endl;
|
||||
|
||||
_frameBlock->reset();
|
||||
}
|
||||
|
||||
void DatabasePager::signalEndFrame()
|
||||
{
|
||||
osg::notify(osg::INFO) << "signalEndFrame <<<<<<<<<<<<<<<<<<<< "<<std::endl;
|
||||
_frameBlock->release();
|
||||
}
|
||||
|
||||
class FindCompileableRenderingObjectsVisitor : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
@@ -232,6 +263,17 @@ void DatabasePager::run()
|
||||
|
||||
do
|
||||
{
|
||||
//std::cout<<"In run loop"<<std::endl;
|
||||
|
||||
|
||||
osg::Timer_t t1 = osg::Timer::instance()->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()"<<osg::Timer::instance()->delta_m(t1,t2)<<std::endl;
|
||||
//std::cout<<"Time in _frameBlock block()"<<osg::Timer::instance()->delta_m(t2,t3)<<std::endl;
|
||||
|
||||
//
|
||||
// delete any children if required.
|
||||
@@ -263,74 +305,95 @@ void DatabasePager::run()
|
||||
|
||||
if (databaseRequest.valid())
|
||||
{
|
||||
// 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.
|
||||
databaseRequest->_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("<<databaseRequest->_fileName<<")"<<std::endl;
|
||||
osg::Timer_t before = osg::Timer::instance()->tick();
|
||||
databaseRequest->_loadedModel = osgDB::readNodeFile(databaseRequest->_fileName);
|
||||
osg::notify(osg::INFO)<<" node read"<<osg::Timer::instance()->delta_m(before,osg::Timer::instance()->tick())<<std::endl;
|
||||
|
||||
bool loadedObjectsNeedToBeCompiled = false;
|
||||
|
||||
if (databaseRequest->_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 "<<databaseRequest->_fileName<<" "<<_frameNumber-databaseRequest->_frameNumberLastRequest<<std::endl;
|
||||
// remove the databaseRequest from the front of the fileRequest to the end of
|
||||
// dataLoad list as its is no longer relevant
|
||||
_fileRequestListMutex.lock();
|
||||
|
||||
|
||||
_fileRequestList.erase(_fileRequestList.begin());
|
||||
|
||||
if (_fileRequestList.empty()) _fileRequestListEmptyBlock->reset();
|
||||
|
||||
_fileRequestListMutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
// go to sleep till our the next time our thread gets scheduled.
|
||||
YieldCurrentThread();
|
||||
//YieldCurrentThread();
|
||||
|
||||
//std::cout<<"At end of loop"<<std::endl;
|
||||
|
||||
} while (!testCancel());
|
||||
|
||||
|
||||
@@ -315,6 +315,26 @@ bool Viewer::realize( ThreadingModel thread_model )
|
||||
return realize();
|
||||
}
|
||||
|
||||
class DatabasePagerStartCullCallback : public OsgSceneHandler::Callback
|
||||
{
|
||||
public:
|
||||
|
||||
DatabasePagerStartCullCallback(osgDB::DatabasePager* databasePager):
|
||||
_databasePager(databasePager)
|
||||
{}
|
||||
|
||||
virtual void operator()(OsgSceneHandler& sh, Producer::Camera& camera)
|
||||
{
|
||||
|
||||
_databasePager->signalBeginFrame(sh.getSceneView()->getState()->getFrameStamp());
|
||||
|
||||
sh.cullImplementation(camera);
|
||||
|
||||
}
|
||||
|
||||
osg::ref_ptr<osgDB::DatabasePager> _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<osgDB::DatabasePager> _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)
|
||||
|
||||
Reference in New Issue
Block a user