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:
Robert Osfield
2003-07-10 11:10:39 +00:00
parent 12c7526f87
commit c5c7a1b2ba
3 changed files with 214 additions and 24 deletions

View File

@@ -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;
};

View File

@@ -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());
}
}

View File

@@ -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);
}
}