You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
324 lines
15 KiB
324 lines
15 KiB
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield |
|
* |
|
* This library is open source and may be redistributed and/or modified under |
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or |
|
* (at your option) any later version. The full license is in LICENSE file |
|
* included with this distribution, and on the openscenegraph.org website. |
|
* |
|
* This library is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* OpenSceneGraph Public License for more details. |
|
*/ |
|
|
|
#ifndef OSGUTIL_INCREMENTALCOMPILEOPERATOR |
|
#define OSGUTIL_INCREMENTALCOMPILEOPERATOR |
|
|
|
#include <osgUtil/GLObjectsVisitor> |
|
#include <osg/Geometry> |
|
|
|
namespace osgUtil { |
|
|
|
|
|
class OSGUTIL_EXPORT StateToCompile : public osg::NodeVisitor |
|
{ |
|
public: |
|
|
|
StateToCompile(GLObjectsVisitor::Mode mode); |
|
|
|
typedef std::set<osg::Drawable*> DrawableSet; |
|
typedef std::set<osg::StateSet*> StateSetSet; |
|
typedef std::set<osg::Texture*> TextureSet; |
|
typedef std::set<osg::Program*> ProgramSet; |
|
|
|
DrawableSet _drawablesHandled; |
|
StateSetSet _statesetsHandled; |
|
|
|
GLObjectsVisitor::Mode _mode; |
|
DrawableSet _drawables; |
|
TextureSet _textures; |
|
ProgramSet _programs; |
|
bool _assignPBOToImages; |
|
osg::ref_ptr<osg::PixelBufferObject> _pbo; |
|
|
|
bool empty() const { return _textures.empty() && _programs.empty() && _drawables.empty(); } |
|
|
|
virtual void apply(osg::Node& node); |
|
virtual void apply(osg::Geode& node); |
|
|
|
virtual void apply(osg::Drawable& drawable); |
|
virtual void apply(osg::StateSet& stateset); |
|
virtual void apply(osg::Texture& texture); |
|
|
|
}; |
|
|
|
class OSGUTIL_EXPORT IncrementalCompileOperation : public osg::GraphicsOperation |
|
{ |
|
public: |
|
|
|
IncrementalCompileOperation(); |
|
|
|
/** Return true if the IncrementCompileOperation is active.*/ |
|
bool isActive() const { return !_contexts.empty(); } |
|
|
|
bool requiresCompile(StateToCompile& stateToCompile); |
|
|
|
/** Set the target frame rate that the IncrementalCompileOperation 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 IncrementalCompileOperation, but are should be used as a guide for how |
|
* long to set aside per frame for compiling and deleting OpenGL objects. The longer amount of |
|
* time to set aside the 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 IncrementalCompileOperation 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; } |
|
|
|
|
|
/** 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; } |
|
|
|
/** Assign a geometry and associated StateSet than is applied after each texture compile to atttempt to force the OpenGL |
|
* drive to download the texture object to OpenGL graphics card.*/ |
|
void assignForceTextureDownloadGeometry(); |
|
|
|
/** Set the osg::Geometry to apply after each texture compile to atttempt to force the OpenGL |
|
* drive to download the texture object to OpenGL graphics card.*/ |
|
void setForceTextureDownloadGeometry(osg::Geometry* geom) { _forceTextureDownloadGeometry = geom; } |
|
osg::Geometry* getForceTextureDownloadGeometry() { return _forceTextureDownloadGeometry.get(); } |
|
const osg::Geometry* getForceTextureDownloadGeometry() const { return _forceTextureDownloadGeometry.get(); } |
|
|
|
typedef std::vector<osg::GraphicsContext*> Contexts; |
|
void assignContexts(Contexts& contexts); |
|
void removeContexts(Contexts& contexts); |
|
|
|
void addGraphicsContext(osg::GraphicsContext* gc); |
|
void removeGraphicsContext(osg::GraphicsContext* gc); |
|
|
|
typedef std::set<osg::GraphicsContext*> ContextSet; |
|
ContextSet& getContextSet() { return _contexts; } |
|
const ContextSet& getContextSet() const { return _contexts; } |
|
|
|
|
|
/** Merge subgraphs that have been compiled.*/ |
|
void mergeCompiledSubgraphs(const osg::FrameStamp* frameStamp); |
|
|
|
/** Set the current frame number that the IncrementalCompileOperation should use as a reference |
|
* value for calculations based on current frame number. |
|
* Note, this value is set by the mergeCompiledSubgraphs(..) method so one won't normally need to call |
|
* set the CurrentFrameNumber manually.*/ |
|
void setCurrentFrameNumber(unsigned int fn) { _currentFrameNumber = fn; } |
|
unsigned int getCurrentFrameNumber() const { return _currentFrameNumber; } |
|
|
|
/** tell the IncrementalCompileOperation to compile all pending objects during next draw traversal, |
|
* for specified number of frames.*/ |
|
void compileAllForNextFrame(unsigned int numFramesToDoCompileAll=1); |
|
|
|
/** tell the IncrementalCompileOperation to compile all pending objects during next draw traversal, |
|
* till specified frame number.*/ |
|
void setCompileAllTillFrameNumber(unsigned int fn) { _compileAllTillFrameNumber = fn; } |
|
unsigned int getCompileAllTillFrameNumber() const { return _compileAllTillFrameNumber; } |
|
|
|
|
|
|
|
|
|
virtual void operator () (osg::GraphicsContext* context); |
|
|
|
struct OSGUTIL_EXPORT CompileInfo : public osg::RenderInfo |
|
{ |
|
CompileInfo(osg::GraphicsContext* context, IncrementalCompileOperation* ico); |
|
|
|
bool okToCompile(double estimatedTimeForCompile=0.0) const |
|
{ |
|
if (compileAll) return true; |
|
if (maxNumObjectsToCompile==0) return false; |
|
return (allocatedTime - timer.elapsedTime()) >= estimatedTimeForCompile; |
|
} |
|
|
|
IncrementalCompileOperation* incrementalCompileOperation; |
|
|
|
bool compileAll; |
|
unsigned int maxNumObjectsToCompile; |
|
double allocatedTime; |
|
osg::ElapsedTime timer; |
|
}; |
|
|
|
struct CompileOp : public osg::Referenced |
|
{ |
|
/** return an estimate for how many seconds the compile will take.*/ |
|
virtual double estimatedTimeForCompile(CompileInfo& compileInfo) const = 0; |
|
/** compile associated objects, return true if object as been fully compiled and this CompileOp can be removed from the to compile list.*/ |
|
virtual bool compile(CompileInfo& compileInfo) = 0; |
|
}; |
|
|
|
struct OSGUTIL_EXPORT CompileDrawableOp : public CompileOp |
|
{ |
|
CompileDrawableOp(osg::Drawable* drawable); |
|
double estimatedTimeForCompile(CompileInfo& compileInfo) const; |
|
bool compile(CompileInfo& compileInfo); |
|
osg::ref_ptr<osg::Drawable> _drawable; |
|
}; |
|
|
|
struct OSGUTIL_EXPORT CompileTextureOp : public CompileOp |
|
{ |
|
CompileTextureOp(osg::Texture* texture); |
|
double estimatedTimeForCompile(CompileInfo& compileInfo) const; |
|
bool compile(CompileInfo& compileInfo); |
|
osg::ref_ptr<osg::Texture> _texture; |
|
}; |
|
|
|
struct OSGUTIL_EXPORT CompileProgramOp : public CompileOp |
|
{ |
|
CompileProgramOp(osg::Program* program); |
|
double estimatedTimeForCompile(CompileInfo& compileInfo) const; |
|
bool compile(CompileInfo& compileInfo); |
|
osg::ref_ptr<osg::Program> _program; |
|
}; |
|
|
|
class OSGUTIL_EXPORT CompileList |
|
{ |
|
public: |
|
CompileList(); |
|
~CompileList(); |
|
|
|
bool empty() const { return _compileOps.empty(); } |
|
void add(CompileOp* compileOp); |
|
void add(osg::Drawable* drawable) { add(new CompileDrawableOp(drawable)); } |
|
void add(osg::Texture* texture) { add(new CompileTextureOp(texture)); } |
|
void add(osg::Program* program) { add(new CompileProgramOp(program)); } |
|
|
|
double estimatedTimeForCompile(CompileInfo& compileInfo) const; |
|
bool compile(CompileInfo& compileInfo); |
|
|
|
|
|
typedef std::list< osg::ref_ptr<CompileOp> > CompileOps; |
|
CompileOps _compileOps; |
|
}; |
|
|
|
|
|
class CompileSet; |
|
|
|
struct CompileCompletedCallback : public virtual 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; |
|
}; |
|
|
|
class OSGUTIL_EXPORT CompileSet : public osg::Referenced |
|
{ |
|
public: |
|
CompileSet() {} |
|
|
|
CompileSet(osg::Node*subgraphToCompile): |
|
_subgraphToCompile(subgraphToCompile) {} |
|
|
|
CompileSet(osg::Group* attachmentPoint, osg::Node* subgraphToCompile): |
|
_attachmentPoint(attachmentPoint), |
|
_subgraphToCompile(subgraphToCompile) {} |
|
|
|
void buildCompileMap(ContextSet& contexts, StateToCompile& stateToCompile); |
|
void buildCompileMap(ContextSet& contexts, GLObjectsVisitor::Mode mode=GLObjectsVisitor::COMPILE_DISPLAY_LISTS|GLObjectsVisitor::COMPILE_STATE_ATTRIBUTES); |
|
|
|
bool compile(CompileInfo& compileInfo); |
|
|
|
bool compiled() const { return _numberCompileListsToCompile==0; } |
|
|
|
OpenThreads::Atomic _numberCompileListsToCompile; |
|
|
|
osg::observer_ptr<osg::Group> _attachmentPoint; |
|
osg::ref_ptr<osg::Node> _subgraphToCompile; |
|
osg::ref_ptr<CompileCompletedCallback> _compileCompletedCallback; |
|
|
|
typedef std::map<osg::GraphicsContext*, CompileList > CompileMap; |
|
CompileMap _compileMap; |
|
|
|
protected: |
|
|
|
virtual ~CompileSet() {} |
|
}; |
|
|
|
typedef std::list< osg::ref_ptr<CompileSet> > CompileSets; |
|
|
|
/** Add a subgraph to be compiled.*/ |
|
void add(osg::Node* subgraphToCompile); |
|
|
|
/** Add a subgraph to be compiled and add automatically to attachPoint on call to mergeCompiledSubgraphs.*/ |
|
void add(osg::Group* attachmentPoint, osg::Node* subgraphToCompile); |
|
|
|
/** 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 _toCompile; } |
|
|
|
OpenThreads::Mutex* getCompiledMutex() { return &_compiledMutex; } |
|
CompileSets& getCompiled() { return _compiled; } |
|
|
|
protected: |
|
|
|
virtual ~IncrementalCompileOperation(); |
|
|
|
void compileSets(CompileSets& toCompile, CompileInfo compileInfo); |
|
|
|
double _targetFrameRate; |
|
double _minimumTimeAvailableForGLCompileAndDeletePerFrame; |
|
unsigned int _maximumNumOfObjectsToCompilePerFrame; |
|
double _flushTimeRatio; |
|
double _conservativeTimeRatio; |
|
|
|
unsigned int _currentFrameNumber; |
|
unsigned int _compileAllTillFrameNumber; |
|
|
|
osg::ref_ptr<osg::Geometry> _forceTextureDownloadGeometry; |
|
|
|
OpenThreads::Mutex _toCompileMutex; |
|
CompileSets _toCompile; |
|
|
|
OpenThreads::Mutex _compiledMutex; |
|
CompileSets _compiled; |
|
|
|
ContextSet _contexts; |
|
|
|
}; |
|
|
|
} |
|
|
|
#endif |
|
|
|
|