1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     perf-geo.c
4 
5   Copyright 1998-2006 Nintendo.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12   Immediate-mode performance test
13 
14  *---------------------------------------------------------------------------*/
15 
16 #include <demo.h>
17 #include <math.h>
18 
19 /*---------------------------------------------------------------------------*
20    Forward references
21  *---------------------------------------------------------------------------*/
22 
23 void        main             ( void );
24 static void CameraInit       ( void );
25 static void DrawInit         ( void );
26 static void DrawTick         ( void );
27 static void DumpStats        ( void );
28 static void PrintIntro       ( void );
29 static u32  checkForOverflow ( void );
30 static void DrawCubeIndx     ( void );
31 static void DrawCubeDirect   ( void );
32 static void DrawTexCubeIndx  ( void );
33 static void DrawTexCubeDirect( void );
34 
35 
36 /*---------------------------------------------------------------------------*
37    Defines
38  *---------------------------------------------------------------------------*/
39 #define BALL64_TEX_ID   8
40 #define N_TESTS         (sizeof(testData)/sizeof(TestData))
41 #define N_STATS         (sizeof(Stat)/sizeof(StatObj))
42 #define SIDE            50.0F
43 
44 typedef enum {
45     GP_PERF0,
46     GP_PERF1,
47     MEM_PERF,
48     PIX_PERF,
49     VC_PERF
50 } PerfType;
51 
52 /*---------------------------------------------------------------------------*
53    Global variables
54  *---------------------------------------------------------------------------*/
55 //
56 //  Cube data
57 //
58 f32 Vert[] ATTRIBUTE_ALIGN(32) =
59                      {
60                         -SIDE, SIDE, -SIDE, //0
61                         -SIDE, SIDE, SIDE,  //1
62                         -SIDE, -SIDE, SIDE, //2
63                         -SIDE, -SIDE, -SIDE,//3
64                         SIDE, SIDE, -SIDE,  //4
65                         SIDE, -SIDE, -SIDE, //5
66                         SIDE, -SIDE, SIDE,  //6
67                         SIDE, SIDE, SIDE    //7
68                     };
69 
70 f32 Norm[] ATTRIBUTE_ALIGN(32) =
71                      {
72                         -1.0F,  0.0F,  0.0F, //0
73                          0.0F, -1.0F,  0.0F, //1
74                          0.0F,  0.0F, -1.0F, //2
75                          1.0F,  0.0F,  0.0F, //3
76                          0.0F,  1.0F,  0.0F, //4
77                          0.0F,  0.0F,  1.0F  //5
78                     };
79 
80 f32 TexCoord[] ATTRIBUTE_ALIGN(32) =
81                      {
82                          0.0F,  0.0F, //0
83                          1.0F,  0.0F, //1
84                          1.0F,  1.0F, //2
85                          0.0F,  1.0F, //3
86                     };
87 
88 u32 MyColors[] ATTRIBUTE_ALIGN(32) =
89 {
90     0xff0000ff, // red
91     0x00ff00ff, // green
92     0x0000ffff, // blue
93     0xffff00ff, // yellow
94     0xff00ffff, // magenta
95     0x00ffffff  // cyan
96 };
97 
98 // index when lsb=1
99 typedef enum {
100     CUBE_DIR,     // lit and textured
101     CUBE_IDX,     // lit and textured
102     CUBE_TEX_DIR, // textured only
103     CUBE_TEX_IDX  // textured only
104 } CubeType;
105 
106 //
107 //  Test cases
108 //
109 typedef struct {
110     u32      nloops;  // number of loops (ncubes + nmtx)
111     u32      ncubes;  // number of cubes to draw, 24 verts each
112     u32      nmtx;    // number of matrix loads per ncubes
113     u32      fill;    // fill FIFO flag, if true fill FIFO before rendering
114     CubeType type;    // type of vertex data
115 } TestData;
116 
117 static TestData testData[] =
118 {  //  nloops, ncubes, nmtx, fill, type
119 
120 {       1,      0, 1000,    1,    CUBE_DIR }, // test matrix load speed
121 {       1,   1000,    1,    1,    CUBE_DIR }, // test a few large objects
122 {    1000,      1,    1,    1,    CUBE_DIR }, // test very small objects
123 {     500,      2,    1,    1,    CUBE_DIR }, //
124 {     333,      3,    1,    1,    CUBE_DIR }, //
125 {     250,      4,    1,    1,    CUBE_DIR }, //
126 {     200,      5,    1,    1,    CUBE_DIR }, //
127 {     100,     10,    1,    1,    CUBE_DIR }, // test many small objects
128 {     100,     10,    2,    1,    CUBE_DIR }, // how does n mtx effect?
129 {     100,     10,    3,    1,    CUBE_DIR },
130 {     100,     10,   10,    1,    CUBE_DIR },
131 
132 {       1,      0, 1000,    1,    CUBE_IDX }, // test matrix load speed
133 {       1,   1000,    1,    1,    CUBE_IDX }, // test a few large objects
134 {    1000,      1,    1,    1,    CUBE_IDX }, // test very small objects
135 {     500,      2,    1,    1,    CUBE_IDX }, //
136 {     333,      3,    1,    1,    CUBE_IDX }, //
137 {     250,      4,    1,    1,    CUBE_IDX }, //
138 {     200,      5,    1,    1,    CUBE_IDX }, //
139 {     100,     10,    1,    1,    CUBE_IDX }, // test many small objects
140 {     100,     10,    2,    1,    CUBE_IDX }, // how does n mtx effect?
141 {     100,     10,    3,    1,    CUBE_IDX },
142 {     100,     10,   10,    1,    CUBE_IDX },
143 
144 {       1,      0, 1000,    1,    CUBE_TEX_DIR }, // test matrix load speed
145 {       1,   1000,    1,    1,    CUBE_TEX_DIR }, // test a few large objects
146 {    1000,      1,    1,    1,    CUBE_TEX_DIR }, // test very small objects
147 {     500,      2,    1,    1,    CUBE_TEX_DIR }, //
148 {     333,      3,    1,    1,    CUBE_TEX_DIR }, //
149 {     250,      4,    1,    1,    CUBE_TEX_DIR }, //
150 {     200,      5,    1,    1,    CUBE_TEX_DIR }, //
151 {     100,     10,    1,    1,    CUBE_TEX_DIR }, // test many small objects
152 {     100,     10,    2,    1,    CUBE_TEX_DIR }, // how does n mtx effect?
153 {     100,     10,    3,    1,    CUBE_TEX_DIR },
154 {     100,     10,   10,    1,    CUBE_TEX_DIR },
155 
156 {       1,      0, 1000,    1,    CUBE_TEX_IDX }, // test matrix load speed
157 {       1,   1000,    1,    1,    CUBE_TEX_IDX }, // test a few large objects
158 {    1000,      1,    1,    1,    CUBE_TEX_IDX }, // test very small objects
159 {     500,      2,    1,    1,    CUBE_TEX_IDX }, //
160 {     333,      3,    1,    1,    CUBE_TEX_IDX }, //
161 {     250,      4,    1,    1,    CUBE_TEX_IDX }, //
162 {     200,      5,    1,    1,    CUBE_TEX_IDX }, //
163 {     100,     10,    1,    1,    CUBE_TEX_IDX }, // test many small objects
164 {     100,     10,    2,    1,    CUBE_TEX_IDX }, // how does n mtx effect?
165 {     100,     10,    3,    1,    CUBE_TEX_IDX },
166 {     100,     10,   10,    1,    CUBE_TEX_IDX }
167 };
168 
169 //
170 //  Statistics
171 //
172 typedef struct {
173     u32         cnt;
174     PerfType    stat_type;
175     u32         stat;
176     char        text[50];
177 } StatObj;
178 
179 StatObj Stat[] = { // stats to count
180     { 0, GP_PERF0, GX_PERF0_XF_WAIT_IN,       "xf waiting on input........" },
181     { 0, GP_PERF0, GX_PERF0_XF_WAIT_OUT,      "xf waiting on output......." },
182     { 0, GP_PERF0, GX_PERF0_XF_XFRM_CLKS,     "xf transform clocks........" },
183     { 0, GP_PERF0, GX_PERF0_XF_LIT_CLKS,      "xf lighting clocks........." },
184     { 0, GP_PERF0, GX_PERF0_XF_BOT_CLKS,      "xf bot of pipe clocks......" },
185     { 0, GP_PERF0, GX_PERF0_XF_REGLD_CLKS,    "xf register load clocks...." },
186     { 0, GP_PERF0, GX_PERF0_XF_REGRD_CLKS,    "xf register read clocks...." },
187     { 0, GP_PERF0, GX_PERF0_TRIANGLES,        "Triangles.................." },
188     { 0, GP_PERF0, GX_PERF0_CLOCKS,           "Perf0 clocks..............." },
189     { 0, GP_PERF1, GX_PERF1_VERTICES,         "vertices..................." },
190     { 0, GP_PERF1, GX_PERF1_VC_ELEMQ_FULL,    "Vtx$ elem queue full......." },
191     { 0, GP_PERF1, GX_PERF1_VC_MISSQ_FULL,    "Vtx$ miss queue full......." },
192     { 0, GP_PERF1, GX_PERF1_VC_MEMREQ_FULL,   "Vtx$ mem request full......" },
193     { 0, GP_PERF1, GX_PERF1_VC_STATUS7,       "Vtx$ status 7.............." },
194     { 0, GP_PERF1, GX_PERF1_VC_MISSREP_FULL,  "Vtx$ miss replace full....." },
195     { 0, GP_PERF1, GX_PERF1_VC_STREAMBUF_LOW, "Vtx$ stream buf low........" },
196     { 0, GP_PERF1, GX_PERF1_VC_ALL_STALLS,    "Vtx$ all stalls............" },
197     { 0, GP_PERF1, GX_PERF1_VERTICES,         "Perf1 vertices............." },
198     { 0, GP_PERF1, GX_PERF1_FIFO_REQ,         "CP fifo requests..........." },
199     { 0, GP_PERF1, GX_PERF1_CALL_REQ,         "CP call requests..........." },
200     { 0, GP_PERF1, GX_PERF1_VC_MISS_REQ,      "Vtx$ miss request.........." },
201     { 0, GP_PERF1, GX_PERF1_CP_ALL_REQ,       "CP all requests............" },
202     { 0, GP_PERF1, GX_PERF1_CLOCKS,           "Perf1 clocks..............." },
203     { 0, MEM_PERF, 0,                         "Memory requests............" }
204 };
205 
206 //
207 //  Global vars
208 //
209 static Mtx v, mv;
210 
211 static u32 Test    = 0;
212 static u32 curStat = 0;
213 static void (*testDraw)() = NULL; // function pointer for draw routine
214 
215 // pixel statistics counters
216 static u32 topPixIn;
217 static u32 topPixOut;
218 static u32 botPixIn;
219 static u32 botPixOut;
220 static u32 clrPixIn;
221 static u32 copyClks;
222 // vcache statistics counters
223 static u32 vcCheck;
224 static u32 vcMiss;
225 static u32 vcStall;
226 // clocks per verts
227 static u32 cpReq,
228            tcReq,
229            cpuRdReq,
230            cpuWrReq,
231            dspReq,
232            ioReq,
233            viReq,
234            peReq,
235            rfReq,
236            fiReq;
237 
238 static OSStopwatch myTotTime;
239 static OSStopwatch myCpuTime;
240 static OSStopwatch myGpTime;
241 static GXFifoObj newFifo;
242 
243 /*---------------------------------------------------------------------------*
244    Application main loop
245  *---------------------------------------------------------------------------*/
main(void)246 void main ( void )
247 {
248     u32 fillFifo = 0;
249     u32 i        = 0;
250     GXFifoObj waitFifo; // this is the default GX fifo
251     GXFifoObj tmpFifo;
252 
253 
254     DEMOInit(NULL);
255     DrawInit();
256     PrintIntro();
257 
258     OSInitStopwatch(&myTotTime, "myTotTime");
259     OSInitStopwatch(&myCpuTime, "myCpuTime");
260     OSInitStopwatch(&myGpTime, "myGpTime");
261 
262     // Allocate memory initialize the newFifo.  This fifo is used to hold
263     // a complete 'frame' to draw.  We don't really need a complete frame,
264     // just enough to see the performance difference.
265     GXInitFifoBase(&newFifo,
266                    MEMAllocFromAllocator(&DemoAllocator1, sizeof(u8)*1000*1500), sizeof(u8)*1000*1500);
267 
268     // get the default fifo, this will be emptied and then used
269     // to keep the GP from reading when we select fillFifo mode
270     GXGetCPUFifo(&waitFifo);
271     Test = 0;
272 
273     while (Test != N_TESTS)
274     {
275         OSResetStopwatch(&myTotTime);
276         OSResetStopwatch(&myCpuTime);
277         OSResetStopwatch(&myGpTime);
278 
279         fillFifo = testData[Test].fill;
280         curStat = 0;
281         while (curStat != N_STATS)
282         {
283             DEMOBeforeRender();
284 
285             //
286             //  Enable various statistics
287             //  clear counters
288             //
289             if (Stat[curStat].stat_type == GP_PERF0)
290             {
291                 GXSetGP0Metric((GXPerf0)Stat[curStat].stat);
292                 GXClearGP0Metric();
293             }
294             else if (Stat[curStat].stat_type == GP_PERF1)
295             {
296                 GXSetGP1Metric((GXPerf1)Stat[curStat].stat);
297                 GXClearGP1Metric();
298             }
299             else if (Stat[curStat].stat_type == MEM_PERF)
300             {
301                 GXClearMemMetric();
302             }
303             else if (Stat[curStat].stat_type == PIX_PERF)
304             {
305                 GXClearPixMetric();
306             }
307             else // vcache stat
308             {
309                 GXSetVCacheMetric(GX_VC_ALL);
310                 GXClearVCacheMetric();
311             }
312 
313             // make sure all GX commands to here are flushed
314             GXGetCPUFifo(&tmpFifo);
315 
316             // choose normal immediate mode or delayed immediate mode
317             if (fillFifo)
318             {
319                 // set new FIFO
320                 if (GXGetFifoBase(&tmpFifo) != GXGetFifoBase(&newFifo))
321                 {
322                     // reset read/write pointers
323                     GXInitFifoPtrs(&newFifo,
324                                     GXGetFifoBase(&newFifo),
325                                     GXGetFifoBase(&newFifo));
326                     GXSetCPUFifo(&newFifo);
327                 }
328                 OSStartStopwatch(&myCpuTime);
329             }
330             else
331             {
332                 // reset read write pointers
333                 if (GXGetFifoBase(&tmpFifo) != GXGetFifoBase(&waitFifo))
334                 {
335                     GXInitFifoPtrs(&waitFifo,
336                                    GXGetFifoBase(&waitFifo),
337                                    GXGetFifoBase(&waitFifo));
338                     // set new FIFO
339                     GXSetCPUFifo(&waitFifo);
340                 }
341             }
342 
343             OSStartStopwatch(&myTotTime);
344 
345 
346             DrawTick();
347 
348             // turn on FIFO reads after whole FIFO is filled
349             if (fillFifo)
350             {
351                 // push all data out
352                 GXFlush();
353                 OSStopStopwatch(&myCpuTime); // CPU is done here
354 
355                 // make sure we are in the newFifo limits
356                 if (checkForOverflow())
357                     OSHalt("Error, FIFO overflowed");
358 
359                 // switch to new fifo
360                 if ( !GXIsCPUGPFifoLinked() )
361                 {
362                     GXGetCPUFifo(&tmpFifo);
363                     GXSetGPFifo(&tmpFifo);
364                 }
365 
366                 OSStartStopwatch(&myGpTime); // GP starts here
367             }
368 
369             GXDrawDone();   // wait for GP to be done
370                             // GXDrawDone does flush too
371 
372             //GXGetFifoPtrs(GXGetCPUFifo(), &readPtr1, &writePtr1);
373             //OSReport("Write pointer, after loop:  %08x\n", writePtr1);
374             //OSReport("Diff:  %8d (cache lines)\n",
375             //        ((u32)writePtr1 - (u32)writePtr0) / 32);
376 
377             OSStopStopwatch(&myTotTime);
378 
379             //
380             //  Read back various statistics
381             //
382             if (Stat[curStat].stat_type == GP_PERF0)
383             {
384                 Stat[curStat].cnt = GXReadGP0Metric();
385             }
386             else if (Stat[curStat].stat_type == GP_PERF1)
387             {
388                 Stat[curStat].cnt = GXReadGP1Metric();
389             }
390             else if (Stat[curStat].stat_type == MEM_PERF)
391             {
392                 GXReadMemMetric   ( &cpReq,
393                                     &tcReq,
394                                     &cpuRdReq,
395                                     &cpuWrReq,
396                                     &dspReq,
397                                     &ioReq,
398                                     &viReq,
399                                     &peReq,
400                                     &rfReq,
401                                     &fiReq );
402             }
403             else if (Stat[curStat].stat_type == PIX_PERF)
404             {
405                 GXReadPixMetric(&topPixIn, &topPixOut, &botPixIn, &botPixOut,
406                                 &clrPixIn, &copyClks);
407             }
408             else // vcache stats
409             {
410                 GXReadVCacheMetric(&vcCheck, &vcMiss, &vcStall);
411             }
412 
413             // turn off FIFO reads.
414             if (fillFifo)
415             {
416                 OSStopStopwatch(&myGpTime);
417                 // GP fifo is already empty, waitFifo is empty and no one
418                 // will write to it when fillFifo is true.  This is how
419                 // we keep the GP waiting until newFifo is ready.
420                 GXGetGPFifo(&tmpFifo);
421                 if ( GXGetFifoBase(&tmpFifo) != GXGetFifoBase(&waitFifo) )
422                     GXSetGPFifo(&waitFifo);
423 
424                 // make cpu fifo = wait fifo, so next time through we can
425                 // reset the pointer to the top.
426                 GXGetCPUFifo(&tmpFifo);
427                 if ( GXGetFifoBase(&tmpFifo) != GXGetFifoBase(&waitFifo))
428                     GXSetCPUFifo(&waitFifo);
429             }
430 
431             DEMODoneRender();
432             curStat++;
433         }
434 
435         DumpStats();
436         Test++;
437     }
438 
439     OSHalt("End of demo");
440 }
441 
442 /*---------------------------------------------------------------------------*
443    Functions
444  *---------------------------------------------------------------------------*/
445 
446 
447 /*---------------------------------------------------------------------------*
448     Name:           CameraInit
449 
450     Description:    Initialize the projection matrix and load into hardware.
451 
452     Arguments:      v   view matrix to be passed to ViewInit
453                     cameraLocScale  scale for the camera's distance from the
454                                     object - to be passed to ViewInit
455 
456     Returns:        none
457  *---------------------------------------------------------------------------*/
458 static
CameraInit(void)459 void CameraInit      ( void )
460 {
461     Mtx44 p;
462     Vec camPt  = {0.0F, 0.0F, 650.0F};
463     Vec up     = {0.0F, 1.0F, 0.0F};
464     Vec origin = {0.0F, 0.0F, -100.0F};
465 
466     MTXFrustum(p, 240, -240, -320, 320, 500, 2000);
467 
468     GXSetProjection(p, GX_PERSPECTIVE);
469 
470     MTXLookAt(v, &camPt, &up, &origin);
471 }
472 
473 /*---------------------------------------------------------------------------*
474     Name:           DrawInit
475 
476     Description:    Calls the correct initialization function for the current
477                     model.
478 
479     Arguments:      none
480 
481     Returns:        none
482  *---------------------------------------------------------------------------*/
483 static
DrawInit(void)484 void DrawInit( void )
485 {
486     GXLightObj MyLight;
487     GXColor color = {0, 255, 255, 255};
488     GXTexObj      texObj;  // texture object
489     TPLPalettePtr tpl = 0; // texture palette
490 
491     GXSetCullMode(GX_CULL_ALL);
492 
493     // constant matrix, just want to see load performance
494     CameraInit();   // Initialize the camera (v)
495     MTXTrans(mv, 0, 0, 0);
496     MTXConcat(v, mv, mv);
497 
498     GXSetCurrentMtx(0);
499 
500     GXInitLightPos(&MyLight, 0.0F, 0.0F, 0.0F);
501     GXInitLightColor(&MyLight, color);
502     GXLoadLightObjImm(&MyLight, GX_LIGHT0);
503 
504     GXSetChanMatColor(GX_COLOR0A0, color);
505     //  Load the texture palette
506     TPLGetPalette(&tpl, "gxTextrs.tpl");
507     //  Initialize a texture object to contain the correct texture
508     TPLGetGXTexObjFromPalette(tpl, &texObj, BALL64_TEX_ID);
509     //  Load the texture object; tex0 is used in stage 0
510     GXLoadTexObj(&texObj, GX_TEXMAP0);
511 
512     GXSetNumTevStages(1);
513 
514     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
515     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
516     GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE);
517 
518     GXSetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR);
519 
520     GXSetArray(GX_VA_POS,  Vert,     sizeof(f32)*3);
521     GXSetArray(GX_VA_NRM,  Norm,     sizeof(f32)*3);
522     GXSetArray(GX_VA_CLR0, MyColors, sizeof(u32));
523     GXSetArray(GX_VA_TEX0, TexCoord, sizeof(f32)*2);
524 
525     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
526     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
527     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
528     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
529 
530     //GXDrawDone(); // make sure state is in GP
531 }
532 
533 
534 
535 /*---------------------------------------------------------------------------*
536     Name:           DrawTick
537 
538     Description:    Draws cubes
539 
540     Arguments:      none
541 
542     Returns:        none
543  *---------------------------------------------------------------------------*/
544 static
DrawTick(void)545 void DrawTick( void )
546 {
547     u32 i, j; // indices
548 
549     if (testData[Test].type == CUBE_IDX)
550     {
551         //OSReport("Using indexed data, tex and lit\n");
552         GXSetNumChans(1);
553         GXSetNumTexGens(1);
554 
555         GXSetChanCtrl(
556                 GX_COLOR0A0,
557                 GX_ENABLE,      // enable channel
558                 GX_SRC_REG,     // amb source
559                 GX_SRC_VTX,     // mat source
560                 GX_LIGHT0,      // light mask
561                 GX_DF_NONE,     // diffuse function
562                 GX_AF_NONE);
563 
564         GXClearVtxDesc();
565         GXSetVtxDesc(GX_VA_POS,  GX_INDEX16);
566         GXSetVtxDesc(GX_VA_NRM,  GX_INDEX8);
567         GXSetVtxDesc(GX_VA_CLR0, GX_INDEX8);
568         GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
569         testDraw = DrawCubeIndx;
570     }
571     else if (testData[Test].type == CUBE_DIR)
572     {
573         //OSReport("Using direct data, tex and lit\n");
574         GXSetNumChans(1);
575         GXSetNumTexGens(1);
576 
577         GXSetChanCtrl(
578                 GX_COLOR0A0,
579                 GX_ENABLE,      // enable channel
580                 GX_SRC_REG,     // amb source
581                 GX_SRC_VTX,     // mat source
582                 GX_LIGHT0,      // light mask
583                 GX_DF_NONE,     // diffuse function
584                 GX_AF_NONE);
585 
586         GXClearVtxDesc();
587         GXSetVtxDesc(GX_VA_POS,  GX_DIRECT);
588         GXSetVtxDesc(GX_VA_NRM,  GX_DIRECT);
589         GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
590         GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
591         testDraw = DrawCubeDirect;
592     }
593     else if (testData[Test].type == CUBE_TEX_IDX)
594     {
595         //OSReport("Using indexed data, tex-only\n");
596         GXSetNumChans(0);
597         GXSetNumTexGens(1);
598 
599         GXSetChanCtrl(
600                 GX_COLOR0A0,
601                 GX_DISABLE,     // enable channel
602                 GX_SRC_REG,     // amb source
603                 GX_SRC_REG,     // mat source
604                 GX_LIGHT0,      // light mask
605                 GX_DF_NONE,     // diffuse function
606                 GX_AF_NONE);
607 
608         GXClearVtxDesc();
609         GXSetVtxDesc(GX_VA_POS,  GX_INDEX16);
610         GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
611         testDraw = DrawTexCubeIndx;
612     }
613     else if (testData[Test].type == CUBE_TEX_DIR)
614     {
615         //OSReport("Using direct data, tex-only\n");
616         GXSetNumChans(0);
617         GXSetNumTexGens(1);
618 
619         GXSetChanCtrl(
620                 GX_COLOR0A0,
621                 GX_DISABLE,     // enable channel
622                 GX_SRC_REG,     // amb source
623                 GX_SRC_REG,     // mat source
624                 GX_LIGHT0,      // light mask
625                 GX_DF_NONE,     // diffuse function
626                 GX_AF_NONE);
627 
628         GXClearVtxDesc();
629         GXSetVtxDesc(GX_VA_POS,  GX_DIRECT);
630         GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
631         testDraw = DrawTexCubeDirect;
632     }
633 
634 
635     for (i = 0; i < testData[Test].nloops; i++)
636     {
637         for (j = 0; j < testData[Test].nmtx; j++)
638         {
639             GXLoadPosMtxImm(mv, 0);
640             GXLoadNrmMtxImm(mv, 0);
641         }
642         for (j = 0; j < testData[Test].ncubes; j++)
643         {
644             testDraw();
645         }
646     }
647 }
648 
649 /*---------------------------------------------------------------------------*
650     Name:           DumpStats
651 
652     Description:    Print current counters to stdout
653 
654     Arguments:      none
655 
656     Returns:        none
657  *---------------------------------------------------------------------------*/
658 static
DumpStats(void)659 void DumpStats( void )
660 {
661     u32 i;
662 
663         OSReport("******** Test %3d ********\n", Test);
664 
665         if (testData[Test].fill)
666             OSReport("Fill FIFO before rendering\n");
667         else
668             OSReport("Write to FIFO while rendering\n");
669 
670         switch (testData[Test].type)
671         {
672             case CUBE_DIR: OSReport("Direct data, tex and lit\n"); break;
673             case CUBE_IDX: OSReport("Indirect data, tex and lit\n"); break;
674             case CUBE_TEX_DIR: OSReport("Direct data, tex only\n"); break;
675             case CUBE_TEX_IDX: OSReport("Indirect data, tex only\n"); break;
676         }
677 
678         OSReport("Number of loops.......... %8d\n", testData[Test].nloops);
679         OSReport("Number of cubes.......... %8d\n", testData[Test].ncubes);
680         OSReport("Number of matrices/cube.. %8d\n", testData[Test].nmtx);
681 
682         for (i = 0; i < N_STATS; i++)
683         {
684             if (Stat[i].stat_type == PIX_PERF)
685             {
686                 OSReport("Top pixels in..............:   %8d\n", topPixIn);
687                 OSReport("Top pixels out.............:   %8d\n", topPixOut);
688                 OSReport("Bot pixels in..............:   %8d\n", botPixIn);
689                 OSReport("Bot pixels out.............:   %8d\n", botPixOut);
690                 OSReport("Clr pixels in..............:   %8d\n", clrPixIn);
691                 OSReport("Copy clocks................:   %8d\n", copyClks);
692             }
693             else if (Stat[i].stat_type == VC_PERF)
694             {
695                 OSReport("Vcache checks..............:   %8d\n", vcCheck);
696                 OSReport("Vcache misses..............:   %8d\n", vcMiss);
697                 OSReport("Vcache stalls..............:   %8d\n", vcStall);
698             }
699             else if (Stat[i].stat_type == MEM_PERF)
700             {
701                 OSReport("CP requests................:   %8d\n", cpReq);
702                 OSReport("TC requests................:   %8d\n", tcReq);
703                 OSReport("CPU Rd requests............:   %8d\n", cpuRdReq);
704                 OSReport("CPU Wr requests............:   %8d\n", cpuWrReq);
705                 OSReport("DSP requests...............:   %8d\n", dspReq);
706                 OSReport("IO requests................:   %8d\n", ioReq);
707                 OSReport("VI requests................:   %8d\n", viReq);
708                 OSReport("PE requests................:   %8d\n", peReq);
709                 OSReport("RF requests................:   %8d\n", rfReq);
710                 OSReport("FI requests................:   %8d\n", fiReq);
711             }
712             else
713                 OSReport("%s:   %8d\n", Stat[i].text, Stat[i].cnt);
714         }
715 
716 
717         if (testData[Test].fill)
718         {
719             OSDumpStopwatch(&myCpuTime);
720             OSDumpStopwatch(&myGpTime);
721         }
722         OSDumpStopwatch(&myTotTime);
723 }
724 
725 
726 /*---------------------------------------------------------------------------*
727     Name:           PrintIntro
728 
729     Description:    Print usage for test
730 
731     Arguments:      none
732 
733     Returns:        none
734  *---------------------------------------------------------------------------*/
735 static
PrintIntro(void)736 void PrintIntro( void )
737 {
738     OSReport("\n\n********************************\n");
739     OSReport(" Check immediate mode performance\n");
740     OSReport(" Check transform performance\n");
741     OSReport("\n");
742     OSReport(" This test outputs only text info\n");
743     OSReport("************************************\n");
744 }
745 
746 /*---------------------------------------------------------------------------*
747     Name:           checkForOverflow
748 
749     Description:    return overflow bit of newFifo
750 
751     Arguments:      none
752 
753     Returns:        none
754  *---------------------------------------------------------------------------*/
755 static u32
checkForOverflow(void)756 checkForOverflow( void )
757 {
758 #if 0
759     GXBool overhi, underlow;
760     GXBool cpu_write, gp_read, fifowrap;
761     u32    fifo_cnt;
762 
763     GXGetFifoStatus(&newFifo, &overhi, &underlow, &fifo_cnt, &cpu_write,
764                     &gp_read, &fifowrap);
765 
766     return ((u32)fifowrap);
767 #endif
768     return 0;
769 }
770 
771 /*---------------------------------------------------------------------------*
772     Name:           DrawCubeIndx
773 
774     Description:
775 
776     Arguments:      none
777 
778     Returns:        none
779  *---------------------------------------------------------------------------*/
780 static
DrawCubeIndx(void)781 void DrawCubeIndx( void )
782 {
783     GXBegin(GX_QUADS, GX_VTXFMT0, 4*6);
784         GXPosition1x16(4);
785         GXNormal1x8(0);
786         GXColor1x8(0);
787         GXTexCoord1x8(0); //
788         GXPosition1x16(5);
789         GXNormal1x8(0);
790         GXColor1x8(0);
791         GXTexCoord1x8(1); //
792         GXPosition1x16(6);
793         GXNormal1x8(0);
794         GXColor1x8(0);
795         GXTexCoord1x8(2); //
796         GXPosition1x16(7);
797         GXNormal1x8(0);
798         GXColor1x8(0);
799         GXTexCoord1x8(3); //
800 
801         GXPosition1x16(2);
802         GXNormal1x8(0);
803         GXColor1x8(1);
804         GXTexCoord1x8(0); //
805         GXPosition1x16(6);
806         GXNormal1x8(0);
807         GXColor1x8(1);
808         GXTexCoord1x8(1); //
809         GXPosition1x16(5);
810         GXNormal1x8(0);
811         GXColor1x8(1);
812         GXTexCoord1x8(2); //
813         GXPosition1x16(3);
814         GXNormal1x8(0);
815         GXColor1x8(1);
816         GXTexCoord1x8(3); //
817 
818         GXPosition1x16(1);
819         GXNormal1x8(0);
820         GXColor1x8(2);
821         GXTexCoord1x8(0); //
822         GXPosition1x16(0);
823         GXNormal1x8(0);
824         GXColor1x8(2);
825         GXTexCoord1x8(1); //
826         GXPosition1x16(4);
827         GXNormal1x8(0);
828         GXColor1x8(2);
829         GXTexCoord1x8(2); //
830         GXPosition1x16(7);
831         GXNormal1x8(0);
832         GXColor1x8(2);
833         GXTexCoord1x8(3); //
834 
835         GXPosition1x16(0);
836         GXNormal1x8(0);
837         GXColor1x8(3);
838         GXTexCoord1x8(0); //
839         GXPosition1x16(1);
840         GXNormal1x8(0);
841         GXColor1x8(3);
842         GXTexCoord1x8(1); //
843         GXPosition1x16(2);
844         GXNormal1x8(0);
845         GXColor1x8(3);
846         GXTexCoord1x8(2); //
847         GXPosition1x16(3);
848         GXNormal1x8(0);
849         GXColor1x8(3);
850         GXTexCoord1x8(3); //
851 
852         GXPosition1x16(5);
853         GXNormal1x8(0);
854         GXColor1x8(4);
855         GXTexCoord1x8(0); //
856         GXPosition1x16(4);
857         GXNormal1x8(0);
858         GXColor1x8(4);
859         GXTexCoord1x8(1); //
860         GXPosition1x16(0);
861         GXNormal1x8(0);
862         GXColor1x8(4);
863         GXTexCoord1x8(2); //
864         GXPosition1x16(3);
865         GXNormal1x8(0);
866         GXColor1x8(4);
867         GXTexCoord1x8(3); //
868 
869         GXPosition1x16(6);
870         GXNormal1x8(0);
871         GXColor1x8(5);
872         GXTexCoord1x8(0); //
873         GXPosition1x16(2);
874         GXNormal1x8(0);
875         GXColor1x8(5);
876         GXTexCoord1x8(1); //
877         GXPosition1x16(1);
878         GXNormal1x8(0);
879         GXColor1x8(5);
880         GXTexCoord1x8(2); //
881         GXPosition1x16(7);
882         GXNormal1x8(0);
883         GXColor1x8(5);
884         GXTexCoord1x8(3); //
885 
886     GXEnd();
887 }
888 
889 /*---------------------------------------------------------------------------*
890     Name:           DrawCubeDirect
891 
892     Description:
893 
894     Arguments:      none
895 
896     Returns:        none
897  *---------------------------------------------------------------------------*/
898 static
DrawCubeDirect(void)899 void DrawCubeDirect( void )
900 {
901     GXBegin(GX_QUADS, GX_VTXFMT0, 4*6);
902         GXPosition3f32( SIDE, SIDE, -SIDE); //4
903         GXNormal3f32( SIDE, SIDE, -SIDE); //4
904         GXColor1u32(0xff0000ff);// red
905         GXTexCoord2f32(0.0F, 0.0F);//
906         GXPosition3f32(SIDE, -SIDE, -SIDE);//5
907         GXNormal3f32( SIDE, SIDE, -SIDE); //4
908         GXColor1u32(0xff0000ff);// red
909         GXTexCoord2f32(1.0F, 0.0F);//
910         GXPosition3f32(SIDE, -SIDE, SIDE); //6
911         GXNormal3f32( SIDE, SIDE, -SIDE); //4
912         GXColor1u32(0xff0000ff);// red
913         GXTexCoord2f32(1.0F, 1.0F);//
914         GXPosition3f32(SIDE, SIDE, SIDE);  //7
915         GXNormal3f32( SIDE, SIDE, -SIDE); //4
916         GXColor1u32(0xff0000ff);// red
917         GXTexCoord2f32(0.0F, 1.0F);//
918 
919         GXPosition3f32(-SIDE, -SIDE, SIDE);//2
920         GXNormal3f32( SIDE, SIDE, -SIDE); //4
921         GXColor1u32(0x00ff00ff);// green
922         GXTexCoord2f32(0.0F, 0.0F);//
923         GXPosition3f32(SIDE, -SIDE, SIDE); //6
924         GXNormal3f32( SIDE, SIDE, -SIDE); //4
925         GXColor1u32(0x00ff00ff);// green
926         GXTexCoord2f32(1.0F, 0.0F);//
927         GXPosition3f32(SIDE, -SIDE, -SIDE);//5
928         GXNormal3f32( SIDE, SIDE, -SIDE); //4
929         GXColor1u32(0x00ff00ff);// green
930         GXTexCoord2f32(1.0F, 1.0F);//
931         GXPosition3f32(-SIDE, -SIDE, -SIDE);//3
932         GXNormal3f32( SIDE, SIDE, -SIDE); //4
933         GXColor1u32(0x00ff00ff);// green
934         GXTexCoord2f32(0.0F, 1.0F);//
935 
936         GXPosition3f32(-SIDE, SIDE, SIDE); //1
937         GXNormal3f32( SIDE, SIDE, -SIDE); //4
938         GXColor1u32(0x0000ffff);// blue
939         GXTexCoord2f32(0.0F, 0.0F);//
940         GXPosition3f32(-SIDE, SIDE, -SIDE);//0
941         GXNormal3f32( SIDE, SIDE, -SIDE); //4
942         GXColor1u32(0x0000ffff);// blue
943         GXTexCoord2f32(1.0F, 0.0F);//
944         GXPosition3f32( SIDE, SIDE, -SIDE); //4
945         GXNormal3f32( SIDE, SIDE, -SIDE); //4
946         GXColor1u32(0x0000ffff);// blue
947         GXTexCoord2f32(1.0F, 1.0F);//
948         GXPosition3f32(SIDE, SIDE, SIDE);  //7
949         GXNormal3f32( SIDE, SIDE, -SIDE); //4
950         GXColor1u32(0x0000ffff);// blue
951         GXTexCoord2f32(0.0F, 1.0F);//
952 
953         GXPosition3f32(-SIDE, SIDE, -SIDE);//0
954         GXNormal3f32( SIDE, SIDE, -SIDE); //4
955         GXColor1u32(0xffff00ff);// yellow
956         GXTexCoord2f32(0.0F, 0.0F);//
957         GXPosition3f32(-SIDE, SIDE, SIDE); //1
958         GXNormal3f32( SIDE, SIDE, -SIDE); //4
959         GXColor1u32(0xffff00ff);// yellow
960         GXTexCoord2f32(1.0F, 0.0F);//
961         GXPosition3f32(-SIDE, -SIDE, SIDE);//2
962         GXNormal3f32( SIDE, SIDE, -SIDE); //4
963         GXColor1u32(0xffff00ff);// yellow
964         GXTexCoord2f32(1.0F, 1.0F);//
965         GXPosition3f32(-SIDE, -SIDE, -SIDE);//3
966         GXNormal3f32( SIDE, SIDE, -SIDE); //4
967         GXColor1u32(0xffff00ff);// yellow
968         GXTexCoord2f32(0.0F, 1.0F);//
969 
970         GXPosition3f32(SIDE, -SIDE, -SIDE);//5
971         GXNormal3f32( SIDE, SIDE, -SIDE); //4
972         GXColor1u32(0xff00ffff);// magenta
973         GXTexCoord2f32(0.0F, 0.0F);//
974         GXPosition3f32( SIDE, SIDE, -SIDE); //4
975         GXNormal3f32( SIDE, SIDE, -SIDE); //4
976         GXColor1u32(0xff00ffff);// magenta
977         GXTexCoord2f32(1.0F, 0.0F);//
978         GXPosition3f32(-SIDE, SIDE, -SIDE);//0
979         GXNormal3f32( SIDE, SIDE, -SIDE); //4
980         GXColor1u32(0xff00ffff);// magenta
981         GXTexCoord2f32(1.0F, 1.0F);//
982         GXPosition3f32(-SIDE, -SIDE, -SIDE);//3
983         GXNormal3f32( SIDE, SIDE, -SIDE); //4
984         GXColor1u32(0xff00ffff);// magenta
985         GXTexCoord2f32(0.0F, 1.0F);//
986 
987         GXPosition3f32(SIDE, -SIDE, SIDE); //6
988         GXNormal3f32( SIDE, SIDE, -SIDE); //4
989         GXColor1u32(0x00ffffff);// cyan
990         GXTexCoord2f32(0.0F, 0.0F);//
991         GXPosition3f32(-SIDE, -SIDE, SIDE);//2
992         GXNormal3f32( SIDE, SIDE, -SIDE); //4
993         GXColor1u32(0x00ffffff);// cyan
994         GXTexCoord2f32(1.0F, 0.0F);//
995         GXPosition3f32(-SIDE, SIDE, SIDE); //1
996         GXNormal3f32( SIDE, SIDE, -SIDE); //4
997         GXColor1u32(0x00ffffff);// cyan
998         GXTexCoord2f32(1.0F, 1.0F);//
999         GXPosition3f32(SIDE, SIDE, SIDE);  //7
1000         GXNormal3f32( SIDE, SIDE, -SIDE); //4
1001         GXColor1u32(0x00ffffff);// cyan
1002         GXTexCoord2f32(0.0F, 1.0F);//
1003     GXEnd();
1004 }
1005 
1006 
1007 /*---------------------------------------------------------------------------*
1008     Name:           DrawTexCubeIndx
1009 
1010     Description:
1011 
1012     Arguments:      none
1013 
1014     Returns:        none
1015  *---------------------------------------------------------------------------*/
1016 static
DrawTexCubeIndx(void)1017 void DrawTexCubeIndx( void )
1018 {
1019     GXBegin(GX_QUADS, GX_VTXFMT0, 4*6);
1020         GXPosition1x16(4);
1021         GXTexCoord1x8(0); //
1022         GXPosition1x16(5);
1023         GXTexCoord1x8(1); //
1024         GXPosition1x16(6);
1025         GXTexCoord1x8(2); //
1026         GXPosition1x16(7);
1027         GXTexCoord1x8(3); //
1028 
1029         GXPosition1x16(2);
1030         GXTexCoord1x8(0); //
1031         GXPosition1x16(6);
1032         GXTexCoord1x8(1); //
1033         GXPosition1x16(5);
1034         GXTexCoord1x8(2); //
1035         GXPosition1x16(3);
1036         GXTexCoord1x8(3); //
1037 
1038         GXPosition1x16(1);
1039         GXTexCoord1x8(0); //
1040         GXPosition1x16(0);
1041         GXTexCoord1x8(1); //
1042         GXPosition1x16(4);
1043         GXTexCoord1x8(2); //
1044         GXPosition1x16(7);
1045         GXTexCoord1x8(3); //
1046 
1047         GXPosition1x16(0);
1048         GXTexCoord1x8(0); //
1049         GXPosition1x16(1);
1050         GXTexCoord1x8(1); //
1051         GXPosition1x16(2);
1052         GXTexCoord1x8(2); //
1053         GXPosition1x16(3);
1054         GXTexCoord1x8(3); //
1055 
1056         GXPosition1x16(5);
1057         GXTexCoord1x8(0); //
1058         GXPosition1x16(4);
1059         GXTexCoord1x8(1); //
1060         GXPosition1x16(0);
1061         GXTexCoord1x8(2); //
1062         GXPosition1x16(3);
1063         GXTexCoord1x8(3); //
1064 
1065         GXPosition1x16(6);
1066         GXTexCoord1x8(0); //
1067         GXPosition1x16(2);
1068         GXTexCoord1x8(1); //
1069         GXPosition1x16(1);
1070         GXTexCoord1x8(2); //
1071         GXPosition1x16(7);
1072         GXTexCoord1x8(3); //
1073 
1074     GXEnd();
1075 }
1076 
1077 /*---------------------------------------------------------------------------*
1078     Name:           DrawTexCubeDirect
1079 
1080     Description:
1081 
1082     Arguments:      none
1083 
1084     Returns:        none
1085  *---------------------------------------------------------------------------*/
1086 static
DrawTexCubeDirect(void)1087 void DrawTexCubeDirect( void )
1088 {
1089     GXBegin(GX_QUADS, GX_VTXFMT0, 4*6);
1090         GXPosition3f32( SIDE, SIDE, -SIDE); //4
1091         GXTexCoord2f32(0.0F, 0.0F);//
1092         GXPosition3f32(SIDE, -SIDE, -SIDE);//5
1093         GXTexCoord2f32(1.0F, 0.0F);//
1094         GXPosition3f32(SIDE, -SIDE, SIDE); //6
1095         GXTexCoord2f32(1.0F, 1.0F);//
1096         GXPosition3f32(SIDE, SIDE, SIDE);  //7
1097         GXTexCoord2f32(0.0F, 1.0F);//
1098 
1099         GXPosition3f32(-SIDE, -SIDE, SIDE);//2
1100         GXTexCoord2f32(0.0F, 0.0F);//
1101         GXPosition3f32(SIDE, -SIDE, SIDE); //6
1102         GXTexCoord2f32(1.0F, 0.0F);//
1103         GXPosition3f32(SIDE, -SIDE, -SIDE);//5
1104         GXTexCoord2f32(1.0F, 1.0F);//
1105         GXPosition3f32(-SIDE, -SIDE, -SIDE);//3
1106         GXTexCoord2f32(0.0F, 1.0F);//
1107 
1108         GXPosition3f32(-SIDE, SIDE, SIDE); //1
1109         GXTexCoord2f32(0.0F, 0.0F);//
1110         GXPosition3f32(-SIDE, SIDE, -SIDE);//0
1111         GXTexCoord2f32(1.0F, 0.0F);//
1112         GXPosition3f32( SIDE, SIDE, -SIDE); //4
1113         GXTexCoord2f32(1.0F, 1.0F);//
1114         GXPosition3f32(SIDE, SIDE, SIDE);  //7
1115         GXTexCoord2f32(0.0F, 1.0F);//
1116 
1117         GXPosition3f32(-SIDE, SIDE, -SIDE);//0
1118         GXTexCoord2f32(0.0F, 0.0F);//
1119         GXPosition3f32(-SIDE, SIDE, SIDE); //1
1120         GXTexCoord2f32(1.0F, 0.0F);//
1121         GXPosition3f32(-SIDE, -SIDE, SIDE);//2
1122         GXTexCoord2f32(1.0F, 1.0F);//
1123         GXPosition3f32(-SIDE, -SIDE, -SIDE);//3
1124         GXTexCoord2f32(0.0F, 1.0F);//
1125 
1126         GXPosition3f32(SIDE, -SIDE, -SIDE);//5
1127         GXTexCoord2f32(0.0F, 0.0F);//
1128         GXPosition3f32( SIDE, SIDE, -SIDE); //4
1129         GXTexCoord2f32(1.0F, 0.0F);//
1130         GXPosition3f32(-SIDE, SIDE, -SIDE);//0
1131         GXTexCoord2f32(1.0F, 1.0F);//
1132         GXPosition3f32(-SIDE, -SIDE, -SIDE);//3
1133         GXTexCoord2f32(0.0F, 1.0F);//
1134 
1135         GXPosition3f32(SIDE, -SIDE, SIDE); //6
1136         GXTexCoord2f32(0.0F, 0.0F);//
1137         GXPosition3f32(-SIDE, -SIDE, SIDE);//2
1138         GXTexCoord2f32(1.0F, 0.0F);//
1139         GXPosition3f32(-SIDE, SIDE, SIDE); //1
1140         GXTexCoord2f32(1.0F, 1.0F);//
1141         GXPosition3f32(SIDE, SIDE, SIDE);  //7
1142         GXTexCoord2f32(0.0F, 1.0F);//
1143     GXEnd();
1144 }
1145