Hi all,

Our immersive system is a single host computer with 8 cores and 4 graphics
cards running Linux. (1)  We are using OSG 2.8.3.

We are having a heck of a hard time getting OSG to take advantage of
our multiple graphics cards.  Help!

Here's what we did:

If we load a fairly large model into our test program we can get a frame
rate of about 150 FPS when displaying in a single window. (2) We are
running single-threaded, and assign to a specific core.

When we background this and run a second copy of the program to another
graphics card and core then both programs run at 150 FPS.  Same thing for
running three and four copies at once.

That is, four processes using four graphics cards on four cores run just as
fast as a single process.  All four cores are at near 100% CPU utilization
according to top.  So far, so good.

Now we modify the program to load the model and create multiple windows on
multiple cards.  There's one window per card and each uses a different
core. (3)

The threading model is "CullThreadPerCameraDrawThreadPerContext", the
default chosen by OSG.  The environment variable OSG_SERIALIZE_DRAW_DISPATCH
is not set, so it defaults to ON, which we think means draw in serial.

If we draw to four windows on four different cards we get about 36 FPS.
There are four different cores being used, and each has about 25% of the
CPU.  This probably this makes sense as the draws are in serial.  150 FPS/4
is about 36 FPS.  As expected, we get nearly identical results if we create
four windows on a single card using four different cores.

If we set OSG_SERIALIZE_DRAW_DISPATCH=OFF we hope to see better performance,
but with four windows on four graphics cards we only get 16 FPS!  There are
four different cores bring used, one at about 82%, and the other three at
75%, but what are they doing?  Again, we get nearly identical results if
using four windows on a single card.

So....

How can we get OSG to draw to four windows on four cards in one process as
fast as running four separate processes?

Any pointers or suggestions are welcome.

Thanks,

John


1 - Our immersive system consists of 3 projectors and a console each driven
    by an Nvidia FX5800 graphics card all genlocked for 3D stereo
    display. The four graphics cards are in two QuardoPlex Model D2 units
    connected to the host.  The host computer is an 8 core Dell Precision
    T5400 running 64 bit Linux (CentOS 5.5). We are using Nvidia driver
    version 195.36.24

2 - the program is attached- it uses only OSG.  We run our tests with
    _GL_SYNC_TO_VBLANK=0 to get the maximum frame rate.

3 - one graphics context per window and one camera per window
#include <osgDB/ReadFile>

#include <osgViewer/Viewer>

#include <osgViewer/ViewerEventHandlers>

#include <osgGA/TrackballManipulator>

#include <iostream>

#include <OpenThreads/Thread>



#include "Nerves.h"



void newWindow(osgViewer::Viewer& viewer, unsigned int sn, char *name=NULL)

{

    osg::ref_ptr<osg::GraphicsContext::Traits> traits = new 
osg::GraphicsContext::Traits;

    //printf("traits->referenceCount() = %d\n",traits->referenceCount()) ;

    traits->screenNum = sn ;

    traits->x = 111 ;

    traits->y = 0 ;

    traits->width = 1058 ;

    traits->height = 990 ;

    traits->windowDecoration = true;

    traits->doubleBuffer = true;

    traits->sharedContext = 0;

    char foo[256] = "display-" ;

    strcat(foo,name) ;

    if (name) traits->windowName = foo ;

    

    osg::ref_ptr<osg::GraphicsContext> gc = 
osg::GraphicsContext::createGraphicsContext(traits.get());

    //printf("traits->referenceCount() = %d\n",traits->referenceCount()) ;

    //printf("gc->referenceCount() = %d\n",gc->referenceCount()) ;

    if (gc.valid())

    {

        osg::notify(osg::INFO)<<"  GraphicsWindow has been created 
successfully."<<std::endl;

    }

    else

    {

        osg::notify(osg::NOTICE)<<"  GraphicsWindow has not been created 
successfully."<<std::endl;

    }

    

    osg::ref_ptr<osg::Camera> camera = new osg::Camera;

    //printf("camera->referenceCount() = %d\n",camera->referenceCount()) ;

    camera->setGraphicsContext(gc.get());

    //printf("gc->referenceCount() = %d\n",gc->referenceCount()) ;

    camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));

    // running in mono

    GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;

    camera->setDrawBuffer(buffer);

    // does this make any difference?

    camera->setReadBuffer(buffer);

    

    viewer.addSlave(camera.get()) ;

    //printf("camera->referenceCount() = %d\n",camera->referenceCount()) ;

    //printf("traits->referenceCount() = %d\n",traits->referenceCount()) ;

    //printf("gc->referenceCount() = %d\n",gc->referenceCount()) ;

    //printf("---------camera->referenceCount() = 
%d\n",camera->referenceCount()) ;

}



int main( int argc, char **argv )

{

  

    osgViewer::Viewer viewer ;

    viewer.addEventHandler(new osgViewer::StatsHandler) ;

    viewer.addEventHandler(new osgViewer::ThreadingHandler) ;



    //viewer.setThreadingModel( osgViewer::ViewerBase::SingleThreaded );



    osg::DisplaySettings::instance()->setCompileContextsHint(true) ;



    osg::GraphicsContext::WindowingSystemInterface* wsi = 
osg::GraphicsContext::getWindowingSystemInterface();

    if (!wsi) 

    {

        osg::notify(osg::NOTICE)<<"Error, no WindowSystemInterface available, 
cannot create windows."<<std::endl;

        return 1;

    }

    

    int sn ;

    for (unsigned int i=1; i<argc-1; i++)

    {

        sscanf(argv[i],"%d",&sn) ;

        printf("argv[%d] = %s, sn = %d\n",i,argv[i],sn) ;

        newWindow(viewer,sn,argv[i]);

    }



    // load the scene.

    osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFile(argv[argc-1]);

    

    if (!loadedModel) 

    {

        std::cout << argv[0] <<": No data loaded." << std::endl;

        return 1;

    }

    

    viewer.setSceneData(loadedModel.get());

    

    viewer.realize();



#if 0

    if (argc==3)

    {

        printf("setting 
OpenThreads::SetProcessorAffinityOfCurrentThread(%d)\n",sn) ;

        OpenThreads::SetProcessorAffinityOfCurrentThread(sn);

    }

#endif



    if (!viewer.getCameraManipulator() && 
viewer.getCamera()->getAllowEventFocus())

    {

        viewer.setCameraManipulator(new osgGA::TrackballManipulator());

    }

    

    viewer.setReleaseContextAtEndOfFrameHint(false);

            

    viewer.frame() ;





    printf("starting loop\n") ;



    double start = viewer.getViewerFrameStamp()->getReferenceTime() ;

    while (!viewer.done())

    {

        viewer.frame() ;

        //if (viewer.getViewerFrameStamp()->getReferenceTime()>start+100.0) 
break ;

    }





    osg::FrameStamp *fs = viewer.getViewerFrameStamp() ;



    printf("%s: %d frames in %f seconds = %f frames/second\n",argv[0], 
fs->getFrameNumber(), fs->getReferenceTime(), 
fs->getFrameNumber()/fs->getReferenceTime()) ;



    return 0;

}

_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to