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

Revision 9149, 18.1 kB (checked in by robert, 5 years ago)

Improved naming

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