Introduction of IncrementalCompileOperation support to DatabasePager.

This commit is contained in:
Robert Osfield
2010-10-14 18:16:03 +00:00
parent 00fe3c0417
commit 6ed74470b2
9 changed files with 141 additions and 35 deletions

View File

@@ -28,10 +28,13 @@
#include <OpenThreads/ScopedLock>
#include <OpenThreads/Condition>
#include <osgUtil/IncrementalCompileOperation>
#include <osgDB/SharedStateManager>
#include <osgDB/ReaderWriter>
#include <osgDB/Options>
#include <map>
#include <list>
#include <algorithm>
@@ -165,6 +168,15 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
* note, should be only be called from the update thread. */
virtual void registerPagedLODs(osg::Node* subgraph, int frameNumber = 0);
/** Set the incremental compile operation.
* Used to manage the OpenGL object compilation and merging of subgraphs in a way that avoids overloading
* the rendering of frame with too many new objects in one frame. */
void setIncrementalCompileOperation(osgUtil::IncrementalCompileOperation* ico);
/** Get the incremental compile operation. */
osgUtil::IncrementalCompileOperation* getIncrementalCompileOperation() { return _incrementalCompileOperation.get(); }
/** Set whether the database pager should pre compile OpenGL objects before allowing
* them to be merged into the scene graph.
* Pre compilation helps reduce the chances of frame drops, but also slows the
@@ -318,7 +330,7 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
/** Report how many items are in the _dataToCompileList queue */
unsigned int getDataToCompileListSize() const { return _dataToCompileList->size(); }
/** Report how many items are in the _dataToCompileList queue */
/** Report how many items are in the _dataToMergeList queue */
unsigned int getDataToMergeListSize() const { return _dataToMergeList->size(); }
/** Report whether any requests are in the pager.*/
@@ -338,7 +350,8 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
typedef std::set< osg::ref_ptr<osg::StateSet> > StateSetList;
typedef std::vector< osg::ref_ptr<osg::Drawable> > DrawableList;
typedef std::pair<StateSetList,DrawableList> DataToCompile;
//typedef std::pair<StateSetList,DrawableList> DataToCompile;
typedef osgUtil::IncrementalCompileOperation::CompileData DataToCompile;
typedef std::map< unsigned int, DataToCompile > DataToCompileMap;
typedef std::set<unsigned int> ActiveGraphicsContexts;
typedef std::vector< osg::observer_ptr<osg::GraphicsContext> > CompileGraphicsContexts;
@@ -358,6 +371,7 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
virtual bool containsPagedLOD(const osg::observer_ptr<osg::PagedLOD>& plod) const = 0;
};
protected:
virtual ~DatabasePager();
@@ -407,7 +421,8 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
return _valid && (frameNumber - _frameNumberLastRequest <= 1);
}
};
struct RequestQueue : public osg::Referenced
{
public:
@@ -470,7 +485,10 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
// forward declare inner helper classes
class FindCompileableGLObjectsVisitor;
friend class FindCompileableGLObjectsVisitor;
struct DatabasePagerCompileCompletedCallback;
friend struct DatabasePagerCompileCompletedCallback;
class FindPagedLODsVisitor;
friend class FindPagedLODsVisitor;
@@ -568,7 +586,8 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
return true;
}
void compileCompleted(DatabaseRequest* databaseRequest);
/** 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. */
@@ -620,6 +639,8 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
// CompileGraphicsContexts _compileGraphicsContexts;
bool _doPreCompile;
osg::ref_ptr<osgUtil::IncrementalCompileOperation> _incrementalCompileOperation;
double _targetFrameRate;
double _minimumTimeAvailableForGLCompileAndDeletePerFrame;
unsigned int _maximumNumOfObjectsToCompilePerFrame;

View File

@@ -62,10 +62,14 @@ namespace osgDB {
void apply(osg::Node& node);
void apply(osg::Geode& geode);
// Answers the question "Will this state set be eliminated by
// the SharedStateManager because an equivalent one has been
// seen already?" Safe to call from the pager thread.
bool isShared(osg::StateSet* stateSet);
bool isShared(osg::Texture* texture);
protected:
inline bool shareTexture(osg::Object::DataVariance variance)

View File

@@ -109,6 +109,8 @@ class OSGUTIL_EXPORT IncrementalCompileOperation : public osg::GraphicsOperation
struct CompileCompletedCallback : public osg::Referenced
{
/// return true if the callback assumes responsibility for merging any associated subgraphs with the main scene graph
/// return false if callback doesn't handle the merge, and instead requires the IncrementalCompileOperation to handle this for us
virtual bool compileCompleted(CompileSet* compileSet) = 0;
};

View File

@@ -151,6 +151,7 @@ ADD_DEFINITIONS(-DOSG_PLUGIN_EXTENSION=${CMAKE_SHARED_MODULE_SUFFIX})
LINK_INTERNAL(${LIB_NAME}
osg
osgUtil
OpenThreads
)
LINK_EXTERNAL(${LIB_NAME} ${OSGDB_PLATFORM_SPECIFIC_LIBRARIES} ${DL_LIBRARY})

View File

@@ -105,6 +105,32 @@ RefPtrAdapter<FuncObj> refPtrAdapt(const FuncObj& func)
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// CountPagedLODList
//
struct DatabasePager::DatabasePagerCompileCompletedCallback : public osgUtil::IncrementalCompileOperation::CompileCompletedCallback
{
DatabasePagerCompileCompletedCallback(osgDB::DatabasePager* pager, osgDB::DatabasePager::DatabaseRequest* databaseRequest):
_pager(pager),
_databaseRequest(databaseRequest) {}
virtual bool compileCompleted(osgUtil::IncrementalCompileOperation::CompileSet* compileSet)
{
_pager->compileCompleted(_databaseRequest.get());
return true;
}
osgDB::DatabasePager* _pager;
osg::ref_ptr<osgDB::DatabasePager::DatabaseRequest> _databaseRequest;
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// CountPagedLODList
//
class DatabasePager::CountPagedLODsVisitor : public osg::NodeVisitor
{
public:
@@ -362,7 +388,6 @@ public:
// if texture object attributes exist and need to be
// compiled, add the state to the list for later
// compilation.
bool compileStateSet = false;
for(unsigned int i=0;i<stateset->getTextureAttributeList().size();++i)
{
osg::Texture* texture = dynamic_cast<osg::Texture*>(stateset->getTextureAttribute(i,osg::StateAttribute::TEXTURE));
@@ -380,7 +405,8 @@ public:
if (!_pager->isCompiled(texture))
{
compileStateSet = true;
_dataToCompile->_textures.push_back(texture);
if (osg::getNotifyLevel() >= osg::DEBUG_INFO)
{
OSG_INFO <<"Found compilable texture " << texture << " ";
@@ -392,10 +418,6 @@ public:
}
}
}
if (compileStateSet && _dataToCompile)
{
_dataToCompile->first.insert(stateset);
}
}
}
@@ -437,7 +459,7 @@ public:
// anything for VBOs, does it?
if (_dataToCompile && (drawable->getUseVertexBufferObjects() || drawable->getUseDisplayList()) && !_pager->isCompiled(drawable))
{
_dataToCompile->second.push_back(drawable);
_dataToCompile->_drawables.push_back(drawable);
}
}
@@ -991,13 +1013,21 @@ void DatabasePager::DatabaseThread::run()
databaseRequest->_loadedModel->accept(frov);
if (_pager->_doPreCompile &&
!_pager->_activeGraphicsContexts.empty())
if (_pager->_doPreCompile && !dtc->empty())
{
if (!dtc->first.empty() || !dtc->second.empty())
if (_pager->_incrementalCompileOperation.valid())
{
loadedObjectsNeedToBeCompiled = true;
OSG_NOTICE<<"Using IncrementalCompileOperation"<<std::endl;
osgUtil::IncrementalCompileOperation::CompileSet* compileSet = new osgUtil::IncrementalCompileOperation::CompileSet(databaseRequest->_loadedModel.get());
compileSet->_compileCompletedCallback = new DatabasePagerCompileCompletedCallback(_pager, databaseRequest);
_pager->_incrementalCompileOperation->add(compileSet);
loadedObjectsNeedToBeCompiled = true;
}
else if (!_pager->_activeGraphicsContexts.empty())
{
// copy the objects from the compile list to the other graphics context list.
for(;
itr != _pager->_activeGraphicsContexts.end();
@@ -1012,7 +1042,10 @@ void DatabasePager::DatabaseThread::run()
// dataToCompile or dataToMerge lists.
if (loadedObjectsNeedToBeCompiled)
{
_pager->_dataToCompileList->add(databaseRequest.get());
if (!_pager->_incrementalCompileOperation)
{
_pager->_dataToCompileList->add(databaseRequest.get());
}
}
else
{
@@ -1314,6 +1347,11 @@ DatabasePager::DatabasePager(const DatabasePager& rhs)
}
void DatabasePager::setIncrementalCompileOperation(osgUtil::IncrementalCompileOperation* ico)
{
_incrementalCompileOperation = ico;
}
DatabasePager::~DatabasePager()
{
cancel();
@@ -2052,6 +2090,12 @@ bool DatabasePager::requiresExternalCompileGLObjects(unsigned int contextID) con
return osg::GraphicsContext::getCompileContext(contextID)==0;
}
void DatabasePager::compileCompleted(DatabaseRequest* databaseRequest)
{
OSG_NOTICE<<"DatabasePager::compileCompleted("<<databaseRequest<<")"<<std::endl;
_dataToMergeList->add(databaseRequest);
}
void DatabasePager::compileAllGLObjects(osg::State& state, bool doFlush)
{
double availableTime = DBL_MAX;
@@ -2089,23 +2133,25 @@ void DatabasePager::compileGLObjects(osg::State& state, double& availableTime, b
{
DataToCompileMap& dcm = databaseRequest->_dataToCompileMap;
DataToCompile& dtc = dcm[state.getContextID()];
if (!dtc.first.empty() && (elapsedTime+estimatedTextureDuration)<availableTime && numObjectsCompiled<_maximumNumOfObjectsToCompilePerFrame)
if (!dtc._textures.empty() && (elapsedTime+estimatedTextureDuration)<availableTime && numObjectsCompiled<_maximumNumOfObjectsToCompilePerFrame)
{
#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, 1.0);
#endif
// we have StateSet's to compile
StateSetList& sslist = dtc.first;
//OSG_INFO<<"Compiling statesets"<<std::endl;
StateSetList::iterator itr=sslist.begin();
//OSG_INFO<<"Compiling textures"<<std::endl;
// we have Textures to compile
typedef osgUtil::IncrementalCompileOperation::CompileData::Textures Textures;
Textures& textures = dtc._textures;
Textures::iterator itr=textures.begin();
unsigned int objTemp = numObjectsCompiled;
for(;
itr!=sslist.end() && (compileAll || ((elapsedTime+estimatedTextureDuration)<availableTime && numObjectsCompiled<_maximumNumOfObjectsToCompilePerFrame));
itr!=textures.end() && (compileAll || ((elapsedTime+estimatedTextureDuration)<availableTime && numObjectsCompiled<_maximumNumOfObjectsToCompilePerFrame));
++itr)
{
//OSG_INFO<<" Compiling stateset "<<(*itr).get()<<std::endl;
OSG_INFO<<" Compiling texture "<<(*itr).get()<<std::endl;
if (isCompiled(itr->get(), state.getContextID())
|| (sharedManager && sharedManager->isShared(itr->get())))
{
@@ -2114,7 +2160,7 @@ void DatabasePager::compileGLObjects(osg::State& state, double& availableTime, b
}
double startCompileTime = timer.delta_s(start_tick,timer.tick());
(*itr)->compileGLObjects(state);
(*itr)->apply(state);
#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE)
GLint p;
@@ -2130,19 +2176,20 @@ void DatabasePager::compileGLObjects(osg::State& state, double& availableTime, b
}
if (osg::getNotifyLevel() >= osg::DEBUG_INFO
&& numObjectsCompiled > objTemp)
OSG_INFO<< _frameNumber << " compiled "
OSG_NOTICE<< _frameNumber << " compiled "
<< numObjectsCompiled - objTemp
<< " StateSets" << std::endl;
// remove the compiled statesets from the list.
sslist.erase(sslist.begin(),itr);
textures.erase(textures.begin(),itr);
}
if (!dtc.second.empty() && (compileAll || ((elapsedTime+estimatedDrawableDuration)<availableTime && numObjectsCompiled<_maximumNumOfObjectsToCompilePerFrame)))
if (!dtc._drawables.empty() && (compileAll || ((elapsedTime+estimatedDrawableDuration)<availableTime && numObjectsCompiled<_maximumNumOfObjectsToCompilePerFrame)))
{
// we have Drawable's to compile
//OSG_INFO<<"Compiling drawables"<<std::endl;
DrawableList& dwlist = dtc.second;
DrawableList::iterator itr=dwlist.begin();
typedef osgUtil::IncrementalCompileOperation::CompileData::Drawables Drawables;
Drawables& dwlist = dtc._drawables;
Drawables::iterator itr = dwlist.begin();
unsigned int objTemp = numObjectsCompiled;
for(;
itr!=dwlist.end() && (compileAll || ((elapsedTime+estimatedDrawableDuration)<availableTime && numObjectsCompiled<_maximumNumOfObjectsToCompilePerFrame));
@@ -2186,12 +2233,11 @@ void DatabasePager::compileGLObjects(osg::State& state, double& availableTime, b
itr!=dcm.end() && allCompiled;
++itr)
{
if (!(itr->second.first.empty())) allCompiled=false;
if (!(itr->second.second.empty())) allCompiled=false;
if (!(itr->second.empty())) allCompiled=false;
}
//if (numObjectsCompiled > 0)
//OSG_NOTICE<< _frameNumber << "compiled " << numObjectsCompiled << " objects" << std::endl;
if (numObjectsCompiled > 0)
OSG_NOTICE<< "Framenumber "<<_frameNumber << ": compiled " << numObjectsCompiled << " objects" << std::endl;
if (allCompiled)
{

View File

@@ -108,7 +108,7 @@ void SharedStateManager::apply(osg::Geode& geode)
}
}
bool SharedStateManager::isShared(osg::StateSet *ss)
bool SharedStateManager::isShared(osg::StateSet* ss)
{
if (shareStateSet(ss->getDataVariance()))
{
@@ -119,6 +119,17 @@ bool SharedStateManager::isShared(osg::StateSet *ss)
return false;
}
bool SharedStateManager::isShared(osg::Texture* texture)
{
if (shareTexture(texture->getDataVariance()))
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_listMutex);
return find(texture) != 0;
}
else
return false;
}
//----------------------------------------------------------------
// SharedStateManager::find
//----------------------------------------------------------------

View File

@@ -1601,6 +1601,11 @@ void View::assignSceneDataToCameras()
{
// OSG_NOTICE<<"View::assignSceneDataToCameras()"<<std::endl;
if (_scene.valid() && _scene->getDatabasePager() && getViewerBase())
{
_scene->getDatabasePager()->setIncrementalCompileOperation(getViewerBase()->getIncrementalCompileOperation());
}
osg::Node* sceneData = _scene.valid() ? _scene->getSceneData() : 0;
if (_cameraManipulator.valid())

View File

@@ -66,6 +66,11 @@ Viewer::Viewer(osg::ArgumentParser& arguments)
//arguments.getApplicationUsage()->addCommandLineOption("--collar","");
//arguments.getApplicationUsage()->addCommandLineOption("--im","");
if (arguments.read("--ico"))
{
setIncrementalCompileOperation(new osgUtil::IncrementalCompileOperation());
}
std::string filename;
bool readConfig = false;
while (arguments.read("-c",filename))

View File

@@ -563,6 +563,17 @@ void ViewerBase::setIncrementalCompileOperation(osgUtil::IncrementalCompileOpera
// assign new operation
_incrementalCompileOperation = ico;
Scenes scenes;
getScenes(scenes,false);
for(Scenes::iterator itr = scenes.begin();
itr != scenes.end();
++itr)
{
osgDB::DatabasePager* dp = (*itr)->getDatabasePager();
dp->setIncrementalCompileOperation(ico);
}
if (_incrementalCompileOperation) _incrementalCompileOperation->assignContexts(contexts);
}