Improvements to the DatabasePager and PagedLOD class adding support for
deleting expuired children in the database thread.
This commit is contained in:
parent
dcbaf59753
commit
5aa47a77c2
@ -19,6 +19,8 @@
|
||||
|
||||
namespace osg {
|
||||
|
||||
typedef std::vector< ref_ptr<Node> > NodeList;
|
||||
|
||||
/** General group node which maintains a list of children.
|
||||
Children are reference counted. This allows children to be shared
|
||||
with memory management handled automatically via osg::Referenced.
|
||||
@ -27,7 +29,6 @@ class SG_EXPORT Group : public Node
|
||||
{
|
||||
public :
|
||||
|
||||
typedef std::vector<ref_ptr<Node> > ChildList;
|
||||
|
||||
Group();
|
||||
|
||||
@ -89,7 +90,7 @@ class SG_EXPORT Group : public Node
|
||||
inline bool containsNode( const Node* node ) const
|
||||
{
|
||||
|
||||
for (ChildList::const_iterator itr=_children.begin();
|
||||
for (NodeList::const_iterator itr=_children.begin();
|
||||
itr!=_children.end();
|
||||
++itr)
|
||||
{
|
||||
@ -116,7 +117,7 @@ class SG_EXPORT Group : public Node
|
||||
|
||||
virtual bool computeBound() const;
|
||||
|
||||
ChildList _children;
|
||||
NodeList _children;
|
||||
|
||||
|
||||
};
|
||||
|
@ -74,7 +74,10 @@ class SG_EXPORT PagedLOD : public LOD
|
||||
/** return the list of time stamps.*/
|
||||
inline const TimeStampList& getTimeStampList() const { return _timeStampList; }
|
||||
|
||||
void removeExpiredChildren(double expiryTime);
|
||||
/** Remove the children from the PagedLOD which haven't be visited since specified expiry time.
|
||||
The removed children are added the removeChildren list passed into the method,
|
||||
this allows the children to be deleted later at the callers discression.*/
|
||||
void removeExpiredChildren(double expiryTime,NodeList& removedChildren);
|
||||
|
||||
protected :
|
||||
|
||||
|
@ -33,19 +33,23 @@ class OSGPRODUCER_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseReques
|
||||
|
||||
DatabasePager();
|
||||
|
||||
/** add a request to load a node file to end the the database request list.*/
|
||||
/** Add a request to load a node file to end the the database request list.*/
|
||||
virtual void requestNodeFile(const std::string& fileName,osg::Group* group);
|
||||
|
||||
/** run does the database paging.*/
|
||||
virtual void run();
|
||||
|
||||
/** add the loaded data to the scene graph.*/
|
||||
|
||||
/** Add the loaded data to the scene graph.*/
|
||||
void addLoadedDataToSceneGraph();
|
||||
|
||||
/** find all PagedLOD nodes in a subgraph and register them with
|
||||
* the DatabasePager so it can keep track of expired nodes.*/
|
||||
|
||||
/** Find all PagedLOD nodes in a subgraph and register them with
|
||||
* the DatabasePager so it can keep track of expired nodes.
|
||||
* note, should be only be called from the update thread. */
|
||||
void registerPagedLODs(osg::Node* subgraph);
|
||||
|
||||
|
||||
/** Set the amount of time that a subgraph will be kept without being visited in the cull traversal
|
||||
* before being removed.*/
|
||||
void setExpiryDelay(double expiryDelay) { _expiryDelay = expiryDelay; }
|
||||
@ -54,10 +58,27 @@ class OSGPRODUCER_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseReques
|
||||
* before being removed.*/
|
||||
double getExpiryDelay() const { return _expiryDelay; }
|
||||
|
||||
/** iterate through the active PagedLOD nodes children removing
|
||||
* children which havn't been visited since specified expiryTime.*/
|
||||
/** set whether the removed subgraphs should be deleted in the database thread or not.*/
|
||||
void setDeleteRemovedSubgraphsInDatabaseThread(bool flag) { _deleteRemovedSubgraphsInDatabaseThread = flag; }
|
||||
|
||||
/** get whether the removed subgraphs should be deleted in the database thread or not.*/
|
||||
bool getDeleteRemovedSubgraphsInDatabaseThread() const { return _deleteRemovedSubgraphsInDatabaseThread; }
|
||||
|
||||
/** Iterate through the active PagedLOD nodes children removing
|
||||
* children which havn't been visited since specified expiryTime.
|
||||
* note, should be only be called from the update thread. */
|
||||
void removeExpiredSubgraphs(double currentFrameTime);
|
||||
|
||||
|
||||
/* Set the maximum amount of time available for compile rendering objects. */
|
||||
void setMaximumTimeForCompilingRenderingObjects(double time) { _maximumTimeForCompiling = time; }
|
||||
|
||||
/* Get the maximum amount of time available for compile rendering objects. */
|
||||
double getMaximumTimeForCompilingRenderingObjects() const { return _maximumTimeForCompiling; }
|
||||
|
||||
/** Compile the rendering objects (display lists,texture objects, VBO's) on loaded subgraph.
|
||||
* note, should only be called from the draw thread.*/
|
||||
void compileRenderingObjects(osg::State& state);
|
||||
|
||||
public:
|
||||
|
||||
@ -66,6 +87,9 @@ class OSGPRODUCER_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseReques
|
||||
protected :
|
||||
|
||||
virtual ~DatabasePager() {}
|
||||
|
||||
typedef std::vector< osg::ref_ptr<osg::StateSet> > StateSetList;
|
||||
typedef std::vector< osg::ref_ptr<osg::Drawable> > DrawableList;
|
||||
|
||||
struct DatabaseRequest : public osg::Referenced
|
||||
{
|
||||
@ -84,13 +108,23 @@ class OSGPRODUCER_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseReques
|
||||
DatabaseRequestList _fileRequestList;
|
||||
Producer::Mutex _fileRequestListMutex;
|
||||
|
||||
DatabaseRequestList _fileLoadedList;
|
||||
Producer::Mutex _fileLoadedListMutex;
|
||||
DatabaseRequestList _dataLoadedList;
|
||||
Producer::Mutex _dataLoadedListMutex;
|
||||
|
||||
bool _deleteRemovedSubgraphsInDatabaseThread;
|
||||
osg::NodeList _childrenToDeleteList;
|
||||
Producer::Mutex _childrenToDeleteListMutex;
|
||||
|
||||
DatabaseRequestList _dataToMergeList;
|
||||
Producer::Mutex _dataToMergeMutex;
|
||||
|
||||
|
||||
PagedLODList _pagedLODList;
|
||||
|
||||
double _expiryDelay;
|
||||
|
||||
double _maximumTimeForCompiling;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ class OSGPRODUCER_EXPORT OsgSceneHandler : public Producer::Camera::SceneHandler
|
||||
{
|
||||
public:
|
||||
virtual ~Callback() {}
|
||||
virtual void operator()(OsgSceneHandler&, const Producer::Camera &) = 0;
|
||||
virtual void operator()(OsgSceneHandler&, Producer::Camera &) = 0;
|
||||
};
|
||||
|
||||
virtual void clear(Producer::Camera& camera)
|
||||
|
@ -31,7 +31,7 @@ Group::Group()
|
||||
Group::Group(const Group& group,const CopyOp& copyop):
|
||||
Node(group,copyop)
|
||||
{
|
||||
for(ChildList::const_iterator itr=group._children.begin();
|
||||
for(NodeList::const_iterator itr=group._children.begin();
|
||||
itr!=group._children.end();
|
||||
++itr)
|
||||
{
|
||||
@ -43,7 +43,7 @@ Group::Group(const Group& group,const CopyOp& copyop):
|
||||
Group::~Group()
|
||||
{
|
||||
// remove reference to this from children's parent lists.
|
||||
for(ChildList::iterator itr=_children.begin();
|
||||
for(NodeList::iterator itr=_children.begin();
|
||||
itr!=_children.end();
|
||||
++itr)
|
||||
{
|
||||
@ -55,7 +55,7 @@ Group::~Group()
|
||||
|
||||
void Group::traverse(NodeVisitor& nv)
|
||||
{
|
||||
for(ChildList::iterator itr=_children.begin();
|
||||
for(NodeList::iterator itr=_children.begin();
|
||||
itr!=_children.end();
|
||||
++itr)
|
||||
{
|
||||
@ -298,7 +298,7 @@ bool Group::computeBound() const
|
||||
|
||||
BoundingBox bb;
|
||||
bb.init();
|
||||
ChildList::const_iterator itr;
|
||||
NodeList::const_iterator itr;
|
||||
for(itr=_children.begin();
|
||||
itr!=_children.end();
|
||||
++itr)
|
||||
|
@ -129,7 +129,7 @@ void PagedLOD::setTimeStamp(unsigned int childNo, double timeStamp)
|
||||
_timeStampList[childNo] = timeStamp;
|
||||
}
|
||||
|
||||
void PagedLOD::removeExpiredChildren(double expiryTime)
|
||||
void PagedLOD::removeExpiredChildren(double expiryTime,NodeList& removedChildren)
|
||||
{
|
||||
for(unsigned int i=_children.size();i>0;)
|
||||
{
|
||||
@ -137,6 +137,7 @@ void PagedLOD::removeExpiredChildren(double expiryTime)
|
||||
if (!_fileNameList[i].empty() && _timeStampList[i]<expiryTime)
|
||||
{
|
||||
//std::cout<<"Removing child "<<_children[i].get()<<std::endl;
|
||||
removedChildren.push_back(_children[i]);
|
||||
Group::removeChild(_children[i].get());
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,13 @@ using namespace osgProducer;
|
||||
|
||||
DatabasePager::DatabasePager()
|
||||
{
|
||||
std::cout<<"Constructing DatabasePager()"<<std::endl;
|
||||
//std::cout<<"Constructing DatabasePager()"<<std::endl;
|
||||
|
||||
_deleteRemovedSubgraphsInDatabaseThread = true;
|
||||
|
||||
_expiryDelay = 1.0;
|
||||
|
||||
_maximumTimeForCompiling = 0.005; // 5ms.
|
||||
}
|
||||
|
||||
void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* group)
|
||||
@ -19,10 +24,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;
|
||||
|
||||
_fileLoadedListMutex.lock();
|
||||
_dataLoadedListMutex.lock();
|
||||
|
||||
for(DatabaseRequestList::iterator litr = _fileLoadedList.begin();
|
||||
litr != _fileLoadedList.end() && !foundEntry;
|
||||
for(DatabaseRequestList::iterator litr = _dataLoadedList.begin();
|
||||
litr != _dataLoadedList.end() && !foundEntry;
|
||||
++litr)
|
||||
{
|
||||
if ((*litr)->_fileName==fileName)
|
||||
@ -32,7 +37,7 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou
|
||||
}
|
||||
}
|
||||
|
||||
_fileLoadedListMutex.unlock();
|
||||
_dataLoadedListMutex.unlock();
|
||||
|
||||
if (!foundEntry)
|
||||
{
|
||||
@ -78,6 +83,23 @@ void DatabasePager::run()
|
||||
|
||||
while(true)
|
||||
{
|
||||
//
|
||||
// delete any children if required.
|
||||
//
|
||||
if (_deleteRemovedSubgraphsInDatabaseThread)
|
||||
{
|
||||
_childrenToDeleteListMutex.lock();
|
||||
if (!_childrenToDeleteList.empty())
|
||||
{
|
||||
std::cout<<"In DatabasePager thread deleting "<<_childrenToDeleteList.size()<<" subgraphs"<<std::endl;
|
||||
_childrenToDeleteList.clear();
|
||||
}
|
||||
_childrenToDeleteListMutex.unlock();
|
||||
}
|
||||
|
||||
//
|
||||
// load any subgraphs that are required.
|
||||
//
|
||||
osg::ref_ptr<DatabaseRequest> databaseRequest;
|
||||
|
||||
// get the front of the file request list.
|
||||
@ -97,11 +119,11 @@ void DatabasePager::run()
|
||||
|
||||
if (databaseRequest->_loadedModel.valid())
|
||||
{
|
||||
_fileLoadedListMutex.lock();
|
||||
_dataLoadedListMutex.lock();
|
||||
|
||||
_fileLoadedList.push_back(databaseRequest);
|
||||
_dataLoadedList.push_back(databaseRequest);
|
||||
|
||||
_fileLoadedListMutex.unlock();
|
||||
_dataLoadedListMutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,10 +143,10 @@ void DatabasePager::addLoadedDataToSceneGraph()
|
||||
{
|
||||
DatabaseRequestList localFileLoadedList;
|
||||
|
||||
// get the dat for the _fileLoadedList, leaving it empty via a std::vector<>.swap.
|
||||
_fileLoadedListMutex.lock();
|
||||
localFileLoadedList.swap(_fileLoadedList);
|
||||
_fileLoadedListMutex.unlock();
|
||||
// get the dat for the _dataLoadedList, leaving it empty via a std::vector<>.swap.
|
||||
_dataLoadedListMutex.lock();
|
||||
localFileLoadedList.swap(_dataLoadedList);
|
||||
_dataLoadedListMutex.unlock();
|
||||
|
||||
// add the loaded data into the scene graph.
|
||||
for(DatabaseRequestList::iterator itr=localFileLoadedList.begin();
|
||||
@ -144,13 +166,15 @@ void DatabasePager::removeExpiredSubgraphs(double currentFrameTime)
|
||||
{
|
||||
double expiryTime = currentFrameTime - _expiryDelay;
|
||||
|
||||
osg::NodeList childrenRemoved;
|
||||
|
||||
//std::cout<<"DatabasePager::removeExpiredSubgraphs("<<expiryTime<<") "<<std::endl;
|
||||
for(PagedLODList::iterator itr=_pagedLODList.begin();
|
||||
itr!=_pagedLODList.end();
|
||||
++itr)
|
||||
{
|
||||
osg::PagedLOD* plod = itr->get();
|
||||
plod->removeExpiredChildren(expiryTime);
|
||||
plod->removeExpiredChildren(expiryTime,childrenRemoved);
|
||||
}
|
||||
|
||||
for(unsigned int i=_pagedLODList.size();
|
||||
@ -171,7 +195,14 @@ void DatabasePager::removeExpiredSubgraphs(double currentFrameTime)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (_deleteRemovedSubgraphsInDatabaseThread)
|
||||
{
|
||||
// transfer the removed children over to the to delete list so the database thread can delete them.
|
||||
_childrenToDeleteListMutex.lock();
|
||||
_childrenToDeleteList.insert(_childrenToDeleteList.begin(),childrenRemoved.begin(),childrenRemoved.end());
|
||||
_childrenToDeleteListMutex.unlock();
|
||||
}
|
||||
// otherwise the childrenRemoved list will automatically unref() and deleting the nodes.
|
||||
}
|
||||
|
||||
|
||||
@ -200,3 +231,8 @@ void DatabasePager::registerPagedLODs(osg::Node* subgraph)
|
||||
if (subgraph) subgraph->accept(fplv);
|
||||
}
|
||||
|
||||
void DatabasePager::compileRenderingObjects(osg::State& state)
|
||||
{
|
||||
// std::cout<<"Compiling rendering objects"<<std::endl;
|
||||
}
|
||||
|
||||
|
@ -413,24 +413,6 @@ bool OsgCameraGroup::realize()
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (sfsn._foundPagedLOD)
|
||||
{
|
||||
std::cout << "setting up paged LOD"<<std::endl;
|
||||
|
||||
_databasePager = new DatabasePager;
|
||||
|
||||
_databasePager->registerPagedLODs(getTopMostSceneData());
|
||||
|
||||
for(SceneHandlerList::iterator p=_shvec.begin();
|
||||
p!=_shvec.end();
|
||||
++p)
|
||||
{
|
||||
(*p)->getSceneView()->getCullVisitor()->setDatabaseRequestHandler(_databasePager.get());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -296,11 +296,44 @@ bool Viewer::realize( ThreadingModel thread_model )
|
||||
return realize();
|
||||
}
|
||||
|
||||
class DatabasePagerCompileCallback : public OsgSceneHandler::Callback
|
||||
{
|
||||
public:
|
||||
|
||||
DatabasePagerCompileCallback(DatabasePager* databasePager):
|
||||
_databasePager(databasePager)
|
||||
{}
|
||||
|
||||
virtual void operator()(OsgSceneHandler& sh, Producer::Camera& camera)
|
||||
{
|
||||
_databasePager->compileRenderingObjects(*(sh.getSceneView()->getState()));
|
||||
|
||||
sh.drawImplementation(camera);
|
||||
}
|
||||
|
||||
osg::ref_ptr<DatabasePager> _databasePager;
|
||||
};
|
||||
|
||||
bool Viewer::realize()
|
||||
{
|
||||
if (_realized) return _realized;
|
||||
|
||||
OsgCameraGroup::realize();
|
||||
|
||||
|
||||
// by default set up the DatabasePager.
|
||||
{
|
||||
_databasePager = new DatabasePager;
|
||||
_databasePager->registerPagedLODs(getTopMostSceneData());
|
||||
|
||||
for(SceneHandlerList::iterator p=_shvec.begin();
|
||||
p!=_shvec.end();
|
||||
++p)
|
||||
{
|
||||
(*p)->getSceneView()->getCullVisitor()->setDatabaseRequestHandler(_databasePager.get());
|
||||
(*p)->setDrawCallback(new DatabasePagerCompileCallback(_databasePager.get()));
|
||||
}
|
||||
}
|
||||
|
||||
// force a sync before we intialize the keyswitch manipulator to home
|
||||
// so that Producer has a chance to set up the windows before we do
|
||||
|
Loading…
Reference in New Issue
Block a user