Updates to the DatabasePager code to include support for compiling texture
objects and display lists before merging loaded subgraphs with the main scene graph.
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#include <osgProducer/Export>
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
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<osg::PagedLOD> > PagedLODList;
|
||||
@@ -99,6 +106,8 @@ class OSGPRODUCER_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseReques
|
||||
typedef std::pair<StateSetList,DrawableList> DataToCompile;
|
||||
typedef std::map< unsigned int, DataToCompile > DataToCompileMap;
|
||||
|
||||
typedef std::set<unsigned int> 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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <osgProducer/DatabasePager>
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Timer>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
@@ -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"<<std::endl;
|
||||
_dataToCompile.first.push_back(stateset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,6 +139,7 @@ public:
|
||||
|
||||
if (drawable->getUseDisplayList() || drawable->getUseVertexBufferObjects())
|
||||
{
|
||||
//std::cout<<"Found compilable drawable"<<std::endl;
|
||||
_dataToCompile.second.push_back(drawable);
|
||||
}
|
||||
}
|
||||
@@ -166,18 +184,61 @@ void DatabasePager::run()
|
||||
// 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())
|
||||
{
|
||||
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"<<std::endl;
|
||||
if (on)
|
||||
{
|
||||
_activeGraphicsContexts.insert(contextID);
|
||||
}
|
||||
else
|
||||
{
|
||||
_activeGraphicsContexts.erase(contextID);
|
||||
}
|
||||
}
|
||||
|
||||
bool DatabasePager::getCompileRenderingObjectsForContexID(unsigned int contextID)
|
||||
{
|
||||
return _activeGraphicsContexts.count(contextID)!=0;
|
||||
}
|
||||
|
||||
|
||||
void DatabasePager::compileRenderingObjects(osg::State& state)
|
||||
{
|
||||
|
||||
osg::Timer timer;
|
||||
osg::Timer_t start_tick = timer.tick();
|
||||
double elapsedTime = 0.0;
|
||||
|
||||
osg::ref_ptr<DatabaseRequest> 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"<<std::endl;
|
||||
StateSetList::iterator itr=sslist.begin();
|
||||
for(;
|
||||
itr!=sslist.end() && elapsedTime<_maximumTimeForCompiling;
|
||||
++itr)
|
||||
{
|
||||
//std::cout<<" Compiling stateset"<<(*itr).get()<<std::endl;
|
||||
(*itr)->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"<<std::endl;
|
||||
DrawableList& dwlist = dtc.second;
|
||||
DrawableList::iterator itr=dwlist.begin();
|
||||
for(;
|
||||
itr!=dwlist.end() && elapsedTime<_maximumTimeForCompiling;
|
||||
++itr)
|
||||
{
|
||||
//std::cout<<" Compiling drawable"<<(*itr).get()<<std::endl;
|
||||
(*itr)->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"<<std::endl;
|
||||
|
||||
// now check the to compile entries for all active graphics contexts
|
||||
// to make sure that all have been compiled.
|
||||
bool allCompiled = true;
|
||||
for(DataToCompileMap::iterator itr=dcm.begin();
|
||||
itr!=dcm.end() && allCompiled;
|
||||
++itr)
|
||||
{
|
||||
if (!(itr->second.first.empty())) allCompiled=false;
|
||||
if (!(itr->second.second.empty())) allCompiled=false;
|
||||
}
|
||||
|
||||
|
||||
if (allCompiled)
|
||||
{
|
||||
//std::cout<<"All compiled"<<std::endl;
|
||||
|
||||
// we've compile all of the current databaseRequest so we can now pop it off the
|
||||
// to compile list and place it on the merge list.
|
||||
_dataToCompileListMutex.lock();
|
||||
|
||||
_dataToMergeListMutex.lock();
|
||||
_dataToMergeList.push_back(databaseRequest);
|
||||
_dataToMergeListMutex.unlock();
|
||||
|
||||
_dataToCompileList.erase(_dataToCompileList.begin());
|
||||
|
||||
if (!_dataToCompileList.empty()) databaseRequest = _dataToCompileList.front();
|
||||
else databaseRequest = 0;
|
||||
|
||||
_dataToCompileListMutex.unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
//std::cout<<"Not all compiled"<<std::endl;
|
||||
databaseRequest = 0;
|
||||
}
|
||||
|
||||
elapsedTime = timer.delta_s(start_tick,timer.tick());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -306,9 +306,10 @@ public:
|
||||
|
||||
virtual void operator()(OsgSceneHandler& sh, Producer::Camera& camera)
|
||||
{
|
||||
_databasePager->compileRenderingObjects(*(sh.getSceneView()->getState()));
|
||||
|
||||
sh.drawImplementation(camera);
|
||||
|
||||
_databasePager->compileRenderingObjects(*(sh.getSceneView()->getState()));
|
||||
}
|
||||
|
||||
osg::ref_ptr<DatabasePager> _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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user