Refactor of DatabasePage/IncrementalCompileOperation to use the IncrementalCompileOperator for compiling objects

This commit is contained in:
Robert Osfield 2010-12-10 15:27:19 +00:00
parent c040b25699
commit 017a03ffe5
9 changed files with 240 additions and 745 deletions

View File

@ -110,8 +110,6 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
void setActive(bool active) { _active = active; }
bool getActive() const { return _active; }
double getTimeSinceStartOfIteration() const;
virtual int cancel();
virtual void run();
@ -120,12 +118,11 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
virtual ~DatabaseThread();
bool _done;
bool _active;
DatabasePager* _pager;
Mode _mode;
std::string _name;
osg::Timer_t _tickSinceStartOfIteration;
volatile bool _done;
volatile bool _active;
DatabasePager* _pager;
Mode _mode;
std::string _name;
};
@ -188,42 +185,6 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
bool getDoPreCompile() const { return _doPreCompile; }
/** Set the target frame rate that the DatabasePager should assume.
* Typically one would set this to the value refresh rate of your display system i.e. 60Hz.
* Default value is 100.
* Usage notes. The TargetFrameRate and the MinimumTimeAvailableForGLCompileAndDeletePerFrame
* parameters are not directly used by DatabasePager, but are should be used as a guide for how
* long to set aside per frame for compiling and deleting OpenGL objects - ie. the value to use
* when calling DatabasePager::compileGLObjectgs(state,availableTime,). The longer amount of
* time to set aside cthe faster databases will be paged in but with increased chance of frame drops,
* the lower the amount of time the set aside the slower databases will paged it but with better
* chance of avoid any frame drops. The default values are chosen to achieve the later when running
* on a modern mid to high end PC.
* The way to compute the amount of available time use a scheme such as :
* availableTime = maximum(1.0/targetFrameRate - timeTakenDuringUpdateCullAndDraw, minimumTimeAvailableForGLCompileAndDeletePerFrame).
*/
void setTargetFrameRate(double tfr) { _targetFrameRate = tfr; }
/** Get the target frame rate that the DatabasePager should assume.*/
double getTargetFrameRate() const { return _targetFrameRate; }
/** Set the minimum amount of time (in seconds) that should be made available for compiling and delete OpenGL objects per frame.
* Default value is 0.001 (1 millisecond).
* For usage see notes in setTargetFrameRate.*/
void setMinimumTimeAvailableForGLCompileAndDeletePerFrame(double ta) { _minimumTimeAvailableForGLCompileAndDeletePerFrame = ta; }
/** Get the minimum amount of time that should be made available for compiling and delete OpenGL objects per frame.
* For usage see notes in setTargetFrameRate.*/
double getMinimumTimeAvailableForGLCompileAndDeletePerFrame() const { return _minimumTimeAvailableForGLCompileAndDeletePerFrame; }
/** Set the maximum number of OpenGL objects that the page should attempt to compile per frame.
* Note, Lower values reduces chances of a frame drop but lower the rate that database will be paged in at.
* Default value is 8. */
void setMaximumNumOfObjectsToCompilePerFrame(unsigned int num) { _maximumNumOfObjectsToCompilePerFrame = num; }
/** Get the maximum number of OpenGL objects that the page should attempt to compile per frame.*/
unsigned int getMaximumNumOfObjectsToCompilePerFrame() const { return _maximumNumOfObjectsToCompilePerFrame; }
/** Set the target maximum number of PagedLOD to maintain in memory.
* Note, if more than the target number are required for rendering of a frame then these active PagedLOD are excempt from being expiried.
@ -275,29 +236,6 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
/** Merge the changes to the scene graph by calling calling removeExpiredSubgraphs then addLoadedDataToSceneGraph.
* Note, must only be called from single thread update phase. */
virtual void updateSceneGraph(const osg::FrameStamp& frameStamp);
/** Turn the compilation of rendering objects for specified graphics context on (true) or off(false). */
void setCompileGLObjectsForContextID(unsigned int contextID, bool on);
/** Get whether the compilation of rendering objects for specified graphics context on (true) or off(false). */
bool getCompileGLObjectsForContextID(unsigned int contextID);
/** Return true if an external draw thread should call compileGLObjects(..) or not.*/
bool requiresExternalCompileGLObjects(unsigned int contextID) const;
/** Return true if there are pending compile operations that are required.
* If requiresCompileGLObjects() return true the application should call compileGLObjects() .*/
bool requiresCompileGLObjects() const;
/** Compile the rendering objects (display lists,texture objects, VBO's) on loaded subgraph.
* note, should only be called from the draw thread.
* Note, must only be called from a valid graphics context. */
virtual void compileGLObjects(osg::State& state,double& availableTime, bool doFlush = false);
/** Compile the rendering objects (display lists,texture objects, VBO's) on loaded subgraph.
* note, should only be called from the draw thread.
* Note, must only be called from a valid graphics context. */
virtual void compileAllGLObjects(osg::State& state, bool doFlush = false);
/** Report how many items are in the _fileRequestList queue */
unsigned int getFileRequestListSize() const { return _fileRequestQueue->size() + _httpRequestQueue->size(); }
@ -325,10 +263,6 @@ 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 osgUtil::CompileData DataToCompile;
typedef std::map< unsigned int, DataToCompile > DataToCompileMap;
typedef std::set<unsigned int> ActiveGraphicsContexts;
typedef std::vector< osg::observer_ptr<osg::GraphicsContext> > CompileGraphicsContexts;
class CountPagedLODsVisitor;
@ -374,21 +308,22 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
bool valid() const { return _valid; }
bool _valid;
std::string _fileName;
int _frameNumberFirstRequest;
double _timestampFirstRequest;
float _priorityFirstRequest;
int _frameNumberLastRequest;
double _timestampLastRequest;
float _priorityLastRequest;
unsigned int _numOfRequests;
osg::ObserverNodePath _observerNodePath;
osg::Group* _groupForAddingLoadedSubgraph;
osg::ref_ptr<osg::Node> _loadedModel;
DataToCompileMap _dataToCompileMap;
osg::ref_ptr<Options> _loadOptions;
RequestQueue* _requestQueue;
bool _valid;
std::string _fileName;
int _frameNumberFirstRequest;
double _timestampFirstRequest;
float _priorityFirstRequest;
int _frameNumberLastRequest;
double _timestampLastRequest;
float _priorityLastRequest;
unsigned int _numOfRequests;
osg::ObserverNodePath _observerNodePath;
osg::Group* _groupForAddingLoadedSubgraph;
osg::ref_ptr<osg::Node> _loadedModel;
osg::ref_ptr<Options> _loadOptions;
RequestQueue* _requestQueue;
osg::observer_ptr<osgUtil::IncrementalCompileOperation::CompileSet> _compileSet;
bool isRequestCurrent (int frameNumber) const
{
@ -404,6 +339,8 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
RequestQueue(DatabasePager* pager);
void add(DatabaseRequest* databaseRequest);
void remove(DatabaseRequest* databaseRequest);
void addNoLock(DatabaseRequest* databaseRequest);
void takeFirst(osg::ref_ptr<DatabaseRequest>& databaseRequest);
@ -413,6 +350,8 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
virtual void updateBlock() {}
void invalidate(DatabaseRequest* dr);
bool empty() const { return size()==0; }
unsigned int size() const { return _size; }
@ -424,7 +363,7 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
void swap(RequestList& requestList);
DatabasePager* _pager;
unsigned int _size;
volatile unsigned int _size;
RequestList _requestList;
OpenThreads::Mutex _requestMutex;
int _frameNumberLastPruned;
@ -473,93 +412,6 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
OpenThreads::Mutex _run_mutex;
bool _startThreadCalled;
// Helper functions for determining if objects need to be
// compiled.
inline static bool isCompiled(const osg::Texture* texture,
unsigned int contextID)
{
return( texture->getTextureObject(contextID) != NULL );
}
// Is texture compiled for all active contexts?
inline bool isCompiled(osg::Texture* texture) const
{
for (ActiveGraphicsContexts::const_iterator iter=_activeGraphicsContexts.begin();
iter!=_activeGraphicsContexts.end(); ++iter )
{
if ( texture->getTextureObject(*iter) == NULL ) return false;
}
return true;
}
inline static bool isCompiled(const osg::StateSet* stateSet,
unsigned int contextID)
{
for (unsigned i = 0;
i < stateSet->getTextureAttributeList().size();
++i)
{
const osg::Texture* texture
= dynamic_cast<const osg::Texture*>(stateSet->getTextureAttribute(i,osg::StateAttribute::TEXTURE));
if (texture && !isCompiled(texture, contextID))
return false;
}
return true;
}
inline bool isCompiled(osg::StateSet* stateSet)
{
for (unsigned i = 0;
i < stateSet->getTextureAttributeList().size();
++i)
{
osg::Texture* texture
= dynamic_cast<osg::Texture*>(stateSet->getTextureAttribute(i,osg::StateAttribute::TEXTURE));
if (texture)
{
for (ActiveGraphicsContexts::iterator iter=_activeGraphicsContexts.begin();
iter!=_activeGraphicsContexts.end(); ++iter )
{
if ( texture->getTextureObject(*iter) == NULL ) return false;
}
}
}
return true;
}
inline static bool isCompiled(const osg::Drawable* drawable,
unsigned int contextID)
{
if (drawable->getUseVertexBufferObjects())
{
// say it's not compiled leaving it up to the compileGLObjects() to handle.
return false;
}
else if (drawable->getUseDisplayList())
{
return drawable->getDisplayList(contextID) != 0;
}
return true;
}
inline bool isCompiled(const osg::Drawable* drawable) const
{
if (drawable->getUseVertexBufferObjects())
{
// say it's not compiled leaving it up to the compileGLObjects() to handle.
return false;
}
if (drawable->getUseDisplayList())
{
for (ActiveGraphicsContexts::const_iterator iter=_activeGraphicsContexts.begin();
iter!=_activeGraphicsContexts.end(); ++iter )
{
if ( drawable->getDisplayList(*iter) == 0 ) return false;
}
}
return true;
}
void compileCompleted(DatabaseRequest* databaseRequest);
/** Iterate through the active PagedLOD nodes children removing
@ -583,9 +435,8 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
osg::ref_ptr<ReadQueue> _fileRequestQueue;
osg::ref_ptr<ReadQueue> _httpRequestQueue;
osg::ref_ptr<RequestQueue> _dataToCompileList;
osg::ref_ptr<RequestQueue> _dataToMergeList;
DrawablePolicy _drawablePolicy;
@ -596,36 +447,20 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
bool _deleteRemovedSubgraphsInDatabaseThread;
osg::ref_ptr<RequestQueue> _dataToMergeList;
osg::ref_ptr<PagedLODList> _activePagedLODList;
osg::ref_ptr<PagedLODList> _inactivePagedLODList;
unsigned int _targetMaximumNumberOfPageLOD;
ActiveGraphicsContexts _activeGraphicsContexts;
// CompileGraphicsContexts _compileGraphicsContexts;
bool _doPreCompile;
osg::ref_ptr<osgUtil::IncrementalCompileOperation> _incrementalCompileOperation;
double _targetFrameRate;
double _minimumTimeAvailableForGLCompileAndDeletePerFrame;
unsigned int _maximumNumOfObjectsToCompilePerFrame;
double _minimumTimeToMergeTile;
double _maximumTimeToMergeTile;
double _totalTimeToMergeTiles;
unsigned int _numTilesMerges;
struct CompileOperation : public osg::GraphicsOperation
{
CompileOperation(DatabasePager* databasePager);
virtual void operator () (osg::GraphicsContext* context);
osg::observer_ptr<DatabasePager> _databasePager;
};
};
}

View File

@ -25,8 +25,8 @@
#include <osgDB/Options>
#include <osgDB/DotOsgWrapper>
#include <osgDB/ObjectWrapper>
#include <osgDB/DatabasePager>
#include <osgDB/FileCache>
#include <osgDB/SharedStateManager>
#include <vector>
#include <map>
@ -308,10 +308,10 @@ class OSGDB_EXPORT Registry : public osg::Referenced
}
}
/** Set the callback to use inform the DatabasePager whether a file is located on local or remote file system.*/
/** Set the callback to use inform to the DatabasePager whether a file is located on local or remote file system.*/
void setFileLocationCallback( FileLocationCallback* cb) { _fileLocationCallback = cb; }
/** Get the callback to use inform the DatabasePager whether a file is located on local or remote file system.*/
/** Get the callback to use inform to the DatabasePager whether a file is located on local or remote file system.*/
FileLocationCallback* getFileLocationCallback() const { return _fileLocationCallback.get(); }

View File

@ -266,7 +266,7 @@ class OSGUTIL_EXPORT IncrementalCompileOperation : public osg::GraphicsOperation
return true;
}
osg::ref_ptr<osg::Group> _attachmentPoint;
osg::observer_ptr<osg::Group> _attachmentPoint;
osg::ref_ptr<osg::Node> _subgraphToCompile;
osg::ref_ptr<CompileCompletedCallback> _compileCompletedCallback;
CompileMap _compileMap;
@ -287,9 +287,12 @@ class OSGUTIL_EXPORT IncrementalCompileOperation : public osg::GraphicsOperation
/** Add a CompileSet to be compiled.*/
void add(CompileSet* compileSet, bool callBuildCompileMap=true);
/** Remove CompileSet from list.*/
void remove(CompileSet* compileSet);
OpenThreads::Mutex* getToCompiledMutex() { return &_toCompileMutex; }
CompileSets& getToCompile() { return _compiled; }
CompileSets& getToCompile() { return _toCompile; }
OpenThreads::Mutex* getCompiledMutex() { return &_compiledMutex; }
CompileSets& getCompiled() { return _compiled; }

View File

@ -478,7 +478,11 @@ class OSGUTIL_EXPORT SceneView : public osg::Object, public osg::CullSettings
virtual void flushDeletedGLObjects(double& availableTime);
/** Extract stats for current draw list. */
bool getStats(Statistics& primStats);
bool getStats(Statistics& primStats);
/** Set whether the SceneView should automatically call flishDeletedObjects() on each new frame.*/
void setAutomaticFlush(bool automaticFlush) { _automaticFlush = automaticFlush; }
bool getAutomaticFlush() const { return _automaticFlush; }
protected:
@ -536,6 +540,7 @@ class OSGUTIL_EXPORT SceneView : public osg::Object, public osg::CullSettings
bool _prioritizeTextures;
bool _automaticFlush;
bool _requiresFlush;
int _activeUniforms;

View File

@ -68,50 +68,6 @@ class OSGVIEWER_EXPORT Renderer : public osg::GraphicsOperation
virtual void release();
/** Set the target frame rate that the DatabasePager should assume.
* Typically one would set this to the value refresh rate of your display system i.e. 60Hz.
* Default value is 100.
* Usage notes. The TargetFrameRate and the MinimumTimeAvailableForGLCompileAndDeletePerFrame
* parameters are not directly used by DatabasePager, but are should be used as a guide for how
* long to set aside per frame for compiling and deleting OpenGL objects - ie. the value to use
* when calling DatabasePager::compileGLObjectgs(state,availableTime,). The longer amount of
* time to set aside cthe faster databases will be paged in but with increased chance of frame drops,
* the lower the amount of time the set aside the slower databases will paged it but with better
* chance of avoid any frame drops. The default values are chosen to achieve the later when running
* on a modern mid to high end PC.
* The way to compute the amount of available time use a scheme such as :
* availableTime = maximum(1.0/targetFrameRate - timeTakenDuringUpdateCullAndDraw, minimumTimeAvailableForGLCompileAndDeletePerFrame).
*
* Note, the actual TargetFrameRate used is the minimum of this value and that set in the DatabasePager. */
void setTargetFrameRate(double tfr) { _targetFrameRate = tfr; }
/** Get the target frame rate that the DatabasePager should assume.*/
double getTargetFrameRate() const { return _targetFrameRate; }
/** Set the minimum amount of time (in seconds) that should be made available for compiling and delete OpenGL objects per frame.
* Default value is 0.001 (1 millisecond).
* For usage see notes in setTargetFrameRate.
*
* Note, the actual TargetFrameRate used is the minimum of this value and that set in the DatabasePager. */
void setMinimumTimeAvailableForGLCompileAndDeletePerFrame(double ta) { _minimumTimeAvailableForGLCompileAndDeletePerFrame = ta; }
/** Get the minimum amount of time that should be made available for compiling and delete OpenGL objects per frame.
* For usage see notes in setTargetFrameRate.*/
double getMinimumTimeAvailableForGLCompileAndDeletePerFrame() const { return _minimumTimeAvailableForGLCompileAndDeletePerFrame; }
/** FlushTimeRatio governs how much of the spare time in each frame is used for flushing deleted OpenGL objects.
* Default value is 0.5, valid range is 0.1 to 0.9.*/
void setFlushTimeRatio(double ratio) { _flushTimeRatio = ratio; }
double getFlushTimeRatio() const { return _flushTimeRatio; }
/** ConservativeTimeRatio governs how much of the measured spare time in each frame is used for flushing deleted and compile new OpenGL objects.
* Default value is 0.5, valid range is 0.1 to 1.0.
* A ratio near 1.0 will lead to paged databases being compiled and merged quicker but increase the chances of frame drop.
* A ratio near 0.1 will lead to paged databases being compiled and merged closer but reduse the chances of frame drop.*/
void setConservativeTimeRatio(double ratio) { _conservativeTimeRatio = ratio; }
double getConservativeTimeRatio() const { return _conservativeTimeRatio; }
/** Force update of state associated with cameras. */
void setCameraRequiresSetUp(bool flag);
bool getCameraRequiresSetUp() const;
@ -121,12 +77,6 @@ class OSGVIEWER_EXPORT Renderer : public osg::GraphicsOperation
virtual ~Renderer();
virtual void updateSceneView(osgUtil::SceneView* sceneView);
virtual void flushAndCompile(double currentElapsedFrameTime, osgUtil::SceneView* sceneView, osgDB::DatabasePager* databasePager, osg::GraphicsThread* compileThread);
double _targetFrameRate;
double _minimumTimeAvailableForGLCompileAndDeletePerFrame;
double _flushTimeRatio;
double _conservativeTimeRatio;
osg::observer_ptr<osg::Camera> _camera;
@ -135,9 +85,6 @@ class OSGVIEWER_EXPORT Renderer : public osg::GraphicsOperation
bool _compileOnNextDraw;
osg::ref_ptr<osgUtil::SceneView> _sceneView[2];
osg::ref_ptr<osg::FlushDeletedGLObjectsOperation> _flushOperation;
struct OSGVIEWER_EXPORT ThreadSafeQueue
{

View File

@ -44,8 +44,6 @@ using namespace osgDB;
using namespace OpenThreads;
static osg::ApplicationUsageProxy DatabasePager_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_DO_PRE_COMPILE <ON/OFF>","Switch on or off the pre compile of OpenGL object database pager.");
static osg::ApplicationUsageProxy DatabasePager_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_MINIMUM_COMPILE_TIME_PER_FRAME <float>","minimum compile time alloted to compiling OpenGL objects per frame in database pager.");
static osg::ApplicationUsageProxy DatabasePager_e2(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_MAXIMUM_OBJECTS_TO_COMPILE_PER_FRAME <int>","maximum number of OpenGL objects to compile per frame in database pager.");
static osg::ApplicationUsageProxy DatabasePager_e3(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_DATABASE_PAGER_DRAWABLE <mode>","Set the drawable policy for setting of loaded drawable to specified type. mode can be one of DoNotModify, DisplayList, VBO or VertexArrays>.");
static osg::ApplicationUsageProxy DatabasePager_e4(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_DATABASE_PAGER_PRIORITY <mode>", "Set the thread priority to DEFAULT, MIN, LOW, NOMINAL, HIGH or MAX.");
static osg::ApplicationUsageProxy DatabasePager_e7(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_EXPIRY_DELAY <float> ","Set the length of time a PagedLOD child is kept in memory, without being used, before its tagged as expired, and ear marked to deletion.");
@ -127,6 +125,13 @@ struct DatabasePager::DatabasePagerCompileCompletedCallback : public osgUtil::In
};
void DatabasePager::compileCompleted(DatabaseRequest* databaseRequest)
{
//OSG_NOTICE<<"DatabasePager::compileCompleted("<<databaseRequest<<")"<<std::endl;
_dataToCompileList->remove(databaseRequest);
_dataToMergeList->add(databaseRequest);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// CountPagedLODList
@ -335,13 +340,11 @@ public:
class DatabasePager::FindCompileableGLObjectsVisitor : public osg::NodeVisitor
{
public:
FindCompileableGLObjectsVisitor(DatabasePager::DataToCompile* dataToCompile,
bool changeAutoUnRef, bool valueAutoUnRef,
bool changeAnisotropy, float valueAnisotropy,
DatabasePager::DrawablePolicy drawablePolicy,
const DatabasePager* pager):
FindCompileableGLObjectsVisitor(bool changeAutoUnRef, bool valueAutoUnRef,
bool changeAnisotropy, float valueAnisotropy,
DatabasePager::DrawablePolicy drawablePolicy,
const DatabasePager* pager):
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
_dataToCompile(dataToCompile),
_changeAutoUnRef(changeAutoUnRef), _valueAutoUnRef(valueAutoUnRef),
_changeAnisotropy(changeAnisotropy), _valueAnisotropy(valueAnisotropy),
_drawablePolicy(drawablePolicy), _pager(pager)
@ -355,6 +358,8 @@ public:
META_NodeVisitor("osgDB","FindCompileableGLObjectsVisitor")
bool requiresCompilation() const { return true; }
virtual void apply(osg::Node& node)
{
apply(node.getStateSet());
@ -402,20 +407,6 @@ public:
if (_changeAnisotropy)
texture->setMaxAnisotropy(_valueAnisotropy);
}
if (!_pager->isCompiled(texture))
{
_dataToCompile->_textures.insert(texture);
if (osg::getNotifyLevel() >= osg::DEBUG_INFO)
{
OSG_INFO <<"Found compilable texture " << texture << " ";
osg::Image* image = texture->getImage(0);
if (image) OSG_INFO << image->getFileName();
OSG_INFO << std:: endl;
}
break;
}
}
}
@ -452,18 +443,8 @@ public:
// OSG_NOTICE<<"USE_VERTEX_ARRAYS"<<std::endl;
break;
}
// Don't compile if already compiled. This can happen if the
// subgraph is shared with already-loaded nodes.
//
// XXX This "compiles" VBOs too, but compilation doesn't do
// anything for VBOs, does it?
if (_dataToCompile && (drawable->getUseVertexBufferObjects() || drawable->getUseDisplayList()) && !_pager->isCompiled(drawable))
{
_dataToCompile->_drawables.insert(drawable);
}
}
DatabasePager::DataToCompile* _dataToCompile;
bool _changeAutoUnRef;
bool _valueAutoUnRef;
bool _changeAnisotropy;
@ -506,8 +487,8 @@ void DatabasePager::DatabaseRequest::invalidate()
_valid = false;
_groupForAddingLoadedSubgraph = 0;
_loadedModel = 0;
_dataToCompileMap.clear();
_requestQueue = 0;
_compileSet = 0;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -528,10 +509,25 @@ DatabasePager::RequestQueue::~RequestQueue()
itr != _requestList.end();
++itr)
{
(*itr)->invalidate();
invalidate(itr->get());
}
}
void DatabasePager::RequestQueue::invalidate(DatabaseRequest* dr)
{
// OSG_NOTICE<<"DatabasePager::RequestQueue::invalidate(DatabaseRequest* dr) dr->_compileSet="<<dr->_compileSet.get()<<std::endl;
osg::ref_ptr<osgUtil::IncrementalCompileOperation::CompileSet> compileSet;
if (dr->_compileSet.lock(compileSet) && _pager->getIncrementalCompileOperation())
{
_pager->getIncrementalCompileOperation()->remove(compileSet.get());
}
dr->invalidate();
}
bool DatabasePager::RequestQueue::pruneOldRequestsAndCheckIfEmpty()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_requestMutex);
@ -548,7 +544,7 @@ bool DatabasePager::RequestQueue::pruneOldRequestsAndCheckIfEmpty()
}
else
{
(*citr)->invalidate();
invalidate(citr->get());
OSG_INFO<<"DatabasePager::RequestQueue::pruneOldRequestsAndCheckIfEmpty(): Pruning "<<(*citr)<<std::endl;
citr = _requestList.erase(citr);
@ -578,7 +574,7 @@ void DatabasePager::RequestQueue::clear()
citr != _requestList.end();
++citr)
{
(*citr)->invalidate();
invalidate(citr->get());
}
_requestList.clear();
@ -603,6 +599,25 @@ void DatabasePager::RequestQueue::add(DatabasePager::DatabaseRequest* databaseRe
addNoLock(databaseRequest);
}
void DatabasePager::RequestQueue::remove(DatabasePager::DatabaseRequest* databaseRequest)
{
// OSG_NOTICE<<"DatabasePager::RequestQueue::remove(DatabaseRequest* databaseRequest)"<<std::endl;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_requestMutex);
for(RequestList::iterator citr = _requestList.begin();
citr != _requestList.end();
++citr)
{
if (citr->get()==databaseRequest)
{
// OSG_NOTICE<<" done remove(DatabaseRequest* databaseRequest)"<<std::endl;
_requestList.erase(citr);
--_size;
return;
}
}
}
void DatabasePager::RequestQueue::addNoLock(DatabasePager::DatabaseRequest* databaseRequest)
{
_requestList.push_back(databaseRequest);
@ -649,8 +664,8 @@ void DatabasePager::RequestQueue::takeFirst(osg::ref_ptr<DatabaseRequest>& datab
}
else
{
(*citr)->invalidate();
invalidate(citr->get());
OSG_INFO<<"DatabasePager::RequestQueue::takeFirst(): Pruning "<<(*citr)<<std::endl;
citr = _requestList.erase(citr);
--_size;
@ -708,8 +723,7 @@ DatabasePager::DatabaseThread::DatabaseThread(DatabasePager* pager, Mode mode, c
_active(false),
_pager(pager),
_mode(mode),
_name(name),
_tickSinceStartOfIteration(0)
_name(name)
{
}
@ -718,8 +732,7 @@ DatabasePager::DatabaseThread::DatabaseThread(const DatabaseThread& dt, Database
_active(false),
_pager(pager),
_mode(dt._mode),
_name(dt._name),
_tickSinceStartOfIteration(0)
_name(dt._name)
{
}
@ -750,30 +763,22 @@ int DatabasePager::DatabaseThread::cancel()
break;
}
// release the frameBlock and _databasePagerThreadBlock in case its holding up thread cancellation.
// _databasePagerThreadBlock->release();
// then wait for the the thread to stop running.
while(isRunning())
{
// commenting out debug info as it was cashing crash on exit, presumable
// due to OSG_NOTICE or std::cout destructing earlier than this destructor.
// OSG_INFO<<"Waiting for DatabasePager to cancel"<<std::endl;
// OSG_INFO<<"Waiting for DatabasePager::DatabaseThread to cancel"<<std::endl;
OpenThreads::Thread::YieldCurrentThread();
}
// _startThreadCalled = false;
}
//std::cout<<"DatabasePager::~DatabasePager() stopped running"<<std::endl;
//OSG_NOTICE<<"DatabasePager::DatabaseThread stopped running"<<std::endl;
return result;
}
double DatabasePager::DatabaseThread::getTimeSinceStartOfIteration() const
{
return osg::Timer::instance()->delta_s(_tickSinceStartOfIteration, osg::Timer::instance()->tick());
}
void DatabasePager::DatabaseThread::run()
{
OSG_INFO<<_name<<": DatabasePager::DatabaseThread::run"<<std::endl;
@ -803,11 +808,12 @@ void DatabasePager::DatabaseThread::run()
{
_active = false;
_tickSinceStartOfIteration = osg::Timer::instance()->tick();
read_queue->block();
_tickSinceStartOfIteration = osg::Timer::instance()->tick();
if (_done)
{
break;
}
_active = true;
@ -960,83 +966,43 @@ void DatabasePager::DatabaseThread::run()
//OSG_NOTICE<<" node read in "<<osg::Timer::instance()->delta_m(before,osg::Timer::instance()->tick())<<" ms"<<std::endl;
bool loadedObjectsNeedToBeCompiled = false;
if (databaseRequest->_loadedModel.valid())
{
databaseRequest->_loadedModel->getBound();
osg::NodePath nodePath;
// find all the compileable rendering objects
DatabasePager::FindCompileableGLObjectsVisitor frov(_pager->_changeAutoUnRef, _pager->_valueAutoUnRef,
_pager->_changeAnisotropy, _pager->_valueAnisotropy,
_pager->_drawablePolicy,
_pager);
// push the soon to be parent on the nodepath of the NodeVisitor so that
// during traversal one can test for where it'll be in the overall scene graph
for(osg::RefNodePath::iterator rnp_itr = refNodePath.begin();
rnp_itr != refNodePath.end();
++rnp_itr)
{
nodePath.push_back(rnp_itr->get());
}
// 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.
ActiveGraphicsContexts::iterator itr = _pager->_activeGraphicsContexts.begin();
DataToCompile* dtc = 0;
if (itr != _pager->_activeGraphicsContexts.end())
{
dtc = &(databaseRequest->_dataToCompileMap[*itr]);
++itr;
}
// find all the compileable rendering objects
DatabasePager::FindCompileableGLObjectsVisitor frov(dtc,
_pager->_changeAutoUnRef, _pager->_valueAutoUnRef,
_pager->_changeAnisotropy, _pager->_valueAnisotropy,
_pager->_drawablePolicy,
_pager);
// push the soon to be parent on the nodepath of the NodeVisitor so that
// during traversal one can test for where it'll be in the overall scene graph
for(osg::NodePath::iterator nitr = nodePath.begin();
nitr != nodePath.end();
++nitr)
{
frov.pushOntoNodePath(*nitr);
frov.pushOntoNodePath(rnp_itr->get());
}
databaseRequest->_loadedModel->accept(frov);
if (_pager->_doPreCompile && !dtc->empty())
{
if (_pager->_incrementalCompileOperation.valid())
{
//OSG_NOTICE<<"Using IncrementalCompileOperation"<<std::endl;
osgUtil::IncrementalCompileOperation::CompileSet* compileSet = new osgUtil::IncrementalCompileOperation::CompileSet(databaseRequest->_loadedModel.get());
compileSet->_compileCompletedCallback = new DatabasePagerCompileCompletedCallback(_pager, databaseRequest.get());
_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();
++itr)
{
databaseRequest->_dataToCompileMap[*itr] = *dtc;
}
}
}
bool loadedObjectsNeedToBeCompiled = (_pager->_doPreCompile && frov.requiresCompilation() && _pager->_incrementalCompileOperation.valid());
// move the databaseRequest from the front of the fileRequest to the end of
// dataToCompile or dataToMerge lists.
if (loadedObjectsNeedToBeCompiled)
{
if (!_pager->_incrementalCompileOperation)
{
_pager->_dataToCompileList->add(databaseRequest.get());
}
// OSG_NOTICE<<"Using IncrementalCompileOperation"<<std::endl;
osgUtil::IncrementalCompileOperation::CompileSet* compileSet = new osgUtil::IncrementalCompileOperation::CompileSet(databaseRequest->_loadedModel.get());
compileSet->_compileCompletedCallback = new DatabasePagerCompileCompletedCallback(_pager, databaseRequest.get());
_pager->_incrementalCompileOperation->add(compileSet);
databaseRequest->_compileSet = compileSet;
_pager->_dataToCompileList->add(databaseRequest.get());
}
else
{
@ -1044,41 +1010,7 @@ void DatabasePager::DatabaseThread::run()
}
}
// Prepare and prune the to-be-compiled list here in
// the pager thread rather than in the draw or
// graphics context thread(s).
if (loadedObjectsNeedToBeCompiled)
{
loadedObjectsNeedToBeCompiled = ! _pager->_dataToCompileList->pruneOldRequestsAndCheckIfEmpty();
}
if (loadedObjectsNeedToBeCompiled && !_pager->_activeGraphicsContexts.empty())
{
for(ActiveGraphicsContexts::iterator itr = _pager->_activeGraphicsContexts.begin();
itr != _pager->_activeGraphicsContexts.end();
++itr)
{
osg::GraphicsContext* gc = osg::GraphicsContext::getCompileContext(*itr);
if (gc)
{
osg::GraphicsThread* gt = gc->getGraphicsThread();
if (gt)
{
gt->add(new DatabasePager::CompileOperation(_pager));
}
else
{
gc->makeCurrent();
_pager->compileAllGLObjects(*(gc->getState()));
gc->releaseContext();
}
}
}
// OSG_NOTICE<<"Done compiling in paging thread"<<std::endl;
}
// _pager->_dataToCompileList->pruneOldRequestsAndCheckIfEmpty();
}
else
{
@ -1175,19 +1107,6 @@ DatabasePager::DatabasePager()
strcmp(ptr,"on")==0 || strcmp(ptr,"ON")==0;
}
_targetFrameRate = 100.0;
_minimumTimeAvailableForGLCompileAndDeletePerFrame = 0.001; // 1ms.
_maximumNumOfObjectsToCompilePerFrame = 4;
if( (ptr = getenv("OSG_MINIMUM_COMPILE_TIME_PER_FRAME")) != 0)
{
_minimumTimeAvailableForGLCompileAndDeletePerFrame = osg::asciiToDouble(ptr);
}
if( (ptr = getenv("OSG_MAXIMUM_OBJECTS_TO_COMPILE_PER_FRAME")) != 0)
{
_maximumNumOfObjectsToCompilePerFrame = atoi(ptr);
}
// initialize the stats variables
resetStats();
@ -1260,16 +1179,11 @@ DatabasePager::DatabasePager(const DatabasePager& rhs)
_changeAnisotropy = rhs._changeAnisotropy;
_valueAnisotropy = rhs._valueAnisotropy;
_deleteRemovedSubgraphsInDatabaseThread = rhs._deleteRemovedSubgraphsInDatabaseThread;
_targetMaximumNumberOfPageLOD = rhs._targetMaximumNumberOfPageLOD;
_doPreCompile = rhs._doPreCompile;
_targetFrameRate = rhs._targetFrameRate;
_minimumTimeAvailableForGLCompileAndDeletePerFrame = rhs._minimumTimeAvailableForGLCompileAndDeletePerFrame;
_maximumNumOfObjectsToCompilePerFrame = rhs._maximumNumOfObjectsToCompilePerFrame;
_fileRequestQueue = new ReadQueue(this,"fileRequestQueue");
_httpRequestQueue = new ReadQueue(this,"httpRequestQueue");
@ -1313,7 +1227,23 @@ void DatabasePager::setIncrementalCompileOperation(osgUtil::IncrementalCompileOp
DatabasePager::~DatabasePager()
{
// cancel the threads
cancel();
// destruct all the threads
_databaseThreads.clear();
// destruct all the queues
_fileRequestQueue = 0;
_httpRequestQueue = 0;
_dataToCompileList = 0;
_dataToMergeList = 0;
// remove reference to the ICO
_incrementalCompileOperation = 0;
//_activePagedLODList;
//_inactivePagedLODList;
}
osg::ref_ptr<DatabasePager>& DatabasePager::prototype()
@ -1411,7 +1341,7 @@ int DatabasePager::cancel()
(*dt_itr)->setDone(true);
}
// release the frameBlock and _databasePagerThreadBlock in case its holding up thread cancellation.
// release the queue blocks in case they are holding up thread cancellation.
_fileRequestQueue->release();
_httpRequestQueue->release();
@ -1425,7 +1355,6 @@ int DatabasePager::cancel()
_done = true;
_startThreadCalled = false;
//std::cout<<"DatabasePager::~DatabasePager() stopped running"<<std::endl;
return result;
}
@ -1637,11 +1566,19 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou
void DatabasePager::signalBeginFrame(const osg::FrameStamp* framestamp)
{
#if 0
OSG_NOTICE<<"DatabasePager : _fileRequestQueue->size()="<<_fileRequestQueue->size()
<<", _httpRequestQueue->size()= "<<_httpRequestQueue->size()
<<", _dataToCompileList->size()= "<<_dataToCompileList->size()
<<", _dataToMergeList->size()= "<<_dataToMergeList->size()<<std::endl;
#endif
if (framestamp)
{
_dataToCompileList->pruneOldRequestsAndCheckIfEmpty();
//OSG_INFO << "signalBeginFrame "<<framestamp->getFrameNumber()<<">>>>>>>>>>>>>>>>"<<std::endl;
_frameNumber = framestamp->getFrameNumber();
} //else OSG_INFO << "signalBeginFrame >>>>>>>>>>>>>>>>"<<std::endl;
}
@ -1713,7 +1650,7 @@ void DatabasePager::addLoadedDataToSceneGraph(const osg::FrameStamp &frameStamp)
RequestQueue::RequestList localFileLoadedList;
// get the data for the _dataToCompileList, leaving it empty via a std::vector<>.swap.
// get the data from the _dataToMergeList, leaving it empty via a std::vector<>.swap.
_dataToMergeList->swap(localFileLoadedList);
mid = osg::Timer::instance()->tick();
@ -1945,235 +1882,3 @@ void DatabasePager::registerPagedLODs(osg::Node* subgraph, int frameNumber)
FindPagedLODsVisitor fplv(*_activePagedLODList, frameNumber);
subgraph->accept(fplv);
}
bool DatabasePager::requiresCompileGLObjects() const
{
return !_dataToCompileList->empty();
}
void DatabasePager::setCompileGLObjectsForContextID(unsigned int contextID, bool on)
{
if (on)
{
_activeGraphicsContexts.insert(contextID);
}
else
{
_activeGraphicsContexts.erase(contextID);
}
}
bool DatabasePager::getCompileGLObjectsForContextID(unsigned int contextID)
{
return _activeGraphicsContexts.count(contextID)!=0;
}
DatabasePager::CompileOperation::CompileOperation(osgDB::DatabasePager* databasePager):
osg::GraphicsOperation("DatabasePager::CompileOperation",false),
_databasePager(databasePager)
{
}
void DatabasePager::CompileOperation::operator () (osg::GraphicsContext* context)
{
// OSG_NOTICE<<"Background thread compiling"<<std::endl;
if (_databasePager.valid()) _databasePager->compileAllGLObjects(*(context->getState()), true);
}
bool DatabasePager::requiresExternalCompileGLObjects(unsigned int contextID) const
{
if (_activeGraphicsContexts.count(contextID)==0) return false;
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;
compileGLObjects(state, availableTime, doFlush);
}
void DatabasePager::compileGLObjects(osg::State& state, double& availableTime, bool doFlush)
{
// OSG_NOTICE<<"DatabasePager::compileGLObjects "<<_frameNumber<<std::endl;
bool compileAll = (availableTime==DBL_MAX);
SharedStateManager *sharedManager
= Registry::instance()->getSharedStateManager();
osg::RenderInfo renderInfo;
renderInfo.setState(&state);
if (availableTime>0.0)
{
const osg::Timer& timer = *osg::Timer::instance();
osg::Timer_t start_tick = timer.tick();
double elapsedTime = 0.0;
double estimatedTextureDuration = 0.0001;
double estimatedDrawableDuration = 0.0001;
osg::ref_ptr<DatabaseRequest> databaseRequest;
_dataToCompileList->takeFirst(databaseRequest);
unsigned int numObjectsCompiled = 0;
// 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() && databaseRequest->valid() && (compileAll || (elapsedTime<availableTime && numObjectsCompiled<_maximumNumOfObjectsToCompilePerFrame)) )
{
DataToCompileMap& dcm = databaseRequest->_dataToCompileMap;
DataToCompile& dtc = dcm[state.getContextID()];
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
//OSG_INFO<<"Compiling textures"<<std::endl;
// we have Textures to compile
typedef osgUtil::CompileData::Textures Textures;
Textures& textures = dtc._textures;
Textures::iterator itr=textures.begin();
unsigned int objTemp = numObjectsCompiled;
for(;
itr!=textures.end() && (compileAll || ((elapsedTime+estimatedTextureDuration)<availableTime && numObjectsCompiled<_maximumNumOfObjectsToCompilePerFrame));
++itr)
{
OSG_INFO<<" Compiling texture "<<(*itr).get()<<std::endl;
if (isCompiled(itr->get(), state.getContextID())
|| (sharedManager && sharedManager->isShared(itr->get())))
{
elapsedTime = timer.delta_s(start_tick,timer.tick());
continue;
}
double startCompileTime = timer.delta_s(start_tick,timer.tick());
(*itr)->apply(state);
#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE)
GLint p;
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_RESIDENT, &p);
#endif
elapsedTime = timer.delta_s(start_tick,timer.tick());
// estimate the duration of the compile based on current compile duration.
estimatedTextureDuration = (elapsedTime-startCompileTime);
++numObjectsCompiled;
}
if (osg::getNotifyLevel() >= osg::DEBUG_INFO
&& numObjectsCompiled > objTemp)
OSG_NOTICE<< _frameNumber << " compiled "
<< numObjectsCompiled - objTemp
<< " StateSets" << std::endl;
// remove the compiled statesets from the list.
textures.erase(textures.begin(),itr);
}
if (!dtc._drawables.empty() && (compileAll || ((elapsedTime+estimatedDrawableDuration)<availableTime && numObjectsCompiled<_maximumNumOfObjectsToCompilePerFrame)))
{
// we have Drawable's to compile
//OSG_INFO<<"Compiling drawables"<<std::endl;
typedef osgUtil::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));
++itr)
{
//OSG_INFO<<" Compiling drawable "<<(*itr).get()<<std::endl;
if (isCompiled(itr->get(), state.getContextID()))
{
elapsedTime = timer.delta_s(start_tick,timer.tick());
continue;
}
double startCompileTime = timer.delta_s(start_tick,timer.tick());
(*itr)->compileGLObjects(renderInfo);
elapsedTime = timer.delta_s(start_tick,timer.tick());
// estimate the duration of the compile based on current compile duration.
estimatedDrawableDuration = (elapsedTime-startCompileTime);
++numObjectsCompiled;
}
if (osg::getNotifyLevel() >= osg::DEBUG_INFO
&& numObjectsCompiled > objTemp)
{
OSG_INFO<< _frameNumber << " compiled "
<< numObjectsCompiled - objTemp
<< " Drawables" << std::endl;
}
// remove the compiled drawables from the list.
dwlist.erase(dwlist.begin(),itr);
}
//OSG_INFO<<"Checking if compiled"<<std::endl;
// now check the to compile entries for all active graphics contexts
// to make sure that all have been compiled. They won't be
// if we ran out of time or if another thread is still
// compiling for its graphics context.
bool allCompiled = true;
for(DataToCompileMap::iterator itr=dcm.begin();
itr!=dcm.end() && allCompiled;
++itr)
{
if (!(itr->second.empty())) allCompiled=false;
}
if (numObjectsCompiled > 0)
OSG_NOTICE<< "Framenumber "<<_frameNumber << ": compiled " << numObjectsCompiled << " objects" << std::endl;
if (allCompiled)
{
if (doFlush)
{
glFlush();
}
// we've compiled all of the current databaseRequest so we can now pop it off the
// to compile list and place it on the merge list.
OSG_INFO<<"All compiled"<<std::endl;
_dataToMergeList->add(databaseRequest.get());
databaseRequest = 0;
_dataToCompileList->takeFirst(databaseRequest);
}
else
{
OSG_INFO<<"Not all compiled"<<std::endl;
_dataToCompileList->add(databaseRequest.get());
databaseRequest = 0;
}
elapsedTime = timer.delta_s(start_tick,timer.tick());
}
availableTime -= elapsedTime;
//OSG_NOTICE<<"elapsedTime="<<elapsedTime<<"\ttime remaining ="<<availableTime<<"\tnumObjectsCompiled = "<<numObjectsCompiled<<std::endl;
//OSG_NOTICE<<"estimatedTextureDuration="<<estimatedTextureDuration;
//OSG_NOTICE<<"\testimatedDrawableDuration="<<estimatedDrawableDuration<<std::endl;
}
else
{
availableTime = 0.0f;
}
}

View File

@ -18,6 +18,7 @@
#include <osg/GLObjects>
#include <osg/Depth>
#include <osg/ColorMask>
#include <osg/ApplicationUsage>
#include <OpenThreads/ScopedLock>
@ -29,6 +30,23 @@ namespace osgUtil
{
// TODO
// priority of CompileSets
// isCompiled
// time estimation
// early completion
// needs compile given time slot
// custom CompileData elements
// pruneOldRequestsAndCheckIfEmpty()
// Use? :
// #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE)
// GLint p;
// glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_RESIDENT, &p);
// #endif
static osg::ApplicationUsageProxy ICO_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_MINIMUM_COMPILE_TIME_PER_FRAME <float>","minimum compile time alloted to compiling OpenGL objects per frame in database pager.");
static osg::ApplicationUsageProxy UCO_e2(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_MAXIMUM_OBJECTS_TO_COMPILE_PER_FRAME <int>","maximum number of OpenGL objects to compile per frame in database pager.");
/////////////////////////////////////////////////////////////////
//
// CompileStats
@ -248,6 +266,11 @@ void CompileOperator::runTimingTests(osg::RenderInfo& renderInfo)
bool CompileOperator::compile(osg::RenderInfo& renderInfo, CompileData& cd, unsigned int& maxNumObjectsToCompile, double& compileTime)
{
osg::NotifySeverity level = osg::INFO;
//osg::NotifySeverity level = osg::NOTICE;
OSG_NOTIFY(level)<<"compile(..,maxNumObjectsToCompile="<<maxNumObjectsToCompile<<", compileTime="<<compileTime<<")"<<std::endl;
osg::Timer_t startTick = osg::Timer::instance()->tick();
if (!_timingTestsCompleted)
@ -255,7 +278,6 @@ bool CompileOperator::compile(osg::RenderInfo& renderInfo, CompileData& cd, unsi
runTimingTests(renderInfo);
}
osg::NotifySeverity level = osg::INFO;
unsigned int totalDataSizeCompiled = 0;
unsigned int drawablesCompiled = 0;
@ -436,7 +458,7 @@ bool CompileOperator::compile(osg::RenderInfo& renderInfo, CompileData& cd, unsi
double timeUsed = osg::Timer::instance()->delta_s(startTick, osg::Timer::instance()->tick());
OSG_NOTIFY(level)<<"compile time, texturesCompiled="<<texturesCompiled<<", drawablesCompiled="<<drawablesCompiled<<", programsCompiled="<<programsCompiled<<", timeUsed="<<timeUsed*1000.0<<" totalDataSizeCompiled="<<totalDataSizeCompiled<<" bytes, download rate="<<double(totalDataSizeCompiled)/(1024.0*1024*timeUsed)<<"Mb/sec"<<std::endl;
OSG_NOTIFY(level)<<" texturesCompiled="<<texturesCompiled<<", drawablesCompiled="<<drawablesCompiled<<", programsCompiled="<<programsCompiled<<", timeUsed="<<timeUsed*1000.0<<" totalDataSizeCompiled="<<totalDataSizeCompiled<<" bytes, download rate="<<double(totalDataSizeCompiled)/(1024.0*1024*timeUsed)<<"Mb/sec"<<std::endl;
compileTime -= timeUsed;
@ -467,6 +489,8 @@ IncrementalCompileOperation::IncrementalCompileOperation():
}
_compileOperator = new CompileOperator;
// assignForceTextureDownloadGeometry();
}
IncrementalCompileOperation::~IncrementalCompileOperation()
@ -551,6 +575,44 @@ void IncrementalCompileOperation::add(CompileSet* compileSet, bool callBuildComp
_toCompile.push_back(compileSet);
}
void IncrementalCompileOperation::remove(CompileSet* compileSet)
{
// OSG_NOTICE<<"IncrementalCompileOperation::remove(CompileSet* compileSet)"<<std::endl;
if (!compileSet) return;
// remove CompileSet from _toCompile list if it's present.
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_toCompileMutex);
for(CompileSets::iterator itr = _toCompile.begin();
itr != _toCompile.end();
++itr)
{
if (*itr == compileSet)
{
_toCompile.erase(itr);
return;
}
}
}
// remove CompileSet from _compiled list if it's present.
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_compiledMutex);
for(CompileSets::iterator itr = _compiled.begin();
itr != _compiled.end();
++itr)
{
if (*itr == compileSet)
{
_toCompile.erase(itr);
return;
}
}
}
}
void IncrementalCompileOperation::mergeCompiledSubgraphs()
{
// OSG_INFO<<"IncrementalCompileOperation::mergeCompiledSubgraphs()"<<std::endl;
@ -562,9 +624,10 @@ void IncrementalCompileOperation::mergeCompiledSubgraphs()
++itr)
{
CompileSet* cs = itr->get();
if (cs->_attachmentPoint.valid())
osg::ref_ptr<osg::Group> group;
if (cs->_attachmentPoint.lock(group))
{
cs->_attachmentPoint->addChild(cs->_subgraphToCompile.get());
group->addChild(cs->_subgraphToCompile.get());
}
}
@ -756,6 +819,8 @@ void IncrementalCompileOperation::operator () (osg::GraphicsContext* context)
#endif
//level = osg::NOTICE;
osg::RenderInfo renderInfo;
renderInfo.setState(context->getState());
@ -766,7 +831,7 @@ void IncrementalCompileOperation::operator () (osg::GraphicsContext* context)
}
for(CompileSets::iterator itr = toCompileCopy.begin();
itr != toCompileCopy.end() && compileTime>0.0;
itr != toCompileCopy.end() && compileTime>0.0 && maxNumOfObjectsToCompilePerFrame>0;
++itr)
{
CompileSet* cs = itr->get();
@ -810,6 +875,8 @@ void IncrementalCompileOperation::operator () (osg::GraphicsContext* context)
}
}
}
//glFush();
//glFinish();
}
} // end of namespace osgUtil

View File

@ -148,7 +148,8 @@ SceneView::SceneView(DisplaySettings* ds)
_camera->setDrawBuffer(GL_BACK);
_requiresFlush = true;
_automaticFlush = true;
_requiresFlush = false;
_activeUniforms = DEFAULT_UNIFORMS;
@ -180,7 +181,8 @@ SceneView::SceneView(const SceneView& rhs, const osg::CopyOp& copyop):
_initCalled = false;
_requiresFlush = rhs._requiresFlush;
_automaticFlush = rhs._automaticFlush;
_requiresFlush = false;
_activeUniforms = rhs._activeUniforms;
@ -1025,6 +1027,8 @@ void SceneView::flushAllDeletedGLObjects()
void SceneView::flushDeletedGLObjects(double& availableTime)
{
// OSG_NOTICE<<"SceneView::flushDeletedGLObjects(availableTime="<<availableTime<<")"<<std::endl;
osg::State* state = _renderInfo.getState();
_requiresFlush = false;
@ -1061,7 +1065,7 @@ void SceneView::draw()
}
// assume the the draw which is about to happen could generate GL objects that need flushing in the next frame.
_requiresFlush = true;
_requiresFlush = _automaticFlush;
RenderLeaf* previous = NULL;
if (_displaySettings.valid() && _displaySettings->getStereo())

View File

@ -327,10 +327,6 @@ static OpenThreads::Mutex s_drawSerializerMutex;
// Renderer
Renderer::Renderer(osg::Camera* camera):
osg::GraphicsOperation("Renderer",true),
_targetFrameRate(100.0),
_minimumTimeAvailableForGLCompileAndDeletePerFrame(0.001),
_flushTimeRatio(0.5),
_conservativeTimeRatio(0.5),
_camera(camera),
_done(false),
_graphicsThreadDoesCull(true),
@ -359,7 +355,10 @@ Renderer::Renderer(osg::Camera* camera):
}
osgViewer::View* view = dynamic_cast<osgViewer::View*>(_camera->getView());
osgViewer::ViewerBase* viewer = view ? view->getViewerBase() : 0;
osgUtil::IncrementalCompileOperation* ico = viewer ? viewer->getIncrementalCompileOperation() : 0;
bool automaticFlush = (ico==NULL);
osg::DisplaySettings* ds = _camera->getDisplaySettings() ? _camera->getDisplaySettings() :
((view && view->getDisplaySettings()) ? view->getDisplaySettings() : osg::DisplaySettings::instance().get());
@ -374,9 +373,11 @@ Renderer::Renderer(osg::Camera* camera):
}
}
_sceneView[0]->setAutomaticFlush(automaticFlush);
_sceneView[0]->setGlobalStateSet(global_stateset);
_sceneView[0]->setSecondaryStateSet(secondary_stateset);
_sceneView[1]->setAutomaticFlush(automaticFlush);
_sceneView[1]->setGlobalStateSet(global_stateset);
_sceneView[1]->setSecondaryStateSet(secondary_stateset);
@ -395,8 +396,6 @@ Renderer::Renderer(osg::Camera* camera):
_availableQueue.add(_sceneView[1].get());
DEBUG_MESSAGE<<"_availableQueue.size()="<<_availableQueue._queue.size()<<std::endl;
_flushOperation = new osg::FlushDeletedGLObjectsOperation(0.1);
}
Renderer::~Renderer()
@ -460,7 +459,12 @@ void Renderer::updateSceneView(osgUtil::SceneView* sceneView)
}
osgViewer::View* view = dynamic_cast<osgViewer::View*>(_camera->getView());
osgViewer::ViewerBase* viewer = view ? view->getViewerBase() : 0;
osgUtil::IncrementalCompileOperation* ico = viewer ? viewer->getIncrementalCompileOperation() : 0;
bool automaticFlush = (ico==NULL);
sceneView->setAutomaticFlush(automaticFlush);
osgDB::DatabasePager* databasePager = view ? view->getDatabasePager() : 0;
sceneView->getCullVisitor()->setDatabaseRequestHandler(databasePager);
@ -469,8 +473,6 @@ void Renderer::updateSceneView(osgUtil::SceneView* sceneView)
sceneView->setFrameStamp(view ? view->getFrameStamp() : state->getFrameStamp());
if (databasePager) databasePager->setCompileGLObjectsForContextID(state->getContextID(), true);
osg::DisplaySettings* ds = _camera->getDisplaySettings() ? _camera->getDisplaySettings() :
((view &&view->getDisplaySettings()) ? view->getDisplaySettings() : osg::DisplaySettings::instance().get());
@ -611,9 +613,6 @@ void Renderer::draw()
DEBUG_MESSAGE<<"draw() got SceneView "<<sceneView<<std::endl;
osg::GraphicsContext* compileContext = sceneView ? osg::GraphicsContext::getCompileContext(sceneView->getState()->getContextID()) : 0;
osg::GraphicsThread* compileThread = compileContext ? compileContext->getGraphicsThread() : 0;
if (sceneView && !_done)
{
// since we are running the draw thread in parallel with the main thread it's possible to unreference Camera's
@ -626,9 +625,6 @@ void Renderer::draw()
compile();
}
osgViewer::View* view = dynamic_cast<osgViewer::View*>(_camera->getView());
osgDB::DatabasePager* databasePager = view ? view->getDatabasePager() : 0;
// OSG_NOTICE<<"Drawing buffer "<<_currentDraw<<std::endl;
if (_done)
@ -694,14 +690,7 @@ void Renderer::draw()
}
_availableQueue.add(sceneView);
osg::Timer_t afterDispatchTick = osg::Timer::instance()->tick();
double dispatchTime = osg::Timer::instance()->delta_s(beforeDrawTick, afterDispatchTick);
// now flush delete OpenGL objects and compile any objects as required by the DatabasePager
flushAndCompile(dispatchTime, sceneView, databasePager, compileThread);
if (acquireGPUStats)
{
_querySupport->endQuery(state);
@ -749,11 +738,6 @@ void Renderer::cull_draw()
}
osgViewer::View* view = dynamic_cast<osgViewer::View*>(_camera->getView());
osgDB::DatabasePager* databasePager = view ? view->getDatabasePager() : 0;
osg::GraphicsContext* compileContext = osg::GraphicsContext::getCompileContext(sceneView->getState()->getContextID());
osg::GraphicsThread* compileThread = compileContext ? compileContext->getGraphicsThread() : 0;
// OSG_NOTICE<<"RenderingOperation"<<std::endl;
@ -832,13 +816,6 @@ void Renderer::cull_draw()
sceneView->draw();
}
osg::Timer_t afterDispatchTick = osg::Timer::instance()->tick();
double cullAndDispatchTime = osg::Timer::instance()->delta_s(beforeCullTick, afterDispatchTick);
// now flush delete OpenGL objects and compile any objects as required by the DatabasePager
flushAndCompile(cullAndDispatchTime, sceneView, databasePager, compileThread);
if (acquireGPUStats)
{
_querySupport->endQuery(state);
@ -864,54 +841,6 @@ void Renderer::cull_draw()
}
void Renderer::flushAndCompile(double currentElapsedFrameTime, osgUtil::SceneView* sceneView, osgDB::DatabasePager* databasePager, osg::GraphicsThread* compileThread)
{
double targetFrameRate = _targetFrameRate;
double minimumTimeAvailableForGLCompileAndDeletePerFrame = _minimumTimeAvailableForGLCompileAndDeletePerFrame;
if (databasePager)
{
targetFrameRate = std::min(targetFrameRate, databasePager->getTargetFrameRate());
minimumTimeAvailableForGLCompileAndDeletePerFrame = std::min(minimumTimeAvailableForGLCompileAndDeletePerFrame, databasePager->getMinimumTimeAvailableForGLCompileAndDeletePerFrame());
}
double targetFrameTime = 1.0/targetFrameRate;
double availableTime = std::max((targetFrameTime - currentElapsedFrameTime)*_conservativeTimeRatio,
minimumTimeAvailableForGLCompileAndDeletePerFrame);
double flushTime = availableTime * _flushTimeRatio;
double compileTime = availableTime - flushTime;
#if 0
OSG_NOTICE<<"total availableTime = "<<availableTime*1000.0<<std::endl;
OSG_NOTICE<<" flushTime = "<<flushTime*1000.0<<std::endl;
OSG_NOTICE<<" compileTime = "<<compileTime*1000.0<<std::endl;
#endif
if (compileThread)
{
compileThread->add(_flushOperation.get());
}
else
{
sceneView->flushDeletedGLObjects(flushTime);
}
// if any time left over from flush add this to compile time.
if (flushTime>0.0) compileTime += flushTime;
#if 0
OSG_NOTICE<<" revised compileTime = "<<compileTime*1000.0<<std::endl;
#endif
if (databasePager && databasePager->requiresExternalCompileGLObjects(sceneView->getState()->getContextID()))
{
databasePager->compileGLObjects(*(sceneView->getState()), compileTime);
}
}
void Renderer::operator () (osg::Object* object)
{
osg::GraphicsContext* context = dynamic_cast<osg::GraphicsContext*>(object);