root/OpenSceneGraph/trunk/include/osg/BufferObject @ 9302

Revision 9302, 18.2 kB (checked in by robert, 6 years ago)

From Art Tevs, "here is a submission of an additional class of PixelBufferObejct?, which implements more general way of handling with PBOs. Current osg implementation of PBO does use an attached osg::Image to copy data from. This is somehow only one way of using it and doesn't provide full functionality of PBOs.


Descripton:

The patch does provide a new class PixelDataBufferObject? which is capable of allocating memory on the GPU side (PBO memory) of arbitrary size. The memory can then further be used to be enabled into read mode (GL_PIXEL_UNPACK_BUFFER_ARB) or in write mode (GL_PIXEL_PACK_BUFFER_ARB). Enabling the buffer into write mode will force the driver to write data from bounded textures into that buffer (i.e. glGetTexImage). Using buffer in read mode give you the possibility to read data from the buffer into a texture with e.g. glTexSubImage or other instuctions. Hence no data is copied over the CPU (host memory), all the operations are done in the GPU memory.


Compatibility:

The new class require the unbindBuffer method from the base class BufferObject? to be virtual, which shouldn't break any functionality of already existing classes. Except of this the new class is fully orthogonal to existing one, hence can be safely added into already existing osg system.


Testing:

The new class was tested in the current svn version of osgPPU. I am using the new class to copy data from textures into the PBO and hence provide them to CUDA kernels. Also reading the results back from CUDA is implemented using the provided patch. The given patch gives a possibility of easy interoperability between CUDA and osg (osgPPU ;) )


I think in general it is a better way to derive the PixelBufferObject? class from PixelDataBufferObject?, since the second one is a generalization of the first one. However this could break the current functionality, hence I haven't implemented it in such a way. However I would push that on a stack of wished osg 3.x features, since this will reflect the OpenGL PBO functionality through the classes better.
"

  • 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 OSG_BUFFEROBJECT
15#define OSG_BUFFEROBJECT 1
16
17#include <osg/GL>
18#include <osg/Object>
19#include <osg/buffered_value>
20
21#ifndef GL_ARB_vertex_buffer_object
22
23    #define GL_ARB_vertex_buffer_object
24
25    // for compatibility with gl.h headers that don't support VBO,
26    #if defined(_WIN64)
27        typedef __int64 GLintptrARB;
28        typedef __int64 GLsizeiptrARB;
29    #elif defined(__ia64__) || defined(__x86_64__)
30        typedef long int GLintptrARB;
31        typedef long int GLsizeiptrARB;
32    #else
33        typedef int GLintptrARB;
34        typedef int GLsizeiptrARB;
35    #endif
36
37    #define GL_ARRAY_BUFFER_ARB               0x8892
38    #define GL_ELEMENT_ARRAY_BUFFER_ARB       0x8893
39    #define GL_ARRAY_BUFFER_BINDING_ARB       0x8894
40    #define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895
41    #define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896
42    #define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897
43    #define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898
44    #define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899
45    #define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A
46    #define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B
47    #define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C
48    #define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D
49    #define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E
50    #define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F
51    #define GL_STREAM_DRAW_ARB                0x88E0
52    #define GL_STREAM_READ_ARB                0x88E1
53    #define GL_STREAM_COPY_ARB                0x88E2
54    #define GL_STATIC_DRAW_ARB                0x88E4
55    #define GL_STATIC_READ_ARB                0x88E5
56    #define GL_STATIC_COPY_ARB                0x88E6
57    #define GL_DYNAMIC_DRAW_ARB               0x88E8
58    #define GL_DYNAMIC_READ_ARB               0x88E9
59    #define GL_DYNAMIC_COPY_ARB               0x88EA
60    #define GL_READ_ONLY_ARB                  0x88B8
61    #define GL_WRITE_ONLY_ARB                 0x88B9
62    #define GL_READ_WRITE_ARB                 0x88BA
63    #define GL_BUFFER_SIZE_ARB                0x8764
64    #define GL_BUFFER_USAGE_ARB               0x8765
65    #define GL_BUFFER_ACCESS_ARB              0x88BB
66    #define GL_BUFFER_MAPPED_ARB              0x88BC
67    #define GL_BUFFER_MAP_POINTER_ARB         0x88BD
68
69#endif
70
71#ifndef GL_VERSION_1_5
72    #define GL_STREAM_DRAW                    0x88E0
73    #define GL_STREAM_READ                    0x88E1
74    #define GL_STREAM_COPY                    0x88E2
75    #define GL_STATIC_DRAW                    0x88E4
76    #define GL_STATIC_READ                    0x88E5
77    #define GL_STATIC_COPY                    0x88E6
78    #define GL_DYNAMIC_DRAW                   0x88E8
79    #define GL_DYNAMIC_READ                   0x88E9
80    #define GL_DYNAMIC_COPY                   0x88EA
81#endif
82
83#ifndef GL_VERSION_2_1
84    #define GL_PIXEL_PACK_BUFFER              0x88EB
85    #define GL_PIXEL_UNPACK_BUFFER            0x88EC
86    #define GL_PIXEL_PACK_BUFFER_BINDING      0x88ED
87    #define GL_PIXEL_UNPACK_BUFFER_BINDING    0x88EF
88#endif
89
90
91#ifndef GL_ARB_pixel_buffer_object
92    #define GL_PIXEL_PACK_BUFFER_ARB            0x88EB
93    #define GL_PIXEL_UNPACK_BUFFER_ARB          0x88EC
94    #define GL_PIXEL_PACK_BUFFER_BINDING_ARB    0x88ED
95    #define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB  0x88EF
96#endif
97
98namespace osg
99{
100
101class State;
102
103class OSG_EXPORT BufferObject : public Object
104{
105    public:
106
107        BufferObject();
108
109        /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
110        BufferObject(const BufferObject& bo,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
111
112        virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const BufferObject*>(obj)!=NULL; }
113        virtual const char* libraryName() const { return "osg"; }
114        virtual const char* className() const { return "BufferObject"; }
115
116        /** Set what type of usage the buffer object will have. Options are:
117          *          GL_STREAM_DRAW, GL_STREAM_READ, GL_STREAM_COPY,
118          *          GL_STATIC_DRAW, GL_STATIC_READ, GL_STATIC_COPY,
119          *          GL_DYNAMIC_DRAW, GL_DYNAMIC_READ, or GL_DYNAMIC_COPY.
120          */
121        void setUsage(GLenum usage) { _usage = usage; }
122       
123        /** Get the type of usage the buffer object has been set up for.*/
124        GLenum getUsage() const { return _usage; }
125
126        struct BufferEntry
127        {
128            BufferEntry(): dataSize(0),offset(0) {}
129            BufferEntry(const BufferEntry& be): modifiedCount(be.modifiedCount),dataSize(be.dataSize),offset(be.offset) {}
130       
131            BufferEntry& operator = (const BufferEntry& be) { modifiedCount=be.modifiedCount; dataSize=be.dataSize; offset=be.offset; return *this; }
132
133            mutable buffered_value<unsigned int>    modifiedCount;
134            mutable unsigned int                    dataSize;
135            mutable unsigned int                    offset;
136        };
137
138        inline bool isBufferObjectSupported(unsigned int contextID) const { return getExtensions(contextID,true)->isBufferObjectSupported(); }
139        inline bool isPBOSupported(unsigned int contextID) const { return getExtensions(contextID,true)->isPBOSupported(); }
140
141        inline GLuint& buffer(unsigned int contextID) const { return _bufferObjectList[contextID]; }
142       
143        inline void bindBuffer(unsigned int contextID) const
144        {
145            Extensions* extensions = getExtensions(contextID,true);
146            extensions->glBindBuffer(_target,_bufferObjectList[contextID]);
147        }
148
149        virtual void unbindBuffer(unsigned int contextID) const
150        {
151            Extensions* extensions = getExtensions(contextID,true);
152            extensions->glBindBuffer(_target,0);
153        }
154
155        inline void dirty() { _compiledList.setAllElementsTo(0); }
156
157        bool isDirty(unsigned int contextID) const { return _compiledList[contextID]==0; }
158
159        virtual void compileBuffer(State& state) const = 0;
160       
161        /** Resize any per context GLObject buffers to specified size. */
162        virtual void resizeGLObjectBuffers(unsigned int maxSize);
163
164        /** If State is non-zero, this function releases OpenGL objects for
165          * the specified graphics context. Otherwise, releases OpenGL objects
166          * for all graphics contexts. */
167        void releaseGLObjects(State* state=0) const;
168
169
170        /** Use deleteVertexBufferObject instead of glDeleteBuffers to allow
171          * OpenGL buffer objects to be cached until they can be deleted
172          * by the OpenGL context in which they were created, specified
173          * by contextID.*/
174        static void deleteBufferObject(unsigned int contextID,GLuint globj);
175
176        /** flush all the cached display list which need to be deleted
177          * in the OpenGL context related to contextID.*/
178        static void flushDeletedBufferObjects(unsigned int contextID,double /*currentTime*/, double& availableTime);
179
180        /** dicard all the cached display list which need to be deleted
181          * in the OpenGL context related to contextID.
182          * Note, unlike flush no OpenGL calls are made, instead the handles are all removed.
183          * this call is useful for when an OpenGL context has been destroyed. */
184        static void discardDeletedBufferObjects(unsigned int contextID);
185
186        /** Extensions class which encapsulates the querying of extensions and
187        * associated function pointers, and provide convenience wrappers to
188        * check for the extensions or use the associated functions.*/
189        class OSG_EXPORT Extensions : public osg::Referenced
190        {
191        public:
192            Extensions(unsigned int contextID);
193
194            Extensions(const Extensions& rhs);
195
196            void lowestCommonDenominator(const Extensions& rhs);
197
198            void setupGLExtensions(unsigned int contextID);
199
200            bool isBufferObjectSupported() const { return _glGenBuffers!=0; }
201            bool isPBOSupported() const { return _isPBOSupported; }
202
203            void glGenBuffers (GLsizei n, GLuint *buffers) const;
204            void glBindBuffer (GLenum target, GLuint buffer) const;
205            void glBufferData (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage) const;
206            void glBufferSubData (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data) const;
207            void glDeleteBuffers (GLsizei n, const GLuint *buffers) const;
208            GLboolean glIsBuffer (GLuint buffer) const;
209            void glGetBufferSubData (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data) const;
210            GLvoid* glMapBuffer (GLenum target, GLenum access) const;
211            GLboolean glUnmapBuffer (GLenum target) const;
212            void glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params) const;
213            void glGetBufferPointerv (GLenum target, GLenum pname, GLvoid* *params) const;
214
215        protected:
216
217            typedef void (APIENTRY * GenBuffersProc) (GLsizei n, GLuint *buffers);
218            typedef void (APIENTRY * BindBufferProc) (GLenum target, GLuint buffer);
219            typedef void (APIENTRY * BufferDataProc) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage);
220            typedef void (APIENTRY * BufferSubDataProc) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data);
221            typedef void (APIENTRY * DeleteBuffersProc) (GLsizei n, const GLuint *buffers);
222            typedef GLboolean (APIENTRY * IsBufferProc) (GLuint buffer);
223            typedef void (APIENTRY * GetBufferSubDataProc) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data);
224            typedef GLvoid* (APIENTRY * MapBufferProc) (GLenum target, GLenum access);
225            typedef GLboolean (APIENTRY * UnmapBufferProc) (GLenum target);
226            typedef void (APIENTRY * GetBufferParameterivProc) (GLenum target, GLenum pname, GLint *params);
227            typedef void (APIENTRY * GetBufferPointervProc) (GLenum target, GLenum pname, GLvoid* *params);
228
229            GenBuffersProc          _glGenBuffers;
230            BindBufferProc          _glBindBuffer;
231            BufferDataProc          _glBufferData;
232            BufferSubDataProc       _glBufferSubData;
233            DeleteBuffersProc       _glDeleteBuffers;
234            IsBufferProc            _glIsBuffer;
235            GetBufferSubDataProc    _glGetBufferSubData;
236            MapBufferProc           _glMapBuffer;
237            UnmapBufferProc         _glUnmapBuffer;
238            GetBufferParameterivProc _glGetBufferParameteriv;
239            GetBufferPointervProc   _glGetBufferPointerv;
240
241            bool _isPBOSupported;
242        };
243
244        /** Function to call to get the extension of a specified context.
245        * If the Extension object for that context has not yet been created 
246        * and the 'createIfNotInitalized' flag been set to false then returns NULL.
247        * If 'createIfNotInitalized' is true then the Extensions object is
248        * automatically created.  However, in this case the extension object is
249        * only created with the graphics context associated with ContextID..*/
250        static Extensions* getExtensions(unsigned int contextID,bool createIfNotInitalized);
251
252        /** setExtensions allows users to override the extensions across graphics contexts.
253        * typically used when you have different extensions supported across graphics pipes
254        * but need to ensure that they all use the same low common denominator extensions.*/
255        static void setExtensions(unsigned int contextID,Extensions* extensions);
256
257    protected:
258   
259        virtual ~BufferObject();
260       
261        typedef osg::buffered_value<GLuint> GLObjectList;
262        typedef osg::buffered_value<unsigned int> CompiledList;
263
264        mutable GLObjectList    _bufferObjectList;
265        mutable CompiledList    _compiledList;
266
267        GLenum                  _target;
268        GLenum                  _usage;
269        mutable unsigned int    _totalSize;
270};
271
272class Array;
273class OSG_EXPORT VertexBufferObject : public BufferObject
274{
275    public:
276
277        VertexBufferObject();
278
279        /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
280        VertexBufferObject(const VertexBufferObject& vbo,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
281
282        META_Object(osg,VertexBufferObject);
283       
284        typedef std::pair< BufferEntry, Array* > BufferEntryArrayPair;
285        typedef std::vector< BufferEntryArrayPair > BufferEntryArrayPairs;
286
287        unsigned int addArray(osg::Array* array);
288        void removeArray(osg::Array* array);
289
290        void setArray(unsigned int i, Array* array);
291        Array* getArray(unsigned int i) { return _bufferEntryArrayPairs[i].second; }
292        const Array* getArray(unsigned int i) const { return _bufferEntryArrayPairs[i].second; }
293       
294        const GLvoid* getOffset(unsigned int i) const { return (const GLvoid*)(((char *)0)+(_bufferEntryArrayPairs[i].first.offset)); }
295
296        virtual void compileBuffer(State& state) const;
297
298        /** Resize any per context GLObject buffers to specified size. */
299        virtual void resizeGLObjectBuffers(unsigned int maxSize);
300
301    protected:
302   
303        virtual ~VertexBufferObject();
304       
305        BufferEntryArrayPairs _bufferEntryArrayPairs;
306};
307
308class DrawElements;
309class OSG_EXPORT ElementBufferObject : public BufferObject
310{
311    public:
312
313        ElementBufferObject();
314
315        /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
316        ElementBufferObject(const ElementBufferObject& pbo,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
317
318        META_Object(osg,ElementBufferObject);
319       
320        typedef std::pair< BufferEntry, DrawElements* > BufferEntryDrawElementsPair;
321        typedef std::vector< BufferEntryDrawElementsPair > BufferEntryDrawElementsPairs;
322
323        unsigned int addDrawElements(osg::DrawElements* PrimitiveSet);
324        void removeDrawElements(osg::DrawElements* PrimitiveSet);
325
326        void setDrawElements(unsigned int i, DrawElements* PrimitiveSet);
327        DrawElements* getDrawElements(unsigned int i) { return _bufferEntryDrawElementsPairs[i].second; }
328        const DrawElements* getDrawElements(unsigned int i) const { return _bufferEntryDrawElementsPairs[i].second; }
329       
330        const GLvoid* getOffset(unsigned int i) const { return (const GLvoid*)(((char *)0)+(_bufferEntryDrawElementsPairs[i].first.offset)); }
331
332        virtual void compileBuffer(State& state) const;
333
334        /** Resize any per context GLObject buffers to specified size. */
335        virtual void resizeGLObjectBuffers(unsigned int maxSize);
336
337    protected:
338   
339        virtual ~ElementBufferObject();
340       
341        BufferEntryDrawElementsPairs _bufferEntryDrawElementsPairs;
342};
343
344class Image;
345class OSG_EXPORT PixelBufferObject : public BufferObject
346{
347    public:
348
349        PixelBufferObject(osg::Image* image=0);
350
351        /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
352        PixelBufferObject(const PixelBufferObject& pbo,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
353
354        META_Object(osg,PixelBufferObject);
355       
356        typedef std::pair< BufferEntry, Image* > BufferEntryImagePair;
357
358        void setImage(osg::Image* image);
359
360        Image* getImage() { return _bufferEntryImagePair.second; }
361        const Image* getImage() const { return _bufferEntryImagePair.second; }
362       
363        unsigned int offset() const { return _bufferEntryImagePair.first.offset; }
364       
365        virtual void compileBuffer(State& state) const;
366
367        /** Resize any per context GLObject buffers to specified size. */
368        virtual void resizeGLObjectBuffers(unsigned int maxSize);
369
370    protected:
371   
372        virtual ~PixelBufferObject();
373       
374        BufferEntryImagePair _bufferEntryImagePair;
375};
376
377/**
378 * This object represent a general class of pixel buffer objects,
379 * which are capable of allocating buffer object (memory)
380 * on the GPU. The memory can then be used either for CPU-GPU
381 * pixel transfer or directly for GPU-GPU transfer, without CPU intervention.
382 **/
383class OSG_EXPORT PixelDataBufferObject : public BufferObject
384{
385    public:
386        PixelDataBufferObject();
387        PixelDataBufferObject(const PixelDataBufferObject& pbo, const CopyOp& copyop=CopyOp::SHALLOW_COPY);
388
389        META_Object(osg, PixelDataBufferObject);
390
391        //! Set new size of the buffer object. This will reallocate the memory on the next compile
392        inline void setDataSize(unsigned int size) { _bufferData.dataSize = size; dirty(); }
393
394        //! Get data size of the used buffer
395        inline unsigned int getDataSize() { return _bufferData.dataSize; }
396
397        //! Compile the buffer (reallocate the memory if buffer is dirty)
398        virtual void compileBuffer(State& state) const;
399
400        //! Bind the buffer in read mode, which means that data can be downloaded from the buffer (note: GL_PIXEL_UNPACK_BUFFER_ARB)
401        virtual void bindBufferInReadMode(State& state);
402
403        //! Bind the buffer in write mode, which means following OpenGL instructions will write data into the buffer (note: GL_PIXEL_PACK_BUFFER_ARB)
404        virtual void bindBufferInWriteMode(State& state);
405
406        //! Unbind the buffer
407        virtual void unbindBuffer(unsigned int contextID) const;
408
409        /** Resize any per context GLObject buffers to specified size. */
410        virtual void resizeGLObjectBuffers(unsigned int maxSize);
411
412        enum Mode
413        {
414            //! A normal mode of this data buffer
415            NONE = 0,
416
417            //! Buffer is in read mode (@see bindBufferInReadMode)
418            READ = 1,
419
420            //! Buffer is in write mode (@see bindBufferInWriteMode)
421            WRITE = 2
422        };
423
424        Mode getMode(unsigned int contextID) const { return (Mode)_mode[contextID]; }
425
426    protected:
427
428        virtual ~PixelDataBufferObject();
429
430        BufferEntry _bufferData;
431
432        typedef osg::buffered_value<unsigned int> ModeList;
433       
434        mutable ModeList _mode;
435       
436};
437
438
439}
440
441#endif
Note: See TracBrowser for help on using the browser.