Eric Heft (eheft++at++dnaco.net)
Mon, 7 Oct 1996 09:32:46 -0400 (EDT)
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
This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:53:43 PDT