1 /*---------------------------------------------------------------------------*
2 Project: Dolphin/Revolution gx demo
3 File: fill-perf.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 Fill-rate performance test
13
14 *---------------------------------------------------------------------------*/
15
16 #include <stdlib.h>
17 #include <string.h>
18 #include <demo.h>
19 #include <math.h>
20
21 /*---------------------------------------------------------------------------*
22 Type definitions
23 *---------------------------------------------------------------------------*/
24 // statistic data display style
25 typedef enum
26 {
27 STAT_TL, // top left
28 STAT_BL, // bottom left
29 STAT_TLD, // double-size font, top-left
30 STAT_BLD, // double-size font, bottom-left
31 STAT_IO // dump using OSReport
32 } StatDispMode;
33
34 // statistic types
35 typedef enum
36 {
37 STAT_GP0, // GXReadGP0Metric
38 STAT_GP1, // GXReadGP1Metric
39 STAT_MEM, // GXReadMemMetric
40 STAT_PIX, // GXReadPixMetric
41 STAT_VC, // GXReadVCacheMetric
42 STAT_FR, // Fill rate calc
43 STAT_TBW, // Texture bandwidth calc
44 STAT_TBP, // Texture B/pixel
45 STAT_MYC, // print out user-computed count
46 STAT_MYR // print out user-computed rate (stat/count)
47 } StatType;
48
49 // used as "stat" argument when stat_type == STAT_MEM
50 typedef enum
51 {
52 STAT_MEM_CP, // GXReadMemMetric(CP Req.)
53 STAT_MEM_TC, // GXReadMemMetric(TC Req.)
54 STAT_MEM_CPUR, // GXReadMemMetric(CPU Rd Req.)
55 STAT_MEM_CPUW, // GXReadMemMetric(CPU Wr Req.)
56 STAT_MEM_DSP, // GXReadMemMetric(DSP Req.)
57 STAT_MEM_IO, // GXReadMemMetric(IO Req.)
58 STAT_MEM_VI, // GXReadMemMetric(VI Req.)
59 STAT_MEM_PE, // GXReadMemMetric(PE Req.)
60 STAT_MEM_RF, // GXReadMemMetric(RF Req.)
61 STAT_MEM_FI // GXReadMemMetric(FI Req.)
62 } MemStatArg;
63
64 // used as "stat" argument when stat_type == STAT_PIX
65 typedef enum
66 {
67 STAT_PIX_TI, // GXReadPixMetric(Top Pixel In)
68 STAT_PIX_TO, // GXReadPixMetric(Top Pixel Out)
69 STAT_PIX_BI, // GXReadPixMetric(Bottom Pixel In)
70 STAT_PIX_BO, // GXReadPixMetric(Bottom Pixel Out)
71 STAT_PIX_CI, // GXReadPixMetric(Color Pixel In)
72 STAT_PIX_CC // GXReadPixMetric(Copy Clocks)
73 } PixStatArg;
74
75 // used as "stat" argument when stat_type == STAT_VC
76 typedef enum
77 {
78 STAT_VC_CHK, // GXReadVCacheMetric(Check)
79 STAT_VC_MISS, // GXReadVCacheMetric(Miss)
80 STAT_VC_STALL // GXReadVCacheMetric(Stall)
81 } VcStatArg;
82
83 typedef struct
84 {
85 char text[48]; // 8 x 48 = 386 pixels
86 StatType stat_type; // statics type
87 u32 stat; // metric to measure
88 u32 count; // count returned from metric function
89 } StatObj;
90
91 /*---------------------------------------------------------------------------*
92 Forward references
93 *---------------------------------------------------------------------------*/
94
95 void main ( void );
96 static void CameraInit ( void );
97 static void ViewInit ( void );
98 static void DrawInit ( void );
99 static void InitDrawState ( void );
100 static void DrawTick ( void );
101 static void AnimTick ( void );
102 static void MakeModelMtx ( Vec xAxis, Vec yAxis, Vec zAxis, Mtx m );
103 static void PrintIntro ( void );
104 static void DrawCubeIndx ( void );
105 static void DrawCubeDirect ( void );
106 static void DrawArrow ( void );
107 static void init_rand ( void );
108 static u32 lrand ( void );
109 static f32 frand ( void );
110
111 static GXTexRegion*
112 MyTexRegionCallback( const GXTexObj* texObj, GXTexMapID mapID );
113
114
115 static void PrintStats ( void );
116 static void UpdateStats ( GXBool inc );
117 static void WriteStats ( GXBool update );
118 static void SetStats ( StatObj* stat, u32 nstats, StatDispMode disp );
119
120 /*---------------------------------------------------------------------------*
121 Defines
122 *---------------------------------------------------------------------------*/
123 #define INDEXED_DATA 1 // comment out for direct data
124
125 #define TCACHE_SZ GX_TEXCACHE_32K
126 #define NUM_REGIONS 8 // number of caches
127 #define NUM_TEXOBJS 9 // for 8 tev stages, plus 1 to swap between
128 #define MAX_TEV 8 // for this test
129 #define NUM_ROTMATS 10 // just because
130
131 #define STAT_SIZE (sizeof(MyStats) / sizeof(StatObj))
132 #define SIDE 50.0F
133
134
135 /*---------------------------------------------------------------------------*
136 Global variables
137 *---------------------------------------------------------------------------*/
138 //
139 // Cube data
140 //
141 f32 Vert[] ATTRIBUTE_ALIGN(32) =
142 {
143 -SIDE, SIDE, -SIDE, //0
144 -SIDE, SIDE, SIDE, //1
145 -SIDE, -SIDE, SIDE, //2
146 -SIDE, -SIDE, -SIDE, //3
147 SIDE, SIDE, -SIDE, //4
148 SIDE, -SIDE, -SIDE, //5
149 SIDE, -SIDE, SIDE, //6
150 SIDE, SIDE, SIDE, //7
151 0, 0, -SIDE, //8
152 SIDE/4, 0, 0, //9
153 -SIDE/4, 0, 0, //10
154 0, SIDE/4, 0 //11
155 };
156
157 f32 Norm[] ATTRIBUTE_ALIGN(32) =
158 {
159 -1.0F, 0.0F, 0.0F, //0
160 0.0F, -1.0F, 0.0F, //1
161 0.0F, 0.0F, -1.0F, //2
162 1.0F, 0.0F, 0.0F, //3
163 0.0F, 1.0F, 0.0F, //4
164 0.0F, 0.0F, 1.0F //5
165 };
166
167 f32 TexCoord[] ATTRIBUTE_ALIGN(32) =
168 {
169 0.0F, 0.0F, //0
170 1.0F, 0.0F, //1
171 1.0F, 1.0F, //2
172 0.0F, 1.0F, //3
173 };
174
175 u32 MyColors[] ATTRIBUTE_ALIGN(32) =
176 {
177 0xff0000ff, // red
178 0x00ff00ff, // green
179 0x0000ffff, // blue
180 0xffff00ff, // yellow
181 0xff00ffff, // magenta
182 0x00ffffff // cyan
183 };
184
185 //
186 // Test structure
187 //
188 typedef struct
189 {
190 u32 numx; // number of cubes in x direction
191 u32 numy; // number of cubes in y direction
192 u32 numz; // number of cubes in z direction
193 f32 dx; // dist between cubes in x direction
194 f32 dy; // dist between cubes in y direction
195 f32 dz; // dist between cubes in z direction
196 u8 ntev; // number of textures per cube (num tev stages)
197 u32 nc_tx; // number of cubes per texture change
198 u32 tcb; // texture region allocator callback
199 u32 tci; // invalidate tex region on each GXLoadTexObj when tcb=1
200 f32 mods; // model scale
201 f32 rot; // model rotation
202 f32 dr; // model rotation speed
203 Vec axis[NUM_ROTMATS]; // random rotation axis, initialized by DrawInit
204 } TestData;
205
206 static TestData testData;
207
208 //
209 // Statistics
210 //
211 //
212 StatObj MyStats1[] =
213 {
214 // General Performance
215 { "GP Clocks [1/60]..", STAT_GP0, GX_PERF0_CLOCKS, 0 },
216 { "Vertices..........", STAT_GP1, GX_PERF1_VERTICES, 0 },
217 { "Fill Rate [MP/Sec]", STAT_FR, GX_PERF0_NONE, 0 },
218 { "TextureBW [MB/Sec]", STAT_TBW, GX_PERF0_NONE, 0 },
219 { "TexB/pix..........", STAT_TBP, GX_PERF0_NONE, 0 },
220 };
221
222 StatObj MyStats2[] =
223 {
224 // Texture Performance Detail
225 { "Texels.........", STAT_GP1, GX_PERF1_TEXELS, 0 },
226 { "Tex 1-2 Lines..", STAT_GP1, GX_PERF1_TC_CHECK1_2, 0 },
227 { "Tex 3-4 Lines..", STAT_GP1, GX_PERF1_TC_CHECK3_4, 0 },
228 { "Tex 5-6 Lines..", STAT_GP1, GX_PERF1_TC_CHECK5_6, 0 },
229 { "Tex 7-8 Lines..", STAT_GP1, GX_PERF1_TC_CHECK7_8, 0 },
230 { "Tex Cache Miss.", STAT_GP1, GX_PERF1_TC_MISS, 0 },
231 { "Total Checks...", STAT_MYC, GX_PERF1_NONE, 0 },
232 { "Tex$ Miss Rate.", STAT_MYR, GX_PERF1_NONE, 0 },
233 };
234
235 StatObj MyStats3[] =
236 {
237 // Pixel Performance Detail
238 { "Pixels Entered.", STAT_PIX, STAT_PIX_TI, 0 },
239 { "Pixels Z Passed", STAT_PIX, STAT_PIX_TO, 0 },
240 { "Pixels Blended.", STAT_PIX, STAT_PIX_CI, 0 },
241 { "Quads w>0 Cvg..", STAT_GP0, GX_PERF0_QUAD_NON0CVG, 0 },
242 { "Quads w/1 Cvg..", STAT_GP0, GX_PERF0_QUAD_1CVG, 0 },
243 { "Quads w/2 Cvg..", STAT_GP0, GX_PERF0_QUAD_2CVG, 0 },
244 { "Quads w/3 Cvg..", STAT_GP0, GX_PERF0_QUAD_3CVG, 0 },
245 { "Quads w/4 Cvg..", STAT_GP0, GX_PERF0_QUAD_4CVG, 0 },
246 };
247
248 StatObj MyStats4[] =
249 {
250 // Memory Access Detail
251 { "CP Reqs........", STAT_MEM, STAT_MEM_CP, 0 },
252 { "TX Cache Reqs..", STAT_MEM, STAT_MEM_TC, 0 },
253 { "CPU Rd Reqs....", STAT_MEM, STAT_MEM_CPUR, 0 },
254 { "CPU Wr Reqs....", STAT_MEM, STAT_MEM_CPUW, 0 },
255 { "DSP Reqs.......", STAT_MEM, STAT_MEM_DSP, 0 },
256 { "IO Reqs........", STAT_MEM, STAT_MEM_IO, 0 },
257 { "VI Reqs........", STAT_MEM, STAT_MEM_VI, 0 },
258 { "PE Reqs........", STAT_MEM, STAT_MEM_PE, 0 },
259 { "Refresh Reqs...", STAT_MEM, STAT_MEM_RF, 0 },
260 { "Forced Idle....", STAT_MEM, STAT_MEM_FI, 0 },
261 };
262
263 StatObj MyStats5[] =
264 {
265 // Current Setting
266 { "Num Of Cubes...", STAT_MYC, 0, 0 },
267 { "Cubes/Texture..", STAT_MYC, 0, 0 },
268 { "Num TevStages..", STAT_MYC, 0, 0 },
269 };
270
271 #define STAT_MENU0 0
272 #define STAT_MENU1 (sizeof(MyStats1)/sizeof(StatObj))
273 #define STAT_MENU2 (sizeof(MyStats2)/sizeof(StatObj))
274 #define STAT_MENU3 (sizeof(MyStats3)/sizeof(StatObj))
275 #define STAT_MENU4 (sizeof(MyStats4)/sizeof(StatObj))
276 #define STAT_MENU5 (sizeof(MyStats5)/sizeof(StatObj))
277
278 static Mtx v, mv;
279 static u32 animMode = 0;
280 static u32 showStats = 1; // show fill rate by default
281 static u32 stopAnim = 0;
282 static void (*testDraw)() = NULL; // function pointer for draw routine
283 static GXTexObj texObj[NUM_TEXOBJS]; // texture object
284 static GXTexRegion MyTexRegions[NUM_REGIONS]; // cache regions
285
286 static GXTexRegionCallback oldCallback;
287
288 static GXLightObj MyLight; // light object
289
290 static Vec CamX = {1.0F, 0.0F, 0.0F};
291 static Vec CamY = {0.0F, 1.0F, 0.0F};
292 static Vec CamZ = {0.0F, 0.0F, 1.0F};
293 static f32 CamS = 100.0F; // camera zoom factor
294
295 static OSStopwatch myTotTime;
296
297 // For stats
298 static GXBool StatEnable = GX_FALSE;
299
300 static StatObj* Stat = NULL;
301 static u32 StatIndx = 0;
302 static u32 StatMaxIndx = 0;
303 static u32 StatClocks = 0;
304
305 static u32 StatDisp = 0;
306 static u32 StatStrLen = 0;
307
308 // other statistics counts that can be counted in parallel
309 static u32 topPixIn, topPixOut;
310 static u32 botPixIn, botPixOut;
311 static u32 clrPixIn, copyClks;
312
313 static u32 vcCheck, vcMiss, vcStall;
314
315 static u32 cpReq, tcReq, cpuRdReq, cpuWrReq, dspReq,
316 ioReq, viReq, peReq, rfReq, fiReq;
317
318
319 /*---------------------------------------------------------------------------*
320 Application main loop
321 *---------------------------------------------------------------------------*/
main(void)322 void main ( void )
323 {
324 DEMOInit(NULL);
325 DrawInit();
326 PrintIntro();
327
328 OSInitStopwatch(&myTotTime, "myTotTime");
329 OSResetStopwatch(&myTotTime);
330
331 testDraw = DrawCubeIndx;
332
333 while (!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
334 {
335 DEMOPadRead();
336 AnimTick();
337
338 InitDrawState();
339 CameraInit();
340
341 OSStartStopwatch(&myTotTime);
342 DEMOBeforeRender();
343
344 DrawTick();
345
346 if ( showStats == 2 )
347 {
348 // total check count
349 MyStats2[6].count = MyStats2[1].count + MyStats2[2].count +
350 MyStats2[3].count + MyStats2[4].count;
351 // compute miss rate
352 MyStats2[7].stat = MyStats2[5].count; // misses
353 MyStats2[7].count = MyStats2[6].count; // total checks
354 }
355 else if ( showStats == 5 )
356 {
357 MyStats5[0].count = testData.numx * testData.numy * testData.numz;
358 MyStats5[1].count = testData.nc_tx;
359 MyStats5[2].count = testData.ntev;
360 }
361
362 GXDrawDone();
363 OSStopStopwatch(&myTotTime);
364
365 if ( StatEnable )
366 {
367 UpdateStats(GX_TRUE);
368 PrintStats();
369 GXDrawDone();
370 UpdateStats(GX_FALSE);
371 }
372
373 DEMODoneRender();
374 }
375
376 OSHalt("End of test");
377 }
378
379 /*---------------------------------------------------------------------------*
380 Functions
381 *---------------------------------------------------------------------------*/
382
383
384 /*---------------------------------------------------------------------------*
385 Name: CameraInit
386
387 Description: Initialize the projection matrix and load into hardware.
388
389 Arguments: none
390
391 Returns: none
392 *---------------------------------------------------------------------------*/
CameraInit(void)393 static void CameraInit ( void )
394 {
395 Mtx44 p;
396
397 MTXFrustum(p, .24F * CamS,-.24F * CamS,
398 -.32F * CamS, .32F * CamS,
399 .5F * CamS, 40.0F * CamS);
400
401 GXSetProjection(p, GX_PERSPECTIVE);
402 ViewInit();
403 }
404
405
406 /*---------------------------------------------------------------------------*
407 Name: ViewInit
408
409 Description: Initialize the view matrix.
410
411 Arguments: none
412
413 Returns: none
414 *---------------------------------------------------------------------------*/
ViewInit(void)415 static void ViewInit ( void )
416 {
417 Mtx trans;
418
419 MakeModelMtx(CamX, CamY, CamZ, v); // Make a new view matrix
420 MTXTranspose(v, v);
421 MTXTrans(trans, 0.0F, 0.0F, -8.0F * CamS);
422 MTXConcat(trans, v, v);
423 }
424
425
426 /*---------------------------------------------------------------------------*
427 Name: DrawInit
428
429 Description: Initialize one-time state settings
430
431 Arguments: none
432
433 Returns: none
434 *---------------------------------------------------------------------------*/
DrawInit(void)435 static void DrawInit( void )
436 {
437 u32 i;
438 GXColor color = {0, 255, 255, 255};
439 TPLPalettePtr tpl = 0; // texture palette
440
441 //
442 // Initialize test structure
443 //
444 testData.numx = 1;
445 testData.numy = 1;
446 testData.numz = 1;
447 testData.nc_tx = testData.numx * testData.numz;
448 testData.tcb = 0; // default texregion callback
449 testData.tci = 0; // don't invalidate tex cache regions
450 testData.dx = 2*SIDE + 10.0F;
451 testData.dy = 2*SIDE + 10.0F;
452 testData.dz = -(2*SIDE + 10.0F);
453 testData.ntev = 1; // num textures
454 testData.mods = 1.0F; // model scale
455 testData.rot = 0.0F; // model rotation
456 testData.dr = 1.0F; // rotation speed
457
458 SetStats(MyStats1, STAT_MENU1, STAT_TLD);
459
460 // init texture regions
461 for ( i = 0 ; i < NUM_REGIONS ; i++ )
462 {
463 // The region is used as a 32K cache.
464 GXInitTexCacheRegion(
465 &MyTexRegions[i],
466 GX_FALSE, // 32b mipmap
467 0x00000 + i * 0x08000, // tmem_even
468 TCACHE_SZ, // size_even
469 0x80000 + i * 0x08000, // tmem_odd
470 TCACHE_SZ ); // size_odd
471 }
472
473 // initialize oldCallback to default callback
474 oldCallback = GXSetTexRegionCallback(MyTexRegionCallback);
475 GXSetTexRegionCallback(oldCallback);
476
477 // model axis
478 init_rand();
479 for (i = 0; i < NUM_ROTMATS; i++)
480 {
481 // make random axis
482 testData.axis[i].x = frand();
483 testData.axis[i].y = frand();
484 testData.axis[i].z = frand();
485 VECNormalize(&testData.axis[i], &testData.axis[i]);
486 }
487
488 GXInitLightPos(&MyLight, 0.0F, 0.0F, 0.0F);
489 GXInitLightColor(&MyLight, color);
490
491 // Load the texture palette
492 TPLGetPalette(&tpl, "gxTests/tex-07.tpl");
493
494 // Initialize a texture object to contain the correct texture
495 for (i = 0; i < NUM_TEXOBJS; i++)
496 {
497 OSReport("Reading tex obj %d\n", i);
498 TPLGetGXTexObjFromPalette(tpl, &texObj[i], i);
499 GXInitTexObjUserData(&texObj[i], (void*)i);
500 }
501
502 InitDrawState();
503
504 GXDrawDone(); // make sure state is in GP
505 }
506
507
508 /*---------------------------------------------------------------------------*
509 Name: InitDrawState
510
511 Description: Sets drawing state that gets destroyed by DEMOPrintf
512 when the statistics are printed.
513
514 Arguments: none
515
516 Returns: none
517 *---------------------------------------------------------------------------*/
InitDrawState(void)518 static void InitDrawState( void )
519 {
520 GXColor color = {0, 255, 0, 255};
521
522 GXSetCurrentMtx(0);
523 GXSetCullMode(GX_CULL_BACK);
524
525 GXLoadLightObjImm(&MyLight, GX_LIGHT0);
526
527 GXSetChanMatColor(GX_COLOR0A0, color);
528 GXSetChanCtrl(
529 GX_COLOR0A0,
530 GX_FALSE, // enable channel
531 GX_SRC_REG, // amb source
532 GX_SRC_VTX, // mat source
533 GX_LIGHT_NULL, // light mask
534 GX_DF_NONE, // diffuse function
535 GX_AF_NONE);
536
537 // Load the texture object; tex0 is used in stage 0
538
539 GXSetNumChans(1);
540 GXSetNumTexGens(1);
541 GXSetNumTevStages(testData.ntev);
542
543 GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
544 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
545 GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD0, GX_TEXMAP1, GX_COLOR_NULL);
546 GXSetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD0, GX_TEXMAP2, GX_COLOR_NULL);
547 GXSetTevOrder(GX_TEVSTAGE3, GX_TEXCOORD0, GX_TEXMAP3, GX_COLOR_NULL);
548 GXSetTevOrder(GX_TEVSTAGE4, GX_TEXCOORD0, GX_TEXMAP4, GX_COLOR_NULL);
549 GXSetTevOrder(GX_TEVSTAGE5, GX_TEXCOORD0, GX_TEXMAP5, GX_COLOR_NULL);
550 GXSetTevOrder(GX_TEVSTAGE6, GX_TEXCOORD0, GX_TEXMAP6, GX_COLOR_NULL);
551 GXSetTevOrder(GX_TEVSTAGE7, GX_TEXCOORD0, GX_TEXMAP7, GX_COLOR_NULL);
552 GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);
553 GXSetTevOp(GX_TEVSTAGE1, GX_REPLACE);
554 GXSetTevOp(GX_TEVSTAGE2, GX_REPLACE);
555 GXSetTevOp(GX_TEVSTAGE3, GX_REPLACE);
556 GXSetTevOp(GX_TEVSTAGE4, GX_REPLACE);
557 GXSetTevOp(GX_TEVSTAGE5, GX_REPLACE);
558 GXSetTevOp(GX_TEVSTAGE6, GX_REPLACE);
559 GXSetTevOp(GX_TEVSTAGE7, GX_REPLACE);
560
561 GXSetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR);
562 GXSetZMode(GX_ENABLE, GX_LEQUAL, GX_ENABLE);
563
564 GXClearVtxDesc();
565
566 #ifdef INDEXED_DATA
567 //OSReport("Using indexed data\n");
568 GXSetVtxDesc(GX_VA_POS, GX_INDEX16);
569 GXSetVtxDesc(GX_VA_CLR0, GX_INDEX8);
570 GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
571 #else
572 //OSReport("Using direct data\n");
573 GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
574 GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
575 GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
576 #endif // INDEXED_DATA
577
578 GXSetArray(GX_VA_POS, Vert, sizeof(f32)*3);
579 GXSetArray(GX_VA_CLR0, MyColors, sizeof(u32));
580 GXSetArray(GX_VA_TEX0, TexCoord, sizeof(f32)*2);
581
582 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
583 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
584 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
585 }
586
587 /*---------------------------------------------------------------------------*
588 Name: DrawTick
589
590 Description: Draws spheres
591
592 Arguments: none
593
594 Returns: none
595 *---------------------------------------------------------------------------*/
DrawTick(void)596 static void DrawTick( void )
597 {
598 u32 i, j, k, cnt; // indices
599 u32 tx; // offset of texture
600 Mtx m, t;
601 f32 x, z;
602
603 // for now do only 2-D grid
604 // center grid on 0, 0, 0
605 z = 0.0F - ((testData.numz / 2) * testData.dz);
606 for (cnt = i = 0; i < testData.numz; i++)
607 {
608 x = 0.0F - ((testData.numx / 2) * testData.dx);
609 for (j = 0; j < testData.numx; j++, cnt++)
610 {
611 // Set texture state every n cubes
612 if ((cnt % testData.nc_tx) == 0)
613 {
614 tx = ((cnt / testData.nc_tx) & 1) * (NUM_TEXOBJS - 1);
615 for (k = 0; k < testData.ntev; k++)
616 {
617 if (tx)
618 GXLoadTexObj(&texObj[tx], (GXTexMapID)k);
619 else
620 GXLoadTexObj(&texObj[k], (GXTexMapID)k);
621 }
622 }
623 // build matrix
624 MTXScale(m, testData.mods, testData.mods, testData.mods);
625 MTXRotAxisDeg(t, &testData.axis[cnt%NUM_ROTMATS], testData.rot);
626 MTXConcat(t, m, m); // scale, rotate
627 MTXTrans(t, x, 0.0F, z);
628 MTXConcat(t, m, m); // translate
629 MTXConcat(v, m, mv); // concat view matrix
630
631 GXLoadPosMtxImm(mv, 0);
632 GXLoadNrmMtxImm(mv, 0);
633
634 testDraw();
635
636 x += testData.dx;
637 }
638 z += testData.dz;
639 }
640
641 // draw arrow on top-center
642 MTXScale(m, testData.mods, testData.mods, testData.mods);
643 MTXTrans(t, 0.0F, -100.0F*testData.mods, 0.0F);
644 MTXConcat(t, m, m); // scale, translate
645 MTXConcat(v, m, mv); // concat view matrix
646
647 GXLoadPosMtxImm(mv, 0);
648 DrawArrow();
649 }
650
651 /*---------------------------------------------------------------------------*
652 Name: AnimTick
653
654 Description: Animates the camera and object based on the joystick's
655 state.
656
657 Arguments: v view matrix
658 m model matrix
659
660 Returns: none
661 *---------------------------------------------------------------------------*/
AnimTick(void)662 static void AnimTick ( void )
663 {
664 Mtx rot;
665 Vec temp;
666 Vec yAxis = {0.0F, 1.0F, 0.0F};
667 f32 dot;
668
669 // Get controller status through DEMOPad library
670 u16 buttons = DEMOPadGetButton(0);
671 u16 downs = DEMOPadGetButtonDown(0);
672 u16 dirs = DEMOPadGetDirsNew(0);
673 s8 stickX = DEMOPadGetStickX(0);
674 s8 stickY = DEMOPadGetStickY(0);
675
676 // Scale model up/down
677 if (buttons & PAD_TRIGGER_L)
678 {
679 testData.mods *= 0.95F;
680 if (testData.mods < 0.001F)
681 testData.mods = 0.001F;
682 }
683 if (buttons & PAD_TRIGGER_R)
684 {
685 testData.mods *= 1.05F;
686 }
687
688 // Model rotation
689 testData.rot += testData.dr;
690 if (testData.rot >= 360.0F)
691 testData.rot -= 360.0F;
692
693 // change number of cubes
694 if (dirs & DEMO_SUBSTICK_UP)
695 {
696 testData.numz++;
697 }
698 if (dirs & DEMO_SUBSTICK_DOWN)
699 {
700 testData.numz--;
701 if (testData.numz <= 1)
702 testData.numz = 1;
703 }
704 if (dirs & DEMO_SUBSTICK_RIGHT)
705 {
706 testData.numx++;
707 }
708 if (dirs & DEMO_SUBSTICK_LEFT)
709 {
710 testData.numx--;
711 if (testData.numx <= 1)
712 testData.numx = 1;
713 }
714
715 // Zoom camera in/out
716 if(buttons & PAD_BUTTON_Y)
717 {
718 CamS *= .95F;
719 if(CamS < 0.001F)
720 {
721 CamS = 0.001F;
722 }
723 }
724 if(buttons & PAD_BUTTON_A)
725 {
726 CamS *= 1.05F;
727 }
728
729 // Rotate viewpoint
730 if(stickX || stickY)
731 {
732 if(stickX > 30 || stickX < -30)
733 {
734 if(stickX > 30)
735 MTXRotDeg(rot, 'y', -1.0F);
736 else if(stickX < -30)
737 MTXRotDeg(rot, 'y', 1.0F);
738
739 MTXMultVec(rot, &CamX, &CamX);
740 MTXMultVec(rot, &CamY, &CamY);
741 MTXMultVec(rot, &CamZ, &CamZ);
742 }
743
744 if(stickY > 30 || stickY < -30)
745 {
746 if(stickY > 30)
747 MTXRotAxisDeg(rot, &CamX, -1.0F);
748 else if(stickY < -30)
749 MTXRotAxisDeg(rot, &CamX, 1.0F);
750
751 MTXMultVec(rot, &CamY, &temp);
752 dot = VECDotProduct(&temp, &yAxis);
753 if(dot > 0.05F && dot <= 1.0F)
754 {
755 CamY = temp;
756 MTXMultVec(rot, &CamZ, &CamZ);
757 }
758 }
759 }
760
761 // change mode
762 if(downs & PAD_BUTTON_X)
763 {
764 animMode++;
765 animMode %= 6;
766
767 switch (animMode)
768 {
769 case 0:
770 OSReport("Button B increments the number of tev stages\n");
771 break;
772 case 1:
773 OSReport("Button B toggles the statistics display\n");
774 break;
775 case 2:
776 OSReport("Button B toggles the cube animation\n");
777 break;
778 case 3:
779 OSReport("Button B decrements the number of cubes per texture\n");
780 break;
781 case 4:
782 OSReport("Button B toggles the texture cache algorithm\n");
783 break;
784 case 5:
785 OSReport("Button B toggles texture invalidation mode\n");
786 break;
787 default:
788 break;
789 }
790 }
791
792 // change param depending on mode
793 if (downs & PAD_BUTTON_B)
794 {
795 if (animMode == 0)
796 {
797 testData.ntev++;
798 if (testData.ntev > MAX_TEV)
799 testData.ntev = 1;
800
801 }
802 else if (animMode == 1)
803 {
804 showStats++;
805 switch(showStats)
806 {
807 case 1 :
808 SetStats(MyStats1, STAT_MENU1, STAT_TLD);
809 break;
810 case 2 :
811 SetStats(MyStats2, STAT_MENU2, STAT_TLD);
812 break;
813 case 3 :
814 SetStats(MyStats3, STAT_MENU3, STAT_TLD);
815 break;
816 case 4 :
817 SetStats(MyStats4, STAT_MENU4, STAT_TLD);
818 break;
819 case 5 :
820 SetStats(MyStats5, STAT_MENU5, STAT_TLD);
821 break;
822 default:
823 SetStats(NULL, STAT_MENU0, STAT_TLD);
824 showStats = 0;
825 break;
826 }
827 }
828 else if (animMode == 2)
829 {
830 stopAnim ^= 1;
831 if (stopAnim)
832 testData.dr = 0.0F; // rotation speed
833 else
834 testData.dr = 1.0F; // rotation speed
835 }
836 else if (animMode == 3)
837 {
838 testData.nc_tx /= 2;
839 if (testData.nc_tx == 0)
840 testData.nc_tx = testData.numx * testData.numz;
841 }
842 else if (animMode == 4)
843 {
844 testData.tcb ^= 1;
845 if (testData.tcb == 0)
846 {
847 OSReport("Texture cache = round robin\n");
848 GXSetTexRegionCallback(oldCallback);
849 }
850 else
851 {
852 OSReport("Texture cache = mapID\n");
853 oldCallback = GXSetTexRegionCallback(MyTexRegionCallback);
854 }
855 GXInvalidateTexAll();
856 }
857 else if (animMode == 5)
858 {
859 testData.tci ^= 1;
860 if (testData.tci && testData.tcb)
861 OSReport("Invalidate tex region on each GXLoadTexObj\n");
862 else
863 OSReport("Do not invalidate tex region on each GXLoadTexObj\n");
864 }
865 }
866 }
867
868
869 /*---------------------------------------------------------------------------*
870 Name: MakeModelMtx
871
872 Description: computes a model matrix from 3 vectors representing an
873 object's coordinate system.
874
875 Arguments: xAxis vector for the object's X axis
876 yAxis vector for the object's Y axis
877 zAxis vector for the object's Z axis
878
879 Returns: none
880 *---------------------------------------------------------------------------*/
MakeModelMtx(Vec xAxis,Vec yAxis,Vec zAxis,Mtx m)881 static void MakeModelMtx ( Vec xAxis, Vec yAxis, Vec zAxis, Mtx m )
882 {
883 VECNormalize(&xAxis,&xAxis);
884 VECNormalize(&yAxis,&yAxis);
885 VECNormalize(&zAxis,&zAxis);
886
887 m[0][0] = xAxis.x;
888 m[0][1] = xAxis.y;
889 m[0][2] = xAxis.z;
890 m[0][3] = 0.0F;
891
892 m[1][0] = yAxis.x;
893 m[1][1] = yAxis.y;
894 m[1][2] = yAxis.z;
895 m[1][3] = 0.0F;
896
897 m[2][0] = zAxis.x;
898 m[2][1] = zAxis.y;
899 m[2][2] = zAxis.z;
900 m[2][3] = 0.0F;
901
902 MTXInverse(m, m);
903 }
904
905
906 /*---------------------------------------------------------------------------*
907 Name: MyTexRegionCallback
908
909 Description: Tex cache allocator using simple round algorithm
910
911 Arguments: texObj : a pointer to texture object to be loaded
912 mapID : destination texmap ID (just same as GXLoadTexObj)
913
914 Returns: appropriate tex cache region for loading texture.
915 *---------------------------------------------------------------------------*/
MyTexRegionCallback(const GXTexObj * texObj,GXTexMapID mapID)916 static GXTexRegion* MyTexRegionCallback(const GXTexObj* texObj, GXTexMapID mapID)
917 {
918 #pragma unused(mapID)
919
920 u32 regionNum, texID;
921
922 texID = (u32)GXGetTexObjUserData(texObj);
923 regionNum = texID % NUM_REGIONS;
924
925 // see effect of cold cache load
926 if (testData.tci)
927 GXInvalidateTexRegion(&MyTexRegions[regionNum]);
928
929 return &MyTexRegions[regionNum];
930 }
931
932
933
934 /*---------------------------------------------------------------------------*
935 Name: PrintIntro
936
937 Description: Print usage for test
938
939 Arguments: none
940
941 Returns: none
942 *---------------------------------------------------------------------------*/
PrintIntro(void)943 static void PrintIntro( void )
944 {
945 OSReport("\n");
946 OSReport("************************************\n");
947 OSReport(" Check fill-rate performance\n");
948 OSReport("************************************\n");
949 OSReport("\n");
950 OSReport("SUBSTICK: Change the number of cubes\n");
951 OSReport("TRIGGER R: Increase the size of the cubes\n");
952 OSReport("TRIGGER L: Decrease the size of the cubes\n");
953 OSReport("\n");
954 OSReport("STICK: Rotate camera\n");
955 OSReport("BUTTON A/Y: Zoom camera in/out\n");
956 OSReport("BUTTON X: Change Button B mode\n");
957 OSReport("BUTTON B: Controls various parameters depending on mode\n");
958 OSReport("\n");
959 OSReport("to quit hit the menu button\n");
960 OSReport("\n");
961 }
962
963
964 /*---------------------------------------------------------------------------*
965 Name: DrawCubeIndx
966
967 Description:
968
969 Arguments: none
970
971 Returns: none
972 *---------------------------------------------------------------------------*/
973 static
DrawCubeIndx(void)974 void DrawCubeIndx( void )
975 {
976 GXBegin(GX_QUADS, GX_VTXFMT0, 4*6);
977 GXPosition1x16(4);
978 GXColor1x8(0);
979 GXTexCoord1x8(0); //
980 GXPosition1x16(5);
981 GXColor1x8(0);
982 GXTexCoord1x8(1); //
983 GXPosition1x16(6);
984 GXColor1x8(0);
985 GXTexCoord1x8(2); //
986 GXPosition1x16(7);
987 GXColor1x8(0);
988 GXTexCoord1x8(3); //
989
990 GXPosition1x16(2);
991 GXColor1x8(1);
992 GXTexCoord1x8(0); //
993 GXPosition1x16(6);
994 GXColor1x8(1);
995 GXTexCoord1x8(1); //
996 GXPosition1x16(5);
997 GXColor1x8(1);
998 GXTexCoord1x8(2); //
999 GXPosition1x16(3);
1000 GXColor1x8(1);
1001 GXTexCoord1x8(3); //
1002
1003 GXPosition1x16(1);
1004 GXColor1x8(2);
1005 GXTexCoord1x8(0); //
1006 GXPosition1x16(0);
1007 GXColor1x8(2);
1008 GXTexCoord1x8(1); //
1009 GXPosition1x16(4);
1010 GXColor1x8(2);
1011 GXTexCoord1x8(2); //
1012 GXPosition1x16(7);
1013 GXColor1x8(2);
1014 GXTexCoord1x8(3); //
1015
1016 GXPosition1x16(0);
1017 GXColor1x8(3);
1018 GXTexCoord1x8(0); //
1019 GXPosition1x16(1);
1020 GXColor1x8(3);
1021 GXTexCoord1x8(1); //
1022 GXPosition1x16(2);
1023 GXColor1x8(3);
1024 GXTexCoord1x8(2); //
1025 GXPosition1x16(3);
1026 GXColor1x8(3);
1027 GXTexCoord1x8(3); //
1028
1029 GXPosition1x16(5);
1030 GXColor1x8(4);
1031 GXTexCoord1x8(0); //
1032 GXPosition1x16(4);
1033 GXColor1x8(4);
1034 GXTexCoord1x8(1); //
1035 GXPosition1x16(0);
1036 GXColor1x8(4);
1037 GXTexCoord1x8(2); //
1038 GXPosition1x16(3);
1039 GXColor1x8(4);
1040 GXTexCoord1x8(3); //
1041
1042 GXPosition1x16(6);
1043 GXColor1x8(5);
1044 GXTexCoord1x8(0); //
1045 GXPosition1x16(2);
1046 GXColor1x8(5);
1047 GXTexCoord1x8(1); //
1048 GXPosition1x16(1);
1049 GXColor1x8(5);
1050 GXTexCoord1x8(2); //
1051 GXPosition1x16(7);
1052 GXColor1x8(5);
1053 GXTexCoord1x8(3); //
1054
1055 GXEnd();
1056 }
1057
1058 /*---------------------------------------------------------------------------*
1059 Name: DrawCubeDirect
1060
1061 Description:
1062
1063 Arguments: none
1064
1065 Returns: none
1066 *---------------------------------------------------------------------------*/
1067 static
DrawCubeDirect(void)1068 void DrawCubeDirect( void )
1069 {
1070 GXBegin(GX_QUADS, GX_VTXFMT0, 4*6);
1071 GXPosition3f32( SIDE, SIDE, -SIDE); //4
1072 GXColor1u32(0xff0000ff);// red
1073 GXTexCoord2f32(0.0F, 0.0F);//
1074 GXPosition3f32(SIDE, -SIDE, -SIDE);//5
1075 GXColor1u32(0xff0000ff);// red
1076 GXTexCoord2f32(1.0F, 0.0F);//
1077 GXPosition3f32(SIDE, -SIDE, SIDE); //6
1078 GXColor1u32(0xff0000ff);// red
1079 GXTexCoord2f32(1.0F, 1.0F);//
1080 GXPosition3f32(SIDE, SIDE, SIDE); //7
1081 GXColor1u32(0xff0000ff);// red
1082 GXTexCoord2f32(0.0F, 1.0F);//
1083
1084 GXPosition3f32(-SIDE, -SIDE, SIDE);//2
1085 GXColor1u32(0x00ff00ff);// green
1086 GXTexCoord2f32(0.0F, 0.0F);//
1087 GXPosition3f32(SIDE, -SIDE, SIDE); //6
1088 GXColor1u32(0x00ff00ff);// green
1089 GXTexCoord2f32(1.0F, 0.0F);//
1090 GXPosition3f32(SIDE, -SIDE, -SIDE);//5
1091 GXColor1u32(0x00ff00ff);// green
1092 GXTexCoord2f32(1.0F, 1.0F);//
1093 GXPosition3f32(-SIDE, -SIDE, -SIDE);//3
1094 GXColor1u32(0x00ff00ff);// green
1095 GXTexCoord2f32(0.0F, 1.0F);//
1096
1097 GXPosition3f32(-SIDE, SIDE, SIDE); //1
1098 GXColor1u32(0x0000ffff);// blue
1099 GXTexCoord2f32(0.0F, 0.0F);//
1100 GXPosition3f32(-SIDE, SIDE, -SIDE);//0
1101 GXColor1u32(0x0000ffff);// blue
1102 GXTexCoord2f32(1.0F, 0.0F);//
1103 GXPosition3f32( SIDE, SIDE, -SIDE); //4
1104 GXColor1u32(0x0000ffff);// blue
1105 GXTexCoord2f32(1.0F, 1.0F);//
1106 GXPosition3f32(SIDE, SIDE, SIDE); //7
1107 GXColor1u32(0x0000ffff);// blue
1108 GXTexCoord2f32(0.0F, 1.0F);//
1109
1110 GXPosition3f32(-SIDE, SIDE, -SIDE);//0
1111 GXColor1u32(0xffff00ff);// yellow
1112 GXTexCoord2f32(0.0F, 0.0F);//
1113 GXPosition3f32(-SIDE, SIDE, SIDE); //1
1114 GXColor1u32(0xffff00ff);// yellow
1115 GXTexCoord2f32(1.0F, 0.0F);//
1116 GXPosition3f32(-SIDE, -SIDE, SIDE);//2
1117 GXColor1u32(0xffff00ff);// yellow
1118 GXTexCoord2f32(1.0F, 1.0F);//
1119 GXPosition3f32(-SIDE, -SIDE, -SIDE);//3
1120 GXColor1u32(0xffff00ff);// yellow
1121 GXTexCoord2f32(0.0F, 1.0F);//
1122
1123 GXPosition3f32(SIDE, -SIDE, -SIDE);//5
1124 GXColor1u32(0xff00ffff);// magenta
1125 GXTexCoord2f32(0.0F, 0.0F);//
1126 GXPosition3f32( SIDE, SIDE, -SIDE); //4
1127 GXColor1u32(0xff00ffff);// magenta
1128 GXTexCoord2f32(1.0F, 0.0F);//
1129 GXPosition3f32(-SIDE, SIDE, -SIDE);//0
1130 GXColor1u32(0xff00ffff);// magenta
1131 GXTexCoord2f32(1.0F, 1.0F);//
1132 GXPosition3f32(-SIDE, -SIDE, -SIDE);//3
1133 GXColor1u32(0xff00ffff);// magenta
1134 GXTexCoord2f32(0.0F, 1.0F);//
1135
1136 GXPosition3f32(SIDE, -SIDE, SIDE); //6
1137 GXColor1u32(0x00ffffff);// cyan
1138 GXTexCoord2f32(0.0F, 0.0F);//
1139 GXPosition3f32(-SIDE, -SIDE, SIDE);//2
1140 GXColor1u32(0x00ffffff);// cyan
1141 GXTexCoord2f32(1.0F, 0.0F);//
1142 GXPosition3f32(-SIDE, SIDE, SIDE); //1
1143 GXColor1u32(0x00ffffff);// cyan
1144 GXTexCoord2f32(1.0F, 1.0F);//
1145 GXPosition3f32(SIDE, SIDE, SIDE); //7
1146 GXColor1u32(0x00ffffff);// cyan
1147 GXTexCoord2f32(0.0F, 1.0F);//
1148 GXEnd();
1149 }
1150
1151
1152 /*---------------------------------------------------------------------------*
1153 Name: DrawArrow
1154
1155 Description: Draw arrow pointing in direction of Z sort (-Z axis)
1156
1157 Arguments: none
1158
1159 Returns: none
1160 *---------------------------------------------------------------------------*/
DrawArrow(void)1161 static void DrawArrow( void )
1162 {
1163 GXClearVtxDesc();
1164 GXSetVtxDesc(GX_VA_POS, GX_INDEX16);
1165 GXSetVtxDesc(GX_VA_CLR0, GX_INDEX8);
1166
1167 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
1168 GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
1169
1170 GXSetNumChans(1);
1171 GXSetNumTexGens(0);
1172 GXSetNumTevStages(1);
1173
1174 GXBegin(GX_TRIANGLES, GX_VTXFMT0, 3*4);
1175 // tri 0
1176 GXPosition1x16(10);
1177 GXColor1x8(1);// green
1178
1179 GXPosition1x16(8);
1180 GXColor1x8(1);// green
1181
1182 GXPosition1x16(11);
1183 GXColor1x8(1);// green
1184
1185
1186 // tri 1
1187 GXPosition1x16(10);
1188 GXColor1x8(0);// red
1189
1190 GXPosition1x16(11);
1191 GXColor1x8(0);// red
1192
1193 GXPosition1x16(9);
1194 GXColor1x8(0);// red
1195
1196
1197 // tri 2
1198 GXPosition1x16(9);
1199 GXColor1x8(1);// green
1200
1201 GXPosition1x16(11);
1202 GXColor1x8(1);// green
1203
1204 GXPosition1x16(8);
1205 GXColor1x8(1);// green
1206
1207
1208 // tri 3
1209 GXPosition1x16(10);
1210 GXColor1x8(1);// green
1211
1212 GXPosition1x16(9);
1213 GXColor1x8(1);// green
1214
1215 GXPosition1x16(8);
1216 GXColor1x8(1);// green
1217 GXEnd();
1218 }
1219
1220 //
1221 // My random functions
1222 //
1223 #define MAX_RAND (0xffffffff)
1224 #define SEED (0x38ba990e)
1225
1226 static
init_rand(void)1227 void init_rand( void )
1228 {
1229 srand(SEED);
1230 }
1231
1232
1233 static
lrand(void)1234 u32 lrand( void )
1235 {
1236 u32 r;
1237 r = (u32) ((rand() & 0xffff) << 16) + (rand() & 0xffff);
1238 return(r);
1239 }
1240
1241
1242 static
frand(void)1243 f32 frand( void )
1244 {
1245 f32 f;
1246 f = (f32)lrand()/(f32)MAX_RAND;
1247 return (f);
1248 }
1249
1250
1251 /*---------------------------------------------------------------------------*
1252
1253 Stats engine
1254
1255 *---------------------------------------------------------------------------*/
1256
1257 #define FLIPPER_CLOCK 162.0F // MHz
1258
1259 #define STAT_TEXT_TOP 16
1260 #define STAT_TEXT_BOT 16
1261 #define STAT_TEXT_LFT 16
1262 #define STAT_TEXT_RHT 16
1263
1264 #define STAT_CHAR_WD 8
1265 #define STAT_CHAR_HT 8
1266 #define STAT_CHAR_YSP 2 // vertical space
1267
1268 /*---------------------------------------------------------------------------*
1269 Functions
1270 *---------------------------------------------------------------------------*/
1271
1272 /*---------------------------------------------------------------------------*
1273 Name: SetStats
1274
1275 Description: This function sets an array of GX performance metrics to
1276 count. The name of each metric is specified in the text
1277 array. The current stat count is kept in the count array.
1278 At the end of each loop, the metric will be printed at
1279 the corner of the screen specified, either top-left, top-
1280 right, bottom-left, or bottom-right.
1281
1282 If stat is NULL or nstats is zero, the performance
1283 monitoring is disabled.
1284
1285 Arguments: stat : An array of GXPerf metrics to count.
1286 nstats: number of stats in the array or number you wish
1287 to display.
1288 disp : display style of the stats:
1289 0 = top-left
1290 2 = bot-left
1291 8 = serial output (OSReport)
1292
1293 Returns: None
1294 *---------------------------------------------------------------------------*/
SetStats(StatObj * stat,u32 nstats,StatDispMode disp)1295 static void SetStats( StatObj *stat, u32 nstats, StatDispMode disp )
1296 {
1297 if (stat == NULL || nstats == 0)
1298 {
1299 StatEnable = GX_DISABLE;
1300 }
1301 else
1302 {
1303 StatEnable = GX_TRUE;
1304 Stat = stat;
1305 StatIndx = 0;
1306 StatMaxIndx = nstats;
1307 StatDisp = disp;
1308 StatStrLen = strlen(Stat[0].text);
1309 }
1310 }
1311
1312 /*---------------------------------------------------------------------------*
1313 Name: WriteStats
1314
1315 Description: This function calls a metric function for the next stat
1316 to be counted.
1317
1318 Arguments: none
1319
1320 Returns: None
1321 *---------------------------------------------------------------------------*/
WriteStats(GXBool update)1322 static void WriteStats( GXBool update )
1323 {
1324 u32 cnt0, cnt1, cnt2, cnt3, cnt4;
1325 u32 cnt5, cnt6, cnt7, cnt8, cnt9;
1326
1327 switch (Stat[StatIndx].stat_type)
1328 {
1329 case STAT_GP0:
1330 if (update)
1331 {
1332 cnt0 = GXReadGP0Metric();
1333 Stat[StatIndx].count = cnt0;
1334 GXSetGP0Metric(GX_PERF0_NONE);
1335 } else {
1336 GXSetGP0Metric((GXPerf0)Stat[StatIndx].stat);
1337 GXClearGP0Metric();
1338 }
1339
1340 break;
1341
1342 case STAT_GP1:
1343 if (update)
1344 {
1345 cnt0 = GXReadGP1Metric();
1346 Stat[StatIndx].count = cnt0;
1347 GXSetGP1Metric(GX_PERF1_NONE);
1348 } else {
1349 GXSetGP1Metric((GXPerf1)Stat[StatIndx].stat);
1350 GXClearGP1Metric();
1351 }
1352 break;
1353
1354 case STAT_MEM:
1355 if (update)
1356 {
1357 GXReadMemMetric( &cnt0, &cnt1, &cnt2, &cnt3, &cnt4,
1358 &cnt5, &cnt6, &cnt7, &cnt8, &cnt9 );
1359 cpReq = cnt0;
1360 tcReq = cnt1;
1361 cpuRdReq = cnt2;
1362 cpuWrReq = cnt3;
1363 dspReq = cnt4;
1364 ioReq = cnt5;
1365 viReq = cnt6;
1366 peReq = cnt7;
1367 rfReq = cnt8;
1368 fiReq = cnt9;
1369 } else {
1370 GXClearMemMetric();
1371 }
1372 break;
1373
1374 case STAT_PIX:
1375 if (update)
1376 {
1377 GXReadPixMetric(&cnt0, &cnt1, &cnt2, &cnt3, &cnt4, &cnt5);
1378 topPixIn = cnt0;
1379 topPixOut = cnt1;
1380 botPixIn = cnt2;
1381 botPixOut = cnt3;
1382 clrPixIn = cnt4;
1383 copyClks = cnt5;
1384 } else {
1385 GXClearPixMetric();
1386 }
1387 break;
1388
1389 case STAT_VC:
1390 if (update)
1391 {
1392 GXReadVCacheMetric(&cnt0, &cnt1, &cnt2);
1393 vcCheck = cnt0;
1394 vcMiss = cnt1;
1395 vcStall = cnt2;
1396 } else {
1397 GXSetVCacheMetric(GX_VC_POS);
1398 GXClearVCacheMetric();
1399 }
1400 break;
1401
1402 case STAT_FR: // fill rate info
1403 if (update)
1404 {
1405 GXReadPixMetric(&cnt0, &cnt1, &cnt2, &cnt3, &cnt4, &cnt5);
1406 topPixIn = cnt0;
1407 topPixOut = cnt1;
1408 botPixIn = cnt2;
1409 botPixOut = cnt3;
1410 clrPixIn = cnt4;
1411 copyClks = cnt5;
1412 StatClocks = GXReadGP0Metric();
1413 GXSetGP0Metric(GX_PERF0_NONE);
1414 } else {
1415 GXClearPixMetric();
1416 GXSetGP0Metric(GX_PERF0_CLOCKS);
1417 GXClearGP0Metric();
1418 }
1419 break;
1420
1421 case STAT_TBP: // texture B/pixel
1422 case STAT_TBW: // texture bandwidth/pixel
1423 GXClearPixMetric();
1424 if (update)
1425 {
1426 GXReadPixMetric(&cnt0, &cnt1, &cnt2, &cnt3, &cnt4, &cnt5);
1427 topPixIn = cnt0;
1428 topPixOut = cnt1;
1429 botPixIn = cnt2;
1430 botPixOut = cnt3;
1431 clrPixIn = cnt4;
1432 copyClks = cnt5;
1433 StatClocks = GXReadGP0Metric();
1434 GXReadMemMetric( &cnt0, &cnt1, &cnt2, &cnt3, &cnt4,
1435 &cnt5, &cnt6, &cnt7, &cnt8, &cnt9 );
1436 tcReq = cnt1;
1437 GXSetGP0Metric(GX_PERF0_NONE);
1438 } else {
1439 GXClearMemMetric();
1440 GXSetGP0Metric(GX_PERF0_CLOCKS);
1441 GXClearGP0Metric();
1442 }
1443 break;
1444
1445 case STAT_MYC:
1446 case STAT_MYR:
1447 // do nothing, user will compute
1448 break;
1449 default:
1450 OSHalt("SetStats: Unknown demo stat type\n");
1451 break;
1452 }
1453 }
1454
1455 /*---------------------------------------------------------------------------*
1456 Name: UpdateStats
1457
1458 Description: This function calls GXPerfMetric for the next stat to be
1459 counted.
1460
1461 Arguments: none
1462
1463 Returns: None
1464 *---------------------------------------------------------------------------*/
UpdateStats(GXBool inc)1465 static void UpdateStats( GXBool inc )
1466 {
1467 WriteStats(inc);
1468
1469 if (inc)
1470 {
1471 StatIndx++;
1472 if (StatIndx == StatMaxIndx)
1473 {
1474 StatIndx = 0;
1475 }
1476 }
1477 }
1478
1479 /*---------------------------------------------------------------------------*
1480 Name: PrintStats
1481
1482 Description: This function prints the statistics currently being
1483 counted. Only one statistic gets updated each frame,
1484 but they are printed every frame.
1485
1486 Arguments: none
1487
1488 Returns: None
1489 *---------------------------------------------------------------------------*/
1490 #define StatPrintf(str, val) \
1491 DEMOPrintf(text_x, text_y, 0, str, Stat[i].text, val)
1492
1493 #define StatOSReport(str, val) \
1494 OSReport(str, Stat[i].text, val)
1495
PrintStats(void)1496 static void PrintStats( void )
1497 {
1498 GXRenderModeObj* rmode;
1499 u32 i;
1500 s16 text_x, text_y, text_yinc;
1501 u16 wd, ht;
1502 f32 rate;
1503
1504 if (StatDisp == STAT_IO) // dump to serial output
1505 {
1506 for (i = 0; i < StatMaxIndx; i++)
1507 {
1508 switch (Stat[i].stat_type)
1509 {
1510 case STAT_PIX:
1511 switch(Stat[i].stat)
1512 {
1513 case STAT_PIX_TI:
1514 StatOSReport("%s: %8d\n", topPixIn);
1515 break;
1516 case STAT_PIX_TO:
1517 StatOSReport("%s: %8d\n", topPixOut);
1518 break;
1519 case STAT_PIX_BI:
1520 StatOSReport("%s: %8d\n", botPixIn);
1521 break;
1522 case STAT_PIX_BO:
1523 StatOSReport("%s: %8d\n", botPixOut);
1524 break;
1525 case STAT_PIX_CI:
1526 StatOSReport("%s: %8d\n", clrPixIn);
1527 break;
1528 case STAT_PIX_CC:
1529 StatOSReport("%s: %8d\n", copyClks);
1530 break;
1531 }
1532 break;
1533
1534 case STAT_FR:
1535 rate = FLIPPER_CLOCK * (f32)(topPixIn + botPixIn) /
1536 (f32)(StatClocks - copyClks);
1537 StatOSReport("%s: %8.2f\n", rate);
1538 break;
1539
1540 case STAT_TBW:
1541 rate = FLIPPER_CLOCK * (f32)(tcReq*32) /
1542 (f32)(StatClocks - copyClks);
1543 StatOSReport("%s: %8.2f\n", rate);
1544 break;
1545
1546 case STAT_TBP:
1547 rate = (f32)(tcReq*32) / (topPixIn + botPixIn);
1548 StatOSReport("%s: %8.2f\n", rate);
1549 break;
1550
1551 case STAT_VC:
1552 switch(Stat[i].stat)
1553 {
1554 case STAT_VC_CHK:
1555 StatOSReport("%s: %8d\n", vcCheck);
1556 break;
1557 case STAT_VC_MISS:
1558 StatOSReport("%s: %8d\n", vcMiss);
1559 break;
1560 case STAT_VC_STALL:
1561 StatOSReport("%s: %8d\n", vcStall);
1562 break;
1563 }
1564 break;
1565
1566 case STAT_MYR: // use stat as a second input
1567 rate = (f32) Stat[i].stat / (f32) Stat[i].count;
1568 StatOSReport("%s: %8.2f\n", rate);
1569 break;
1570
1571 case STAT_MEM:
1572 switch(Stat[i].stat)
1573 {
1574 case STAT_MEM_CP:
1575 StatOSReport("%s: %8d\n", cpReq);
1576 break;
1577 case STAT_MEM_TC:
1578 StatOSReport("%s: %8d\n", tcReq);
1579 break;
1580 case STAT_MEM_CPUR:
1581 StatOSReport("%s: %8d\n", cpuRdReq);
1582 break;
1583 case STAT_MEM_CPUW:
1584 StatOSReport("%s: %8d\n", cpuWrReq);
1585 break;
1586 case STAT_MEM_DSP:
1587 StatOSReport("%s: %8d\n", dspReq);
1588 break;
1589 case STAT_MEM_IO:
1590 StatOSReport("%s: %8d\n", ioReq);
1591 break;
1592 case STAT_MEM_VI:
1593 StatOSReport("%s: %8d\n", viReq);
1594 break;
1595 case STAT_MEM_PE:
1596 StatOSReport("%s: %8d\n", peReq);
1597 break;
1598 case STAT_MEM_RF:
1599 StatOSReport("%s: %8d\n", rfReq);
1600 break;
1601 case STAT_MEM_FI:
1602 StatOSReport("%s: %8d\n", fiReq);
1603 break;
1604 }
1605 break;
1606
1607 default:
1608 StatOSReport("%s: %8d\n", Stat[i].count);
1609 break;
1610 }
1611 }
1612 }
1613 else // dump to screen
1614 {
1615 rmode = DEMOGetRenderModeObj();
1616
1617 switch (StatDisp)
1618 {
1619 case STAT_TL:
1620 // text origin is top-left
1621 text_x = STAT_TEXT_LFT;
1622 text_y = STAT_TEXT_TOP;
1623 text_yinc = STAT_CHAR_HT + STAT_CHAR_YSP;
1624 wd = rmode->fbWidth;
1625 ht = rmode->xfbHeight;
1626 break;
1627 case STAT_BL:
1628 // text origin is bottom-left
1629 text_x = STAT_TEXT_LFT;
1630 text_y = (s16)(rmode->xfbHeight - STAT_TEXT_BOT - STAT_CHAR_HT);
1631 text_yinc = -(STAT_CHAR_HT + STAT_CHAR_YSP);
1632 wd = rmode->fbWidth;
1633 ht = rmode->xfbHeight;
1634 break;
1635 case STAT_TLD:
1636 // double-sized fonts, text origin is top-left
1637 text_x = (s16)(STAT_TEXT_LFT / 2);
1638 text_y = (s16)(STAT_TEXT_TOP / 2);
1639 text_yinc = STAT_CHAR_HT + STAT_CHAR_YSP / 2;
1640 wd = (u16)(rmode->fbWidth / 2);
1641 ht = (u16)(rmode->xfbHeight / 2);
1642 break;
1643 case STAT_BLD:
1644 // double-sized fonts, text origin is bottom-left
1645 text_x = (s16)(STAT_TEXT_LFT / 2);
1646 text_y = (s16)((rmode->xfbHeight - STAT_TEXT_BOT - STAT_CHAR_HT) / 2);
1647 text_yinc = -(STAT_CHAR_HT + STAT_CHAR_YSP / 2);
1648 wd = (u16)(rmode->fbWidth / 2);
1649 ht = (u16)(rmode->xfbHeight / 2);
1650 break;
1651 }
1652
1653 // Init DEMOPuts library fonts
1654 DEMOInitCaption(DM_FT_OPQ, wd, ht);
1655
1656 for ( i = 0; i < StatMaxIndx; i++ )
1657 {
1658 switch (Stat[i].stat_type)
1659 {
1660 case STAT_PIX:
1661 // Pix Metric
1662 switch(Stat[i].stat)
1663 {
1664 case STAT_PIX_TI:
1665 StatPrintf("%s: %8d\n", topPixIn);
1666 break;
1667 case STAT_PIX_TO:
1668 StatPrintf("%s: %8d\n", topPixOut);
1669 break;
1670 case STAT_PIX_BI:
1671 StatPrintf("%s: %8d\n", botPixIn);
1672 break;
1673 case STAT_PIX_BO:
1674 StatPrintf("%s: %8d\n", botPixOut);
1675 break;
1676 case STAT_PIX_CI:
1677 StatPrintf("%s: %8d\n", clrPixIn);
1678 break;
1679 case STAT_PIX_CC:
1680 StatPrintf("%s: %8d\n", copyClks);
1681 }
1682 break;
1683
1684 case STAT_FR:
1685 // Fill rate (MPixels/Sec)
1686 rate = FLIPPER_CLOCK * (f32)(topPixIn + botPixIn) /
1687 (f32)(StatClocks - copyClks);
1688 StatPrintf("%s: %8.2f\n", rate);
1689 break;
1690
1691 case STAT_TBW:
1692 // Texture bandwidth (MB/sec)
1693 rate = FLIPPER_CLOCK * (f32)(tcReq*32) /
1694 (f32)(StatClocks - copyClks);
1695 StatPrintf("%s: %8.2f\n", rate);
1696 break;
1697
1698 case STAT_TBP:
1699 // Texture bandwidth per pixel
1700 rate = (f32)(tcReq*32) /
1701 (f32)(topPixIn - botPixIn);
1702 StatPrintf("%s: %8.3f\n", rate);
1703 break;
1704
1705 case STAT_VC:
1706 // VertexCache Metric
1707 switch(Stat[i].stat)
1708 {
1709 case STAT_VC_CHK:
1710 StatPrintf("%s: %8d\n", vcCheck);
1711 break;
1712 case STAT_VC_MISS:
1713 StatPrintf("%s: %8d\n", vcMiss);
1714 break;
1715 case STAT_VC_STALL:
1716 StatPrintf("%s: %8d\n", vcStall);
1717 }
1718 break;
1719
1720 case STAT_MEM:
1721 // Mem Access Metric
1722 switch(Stat[i].stat)
1723 {
1724 case STAT_MEM_CP:
1725 StatPrintf("%s: %8d\n", cpReq);
1726 break;
1727 case STAT_MEM_TC:
1728 StatPrintf("%s: %8d\n", tcReq);
1729 break;
1730 case STAT_MEM_CPUR:
1731 StatPrintf("%s: %8d\n", cpuRdReq);
1732 break;
1733 case STAT_MEM_CPUW:
1734 StatPrintf("%s: %8d\n", cpuWrReq);
1735 break;
1736 case STAT_MEM_DSP:
1737 StatPrintf("%s: %8d\n", dspReq);
1738 break;
1739 case STAT_MEM_IO:
1740 StatPrintf("%s: %8d\n", ioReq);
1741 break;
1742 case STAT_MEM_VI:
1743 StatPrintf("%s: %8d\n", viReq);
1744 break;
1745 case STAT_MEM_PE:
1746 StatPrintf("%s: %8d\n", peReq);
1747 break;
1748 case STAT_MEM_RF:
1749 StatPrintf("%s: %8d\n", rfReq);
1750 break;
1751 case STAT_MEM_FI:
1752 StatPrintf("%s: %8d\n", fiReq);
1753 break;
1754 }
1755 break;
1756
1757 case STAT_GP0:
1758 case STAT_GP1:
1759 case STAT_MYC:
1760 StatPrintf("%s: %8d", Stat[i].count);
1761 break;
1762
1763 case STAT_MYR: // use stat as a second input
1764 rate = (f32) Stat[i].stat / (f32) Stat[i].count;
1765 StatPrintf("%s: %8.3f", rate);
1766 break;
1767
1768 default:
1769 OSReport("Undefined stat type %d in PrintStats()\n",
1770 Stat[i].stat_type);
1771 break;
1772 }
1773
1774 // update current line
1775 text_y += text_yinc;
1776 }
1777 } // screen dump
1778 }
1779
1780 /*===========================================================================*/
1781
1782