MCO Performace

New Message Reply Date view Thread view Subject view Author view

Eric Heft (eheft++at++dnaco.net)
Mon, 7 Oct 1996 09:32:46 -0400 (EDT)


Hi,

Anyone have an tips on how to optimize multipipe.c for use
with a 3 monitor , 1 hw graphics pipe, split using a MCO?
My sim can do 60hz when its just opening one pipe/monitor.
When I go to 2 pipes , performance drops to 20-30hz. Even
when I drop the number of object from 400 to 1!

The hardware: Onyx
2 100 mhz R4400's
64 Meg main memory.
1 RE^2 Graphics board
1 MCO

The Program:

#include <stdlib.h>
#include <math.h>
#include <Performer/pf.h>
#include <Performer/pfdu.h>
#include <Performer/pfutil.h>

#define TRACE() { fprintf(stderr,"Line #%d\n",__LINE__); fflush(stderr); }
/*------------------------------------------------------------------*/
static NumScreens=1;
static NumPipes=2;
static void ConfigPipeDraw(int pipe, uint stage);
static void OpenPipeWin(pfPipeWindow *pw);

pfVec3 *norms, *coords;

static pfGeode*
initLPoints(int NPOINTS)
{
    pfLPointState *lps;
    pfTexGen *tgen;
    pfTexture *tex;
    pfGeoState *gst;
    pfGeode *gd;
    pfGeoSet *gs;
    pfVec4 *colors;
    float phi, dphi, theta, dtheta;
    int i, j, k;
    void *arena = pfGetSharedArena();

    /*------------------ Set up pfLPointState -------------------*/

    lps = pfNewLPState(arena);

    /* Enable perspective size computation */
    pfLPStateMode(lps, PFLPS_SIZE_MODE, PF_ON);

    /* Clamp point size between .25 and 4 pixels */
    pfLPStateVal(lps, PFLPS_SIZE_MIN_PIXEL, 0.25f);
    pfLPStateVal(lps, PFLPS_SIZE_MAX_PIXEL, 4.0f);

    /* Real-world point size is .15 meters */
    pfLPStateVal(lps, PFLPS_SIZE_ACTUAL, .45f);

    /* Fade points smaller than 2 pixels */
    pfLPStateVal(lps, PFLPS_TRANSP_PIXEL_SIZE, 2.0f);

    /* Linear fade, scaled by .6 and alpha clamped at .1 */
    pfLPStateVal(lps, PFLPS_TRANSP_EXPONENT, 1.0f);
    pfLPStateVal(lps, PFLPS_TRANSP_SCALE, .6f);
    pfLPStateVal(lps, PFLPS_TRANSP_CLAMP, .1f);

    /* Points are fogged as if 4 times closer than they really are */
    pfLPStateVal(lps, PFLPS_FOG_SCALE, .25f);

    /* Compute true, slant range from eye to points */
    pfLPStateMode(lps, PFLPS_RANGE_MODE, PFLPS_RANGE_MODE_TRUE);

    /* Points are bidirectional with purple back color */
    pfLPStateMode(lps, PFLPS_SHAPE_MODE, PFLPS_SHAPE_MODE_UNI);
    pfLPStateBackColor(lps, 1.f, 0.0f, 1.f, 1.0f);

    /*
     * Point shape is 60 horiz and 90 degrees vertical with
     * no roll, falloff of 1 and ambient intensity of .1
    */
    pfLPStateShape(lps, 60.0f, 90.0f, 0.0f, 1, .9f);

    /*------------------ Set up pfGeoState -------------------*/

    gst = pfNewGState(arena);

    /* Specify high-quality transparency */
    pfGStateMode(gst, PFSTATE_TRANSPARENCY,
                 PFTR_BLEND_ALPHA | PFTR_NO_OCCLUDE);
    pfGStateVal(gst, PFSTATE_ALPHAREF, 0.0f);
    pfGStateMode(gst, PFSTATE_ALPHAFUNC, PFAF_GREATER);
    pfGStateMode(gst, PFSTATE_ANTIALIAS, PFAA_ON);
     
    pfGStateMode(gst, PFSTATE_ENFOG, 0);
    pfGStateMode(gst, PFSTATE_ENLIGHTING, 0);
    pfGStateMode(gst, PFSTATE_ENTEXTURE, 1);
    pfGStateMode(gst, PFSTATE_ENLPOINTSTATE, 1);
    pfGStateAttr(gst, PFSTATE_LPOINTSTATE, lps);

    /*------------------ Configure texturing -------------------*/

    tgen = pfNewTGen(arena);
    tex = pfNewTex(arena);

    /*
     * Use texture mapping for range and fog attenuation. CPU
     * computes size and directionality.
    */
    pfLPStateMode(lps, PFLPS_DIR_MODE, PFLPS_DIR_MODE_ALPHA);
    pfLPStateMode(lps, PFLPS_TRANSP_MODE, PFLPS_TRANSP_MODE_TEX);
    pfLPStateMode(lps, PFLPS_FOG_MODE, PFLPS_FOG_MODE_TEX);
    pfuMakeLPStateRangeTex(lps, tex, 256, pfNewFog(NULL));
    pfGStateAttr(gst, PFSTATE_TEXTURE, tex);
    pfTGenPlane(tgen, PF_S, 0.0f, 0.0f, 1.0f, 0.0f);
    pfTGenPlane(tgen, PF_T, 0.0f, 0.0f, 1.0f, 0.0f);
    pfTGenMode(tgen, PF_S, PFTG_EYE_LINEAR_IDENT);
    pfTGenMode(tgen, PF_T, PFTG_EYE_LINEAR_IDENT);

    pfGStateAttr(gst, PFSTATE_TEXGEN, tgen);
    pfGStateMode(gst, PFSTATE_ENTEXGEN, 1);

    /* Make PFGS_POINTS pfGeoSet arranged in a sphere */

    gd = pfNewGeode();
    gs = pfNewGSet(arena);
    pfGSetPrimType(gs, PFGS_POINTS);
    pfGSetNumPrims(gs, NPOINTS);

    colors = pfMalloc(sizeof(pfVec4) * NPOINTS, arena);
    coords = pfMalloc(sizeof(pfVec3) * NPOINTS, arena);
    norms = pfMalloc(sizeof(pfVec3) * NPOINTS, arena);
    pfGSetAttr(gs, PFGS_NORMAL3, PFGS_PER_VERTEX, norms, NULL);
    pfGSetAttr(gs, PFGS_COLOR4, PFGS_PER_VERTEX, colors, NULL);
    pfGSetAttr(gs, PFGS_COORD3, PFGS_PER_VERTEX, coords, NULL);

    pfGSetGState(gs, gst);
    pfAddGSet(gd, gs);

    for (i=0; i<NPOINTS; i++)
    {
        pfSetVec3(norms[i],0,-1,0);
        pfSetVec3(coords[i],rand()%100-50,rand()%1000,rand()%100-50);
        pfSetVec4(colors[i],1,1,1,1);
    }

    return gd;
}

int
main (int argc, char *argv[])
{
    double t = 0.;
    pfScene *scene;
    pfDCS *dcs;
    pfPipe *pipe[4];
    pfChannel *chan[4];
    pfSphere bsphere;
    pfCoord view;
    int SPEED,NPOINTS,DEBUG,MODE,REFRESH,loop;
    char name[80];
    pfEarthSky *esky;

    argc--; argv++;

    NPOINTS = 0;
    SPEED = 0;
    DEBUG = 0;
    NumPipes = 0;
    MODE = 0;
    REFRESH = 0;
     
    while (argc)
    {
        if (argv[0][0] == '-')
            switch (argv[0][1])
            {
              case 'n':
                NPOINTS = atoi(argv[0]+2);
                break;
              case 's':
                SPEED = atoi(argv[0]+2);
                break;
              case 'd':
                DEBUG = 1;
                break;
              case 'p':
                NumPipes = atoi(argv[0]+2);
                break;
              case 'm':
                MODE = atoi(argv[0]+2);
                break;
              case 'r':
                REFRESH = atoi(argv[0]+2);
                break;
            }
        else
            printf(" Unknown argument %s ",argv[0]);
        argc--;
        argv++;
    }

    if (!SPEED) SPEED = 5;
    if (!NPOINTS) NPOINTS = 100;
    if (!NumPipes) NumPipes = 1;
    if (!REFRESH)
        REFRESH = 60 / NumPipes;

    printf("Loading using :\n");
    printf(" -n%d -s%d -p%d -m%d -r%d\n",NPOINTS,SPEED,NumPipes,MODE,REFRESH);
    printf("\n");
     
    /* Initialize Performer */
    pfInit();
    if ((NumScreens = ScreenCount(pfGetCurWSConnection())) > 1)
    {
        NumPipes = NumScreens;
    }
    pfMultipipe(NumPipes);

    /* Use default multiprocessing mode based on number of
     * processors.
     */

    switch (MODE)
    {
      case 0:
        pfMultiprocess(PFMP_DEFAULT);
        break;
      case 1:
        pfMultiprocess(PFMP_APPCULLDRAW);
        break;
      case 2:
        pfMultiprocess(PFMP_APPCULL_DRAW);
        break;
      case 3:
        pfMultiprocess(PFMP_APP_CULLDRAW);
        break;
      case 4:
        pfMultiprocess(PFMP_APPCULLoDRAW);
        break;
      default:
        pfMultiprocess(PFMP_DEFAULT);
        break;
    }
     
     
    /* Configure multiprocessing mode and start parallel
     * processes.
     */

    pfConfig();
    /* Create and attach morph to a pfScene. */
    scene = pfNewScene();
    dcs = pfNewDCS();
    pfAddChild(dcs, initLPoints(NPOINTS));
    pfAddChild(scene, dcs);
    esky = pfNewESky();
    pfESkyMode(esky, PFES_BUFFER_CLEAR, PFES_FAST);
    pfESkyColor(esky, PFES_CLEAR,0.0,0.0,0.0,0);

    /* determine extent of scene's geometry */
/* pfGetNodeBSphere (scene, &bsphere); */

    /* Configure and open GL window */
    pfFrameRate(REFRESH);
    pfFieldRate(REFRESH);
    pfPhase(PFPHASE_LOCK);
     
    /* pfPhase( PFPHASE_FLOAT ); */

   for (loop=0; loop < NumPipes; loop++)
    {
        pfPipeWindow *pw;
        char str[PF_MAXSTRING];
        pipe[loop] = pfGetPipe(loop);
        pfPipeScreen(pipe[loop], loop);
        pw = pfNewPWin(pipe[loop]);
        pfPWinType(pw, PFPWIN_TYPE_X);
        sprintf(name,"Star Fields : %d stars at %d : Pipe %d",
                NPOINTS,SPEED,loop);
        pfPWinName(pw,name);
        if (NumScreens > 1)
        {
            pfPWinOriginSize(pw, 0, 0, 1025, 768);
        } else
        {
            switch (loop)
            {
              case 0:
                pfPWinOriginSize(pw, 0, 0, 960, 680);
                break;
              case 1:
                pfPWinOriginSize(pw, 0, 680, 960,680);
                break;
              case 2:
                pfPWinOriginSize(pw, 0, 1360, 960,680);
                break;
            }
        }
        pfPWinConfigFunc(pw, OpenPipeWin);
        pfConfigPWin(pw);
    }
    pfStageConfigFunc(-1 /* selects all pipes */,
                      PFPROC_DRAW /* stage bitmask */,
                      ConfigPipeDraw);
    pfConfigStage(-1, PFPROC_DRAW);
    for (loop=0; loop < NumPipes; loop++)
    {
        chan[loop] = pfNewChan(pipe[loop]);
        pfChanScene(chan[loop], scene);
        pfChanNearFar(chan[loop], 1.0f, 40000);
        pfChanFOV(chan[loop], 32.0f, 0.0f);
         
        pfSetVec3(view.xyz, 1 , 0 , 0 );
        switch (loop)
        {
          case 0:
            pfSetVec3(view.hpr, 0 , 0, 0);
            break;
          case 1:
            pfSetVec3(view.hpr, 45 , 0 , 0);
            break;
          case 2:
            pfSetVec3(view.hpr, -45 , 0 , 0 );
            break;
        }
        pfChanView(chan[loop], view.xyz, view.hpr);
        pfChanESky(chan[loop], esky);
         
    }
    

     
    pfInitClock(0.0f);

    /* Simulate for twenty seconds. */
    while (t < 60.0f)
    {
        int i;

        pfSync();

        /* Spin lightpoints */

        i=NPOINTS;
        while (i)
        {
            i--;
            if (coords[i][1] < 0)
            {
                pfSetVec3(coords[i],rand()%200-100,1000,rand()%200-100);
            }
            else
                coords[i][1] -= SPEED;
        }
         

        if (DEBUG) pfDrawChanStats(chan[0]);

        /* Initiate cull/draw for this frame. */
        pfFrame();
        t = pfGetTime();
    }

    /* Terminate parallel processes and exit. */
    pfExit();

    return 0;
}

static void
ConfigPipeDraw(int pipe, uint stage)
{
    pfPipe *p = pfGetPipe(pipe);
    int x, y;

    pfNotify(PFNFY_NOTICE, PFNFY_PRINT,
             "Initializing stage 0x%x of pipe %d on screen %d, connection \"%s\"",
             stage, pipe,
             pfGetPipeScreen(p),
             pfGetPipeWSConnectionName(p));
    pfGetPipeSize(p, &x, &y);
    pfNotify(PFNFY_NOTICE, PFNFY_PRINT, "Pipe %d size: %dx%d", pipe, x,y);
}

static void
OpenPipeWin(pfPipeWindow *pw)
{
    pfPipe *p;
    pfLight *Sun;
     
    p = pfGetPWinPipe(pw);
     
    /* open the window on the specified screen. By default,
     * if a screen has not yet been set and we are in multipipe mode,
     * a window of pfPipeID i will now open on screen i
     */
    pfOpenPWin(pw);
    pfNotify(PFNFY_NOTICE, PFNFY_PRINT,
             "PipeWin of Pipe %d opened on screen %d",
             pfGetId(p), pfGetPipeScreen(p));
     
    /* create a light source in the "south-west" (QIII) */
    Sun = pfNewLight(NULL);
    pfLightPos(Sun, -0.3f, -0.3f, 1.0f, 0.0f);
}

=======================================================================
List Archives, FAQ, FTP: http://www.sgi.com/Technology/Performer/
            Submissions: info-performer++at++sgi.com
        Admin. requests: info-performer-request++at++sgi.com


New Message Reply Date view Thread view Subject view Author view

This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:53:43 PDT

This message has been cleansed for anti-spam protection. Replace '++at++' in any mail addresses with the '@' symbol.