root/OpenSceneGraph/trunk/examples/osgmemorytest/osgmemorytest.cpp @ 13347

Revision 12292, 18.3 kB (checked in by robert, 4 years ago)

Ran svn propset -R svn:eol-style native . on the OpenSceneGraph

  • Property svn:eol-style set to native
Line 
1/* OpenSceneGraph example, osganimate.
2*
3*  Permission is hereby granted, free of charge, to any person obtaining a copy
4*  of this software and associated documentation files (the "Software"), to deal
5*  in the Software without restriction, including without limitation the rights
6*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7*  copies of the Software, and to permit persons to whom the Software is
8*  furnished to do so, subject to the following conditions:
9*
10*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16*  THE SOFTWARE.
17*/
18
19#include <osg/Notify>
20#include <osg/Timer>
21#include <osg/ArgumentParser>
22#include <osg/Texture1D>
23#include <osg/Texture2D>
24#include <osg/Texture3D>
25#include <osg/Geometry>
26#include <osg/FrameBufferObject>
27
28#include <osgViewer/Version>
29
30#include <stdio.h>
31#include <iostream>
32
33class MemoryTest : public osg::Referenced
34{
35    public:
36};
37
38class GLObject : public osg::Referenced
39{
40    public:
41        virtual void apply(osg::RenderInfo& renderInfo) = 0;
42};
43
44class GLMemoryTest : public MemoryTest
45{
46    public:
47        virtual GLObject* allocate() = 0;
48};
49
50/////////////////////////////////////////////////////////////////////////
51//
52// Context test
53class ContextTest : public MemoryTest
54{
55    public:
56        ContextTest(int width, int height, bool pbuffer):
57            _width(width),
58            _height(height),
59            _pbuffer(pbuffer) {}
60       
61        virtual osg::GraphicsContext* allocate()
62        {
63            osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
64            traits->width = _width;
65            traits->height = _height;
66            traits->windowDecoration = true;
67            traits->pbuffer = _pbuffer;
68           
69            osg::ref_ptr<osg::GraphicsContext> window = osg::GraphicsContext::createGraphicsContext(traits.get());
70            if (window.valid())
71            {
72                if (window->realize())
73                {
74                    return window.release();
75                }
76                else
77                {
78                    if (_pbuffer) throw "Failed to realize PixelBuffer";
79                    else  throw "Failed to realize GraphicsWindow";
80                }
81            }
82            else
83            {
84                std::cerr<<"Error: Unable to create graphics context, problem with running osgViewer-"<<osgViewerGetVersion()<<", cannot create windows/pbuffers."<<std::endl;
85               
86                if (_pbuffer) throw "Failed to create PixelBuffer";
87                else  throw "Failed to create GraphicsWindow";
88            }
89        }
90       
91
92    protected:
93   
94        int     _width;
95        int     _height;
96        bool    _pbuffer;
97};
98
99////////////////////////////////////////////////////////////////////////
100//
101// Wrap StateAttribute
102class StateAttributeObject : public GLObject
103{
104    public:
105   
106        StateAttributeObject(osg::StateAttribute* sa): _attribute(sa) {}
107       
108        void apply(osg::RenderInfo& renderInfo)
109        {
110            _attribute->apply(*renderInfo.getState());
111           
112            if (renderInfo.getState()->checkGLErrors(_attribute.get()))
113            {
114                throw "OpenGL error";
115            }
116        }
117       
118        osg::ref_ptr<osg::StateAttribute> _attribute;
119};
120
121/////////////////////////////////////////////////////////////////////////
122//
123// Texture test
124class TextureTest : public GLMemoryTest
125{
126    public:
127
128        TextureTest(int width=256, int height=256, int depth=1):
129            _width(width),
130            _height(height),
131            _depth(depth) {}
132       
133        virtual GLObject* allocate()
134        {
135            if (_depth>1)
136            {
137                osg::ref_ptr<osg::Image> image = new osg::Image;
138                image->allocateImage(_width, _height, _depth, GL_RGBA, GL_UNSIGNED_BYTE);
139               
140                osg::ref_ptr<osg::Texture3D> texture = new osg::Texture3D;
141                texture->setImage(image.get());
142                texture->setResizeNonPowerOfTwoHint(false);
143               
144                return new StateAttributeObject(texture.get());
145            }
146            if (_height>1)
147            {
148                osg::ref_ptr<osg::Image> image = new osg::Image;
149                image->allocateImage(_width, _height, 1, GL_RGBA, GL_UNSIGNED_BYTE);
150               
151                osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
152                texture->setImage(image.get());
153                texture->setResizeNonPowerOfTwoHint(false);
154               
155                return new StateAttributeObject(texture.get());
156            }
157            if (_width>1)
158            {
159                osg::ref_ptr<osg::Image> image = new osg::Image;
160                image->allocateImage(_width, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE);
161               
162                osg::ref_ptr<osg::Texture1D> texture = new osg::Texture1D;
163                texture->setImage(image.get());
164                texture->setResizeNonPowerOfTwoHint(false);
165               
166                return new StateAttributeObject(texture.get());
167            }
168            else
169            {
170                throw "Invalid texture size of 0,0,0";
171            }
172        }
173       
174
175    protected:
176   
177        int     _width;
178        int     _height;
179        int     _depth;
180};
181
182
183/////////////////////////////////////////////////////////////////////////
184//
185// FrameBufferObject test
186class FboTest : public GLMemoryTest
187{
188    public:
189
190        FboTest(int width=1024, int height=1024, int depth=2):
191            _width(width),
192            _height(height),
193            _depth(depth) {}
194       
195        virtual GLObject* allocate()
196        {
197            osg::ref_ptr<osg::FrameBufferObject> fbo = new osg::FrameBufferObject;
198
199            if (_depth>=1) fbo->setAttachment(osg::Camera::COLOR_BUFFER, osg::FrameBufferAttachment(new osg::RenderBuffer(_width, _height, GL_RGBA)));
200            if (_depth>=2) fbo->setAttachment(osg::Camera::DEPTH_BUFFER, osg::FrameBufferAttachment(new osg::RenderBuffer(_width, _height, GL_DEPTH_COMPONENT24)));
201
202            return new StateAttributeObject(fbo.get());
203        }
204       
205
206    protected:
207   
208        int     _width;
209        int     _height;
210        int     _depth;
211};
212
213
214
215////////////////////////////////////////////////////////////////////////
216//
217// Wrap Drawable
218class DrawableObject : public GLObject
219{
220    public:
221   
222        DrawableObject(osg::Drawable* drawable): _drawable(drawable) {}
223       
224        void apply(osg::RenderInfo& renderInfo)
225        {
226            _drawable->draw(renderInfo);
227           
228            if (renderInfo.getState()->checkGLErrors("Drawable"))
229            {
230                throw "OpenGL error";
231            }
232        }
233       
234        osg::ref_ptr<osg::Drawable> _drawable;
235};
236
237/////////////////////////////////////////////////////////////////////////
238//
239// Geometry test
240class GeometryTest : public GLMemoryTest
241{
242    public:
243   
244        enum GLObjectType
245        {
246            VERTEX_ARRAY,
247            DISPLAY_LIST,
248            VERTEX_BUFFER_OBJECT
249        };
250   
251
252        GeometryTest(GLObjectType type, int width=64, int height=64):
253            _glObjectType(type),
254            _width(width),
255            _height(height) {}
256       
257        virtual GLObject* allocate()
258        {
259            unsigned int numVertices = _width * _height;
260            osg::Vec3Array* vertices = new osg::Vec3Array(numVertices);
261            for(int j=0; j<_height; ++j)
262            {
263                for(int i=0; i<_width; ++i)
264                {
265                    (*vertices)[i+j*_width].set(float(i),float(j),0.0f);
266                }
267            }
268
269            unsigned int numIndices = (_width-1) * (_height-1) * 4;
270            osg::DrawElementsUShort* quads = new osg::DrawElementsUShort(GL_QUADS);
271            quads->reserve(numIndices);
272            for(int j=0; j<_height-1; ++j)
273            {
274                for(int i=0; i<_width-1; ++i)
275                {
276                    quads->push_back(i   + j*_width);
277                    quads->push_back(i+1 + j*_width);
278                    quads->push_back(i+1 + (j+1)*_width);
279                    quads->push_back(i   + (j+1)*_width);
280                }
281            }
282           
283            osg::Geometry* geometry = new osg::Geometry;
284            geometry->setVertexArray(vertices);
285            geometry->addPrimitiveSet(quads);
286           
287            switch(_glObjectType)
288            {
289                case(VERTEX_ARRAY):
290                    geometry->setUseDisplayList(false);
291                    geometry->setUseVertexBufferObjects(false);
292                    break;
293                case(DISPLAY_LIST):
294                    geometry->setUseDisplayList(true);
295                    geometry->setUseVertexBufferObjects(false);
296                    break;
297                case(VERTEX_BUFFER_OBJECT):
298                    geometry->setUseDisplayList(false);
299                    geometry->setUseVertexBufferObjects(true);
300                    break;
301            }
302
303            return new DrawableObject(geometry);
304        }
305       
306
307    protected:
308   
309        GLObjectType    _glObjectType;
310        int             _width;
311        int             _height;
312};
313
314int main( int argc, char **argv )
315{
316    osg::ArgumentParser arguments(&argc,argv);
317   
318    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
319    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" tests OpenGL and Windowing memory scalability..");
320    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","List command line options.");
321    arguments.getApplicationUsage()->addCommandLineOption("--pbuffer","Create a 512x512 pixel buffer.");
322    arguments.getApplicationUsage()->addCommandLineOption("--pbuffer <width> <height>","Create a pixel buffer of specified dimensions.");
323    arguments.getApplicationUsage()->addCommandLineOption("--window","Create a 512x512 graphics window.");
324    arguments.getApplicationUsage()->addCommandLineOption("--window <width> <height>","Create a graphics window of specified dimensions.");
325    arguments.getApplicationUsage()->addCommandLineOption("--delay <micoseconds>","Set a delay in microseconds before all OpenGL object operations.");
326    arguments.getApplicationUsage()->addCommandLineOption("--texture <width> <height> <depth>","Allocate a 3D texture of specified dimensions.");
327    arguments.getApplicationUsage()->addCommandLineOption("--texture <width> <height>","Allocate a 2D texture of specified dimensions.");
328    arguments.getApplicationUsage()->addCommandLineOption("--texture <width>","Allocate a 1D texture of specified dimensions.");
329    arguments.getApplicationUsage()->addCommandLineOption("--geometry <width> <height>","Allocate a osg::Geometry representing a grid of specified size, using OpenGL Dislay Lists.");
330    arguments.getApplicationUsage()->addCommandLineOption("--geometry-va <width> <height>","Allocate a osg::Geometry representing a grid of specified size, using Vertex Arrays.");
331    arguments.getApplicationUsage()->addCommandLineOption("--geometry-vbo <width> <height>","Allocate a osg::Geometry representing a grid of specified size, using Vertex Buffer Objects.");
332    arguments.getApplicationUsage()->addCommandLineOption("--fbo <width> <height>","Allocate a FrameBufferObject of specified dimensions.");
333    arguments.getApplicationUsage()->addCommandLineOption("-c <num>","Set the number of contexts to create of each type specified.");
334    arguments.getApplicationUsage()->addCommandLineOption("-g <num>","Set the number of GL objects to create of each type specified.");
335
336    if (arguments.read("-h") || arguments.read("--help"))
337    {
338        arguments.getApplicationUsage()->write(std::cout, osg::ApplicationUsage::COMMAND_LINE_OPTION);
339        return 1;
340    }
341
342    if (arguments.argc()<=1)
343    {
344        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
345        return 1;
346    }
347
348
349    typedef std::list< osg::ref_ptr<GLMemoryTest> > GLMemoryTests;
350    typedef std::list< osg::ref_ptr<ContextTest> > ContextTests;
351
352    ContextTests contextTests;
353    GLMemoryTests glMemoryTests;
354   
355    int width, height, depth;
356    while(arguments.read("--pbuffer",width,height)) { contextTests.push_back(new ContextTest(width, height, true)); }
357    while(arguments.read("--pbuffer")) { contextTests.push_back(new ContextTest(512, 512, true)); }
358
359    while(arguments.read("--window",width,height)) { contextTests.push_back(new ContextTest(width, height, false)); }
360    while(arguments.read("--window")) { contextTests.push_back(new ContextTest(512,512, false)); }
361
362    while(arguments.read("--texture",width,height,depth)) { glMemoryTests.push_back(new TextureTest(width,height,depth)); }
363    while(arguments.read("--texture",width,height)) { glMemoryTests.push_back(new TextureTest(width,height,1)); }
364    while(arguments.read("--texture",width)) { glMemoryTests.push_back(new TextureTest(width,1,1)); }
365
366    while(arguments.read("--fbo",width,height,depth)) { glMemoryTests.push_back(new FboTest(width,height,depth)); }
367    while(arguments.read("--fbo",width,height)) { glMemoryTests.push_back(new FboTest(width,height,2)); }
368    while(arguments.read("--fbo")) { glMemoryTests.push_back(new FboTest(1024,1024,2)); }
369
370    while(arguments.read("--geometry",width,height)) { glMemoryTests.push_back(new GeometryTest(GeometryTest::DISPLAY_LIST,width,height)); }
371    while(arguments.read("--geometry")) { glMemoryTests.push_back(new GeometryTest(GeometryTest::DISPLAY_LIST,64,64)); }
372
373    while(arguments.read("--geometry-vbo",width,height)) { glMemoryTests.push_back(new GeometryTest(GeometryTest::VERTEX_BUFFER_OBJECT,width,height)); }
374    while(arguments.read("--geometry-vbo")) { glMemoryTests.push_back(new GeometryTest(GeometryTest::VERTEX_BUFFER_OBJECT,64,64)); }
375
376    while(arguments.read("--geometry-va",width,height)) { glMemoryTests.push_back(new GeometryTest(GeometryTest::VERTEX_ARRAY,width,height)); }
377    while(arguments.read("--geometry-va")) { glMemoryTests.push_back(new GeometryTest(GeometryTest::VERTEX_ARRAY,64,64)); }
378
379    unsigned int sleepTime = 0;
380    while(arguments.read("--delay",sleepTime)) {}
381
382    int maxNumContextIterations = 1;
383    while(arguments.read("-c",maxNumContextIterations)) {}
384
385    int maxNumGLIterations = 1000;
386    while(arguments.read("-g",maxNumGLIterations)) {}
387
388#if 0
389    // any option left unread are converted into errors to write out later.
390    arguments.reportRemainingOptionsAsUnrecognized();
391
392    // report any errors if they have occurred when parsing the program arguments.
393    if (arguments.errors())
394    {
395        arguments.writeErrorMessages(std::cout);
396        return 1;
397    }
398#endif
399   
400    typedef std::list< osg::ref_ptr<osg::GraphicsContext> > Contexts;
401    typedef std::list< osg::ref_ptr<GLObject> > GLObjects;
402    Contexts allocatedContexts;
403    GLObjects glObjects;
404   
405    if (contextTests.empty())
406    {
407        if (glMemoryTests.empty())
408        {
409            std::cout<<"No tests specified, please specify test using the command line options below."<<std::endl<<std::endl;
410       
411            arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
412            return 1;           
413        }
414        else
415        {
416            contextTests.push_back(new ContextTest(512,512, false));
417        }
418    }
419
420    osg::Timer_t startTick = osg::Timer::instance()->tick();
421
422    // use printf's below as C++'s ostream classes use more memory and are more likely to fail when everything
423    // goes wrong with memory allocations.
424   
425    int numContextIterations = 0;
426    int numGLObjectIterations = 0;
427    int numGLObjectsApplied = 0;
428    try
429    {
430        for(; numGLObjectIterations<maxNumGLIterations; ++numGLObjectIterations)
431        {   
432            for(GLMemoryTests::iterator itr = glMemoryTests.begin();
433                itr != glMemoryTests.end();
434                ++itr)
435            {
436                osg::ref_ptr<GLObject> glObject = (*itr)->allocate();
437                if (glObject.valid()) glObjects.push_back(glObject.get());
438            }
439        }
440       
441        for(;numContextIterations<maxNumContextIterations; ++numContextIterations)
442        {
443            printf("GraphicsContext %i\n",numContextIterations);
444            for(ContextTests::iterator itr = contextTests.begin();
445                itr != contextTests.end();
446                ++itr)
447            {
448                osg::ref_ptr<osg::GraphicsContext> context = (*itr)->allocate();
449                if (context.valid())
450                {
451                    allocatedContexts.push_back(context);
452
453                    context->makeCurrent();
454                   
455                    osg::RenderInfo renderInfo;
456                    renderInfo.setState(context->getState());
457                   
458                    for(GLObjects::iterator gitr = glObjects.begin();
459                        gitr != glObjects.end();
460                        ++gitr)
461                    {
462                        if (sleepTime>0) OpenThreads::Thread::microSleep( sleepTime );
463
464                        printf("%i ",numGLObjectsApplied);fflush(stdout);
465
466                        (*gitr)->apply(renderInfo);
467                        ++numGLObjectsApplied;
468                    }
469                   
470                    context->releaseContext();
471                   
472                    printf("\n\n"); fflush(stdout);
473                }
474            }
475        }
476    }
477    catch(const char* errorString)
478    {
479        printf("\nException caught, contexts completed = %i, gl objects successfully applied = %i, error = %s\n\n",numContextIterations, numGLObjectsApplied, errorString);
480        return 1;
481    }
482    catch(...)
483    {
484        printf("\nException caught, contexts completed = %i, gl objects successfully applied = %i\n\n",numContextIterations, numGLObjectsApplied);
485        return 1;
486    }
487
488    osg::Timer_t endTick = osg::Timer::instance()->tick();
489
490    printf("\nSuccessful completion, contexts created = %i, gl objects applied = %i\n",numContextIterations, numGLObjectsApplied);
491    printf("Duration = %f seconds.\n\n",osg::Timer::instance()->delta_s(startTick, endTick));
492   
493
494    return 0;
495}
Note: See TracBrowser for help on using the browser.