IncrementalCompileOperation 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
  2. *
  3. * This library is open source and may be redistributed and/or modified under
  4. * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
  5. * (at your option) any later version. The full license is in LICENSE file
  6. * included with this distribution, and on the openscenegraph.org website.
  7. *
  8. * This library is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * OpenSceneGraph Public License for more details.
  12. */
  13. #ifndef OSGUTIL_INCREMENTALCOMPILEOPERATOR
  14. #define OSGUTIL_INCREMENTALCOMPILEOPERATOR
  15. #include <osgUtil/GLObjectsVisitor>
  16. #include <osg/Geometry>
  17. namespace osgUtil {
  18. class OSGUTIL_EXPORT StateToCompile : public osg::NodeVisitor
  19. {
  20. public:
  21. StateToCompile(GLObjectsVisitor::Mode mode, osg::Object* markerObject);
  22. typedef std::set<osg::Drawable*> DrawableSet;
  23. typedef std::set<osg::StateSet*> StateSetSet;
  24. typedef std::set<osg::Texture*> TextureSet;
  25. typedef std::set<osg::Program*> ProgramSet;
  26. DrawableSet _drawablesHandled;
  27. StateSetSet _statesetsHandled;
  28. GLObjectsVisitor::Mode _mode;
  29. DrawableSet _drawables;
  30. TextureSet _textures;
  31. ProgramSet _programs;
  32. bool _assignPBOToImages;
  33. osg::ref_ptr<osg::PixelBufferObject> _pbo;
  34. osg::ref_ptr<osg::Object> _markerObject;
  35. bool empty() const { return _textures.empty() && _programs.empty() && _drawables.empty(); }
  36. virtual void apply(osg::Node& node);
  37. virtual void apply(osg::Drawable& drawable);
  38. virtual void apply(osg::StateSet& stateset);
  39. virtual void apply(osg::Texture& texture);
  40. };
  41. class OSGUTIL_EXPORT IncrementalCompileOperation : public osg::GraphicsOperation
  42. {
  43. public:
  44. IncrementalCompileOperation();
  45. /** Return true if the IncrementCompileOperation is active.*/
  46. bool isActive() const { return !_contexts.empty(); }
  47. bool requiresCompile(StateToCompile& stateToCompile);
  48. /** Set the target frame rate that the IncrementalCompileOperation should assume.
  49. * Typically one would set this to the value refresh rate of your display system i.e. 60Hz.
  50. * Default value is 100.
  51. * Usage notes. The TargetFrameRate and the MinimumTimeAvailableForGLCompileAndDeletePerFrame
  52. * parameters are not directly used by IncrementalCompileOperation, but are should be used as a guide for how
  53. * long to set aside per frame for compiling and deleting OpenGL objects. The longer amount of
  54. * time to set aside the faster databases will be paged in but with increased chance of frame drops,
  55. * the lower the amount of time the set aside the slower databases will paged it but with better
  56. * chance of avoid any frame drops. The default values are chosen to achieve the later when running
  57. * on a modern mid to high end PC.
  58. * The way to compute the amount of available time use a scheme such as :
  59. * availableTime = maximum(1.0/targetFrameRate - timeTakenDuringUpdateCullAndDraw, minimumTimeAvailableForGLCompileAndDeletePerFrame).
  60. */
  61. void setTargetFrameRate(double tfr) { _targetFrameRate = tfr; }
  62. /** Get the target frame rate that the IncrementalCompileOperation should assume.*/
  63. double getTargetFrameRate() const { return _targetFrameRate; }
  64. /** Set the minimum amount of time (in seconds) that should be made available for compiling and delete OpenGL objects per frame.
  65. * Default value is 0.001 (1 millisecond).
  66. * For usage see notes in setTargetFrameRate.*/
  67. void setMinimumTimeAvailableForGLCompileAndDeletePerFrame(double ta) { _minimumTimeAvailableForGLCompileAndDeletePerFrame = ta; }
  68. /** Get the minimum amount of time that should be made available for compiling and delete OpenGL objects per frame.
  69. * For usage see notes in setTargetFrameRate.*/
  70. double getMinimumTimeAvailableForGLCompileAndDeletePerFrame() const { return _minimumTimeAvailableForGLCompileAndDeletePerFrame; }
  71. /** Set the maximum number of OpenGL objects that the page should attempt to compile per frame.
  72. * Note, Lower values reduces chances of a frame drop but lower the rate that database will be paged in at.
  73. * Default value is 8. */
  74. void setMaximumNumOfObjectsToCompilePerFrame(unsigned int num) { _maximumNumOfObjectsToCompilePerFrame = num; }
  75. /** Get the maximum number of OpenGL objects that the page should attempt to compile per frame.*/
  76. unsigned int getMaximumNumOfObjectsToCompilePerFrame() const { return _maximumNumOfObjectsToCompilePerFrame; }
  77. /** FlushTimeRatio governs how much of the spare time in each frame is used for flushing deleted OpenGL objects.
  78. * Default value is 0.5, valid range is 0.1 to 0.9.*/
  79. void setFlushTimeRatio(double ratio) { _flushTimeRatio = ratio; }
  80. double getFlushTimeRatio() const { return _flushTimeRatio; }
  81. /** ConservativeTimeRatio governs how much of the measured spare time in each frame is used for flushing deleted and compile new OpenGL objects.
  82. * Default value is 0.5, valid range is 0.1 to 1.0.
  83. * A ratio near 1.0 will lead to paged databases being compiled and merged quicker but increase the chances of frame drop.
  84. * A ratio near 0.1 will lead to paged databases being compiled and merged closer but reduce the chances of frame drop.*/
  85. void setConservativeTimeRatio(double ratio) { _conservativeTimeRatio = ratio; }
  86. double getConservativeTimeRatio() const { return _conservativeTimeRatio; }
  87. /** Assign a geometry and associated StateSet than is applied after each texture compile to atttempt to force the OpenGL
  88. * drive to download the texture object to OpenGL graphics card.*/
  89. void assignForceTextureDownloadGeometry();
  90. /** Set the osg::Geometry to apply after each texture compile to atttempt to force the OpenGL
  91. * drive to download the texture object to OpenGL graphics card.*/
  92. void setForceTextureDownloadGeometry(osg::Geometry* geom) { _forceTextureDownloadGeometry = geom; }
  93. osg::Geometry* getForceTextureDownloadGeometry() { return _forceTextureDownloadGeometry.get(); }
  94. const osg::Geometry* getForceTextureDownloadGeometry() const { return _forceTextureDownloadGeometry.get(); }
  95. typedef std::vector<osg::GraphicsContext*> Contexts;
  96. void assignContexts(Contexts& contexts);
  97. void removeContexts(Contexts& contexts);
  98. void addGraphicsContext(osg::GraphicsContext* gc);
  99. void removeGraphicsContext(osg::GraphicsContext* gc);
  100. typedef std::set<osg::GraphicsContext*> ContextSet;
  101. ContextSet& getContextSet() { return _contexts; }
  102. const ContextSet& getContextSet() const { return _contexts; }
  103. /** Merge subgraphs that have been compiled.*/
  104. void mergeCompiledSubgraphs(const osg::FrameStamp* frameStamp);
  105. /** Set the current frame number that the IncrementalCompileOperation should use as a reference
  106. * value for calculations based on current frame number.
  107. * Note, this value is set by the mergeCompiledSubgraphs(..) method so one won't normally need to call
  108. * set the CurrentFrameNumber manually.*/
  109. void setCurrentFrameNumber(unsigned int fn) { _currentFrameNumber = fn; }
  110. unsigned int getCurrentFrameNumber() const { return _currentFrameNumber; }
  111. /** tell the IncrementalCompileOperation to compile all pending objects during next draw traversal,
  112. * for specified number of frames.*/
  113. void compileAllForNextFrame(unsigned int numFramesToDoCompileAll=1);
  114. /** tell the IncrementalCompileOperation to compile all pending objects during next draw traversal,
  115. * till specified frame number.*/
  116. void setCompileAllTillFrameNumber(unsigned int fn) { _compileAllTillFrameNumber = fn; }
  117. unsigned int getCompileAllTillFrameNumber() const { return _compileAllTillFrameNumber; }
  118. virtual void operator () (osg::GraphicsContext* context);
  119. struct OSGUTIL_EXPORT CompileInfo : public osg::RenderInfo
  120. {
  121. CompileInfo(osg::GraphicsContext* context, IncrementalCompileOperation* ico);
  122. bool okToCompile(double estimatedTimeForCompile=0.0) const
  123. {
  124. if (compileAll) return true;
  125. if (maxNumObjectsToCompile==0) return false;
  126. return (allocatedTime - timer.elapsedTime()) >= estimatedTimeForCompile;
  127. }
  128. IncrementalCompileOperation* incrementalCompileOperation;
  129. bool compileAll;
  130. unsigned int maxNumObjectsToCompile;
  131. double allocatedTime;
  132. osg::ElapsedTime timer;
  133. };
  134. struct CompileOp : public osg::Referenced
  135. {
  136. /** return an estimate for how many seconds the compile will take.*/
  137. virtual double estimatedTimeForCompile(CompileInfo& compileInfo) const = 0;
  138. /** compile associated objects, return true if object as been fully compiled and this CompileOp can be removed from the to compile list.*/
  139. virtual bool compile(CompileInfo& compileInfo) = 0;
  140. };
  141. struct OSGUTIL_EXPORT CompileDrawableOp : public CompileOp
  142. {
  143. CompileDrawableOp(osg::Drawable* drawable);
  144. double estimatedTimeForCompile(CompileInfo& compileInfo) const;
  145. bool compile(CompileInfo& compileInfo);
  146. osg::ref_ptr<osg::Drawable> _drawable;
  147. };
  148. struct OSGUTIL_EXPORT CompileTextureOp : public CompileOp
  149. {
  150. CompileTextureOp(osg::Texture* texture);
  151. double estimatedTimeForCompile(CompileInfo& compileInfo) const;
  152. bool compile(CompileInfo& compileInfo);
  153. osg::ref_ptr<osg::Texture> _texture;
  154. };
  155. struct OSGUTIL_EXPORT CompileProgramOp : public CompileOp
  156. {
  157. CompileProgramOp(osg::Program* program);
  158. double estimatedTimeForCompile(CompileInfo& compileInfo) const;
  159. bool compile(CompileInfo& compileInfo);
  160. osg::ref_ptr<osg::Program> _program;
  161. };
  162. class OSGUTIL_EXPORT CompileList
  163. {
  164. public:
  165. CompileList();
  166. ~CompileList();
  167. bool empty() const { return _compileOps.empty(); }
  168. void add(CompileOp* compileOp);
  169. void add(osg::Drawable* drawable) { add(new CompileDrawableOp(drawable)); }
  170. void add(osg::Texture* texture) { add(new CompileTextureOp(texture)); }
  171. void add(osg::Program* program) { add(new CompileProgramOp(program)); }
  172. double estimatedTimeForCompile(CompileInfo& compileInfo) const;
  173. bool compile(CompileInfo& compileInfo);
  174. typedef std::list< osg::ref_ptr<CompileOp> > CompileOps;
  175. CompileOps _compileOps;
  176. };
  177. class CompileSet;
  178. struct CompileCompletedCallback : public virtual osg::Referenced
  179. {
  180. /// return true if the callback assumes responsibility for merging any associated subgraphs with the main scene graph
  181. /// return false if callback doesn't handle the merge, and instead requires the IncrementalCompileOperation to handle this for us
  182. virtual bool compileCompleted(CompileSet* compileSet) = 0;
  183. };
  184. class OSGUTIL_EXPORT CompileSet : public osg::Referenced
  185. {
  186. public:
  187. CompileSet() {}
  188. CompileSet(osg::Node*subgraphToCompile):
  189. _subgraphToCompile(subgraphToCompile) {}
  190. CompileSet(osg::Group* attachmentPoint, osg::Node* subgraphToCompile):
  191. _attachmentPoint(attachmentPoint),
  192. _subgraphToCompile(subgraphToCompile) {}
  193. void buildCompileMap(ContextSet& contexts, StateToCompile& stateToCompile);
  194. void buildCompileMap(ContextSet& contexts, GLObjectsVisitor::Mode mode=GLObjectsVisitor::COMPILE_DISPLAY_LISTS|GLObjectsVisitor::COMPILE_STATE_ATTRIBUTES);
  195. bool compile(CompileInfo& compileInfo);
  196. bool compiled() const { return _numberCompileListsToCompile==0; }
  197. OpenThreads::Atomic _numberCompileListsToCompile;
  198. osg::observer_ptr<osg::Group> _attachmentPoint;
  199. osg::ref_ptr<osg::Node> _subgraphToCompile;
  200. osg::ref_ptr<CompileCompletedCallback> _compileCompletedCallback;
  201. typedef std::map<osg::GraphicsContext*, CompileList > CompileMap;
  202. CompileMap _compileMap;
  203. osg::ref_ptr<osg::Object> _markerObject;
  204. protected:
  205. virtual ~CompileSet() {}
  206. };
  207. typedef std::list< osg::ref_ptr<CompileSet> > CompileSets;
  208. /** Add a subgraph to be compiled.*/
  209. void add(osg::Node* subgraphToCompile);
  210. /** Add a subgraph to be compiled and add automatically to attachPoint on call to mergeCompiledSubgraphs.*/
  211. void add(osg::Group* attachmentPoint, osg::Node* subgraphToCompile);
  212. /** Add a CompileSet to be compiled.*/
  213. void add(CompileSet* compileSet, bool callBuildCompileMap=true);
  214. /** Remove CompileSet from list.*/
  215. void remove(CompileSet* compileSet);
  216. OpenThreads::Mutex* getToCompiledMutex() { return &_toCompileMutex; }
  217. CompileSets& getToCompile() { return _toCompile; }
  218. OpenThreads::Mutex* getCompiledMutex() { return &_compiledMutex; }
  219. CompileSets& getCompiled() { return _compiled; }
  220. void setMarkerObject(osg::Object* mo) { _markerObject = mo; }
  221. osg::Object* getMarkerObject() { return _markerObject.get(); }
  222. const osg::Object* getMarkerObject() const { return _markerObject.get(); }
  223. protected:
  224. virtual ~IncrementalCompileOperation();
  225. void compileSets(CompileSets& toCompile, CompileInfo& compileInfo);
  226. double _targetFrameRate;
  227. double _minimumTimeAvailableForGLCompileAndDeletePerFrame;
  228. unsigned int _maximumNumOfObjectsToCompilePerFrame;
  229. double _flushTimeRatio;
  230. double _conservativeTimeRatio;
  231. unsigned int _currentFrameNumber;
  232. unsigned int _compileAllTillFrameNumber;
  233. osg::ref_ptr<osg::Geometry> _forceTextureDownloadGeometry;
  234. OpenThreads::Mutex _toCompileMutex;
  235. CompileSets _toCompile;
  236. OpenThreads::Mutex _compiledMutex;
  237. CompileSets _compiled;
  238. ContextSet _contexts;
  239. osg::ref_ptr<osg::Object> _markerObject;
  240. };
  241. }
  242. #endif