root/OpenSceneGraph/trunk/include/osgDB/DatabasePager @ 7074

Revision 7074, 19.1 kB (checked in by robert, 7 years ago)

Added include/osg/GLObjects + .cpp which provide osg::flush*DeletedGLObjects() methods.

Added and cleaned up DeleteHandler? calls in osgViewer to help avoid crashes on exit.

Changed DatabasePager? across to dynamically checcking osg::getCompileContext(..)

Updated wrappers.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
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
14#ifndef OSGDB_DATABASEPAGER
15#define OSGDB_DATABASEPAGER 1
16
17#include <osg/NodeVisitor>
18#include <osg/Group>
19#include <osg/PagedLOD>
20#include <osg/Drawable>
21#include <osg/GraphicsThread>
22
23#include <OpenThreads/Thread>
24#include <OpenThreads/Mutex>
25#include <OpenThreads/ScopedLock>
26#include <OpenThreads/Condition>
27
28#include <osgDB/SharedStateManager>
29#include <osgDB/ReaderWriter>
30#include <osgDB/Export>
31
32#include <map>
33#include <list>
34
35namespace osgDB {
36
37
38/** Database paging class which manages the loading of files in a background thread,
39  * and syncronizing of loaded models with the main scene graph.*/
40class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandler, public OpenThreads::Thread
41{
42    public :
43
44        typedef OpenThreads::Thread::ThreadPriority ThreadPriority;
45
46        DatabasePager();
47
48        /** Add a request to load a node file to end the the database request list.*/
49        virtual void requestNodeFile(const std::string& fileName,osg::Group* group,
50                                     float priority, const osg::FrameStamp* framestamp);
51
52        virtual void requestNodeFile(const std::string& fileName,osg::Group* group,
53                                     float priority, const osg::FrameStamp* framestamp,
54                                     ReaderWriter::Options* loadOptions);
55
56        /** Run does the database paging.*/       
57        virtual void run();
58       
59        /** Cancel the database pager thread.*/       
60        virtual int cancel();
61       
62        /** Clear all internally cached structures.*/
63        virtual void clear();
64       
65        /** Set whether the database pager thread should be paused or not.*/
66        void setDatabasePagerThreadPause(bool pause);
67       
68        /** Get whether the database pager thread should is paused or not.*/
69        bool getDatabasePagerThreadPause() const { return _databasePagerThreadPaused; }
70       
71        /** Set whether new database request calls are accepted or ignored.*/
72        void setAcceptNewDatabaseRequests(bool acceptNewRequests) { _acceptNewRequests = acceptNewRequests; }
73       
74        /** Get whether new database request calls are accepted or ignored.*/
75        bool getAcceptNewDatabaseRequests() const { return _acceptNewRequests; }
76       
77        /** Set the use of the frame block which, if enabled, blocks the DatabasePager
78          * from executing which the current frame is being drawn. 
79          * When a single processor machine is being used it can be useful to block on
80          * frame to help prevent the database paging thread from slowing the cull and draw
81          * traversals which in turn can cause frame drops.*/
82        void setUseFrameBlock(bool useFrameBlock) { _useFrameBlock = useFrameBlock; }
83       
84        /** Get the whether UseFrameBlock is on or off.*/
85        bool getUseFrameBlock() const { return _useFrameBlock; }
86       
87        osg::RefBlock* getFrameBlock() { return _frameBlock.get(); }
88
89        /** Set the priority of the database pager thread during the frame (i.e. while cull and draw are running.)*/
90        void setThreadPriorityDuringFrame(ThreadPriority duringFrame) { _threadPriorityDuringFrame = duringFrame; }
91
92        /** Get the priority of the database pager thread during the frame*/
93        ThreadPriority getThreadPriorityDuringFrame() const { return _threadPriorityDuringFrame; }
94       
95        /** Set the priority of the database pager thread when the frame is not being exectuted (i.e. before or after cull and draw have run.)*/
96        void setThreadPriorityOutwithFrame(ThreadPriority outwithFrame)  { _threadPriorityOutwithFrame = outwithFrame; }
97
98        /** Get the priority of the database pager thread when the frame is not being exectuted.*/
99        ThreadPriority getThreadPriorityOutwithFrame() const { return _threadPriorityOutwithFrame; }
100       
101       
102        /** Get the number of frames that are currently active.*/
103        int getNumFramesActive() const { return _numFramesActive; }
104
105        /** Signal the database thread that the update, cull and draw has begun for a new frame.
106          * Note, this is called by the application so that the database pager can go to sleep while the CPU is busy on the main rendering threads. */
107        virtual void signalBeginFrame(const osg::FrameStamp* framestamp);
108       
109        /** Signal the database thread that the update, cull and draw dispatch has completed.
110          * Note, this is called by the application so that the database pager can go to wake back up now the main rendering threads are iddle waiting for the next frame.*/
111        virtual void signalEndFrame();
112       
113
114        /** Find all PagedLOD nodes in a subgraph and register them with
115          * the DatabasePager so it can keep track of expired nodes.
116          * note, should be only be called from the update thread. */
117        virtual void registerPagedLODs(osg::Node* subgraph);
118
119        /** Set whether the database pager should pre compile OpenGL objects before allowing
120          * them to be merged into the scene graph.
121          * Pre compilation helps reduce the chances of frame drops, but also slows the
122          * speed at which tiles are merged as they have to be compiled first.*/
123        void setDoPreCompile(bool flag) { _doPreCompile = flag; }
124
125        /** Get whether the database pager should pre compile OpenGL objects before allowing
126          * them to be merged into the scene graph.*/
127        bool getDoPreCompile() const { return _doPreCompile; }
128
129
130        /** Set the target frame rate that the DatabasePager should assume.
131          * Typically one would set this to the value refresh rate of your display system i.e. 60Hz.
132          * Default value is 100.
133          * Usage notes.  The TargetFrameRate and the MinimumTimeAvailableForGLCompileAndDeletePerFrame
134          * parameters are not directly used by DatabasePager, but are should be used as a guide for how
135          * long to set aside per frame for compiling and deleting OpenGL objects - ie. the value to use
136          * when calling DatabasePager::compileGLObjectgs(state,availableTime,). The longer amount of
137          * time to set aside  cthe faster databases will be paged in but with increased chance of frame drops,
138          * the lower the amount of time the set aside the slower databases will paged it but with better
139          * chance of avoid any frame drops.  The default values are chosen to achieve the later when running
140          * on a modern mid to high end  PC.
141          * The way to compute the amount of available time use a scheme such as :
142          *    availableTime = maximum(1.0/targetFrameRate - timeTakenDuringUpdateCullAndDraw, minimumTimeAvailableForGLCompileAndDeletePerFrame).
143          */
144        void setTargetFrameRate(double tfr) { _targetFrameRate = tfr; }
145
146        /** Get the target frame rate that the DatabasePager should assume.*/
147        double getTargetFrameRate() const { return _targetFrameRate; }
148       
149        /** Set the minimum amount of time (in seconds) that should be made available for compiling and delete OpenGL objects per frame.
150          * Default value is 0.001 (1 millisecond).
151          * For usage see notes in setTargetFrameRate.*/
152        void setMinimumTimeAvailableForGLCompileAndDeletePerFrame(double ta) { _minimumTimeAvailableForGLCompileAndDeletePerFrame = ta; }
153
154        /** Get the minimum amount of time that should be made available for compiling and delete OpenGL objects per frame.
155          * For usage see notes in setTargetFrameRate.*/
156        double getMinimumTimeAvailableForGLCompileAndDeletePerFrame() const { return _minimumTimeAvailableForGLCompileAndDeletePerFrame; }
157
158        /** Set the maximum number of OpenGL objects that the page should attempt to compile per frame.
159          * Note, Lower values reduces chances of a frame drop but lower the rate that database will be paged in at.
160          * Default value is 8. */
161        void setMaximumNumOfObjectsToCompilePerFrame(unsigned int num) { _maximumNumOfObjectsToCompilePerFrame = num; }
162
163        /** Get the maximum number of OpenGL objects that the page should attempt to compile per frame.*/
164        unsigned int getMaximumNumOfObjectsToCompilePerFrame() const { return _maximumNumOfObjectsToCompilePerFrame; }
165
166
167        /** Set the amount of time that a subgraph will be kept without being visited in the cull traversal
168          * before being removed.*/
169        void setExpiryDelay(double expiryDelay) { _expiryDelay = expiryDelay; }
170       
171        /** Get the amount of time that a subgraph will be kept without being visited in the cull traversal
172          * before being removed.*/
173        double getExpiryDelay() const { return _expiryDelay; }
174
175        /** Set whether the removed subgraphs should be deleted in the database thread or not.*/
176        void setDeleteRemovedSubgraphsInDatabaseThread(bool flag) { _deleteRemovedSubgraphsInDatabaseThread = flag; }
177       
178        /** Get whether the removed subgraphs should be deleted in the database thread or not.*/
179        bool getDeleteRemovedSubgraphsInDatabaseThread() const { return _deleteRemovedSubgraphsInDatabaseThread; }
180
181        enum DrawablePolicy
182        {
183            DO_NOT_MODIFY_DRAWABLE_SETTINGS,
184            USE_DISPLAY_LISTS,
185            USE_VERTEX_BUFFER_OBJECTS,
186            USE_VERTEX_ARRAYS
187        };
188
189        /** Set how loaded drawables should be handled w.r.t their display list/vertex buffer object/vertex array settings.*/
190        void setDrawablePolicy(DrawablePolicy policy) { _drawablePolicy = policy; }
191
192        /** Get how loaded drawables should be handled w.r.t their display list/vertex buffer object/vertex array settings.*/
193        DrawablePolicy getDrawablePolicy() const { return _drawablePolicy; }
194
195
196        /** Set whether newly loaded textures should have their UnrefImageDataAfterApply set to a specified value.*/
197        void setUnrefImageDataAfterApplyPolicy(bool changeAutoUnRef, bool valueAutoUnRef) { _changeAutoUnRef = changeAutoUnRef; _valueAutoUnRef = valueAutoUnRef; }
198
199        /** Get whether newly loaded textures should have their UnrefImageDataAfterApply set to a specified value.*/
200        void getUnrefImageDataAfterApplyPolicy(bool& changeAutoUnRef, bool& valueAutoUnRef) const { changeAutoUnRef = _changeAutoUnRef; valueAutoUnRef = _valueAutoUnRef; }
201
202
203        /** Set whether newly loaded textures should have their MaxAnisotopy set to a specified value.*/
204        void setMaxAnisotropyPolicy(bool changeAnisotropy, float valueAnisotropy) { _changeAnisotropy = changeAnisotropy; _valueAnisotropy = valueAnisotropy; }
205
206        /** Set whether newly loaded textures should have their MaxAnisotopy set to a specified value.*/
207        void getMaxAnisotropyPolicy(bool& changeAnisotropy, float& valueAnisotropy) const { changeAnisotropy = _changeAnisotropy; valueAnisotropy = _valueAnisotropy; }
208
209
210        /** Return true if there are pending updates to the scene graph that require a call to updateSceneGraph(double). */
211        bool requiresUpdateSceneGraph() const;
212       
213        /** Merge the changes to the scene graph by calling calling removeExpiredSubgraphs then addLoadedDataToSceneGraph.
214          * Note, must only be called from single thread update phase. */
215        virtual void updateSceneGraph(double currentFrameTime)
216        {
217            removeExpiredSubgraphs(currentFrameTime);
218            addLoadedDataToSceneGraph(currentFrameTime);
219        }
220       
221        /** Turn the compilation of rendering objects for specfied graphics context on (true) or off(false). */
222        void setCompileGLObjectsForContextID(unsigned int contextID, bool on);
223       
224        /** Get whether the compilation of rendering objects for specfied graphics context on (true) or off(false). */
225        bool getCompileGLObjectsForContextID(unsigned int contextID);
226
227        /** Rerturn true if an external draw thread should call compileGLObjects(..) or not.*/
228        bool requiresExternalCompileGLObjects(unsigned int contextID) const;
229
230        /** Return true if there are pending compile operations that are required.
231          * If requiresCompileGLObjects() return true the application should call compileGLObjects() .*/
232        bool requiresCompileGLObjects() const;
233
234        /** Compile the rendering objects (display lists,texture objects, VBO's) on loaded subgraph.
235          * note, should only be called from the draw thread.
236          * Note, must only be called from a valid graphics context. */
237        virtual void compileGLObjects(osg::State& state,double& availableTime);
238       
239        /** Compile the rendering objects (display lists,texture objects, VBO's) on loaded subgraph.
240          * note, should only be called from the draw thread.
241          * Note, must only be called from a valid graphics context. */
242        virtual void compileAllGLObjects(osg::State& state);
243
244        /** Report how many items are in the _fileRequestList queue */
245        unsigned int getFileRequestListSize() const { return _fileRequestList.size(); }
246
247        /** Report how many items are in the _dataToCompileList queue */
248        unsigned int getDataToCompileListSize() const { return _dataToCompileList.size(); }
249
250
251        typedef std::list< osg::ref_ptr<osg::PagedLOD> >                PagedLODList;
252        typedef std::set< osg::ref_ptr<osg::StateSet> >                 StateSetList;
253        typedef std::vector< osg::ref_ptr<osg::Drawable> >              DrawableList;
254        typedef std::pair<StateSetList,DrawableList>                    DataToCompile;
255        typedef std::map< unsigned int, DataToCompile >                 DataToCompileMap;
256        typedef std::set<unsigned int>                                  ActiveGraphicsContexts;
257        typedef std::vector< osg::observer_ptr<osg::GraphicsContext> >  CompileGraphicsContexts;
258
259    protected:
260
261        virtual ~DatabasePager();
262
263
264        friend struct DatabaseRequest;
265       
266        struct DatabaseRequest : public osg::Referenced
267        {
268            DatabaseRequest():
269                _numOfRequests(0)
270            {}
271           
272            std::string                 _fileName;
273            int                         _frameNumberFirstRequest;
274            double                      _timestampFirstRequest;
275            float                       _priorityFirstRequest;
276            int                         _frameNumberLastRequest;
277            double                      _timestampLastRequest;
278            float                       _priorityLastRequest;
279            unsigned int                _numOfRequests;
280            osg::ref_ptr<osg::Group>    _groupForAddingLoadedSubgraph;
281            osg::ref_ptr<osg::Node>     _loadedModel;
282            DataToCompileMap            _dataToCompileMap;
283            osg::ref_ptr<ReaderWriter::Options> _loadOptions;
284        };
285       
286        typedef std::vector< osg::ref_ptr<DatabaseRequest> > DatabaseRequestList;
287        typedef std::vector<  osg::ref_ptr<osg::Object> > ObjectList;
288
289        // forward declare inner helper classes
290        class FindCompileableGLObjectsVisitor;
291        friend class FindCompileableGLObjectsVisitor;
292       
293        class FindPagedLODsVisitor;
294        friend class FindPagedLODsVisitor;
295
296        struct SortFileRequestFunctor;
297        friend struct SortFileRequestFunctor;
298
299       
300        OpenThreads::Mutex              _run_mutex;
301        bool                            _startThreadCalled;
302
303       
304        osg::ref_ptr<osg::RefBlock>    _databasePagerThreadBlock;
305
306        inline void updateDatabasePagerThreadBlock()
307        {
308            _databasePagerThreadBlock->set(
309                (!_fileRequestList.empty() || !_childrenToDeleteList.empty()) && !_databasePagerThreadPaused);
310        }
311       
312        inline void updateFrameBlock(int delta)
313        {
314            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_numFramesActiveMutex);
315            _numFramesActive += delta;
316            _frameBlock->set(_numFramesActive==0);
317        }
318
319
320        /** Iterate through the active PagedLOD nodes children removing
321          * children which havn't been visited since specified expiryTime.
322          * note, should be only be called from the update thread. */
323        virtual void removeExpiredSubgraphs(double currentFrameTime);
324
325        /** Add the loaded data to the scene graph.*/
326        void addLoadedDataToSceneGraph(double currentFrameTime);
327
328
329        bool                            _done;
330        bool                            _acceptNewRequests;
331        bool                            _databasePagerThreadPaused;
332   
333        bool                            _useFrameBlock;
334        int                             _numFramesActive;
335        mutable OpenThreads::Mutex      _numFramesActiveMutex;
336        osg::ref_ptr<osg::RefBlock>     _frameBlock;
337        int                             _frameNumber;
338
339        ThreadPriority                  _threadPriorityDuringFrame;
340        ThreadPriority                  _threadPriorityOutwithFrame;
341
342        DatabaseRequestList             _fileRequestList;
343        mutable OpenThreads::Mutex      _fileRequestListMutex;
344       
345        DatabaseRequestList             _dataToCompileList;
346        mutable OpenThreads::Mutex      _dataToCompileListMutex;
347
348        DrawablePolicy                  _drawablePolicy;
349
350        bool                            _changeAutoUnRef;
351        bool                            _valueAutoUnRef;
352        bool                            _changeAnisotropy;
353        float                           _valueAnisotropy;
354
355        bool                            _deleteRemovedSubgraphsInDatabaseThread;
356        ObjectList                      _childrenToDeleteList;
357        mutable OpenThreads::Mutex      _childrenToDeleteListMutex;
358
359        DatabaseRequestList             _dataToMergeList;
360        mutable OpenThreads::Mutex      _dataToMergeListMutex;
361       
362       
363        PagedLODList                    _activePagedLODList;
364        PagedLODList                    _inactivePagedLODList;
365       
366        double                          _expiryDelay;
367
368        ActiveGraphicsContexts          _activeGraphicsContexts;
369        // CompileGraphicsContexts         _compileGraphicsContexts;
370       
371        bool                            _doPreCompile;
372        double                          _targetFrameRate;
373        double                          _minimumTimeAvailableForGLCompileAndDeletePerFrame;
374        unsigned int                    _maximumNumOfObjectsToCompilePerFrame;
375       
376        struct CompileOperation : public osg::Operation
377        {
378            CompileOperation(DatabasePager* databasePager);
379           
380            virtual void operator () (osg::Object* object);
381           
382            osg::observer_ptr<DatabasePager> _databasePager;
383        };
384};
385
386}
387
388#endif
Note: See TracBrowser for help on using the browser.