1 /*---------------------------------------------------------------------------*
2
3 Copyright 2010-2012 Nintendo. All rights reserved.
4
5 These coded instructions, statements, and computer programs contain
6 proprietary information of Nintendo of America Inc. and/or Nintendo
7 Company Ltd., and are protected by Federal copyright law. They may
8 not be disclosed to third parties or copied or duplicated in any form,
9 in whole or in part, without the prior written consent of Nintendo.
10
11 *---------------------------------------------------------------------------*/
12 ////===========================================================================
13 /// DEMOGfx.c
14 ///
15 /// This is graphics system code for the DEMO library.
16 ///
17 ////===========================================================================
18
19 #include <stdio.h>
20 #include <cafe/demo.h>
21 #include <cafe/gx2.h>
22 #include <cafe/procui.h>
23
24 // A bit like asserts, but even for NDEBUG=TRUE:
25 #define DEMOCheck(x,y) if (!(x)) { OSReport("%s\n", y); while(1) OSSleepSeconds(1); }
26
27 GX2ColorBuffer DEMOColorBuffer;
28 GX2DepthBuffer DEMODepthBuffer;
29 void *DEMOScanBufferPtr;
30
31 // DEMO Gfx Context State
32 GX2ContextState *DEMOContextState;
33
34 u32 *DEMOCommandBufferBasePtr;
35 #define DEMO_GFX_COMMAND_BUFFER_POOL_SIZE 1024*1024*sizeof(u32)
36
37 static BOOL gDemoGfxRunningFlag=FALSE;
38 static BOOL gDemoGfxTVEnabled=FALSE;
39
40 BOOL gDemoGfxInForeground=TRUE;
41
42 static MEMHeapHandle gDEMOMem1Heap = MEM_HEAP_INVALID_HANDLE;
43 static MEMHeapHandle gDEMOBucketHeap = MEM_HEAP_INVALID_HANDLE;
44
45 static char gDemoAssetsDir[MAX_ASSET_DIR_LEN];
46
47 // State from init that needs to be preserved when reacquiring foreground.
48 static GX2TVRenderMode gDemoGfxRenderMode;
49 static GX2SurfaceFormat gDemoGfxScanOutCBFormat;
50 static u32 gDemoGfxScanSize;
51
52 // Other preserved items
53 static u32 gDemoGfxRenderWidth;
54 static u32 gDemoGfxRenderHeight;
55 static u32 gDemoGfxSwapInterval;
56
57 // Instance
58 static DEMOGfxInstance* gDemoGfxCurInstance = NULL;
59
60
DEMOGX2RAlloc(GX2RResourceFlags resourceFlags,u32 byteCount,u32 alignment)61 static void* DEMOGX2RAlloc(GX2RResourceFlags resourceFlags, u32 byteCount, u32 alignment)
62 {
63 if (GX2TestBitFlagsAny(resourceFlags, GX2R_BIND_COLOR_BUFFER | GX2R_BIND_DEPTH_BUFFER | GX2R_BIND_SCAN_BUFFER | GX2R_BIND_GS_RING | GX2R_USAGE_FORCE_MEM1) &&
64 !GX2TestBitFlagsAny(resourceFlags, GX2R_USAGE_FORCE_MEM2))
65 {
66 return DEMOGfxAllocMEM1(byteCount, alignment);
67 }
68 else
69 {
70 return DEMOGfxAllocMEM2(byteCount, alignment);
71 }
72 }
73
74
DEMOGX2RFree(GX2RResourceFlags resourceFlags,void * pMem)75 static void DEMOGX2RFree(GX2RResourceFlags resourceFlags, void* pMem)
76 {
77 if (GX2TestBitFlagsAny(resourceFlags, GX2R_BIND_COLOR_BUFFER | GX2R_BIND_DEPTH_BUFFER | GX2R_BIND_SCAN_BUFFER | GX2R_BIND_GS_RING | GX2R_USAGE_FORCE_MEM1) &&
78 !GX2TestBitFlagsAny(resourceFlags, GX2R_USAGE_FORCE_MEM2))
79 {
80 DEMOGfxFreeMEM1(pMem);
81 }
82 else
83 {
84 DEMOGfxFreeMEM2(pMem);
85 }
86 }
87
88
89
DEMOGfxAllocMEM1(u32 size,u32 align)90 void *DEMOGfxAllocMEM1(u32 size, u32 align)
91 {
92 void *ptr;
93
94 if (align < 4)
95 {
96 align = 4;
97 }
98
99 // DEMOGfxMem1HeapInit() must be called first to init the heap.
100 DEMOAssert(gDEMOMem1Heap != MEM_HEAP_INVALID_HANDLE);
101
102 // Use the expanded heap for demos.
103 ptr = MEMAllocFromExpHeapEx(gDEMOMem1Heap, size, align);
104 GX2NotifyMemAlloc(ptr, size, align);
105
106 DEMOAssert(ptr&&"Failed MEM1 alloc");
107
108 return ptr;
109 }
110
DEMOGfxFreeMEM1(void * ptr)111 void DEMOGfxFreeMEM1(void * ptr)
112 {
113 if (gDemoGfxInForeground) MEMFreeToExpHeap(gDEMOMem1Heap, ptr);
114 GX2NotifyMemFree(ptr);
115 }
116
DEMOGfxAllocBucket(u32 size,u32 align)117 void *DEMOGfxAllocBucket(u32 size, u32 align)
118 {
119 DEMOAssert(gDEMOBucketHeap != MEM_HEAP_INVALID_HANDLE);
120
121 void * ptr = MEMAllocFromExpHeapEx(gDEMOBucketHeap, size, align);
122 GX2NotifyMemAlloc(ptr, size, align);
123
124 DEMOAssert(ptr);
125
126 return ptr;
127 }
128
DEMOGfxFreeBucket(void * ptr)129 void DEMOGfxFreeBucket(void * ptr)
130 {
131 if (gDemoGfxInForeground) MEMFreeToExpHeap(gDEMOBucketHeap, ptr);
132 GX2NotifyMemFree(ptr);
133 }
134
DEMOGfxAllocMEM2(u32 size,u32 align)135 void *DEMOGfxAllocMEM2(u32 size, u32 align)
136 {
137 void *ptr;
138
139 if (align < 4)
140 {
141 align = 4;
142 }
143 // FINAL MEMORY MANAGEMENT MODEL
144 ptr = DEMOAllocEx(size, align);
145 GX2NotifyMemAlloc(ptr, size, align);
146
147 DEMOAssert(ptr&&"Failed MEM2 alloc");
148
149 return ptr;
150 }
151
152
DEMOGfxFreeMEM2(void * ptr)153 void DEMOGfxFreeMEM2(void * ptr)
154 {
155 // FINAL MEMORY MANAGEMENT MODEL
156 DEMOFree(ptr);
157 GX2NotifyMemFree(ptr);
158 }
159
DEMOGfxCallbackAcquiredForeground(void * unused)160 static u32 DEMOGfxCallbackAcquiredForeground(void* unused)
161 {
162 DEMOGfxAcquiredForeground();
163
164 // No issues
165 return 0;
166 }
167
DEMOGfxCallbackReleaseForeground(void * unused)168 static u32 DEMOGfxCallbackReleaseForeground(void* unused)
169 {
170 DEMOGfxReleaseForeground();
171
172 // No issues
173 return 0;
174 }
175
DEMOGfxInit(int argc,char * argv[])176 DEMOGfxInstance* DEMOGfxInit(int argc, char *argv[])
177 {
178 void *ptr;
179
180 u32 scanSize;
181 GX2Boolean scaleNeeded;
182
183 u32 i;
184 char *p;
185 u32 renderWidth = 1280;
186 u32 renderHeight = 720;
187 // Default to SRGB for gamma
188 GX2SurfaceFormat renderCBFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB;
189 GX2SurfaceFormat scanOutCBFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB;
190 GX2SurfaceFormat renderDBFormat = GX2_SURFACE_FORMAT_TCD_R32_FLOAT;
191 GX2AAMode renderAAMode = GX2_AA_MODE_1X;
192 GX2Boolean renderHiZ = GX2_TRUE;
193
194 static const u32 tvRenderModeTable[] = {
195 640, 480, GX2_TV_RENDER_480_NARROW, // 4:3 ratio (640x480)
196 854, 480, GX2_TV_RENDER_480_WIDE, // 16:9 ratio (854x480)
197 1280, 720, GX2_TV_RENDER_720, // 16:9 for all the rest...
198 1920, 1080, GX2_TV_RENDER_1080,
199 };
200 #define RM_TABLE_SZ 4
201
202 GX2TVRenderMode renderMode;
203
204 // Init flags
205 gDemoGfxRunningFlag=FALSE;
206 gDemoGfxTVEnabled=FALSE;
207
208 // Asset Directory
209 strcpy(gDemoAssetsDir, "assets/");
210
211 // Alloc Gfx command buffer pool
212 DEMOCommandBufferBasePtr = (u32 *) DEMOAllocEx(
213 DEMO_GFX_COMMAND_BUFFER_POOL_SIZE,
214 GX2_DEFAULT_BUFFER_ALIGNMENT);
215 DEMOCheck(DEMOCommandBufferBasePtr, "Failed to allocate command buffer pool");
216
217 // Passing user allocated cb buffer and command-line arguments to gx2Init
218 u32 gx2InitAttribs[] =
219 {
220 GX2_INIT_ATTRIB_CB_BASE, (u32)DEMOCommandBufferBasePtr, // cb buffer
221 GX2_INIT_ATTRIB_CB_SIZE, (u32)DEMO_GFX_COMMAND_BUFFER_POOL_SIZE, // cb size
222 GX2_INIT_ATTRIB_ARGC, (u32)argc, // number of args
223 GX2_INIT_ATTRIB_ARGV, (u32)argv, // command-line args
224 GX2_INIT_ATTRIB_NULL // terminates the list
225 };
226
227 // Initialize GX2 library
228 GX2Init(gx2InitAttribs);
229
230 s32 gx2DebugMode=-1;
231 s32 gx2rDebugOptions=-1;
232 u32 swapInterval = 1;
233
234 #define SKIP_NON_DIGIT(c) ((c)!=0&&((c)<'0'||(c)>'9'))
235
236 // Analyze arguments
237 // Note that all arguments might be in a single string!
238 for (i = 0; i < argc; ++i)
239 {
240 p = strstr(argv[i], "DEMO_WIDTH");
241 if (p != 0){
242 renderWidth = (u32)atoi(p+10+SKIP_NON_DIGIT(p[10]));
243 }
244 p = strstr(argv[i], "DEMO_HEIGHT");
245 if (p != 0){
246 renderHeight = (u32)atoi(p+11+SKIP_NON_DIGIT(p[11]));
247 }
248 p = strstr(argv[i], "DEMO_CB_FORMAT");
249 if (p != 0){
250 p = p+14+SKIP_NON_DIGIT(p[14]);
251 if(strncmp(p, "10_10_10_2", 10) == 0){
252 renderCBFormat = GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM;
253 } else if(strncmp(p, "2_10_10_10", 10) == 0){
254 renderCBFormat = GX2_SURFACE_FORMAT_TCS_A2_B10_G10_R10_UNORM;
255 } else if(strncmp(p, "8_8_8_8_SRGB", 12) == 0){
256 renderCBFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB;
257 } else if(strncmp(p, "8_8_8_8", 7) == 0){
258 renderCBFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM;
259 } else if(strncmp(p, "16_16_16_16F", 12) == 0){
260 renderCBFormat = GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_FLOAT;
261 } else if(strncmp(p, "32_32_32_32F", 12) == 0){
262 renderCBFormat = GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_FLOAT;
263 } else if(strncmp(p, "16", 2) == 0){
264 renderCBFormat = GX2_SURFACE_FORMAT_TCD_R16_UNORM;
265 } else if(strncmp(p, "32F", 3) == 0){
266 renderCBFormat = GX2_SURFACE_FORMAT_TCD_R32_FLOAT;
267 } else {
268 DEMOPrintf("Unrecognized CB format: %s\n",p);
269 }
270 }
271 p = strstr(argv[i], "DEMO_SCAN_FORMAT");
272 if (p != 0){
273 p = p+16+SKIP_NON_DIGIT(p[16]);
274 if(strncmp(p, "10_10_10_2", 10) == 0){
275 scanOutCBFormat = GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM;
276 }else if(strncmp(p, "2_10_10_10", 10) == 0){
277 scanOutCBFormat = GX2_SURFACE_FORMAT_TCS_A2_B10_G10_R10_UNORM;
278 }else if(strncmp(p, "8_8_8_8_SRGB", 12) == 0){
279 scanOutCBFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB;
280 }else if(strncmp(p, "8_8_8_8", 7) == 0){
281 scanOutCBFormat = GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM;
282 } else {
283 DEMOPrintf("Unrecognized SCAN format: %s\n",p);
284 }
285 }
286 p = strstr(argv[i], "DEMO_DB_FORMAT");
287 if (p != 0){
288 p = p+14+SKIP_NON_DIGIT(p[14]);
289 if(strncmp(p, "16", 2) == 0){
290 renderDBFormat = GX2_SURFACE_FORMAT_TCD_R16_UNORM;
291 }else if(strncmp(p, "8_24F", 5) == 0){
292 renderDBFormat = GX2_SURFACE_FORMAT_D_D24_S8_FLOAT;
293 }else if(strncmp(p, "8_24", 4) == 0){
294 renderDBFormat = GX2_SURFACE_FORMAT_D_D24_S8_UNORM;
295 }else if(strncmp(p, "X24_8_32F", 9) == 0){
296 renderDBFormat = GX2_SURFACE_FORMAT_D_D32_FLOAT_S8_UINT_X24;
297 }else if(strncmp(p, "32F", 3) == 0){
298 renderDBFormat = GX2_SURFACE_FORMAT_TCD_R32_FLOAT;
299 } else {
300 DEMOPrintf("Unrecognized DB format: %s\n",p);
301 }
302 }
303 p = strstr(argv[i], "DEMO_AA_MODE");
304 if (p != 0){
305 renderAAMode = (GX2AAMode)atoi(p+12+SKIP_NON_DIGIT(p[12]));
306 GX2_CHECK_ENUM_RANGE(renderAAMode, GX2_AA_MODE)
307 }
308 p = strstr(argv[i], "DEMO_FONT_DISABLE");
309 if (p != 0){
310 DEMOFontDrawEnable(FALSE);
311 DEMOPrintf("DEMO: DISABLE_FONT\n");
312 }
313 p = strstr(argv[i], "DEMO_HIZ_DISABLE");
314 if (p != 0){
315 DEMOPrintf("DEMO: DISABLE_HIZ\n");
316 renderHiZ = GX2_FALSE;
317 }
318
319 p = strstr(argv[i], "DEMO_GX2_DEBUG_MODE");
320 if (p != 0)
321 {
322 sscanf(p+strlen("DEMO_GX2_DEBUG_MODE="), "%i", &gx2DebugMode); // allows hex notation
323 }
324
325 p = strstr(argv[i], "DEMO_GX2R_DEBUG_OPTIONS");
326 if (p != 0)
327 {
328 sscanf(p+strlen("DEMO_GX2R_DEBUG_OPTIONS="), "%i", &gx2rDebugOptions); // allows hex notation
329 }
330
331 p = strstr(argv[i], "DEMO_SWAP_INTERVAL");
332 if (p != 0)
333 {
334 u32 offset=strlen("DEMO_SWAP_INTERVAL");
335 swapInterval = atoi(p+offset+SKIP_NON_DIGIT(p[offset]));
336 OSReport("DEMO: swap interval=%d\n", swapInterval);
337 }
338
339 // Modify the assets directory if DEMO_ASSETS_DIR is passed in
340 p = strstr(argv[i], "DEMO_ASSETS_DIR=");
341 if (p != 0){
342 char tempBuffer[MAX_ASSET_DIR_LEN];
343 tempBuffer[MAX_ASSET_DIR_LEN - 2] = 0;
344
345 strncpy(tempBuffer, p+strlen("DEMO_ASSETS_DIR="), MAX_ASSET_DIR_LEN - 2);
346 // replace EOL or ',' with terminating 0
347 char* p2 = tempBuffer;
348 for( ; *p2 != '\n' && *p2 != '\r' && *p2 != ',' && *p2 != 0; p2++ ) {}
349 *p2 = 0;
350
351 // Make sure the asset directory ends with a forward slash
352 if (*(p2 - 1) != '/')
353 {
354 *p2 = '/';
355 *(p2 + 1) = 0;
356 }
357
358 strcpy(gDemoAssetsDir, tempBuffer);
359 }
360 }
361
362 //Use a different MEM1 allocator for DEMO lib.
363 DEMOGfxMem1HeapInit();
364 DEMOGfxBucketHeapInit();
365
366 if (gx2DebugMode!=-1)
367 {
368 DEMOPrintf("DEMO: GX2 debug mode=%#04x\n", gx2DebugMode);
369 GX2SetDebugMode((GX2DebugMode)gx2DebugMode);
370 }
371
372 #ifdef _DEBUG
373 // If no GX2R debug options specified, default some of them in debug builds
374 if (gx2rDebugOptions==-1)
375 {
376 gx2rDebugOptions = GX2R_DEBUG_GUARD_BANDS_ENABLED | GX2R_DEBUG_LEAK_CHECK | GX2R_DEBUG_CHECK_GPU_CONTENTION;
377 }
378 #endif
379
380 if (gx2rDebugOptions!=-1)
381 {
382 DEMOPrintf("DEMO: GX2R debug options=%#04x\n", gx2rDebugOptions);
383 GX2RSetDebugOptions((GX2RDebugOptions)gx2rDebugOptions);
384 }
385
386 // Hook in the demo allocators for GX2R
387 GX2RSetAllocator(DEMOGX2RAlloc, DEMOGX2RFree);
388
389 char *aaStr[4]={ "1X", "2X", "4X", "8X" };
390
391 DEMOPrintf("DEMO: Rendering TV:%dx%d CB:%s DB:%s ScanCB:%s AA:%s\n",
392 renderWidth, renderHeight,
393 &DEMOGfxGetSurfaceFormatName(renderCBFormat)[19],
394 &DEMOGfxGetSurfaceFormatName(renderDBFormat)[19],
395 &DEMOGfxGetSurfaceFormatName(scanOutCBFormat)[19],
396 aaStr[renderAAMode]);
397
398 // Choose an appropriate TV render mode based on desired dimensions
399 for (i = 0; i < RM_TABLE_SZ; i++) {
400 if (((tvRenderModeTable[i*3] >= renderWidth) &&
401 (tvRenderModeTable[i*3+1] >= renderHeight)) || i==(RM_TABLE_SZ-1)) {
402 renderMode = (GX2TVRenderMode) tvRenderModeTable[i*3+2];
403 break;
404 }
405 }
406
407 // Setup Scan Buffers; this must be done before setting up TV render targets!
408 GX2CalcTVSize(renderMode, scanOutCBFormat,
409 GX2_BUFFERING_DOUBLE, &scanSize, &scaleNeeded);
410
411 // For Cafe, should put scan buffers in the foreground bucket
412 DEMOScanBufferPtr = DEMOGfxAllocBucket(scanSize, GX2_SCAN_BUFFER_ALIGNMENT);
413 DEMOCheck(DEMOScanBufferPtr!=NULL, "Scan buffer alloc failed");
414 GX2Invalidate(GX2_INVALIDATE_CPU, DEMOScanBufferPtr, scanSize);
415
416 GX2SetTVBuffer(DEMOScanBufferPtr, scanSize, renderMode,
417 scanOutCBFormat, GX2_BUFFERING_DOUBLE);
418
419 // First, we do all the memory allocations to see what fits into MEM1.
420
421 // Setup render buffer; designate it as "final" TV render target.
422 GX2InitColorBufferFTV(&DEMOColorBuffer,
423 renderWidth, renderHeight,
424 renderCBFormat,
425 renderAAMode);
426
427 // AA mode may have changed due to display-related issues.
428 // Please refer to the GX2 display documentation.
429 renderAAMode = DEMOColorBuffer.surface.aa;
430
431 ptr = DEMOGfxAllocMEM1(DEMOColorBuffer.surface.imageSize,
432 DEMOColorBuffer.surface.alignment);
433 DEMOCheck(ptr!=NULL, "Color buffer alloc failed");
434 GX2Invalidate(GX2_INVALIDATE_CPU, ptr, DEMOColorBuffer.surface.imageSize);
435
436 GX2InitColorBufferPtr(&DEMOColorBuffer, ptr);
437
438 // Setup aux buffer
439 if (DEMOColorBuffer.surface.aa != GX2_AA_MODE_1X) {
440 u32 size, align;
441 GX2CalcColorBufferAuxInfo(&DEMOColorBuffer, &size, &align);
442 ptr = DEMOGfxAllocMEM1(size, align);
443 DEMOCheck(ptr!=NULL, "Color aux buffer alloc failed");
444 GX2InitColorBufferAuxPtr(&DEMOColorBuffer, ptr);
445 GX2Invalidate(GX2_INVALIDATE_CPU, ptr, size);
446 // Aux buffer must be cleared manually to this value once:
447 GX2UTSetupColorAuxBuffer(&DEMOColorBuffer);
448 }
449
450 // Setup Depth Buffer
451 GX2InitDepthBuffer(&DEMODepthBuffer,
452 renderWidth, renderHeight,
453 renderDBFormat,
454 renderAAMode);
455 ptr = DEMOGfxAllocMEM1(DEMODepthBuffer.surface.imageSize,
456 DEMODepthBuffer.surface.alignment);
457 DEMOCheck(ptr!=NULL, "Depth buffer alloc failed");
458 GX2Invalidate(GX2_INVALIDATE_CPU, ptr, DEMODepthBuffer.surface.imageSize);
459 GX2InitDepthBufferPtr(&DEMODepthBuffer, ptr);
460
461 // Setup Hi-Z buffer
462 if (renderHiZ) {
463 u32 size, align;
464 GX2CalcDepthBufferHiZInfo(&DEMODepthBuffer, &size, &align);
465 ptr = DEMOGfxAllocMEM1(size, align);
466 DEMOCheck(ptr!=NULL, "Depth Hi-Z buffer alloc failed");
467 GX2Invalidate(GX2_INVALIDATE_CPU, ptr, size);
468 GX2InitDepthBufferHiZPtr(&DEMODepthBuffer, ptr);
469 }
470
471 // Register a callback upon foreground acquire and release
472 ProcUIRegisterCallback(PROCUI_MESSAGE_ACQUIRE, DEMOGfxCallbackAcquiredForeground, NULL, 100);
473 ProcUIRegisterCallback(PROCUI_MESSAGE_RELEASE, DEMOGfxCallbackReleaseForeground, NULL, 100);
474
475 // Save state for DEMOGfxAcquiredForeground
476 gDemoGfxRenderMode = renderMode;
477 gDemoGfxScanOutCBFormat = scanOutCBFormat;
478 gDemoGfxScanSize = scanSize;
479
480 // Save state for instancing
481 gDemoGfxRenderWidth = renderWidth;
482 gDemoGfxRenderHeight = renderHeight;
483 gDemoGfxSwapInterval = swapInterval;
484
485 // Create a new instance (including the context state)
486 gDemoGfxCurInstance = NULL;
487 DEMOGfxAddInstance();
488
489 // The main core is the one with GFX
490 DEMOSetMainCore(OSGetCoreId());
491
492 // Indicate that graphics has been started
493 gDemoGfxRunningFlag = TRUE;
494
495 return gDemoGfxCurInstance;
496 }
497
DEMOGfxShutdown()498 void DEMOGfxShutdown()
499 {
500 // Delete the instances
501 DEMOGfxDeleteInstance(gDemoGfxCurInstance);
502
503 // It is possible to exit from the background, but some API calls
504 // can only happen from the foreground. Check a flag to see if this
505 // processes is exiting from the foreground before calling APIs
506 // that deal with foreground-only resources.
507
508 // Disable video outputs
509 if (gDemoGfxInForeground && OS_SHUTDOWN_RESTART != OSGetShutdownReason())
510 {
511 GX2SetTVEnable(GX2_FALSE);
512 }
513 gDemoGfxTVEnabled = FALSE;
514
515 // Free allocated buffers
516 DEMOGfxFreeBucket(DEMOScanBufferPtr);
517 if (DEMODepthBuffer.hiZPtr) {
518 DEMOGfxFreeMEM1(DEMODepthBuffer.hiZPtr);
519 DEMODepthBuffer.hiZPtr = NULL;
520 }
521 DEMOGfxFreeMEM1(DEMODepthBuffer.surface.imagePtr);
522 if (DEMOColorBuffer.auxPtr) {
523 DEMOGfxFreeMEM1(DEMOColorBuffer.auxPtr);
524 DEMOColorBuffer.auxPtr = NULL;
525 }
526 DEMOGfxFreeMEM1(DEMOColorBuffer.surface.imagePtr);
527 if (gDemoGfxInForeground) DEMOFree(DEMOCommandBufferBasePtr);
528
529 // Shutdown GX2 (which is safe to call from the background);
530 GX2Shutdown();
531
532 // Dump any leaked resources if enabled
533 if (GX2RGetDebugOptions() & GX2R_DEBUG_LEAK_CHECK)
534 {
535 if (GX2TempGetResourceCount()>0)
536 {
537 OSReport("***DEMO: resources were not destroyed on shutdown\n");
538 GX2TempDumpResources();
539 ASSERT(FALSE && "Resources were not destroyed on shutdown");
540 }
541 }
542 // Unhook the GX2R allocator functions.
543 GX2RSetAllocator(NULL, NULL);
544
545 // Only destroy these heaps if this process is in the foreground.
546 if (gDemoGfxInForeground)
547 {
548 DEMOGfxMem1HeapDestroy();
549 DEMOGfxBucketHeapDestroy();
550 }
551
552 gDemoGfxRunningFlag = FALSE;
553 }
554
DEMOGfxReleaseForeground()555 void DEMOGfxReleaseForeground()
556 {
557 // First wait for all pending draws to complete.
558 GX2DrawDone();
559
560 // Release resources in MEM1
561 if (DEMODepthBuffer.hiZPtr) {
562 DEMOGfxFreeMEM1(DEMODepthBuffer.hiZPtr);
563 DEMODepthBuffer.hiZPtr = NULL;
564 }
565 DEMOGfxFreeMEM1(DEMODepthBuffer.surface.imagePtr);
566 if (DEMOColorBuffer.auxPtr) {
567 DEMOGfxFreeMEM1(DEMOColorBuffer.auxPtr);
568 DEMOColorBuffer.auxPtr = NULL;
569 }
570 DEMOGfxFreeMEM1(DEMOColorBuffer.surface.imagePtr);
571
572 // Free resources from the foreground bucket
573 DEMOGfxFreeBucket(DEMOScanBufferPtr);
574
575 // Destroy heaps that will not be available.
576 DEMOGfxMem1HeapDestroy();
577 DEMOGfxBucketHeapDestroy();
578
579 // Mark the TV as disabled.
580 gDemoGfxTVEnabled=FALSE;
581
582 // Set a flag to indicate that this process is in the background.
583 gDemoGfxInForeground=FALSE;
584 OSMemoryBarrier();
585 }
586
DEMOGfxAcquiredForeground()587 void DEMOGfxAcquiredForeground()
588 {
589 void *ptr;
590
591 // Set a flag to indicate that this process is in the foreground.
592 gDemoGfxInForeground=TRUE;
593 OSMemoryBarrier();
594
595 // Recreate heaps that were lost.
596 DEMOGfxMem1HeapInit();
597 DEMOGfxBucketHeapInit();
598
599 // For Cafe, should put scan buffers in the foreground bucket
600 DEMOScanBufferPtr = DEMOGfxAllocBucket(gDemoGfxScanSize, GX2_SCAN_BUFFER_ALIGNMENT);
601 GX2Invalidate(GX2_INVALIDATE_CPU, DEMOScanBufferPtr, gDemoGfxScanSize);
602
603 GX2SetTVBuffer(DEMOScanBufferPtr, gDemoGfxScanSize, gDemoGfxRenderMode,
604 gDemoGfxScanOutCBFormat, GX2_BUFFERING_DOUBLE);
605
606 // Re-allocate color buffer
607 ptr = DEMOGfxAllocMEM1(DEMOColorBuffer.surface.imageSize,
608 DEMOColorBuffer.surface.alignment);
609 GX2Invalidate(GX2_INVALIDATE_CPU, ptr, DEMOColorBuffer.surface.imageSize);
610
611 GX2InitColorBufferPtr(&DEMOColorBuffer, ptr);
612
613 // Setup aux buffer
614 if (DEMOColorBuffer.surface.aa != GX2_AA_MODE_1X) {
615 u32 size, align;
616 GX2CalcColorBufferAuxInfo(&DEMOColorBuffer, &size, &align);
617 ptr = DEMOGfxAllocMEM1(size, align);
618 GX2InitColorBufferAuxPtr(&DEMOColorBuffer, ptr);
619 GX2Invalidate(GX2_INVALIDATE_CPU, ptr, size);
620 // Aux buffer must be cleared manually to this value once:
621 GX2UTSetupColorAuxBuffer(&DEMOColorBuffer);
622 }
623
624 // Re-allocate depth buffer
625 ptr = DEMOGfxAllocMEM1(DEMODepthBuffer.surface.imageSize,
626 DEMODepthBuffer.surface.alignment);
627 GX2Invalidate(GX2_INVALIDATE_CPU, ptr, DEMODepthBuffer.surface.imageSize);
628 GX2InitDepthBufferPtr(&DEMODepthBuffer, ptr);
629
630 // Setup Hi-Z buffer
631 if (1) { // Allow testing with & without Hi-Z
632 u32 size, align;
633 GX2CalcDepthBufferHiZInfo(&DEMODepthBuffer, &size, &align);
634 ptr = DEMOGfxAllocMEM1(size, align);
635 GX2Invalidate(GX2_INVALIDATE_CPU, ptr, size);
636 GX2InitDepthBufferHiZPtr(&DEMODepthBuffer, ptr);
637 }
638
639 GX2SetContextState(DEMOContextState);
640
641 // Indicate that graphics has been started
642 gDemoGfxRunningFlag = TRUE;
643 }
644
DEMOGfxIsRunning()645 BOOL DEMOGfxIsRunning()
646 {
647 return gDemoGfxRunningFlag;
648 }
649
DEMOGfxSetContextState(void)650 void DEMOGfxSetContextState(void)
651 {
652 GX2UTDebugTagIndent("DEMOGfxSetContextState()");
653 GX2SetContextState(DEMOContextState);
654 GX2UTDebugTagUndent();
655 }
656
DEMOGfxBeforeRender(void)657 void DEMOGfxBeforeRender(void)
658 {
659 GX2UTDebugTagIndent("DEMOGfxBeforeRender()");
660 // Allow CPU to run 1 frame ahead of GPU and display
661 //DEMOGfxWaitForSwap(1, 0);
662 //TEMP TODO: most of the demos rely on the CPU not being ahead of the GPU, until that's (maybe) going to get fixed
663 // we need to leave the swap queue depth at 0.
664 DEMOGfxWaitForSwap(0, 0);
665
666 // Enabled when Demo Perf condition is met
667 DEMOTestCheckPerfBegin();
668 GX2UTDebugTagUndent();
669 }
670
DEMOGfxDoneRender(void)671 void DEMOGfxDoneRender(void)
672 {
673 GX2UTDebugTagIndent("DEMOGfxDoneRender()");
674 // Enabled when Demo Perf condition is met
675 DEMOTestCheckPerfEnd();
676
677 // This extra flush avoids a potential race condition that can occur with
678 // the GX2R Resource Tracker: the swap buffer command might finish before
679 // the time stamp of its CB is updated. The race condition would make the
680 // resource appear still in use at the start of the next frame. This extra
681 // flush makes sure that no GX2R resources share the same time stamp as
682 // the swap buffer CB, thus avoiding the problem.
683 GX2Flush();
684
685 GX2SwapBuffers(&DEMOColorBuffer);
686
687 // Restore the context state after copy
688 GX2SetContextState(DEMOContextState);
689
690 // Do this before the flush so it's in the same CB as everything else
691 GX2UTDebugTagUndent();
692
693 // Flush after swap, since swap goes into the FIFO
694 GX2Flush();
695
696 // Enable video output after first frame rendered
697 if (gDemoGfxTVEnabled == FALSE) {
698 GX2SetTVEnable(GX2_TRUE);
699 gDemoGfxTVEnabled = TRUE;
700 }
701 }
702
DEMOGfxDrawDone(void)703 void DEMOGfxDrawDone(void)
704 {
705 // Only if running and in the foreground
706 if (APP_IN_FOREGROUND && DEMOGfxIsRunning())
707 GX2DrawDone();
708 }
709
DEMOGfxWaitForSwap(u32 depth,u32 percent)710 void DEMOGfxWaitForSwap(u32 depth, u32 percent)
711 {
712 GX2UTDebugTagIndent("DEMOGfxWaitForSwap()");
713 u32 swapCount, flipCount, waitCount=0;
714 OSTime tLastFlip, tLastVsync;
715 OSTime tNow;
716 const OSTime t60 = (OSTime)OSSecondsToTicks(1.0f/59.94f);
717 OSTime period;
718 u32 swapInt = GX2GetSwapInterval();
719
720 if (swapInt != 0)
721 {
722 // Note: must be careful about unsigned wrap-around!
723
724 // Wait for "depth" frames ago to post
725 while (1)
726 {
727 GX2GetSwapStatus(&swapCount, &flipCount, &tLastFlip, &tLastVsync);
728 if (flipCount+depth >= swapCount) break;
729
730 // If we've waited over 10 seconds for a flip, consider the GPU hung
731 // and stop running.
732 if (waitCount++ > 60*GX2GetGPUTimeout()/1000) {
733 OSReport("DEMOGfxWaitForSwap timed out. Potential GPU hang detected?\n");
734 GX2SetMiscParam(GX2_MISC_HANG_STATE, GX2_HANG_STATE_ETC);
735 if (GX2GetMiscParam(GX2_MISC_HANG_RESPONSE) == GX2_HANG_RESPONSE_DEBUG) {
736 GX2PrintGPUStatus();
737 OSDebugStrIfConnected(0);
738 DEMOStopRunning();
739 }
740 break;
741 }
742
743 // Call WaitForVsync instead of WaitForFlip due to possible
744 // race condition of flip happening right after above test.
745 // (There will always be more vsyncs, but not always more flips.)
746 GX2WaitForVsync();
747 }
748
749 // Wait for (percent * Swap Period) milliseconds since last flip
750 period = (percent * swapInt * t60 / 100);
751 tNow = OSGetSystemTime();
752 if (period > (tNow - tLastFlip))
753 {
754 OSSleepTicks(period - (tNow - tLastFlip));
755 }
756 }
757
758 GX2UTDebugTagUndent();
759 }
760
DEMOGfxMem1HeapInit(void)761 void DEMOGfxMem1HeapInit(void)
762 {
763 //A real game should use the frame heap directly to save memory,
764 //but using an expanded heap makes the demos simpler.
765
766 //For more information on MEM1 usage, go to
767 // Operating System->Cafe Core OS (COS) Overview->Basic Memory Allocation->MEM1
768 //in the MAN pages.
769 MEMHeapHandle hMEM1 = MEMGetBaseHeapHandle(MEM_ARENA_1);
770 u32 uMEM1Size = MEMGetAllocatableSizeForFrmHeapEx(hMEM1,4);
771 void* pStartOfMem1 = MEMAllocFromFrmHeapEx(hMEM1, uMEM1Size, 4);
772 gDEMOMem1Heap = MEMCreateExpHeap(pStartOfMem1, uMEM1Size);
773 DEMOAssert(gDEMOMem1Heap != MEM_HEAP_INVALID_HANDLE);
774 }
775
DEMOGfxMem1HeapDestroy(void)776 void DEMOGfxMem1HeapDestroy(void)
777 {
778 DEMOAssert(gDEMOMem1Heap != MEM_HEAP_INVALID_HANDLE);
779
780 //Destroy the expanded heap and reset the frame heap to restore the allocation.
781 MEMDestroyExpHeap(gDEMOMem1Heap);
782 gDEMOMem1Heap = MEM_HEAP_INVALID_HANDLE;
783 MEMHeapHandle hMEM1 = MEMGetBaseHeapHandle(MEM_ARENA_1);
784 MEMFreeToFrmHeap(hMEM1, MEM_FRMHEAP_FREE_ALL);
785 }
786
DEMOGfxBucketHeapInit(void)787 void DEMOGfxBucketHeapInit(void)
788 {
789 //A real game should use the frame heap directly to save memory,
790 //but using an expanded heap makes the demos simpler.
791
792 //For more information on Foreground Bucket usage, go to
793 // Operating System->Cafe Core OS (COS) Overview->Basic Memory Allocation->Foreground Bucket
794 //in the MAN pages.
795 MEMHeapHandle hMEMFg = MEMGetBaseHeapHandle(MEM_ARENA_FG);
796 u32 uMEMFgSize = MEMGetAllocatableSizeForFrmHeapEx(hMEMFg,4);
797 void* pStartOfMemFg = MEMAllocFromFrmHeapEx(hMEMFg, uMEMFgSize, 4);
798 gDEMOBucketHeap = MEMCreateExpHeap(pStartOfMemFg, uMEMFgSize);
799 DEMOAssert(gDEMOBucketHeap != MEM_HEAP_INVALID_HANDLE);
800 }
801
DEMOGfxBucketHeapDestroy(void)802 void DEMOGfxBucketHeapDestroy(void)
803 {
804 DEMOAssert(gDEMOBucketHeap != MEM_HEAP_INVALID_HANDLE);
805
806 //Destroy the expanded heap and reset the frame heap to restore the allocation.
807 MEMDestroyExpHeap(gDEMOBucketHeap);
808 gDEMOBucketHeap = MEM_HEAP_INVALID_HANDLE;
809 MEMHeapHandle hMEMFg = MEMGetBaseHeapHandle(MEM_ARENA_FG);
810 MEMFreeToFrmHeap(hMEMFg, MEM_FRMHEAP_FREE_ALL);
811 }
812
813
DEMOGfxAddInstance(void)814 DEMOGfxInstance* DEMOGfxAddInstance(void)
815 {
816 // Setup Context State buffer
817 DEMOContextState = DEMOGfxAllocMEM2(sizeof(GX2ContextState), GX2_CONTEXT_STATE_ALIGNMENT);
818 DEMOCheck(DEMOContextState != NULL, "Context state buffer alloc failed");
819 // GX2SetupContextState will invalidate CPU cache for us
820 GX2SetupContextState(DEMOContextState);
821
822 // Setup render/depth buffers to be used now
823 GX2SetColorBuffer(&DEMOColorBuffer, GX2_RENDER_TARGET_0);
824 GX2SetDepthBuffer(&DEMODepthBuffer);
825
826 // Misc graphics setup
827 GX2SetViewport(0, 0, (f32)gDemoGfxRenderWidth, (f32)gDemoGfxRenderHeight, 0.0f, 1.0f);
828 GX2SetScissor(0, 0, gDemoGfxRenderWidth, gDemoGfxRenderHeight);
829
830 // Indicate that swaps can happen as fast as every vertical interval (1/60 sec)
831 GX2SetSwapInterval(gDemoGfxSwapInterval);
832
833 /////////////////////////////////////////////////////////////////////////////
834 // Create the new instance
835 gDemoGfxCurInstance = DEMOAlloc(sizeof(DEMOGfxInstance));
836 gDemoGfxCurInstance->contextState = DEMOContextState;
837
838 return gDemoGfxCurInstance;
839 }
840
DEMOGfxDeleteInstance(DEMOGfxInstance * instance)841 void DEMOGfxDeleteInstance(DEMOGfxInstance *instance)
842 {
843 DEMOGfxFreeMEM2(instance->contextState);
844 DEMOFree(instance);
845
846 // Edge case: delete current
847 if (gDemoGfxCurInstance == instance) {
848 gDemoGfxCurInstance = NULL;
849 DEMOContextState = NULL;
850 }
851 }
852
853
DEMOGfxSetInstance(DEMOGfxInstance * instance)854 void DEMOGfxSetInstance(DEMOGfxInstance *instance)
855 {
856 gDemoGfxCurInstance = instance;
857
858 DEMOContextState = instance->contextState;
859 GX2SetContextState(DEMOContextState);
860 }
861
DEMOGfxGetInstance(void)862 DEMOGfxInstance* DEMOGfxGetInstance(void)
863 {
864 return gDemoGfxCurInstance;
865 }
866
DEMOGfxOpenAssetFile(const char * path,DEMOFSFileInfo * info)867 s32 DEMOGfxOpenAssetFile(const char* path, DEMOFSFileInfo* info)
868 {
869 char filename[MAX_ASSET_DIR_FULL_LEN];
870
871 strcpy(filename, gDemoAssetsDir);
872 strncat(filename, path, MAX_ASSET_DIR_FULL_LEN - MAX_ASSET_DIR_LEN);
873
874 return DEMOFSOpenFile(filename, info);
875 }
876
DEMOGfxGetAssetFileLength(const DEMOFSFileInfo * fileInfo,u32 * length)877 s32 DEMOGfxGetAssetFileLength(const DEMOFSFileInfo* fileInfo, u32* length)
878 {
879 return DEMOFSGetLength(fileInfo, length);
880 }
881
DEMOGfxReadAssetFile(DEMOFSFileInfo * fileInfo,void * addr,s32 length,s32 offset)882 s32 DEMOGfxReadAssetFile(DEMOFSFileInfo* fileInfo, void* addr, s32 length, s32 offset)
883 {
884 return DEMOFSRead(fileInfo, addr, length, offset);
885 }
886
DEMOGfxCloseAssetFile(DEMOFSFileInfo * fileInfo)887 s32 DEMOGfxCloseAssetFile(DEMOFSFileInfo* fileInfo)
888 {
889 return DEMOFSCloseFile(fileInfo);
890 }
891
DEMOGfxLoadAssetFile(const char * path,u32 * len)892 void* DEMOGfxLoadAssetFile(const char* path, u32* len)
893 {
894 char filename[MAX_ASSET_DIR_FULL_LEN];
895
896 strcpy(filename, gDemoAssetsDir);
897 strncat(filename, path, MAX_ASSET_DIR_FULL_LEN - MAX_ASSET_DIR_LEN);
898
899 return DEMOFSSimpleRead(filename, len);
900 }
901
DEMOGfxLoadAssetFileAlign(const char * path,u32 * len,u32 alignSize)902 void* DEMOGfxLoadAssetFileAlign(const char* path, u32* len, u32 alignSize)
903 {
904 char filename[MAX_ASSET_DIR_FULL_LEN];
905
906 strcpy(filename, gDemoAssetsDir);
907 strncat(filename, path, MAX_ASSET_DIR_FULL_LEN - MAX_ASSET_DIR_LEN);
908
909 return DEMOFSSimpleReadAlign(filename, len, alignSize);
910 }
911
DEMOGfxScanAssetDir(const char * path,u32 * pFileCount,u32 maxFiles,char ** ppFileNames)912 s32 DEMOGfxScanAssetDir(const char *path, u32 *pFileCount, u32 maxFiles, char** ppFileNames)
913 {
914 char filename[MAX_ASSET_DIR_FULL_LEN];
915
916 strcpy(filename, gDemoAssetsDir);
917 strncat(filename, path, MAX_ASSET_DIR_FULL_LEN - MAX_ASSET_DIR_LEN);
918
919 return DEMOFSScanDir(filename, path, pFileCount, maxFiles, ppFileNames);
920 }
921
DEMOGfxGetAttribFormatName(GX2AttribFormat format)922 const char *DEMOGfxGetAttribFormatName(GX2AttribFormat format)
923 {
924 switch(format) {
925 case GX2_ATTRIB_FORMAT_8_UNORM: return "GX2_ATTRIB_FORMAT_8_UNORM"; // 0x0000
926 case GX2_ATTRIB_FORMAT_8_UINT: return "GX2_ATTRIB_FORMAT_8_UINT"; // 0x0100
927 case GX2_ATTRIB_FORMAT_8_SNORM: return "GX2_ATTRIB_FORMAT_8_SNORM"; // 0x0200
928 case GX2_ATTRIB_FORMAT_8_SINT: return "GX2_ATTRIB_FORMAT_8_SINT"; // 0x0300
929 case GX2_ATTRIB_FORMAT_8_UINT_TO_FLOAT: return "GX2_ATTRIB_FORMAT_8_UINT_TO_FLOAT"; // 0x0800
930 case GX2_ATTRIB_FORMAT_8_SINT_TO_FLOAT: return "GX2_ATTRIB_FORMAT_8_SINT_TO_FLOAT"; // 0x0a00
931 case GX2_ATTRIB_FORMAT_4_4_UNORM: return "GX2_ATTRIB_FORMAT_4_4_UNORM"; // 0x0001
932 case GX2_ATTRIB_FORMAT_16_UNORM: return "GX2_ATTRIB_FORMAT_16_UNORM"; // 0x0002
933 case GX2_ATTRIB_FORMAT_16_UINT: return "GX2_ATTRIB_FORMAT_16_UINT"; // 0x0102
934 case GX2_ATTRIB_FORMAT_16_SNORM: return "GX2_ATTRIB_FORMAT_16_SNORM"; // 0x0202
935 case GX2_ATTRIB_FORMAT_16_SINT: return "GX2_ATTRIB_FORMAT_16_SINT"; // 0x0302
936 case GX2_ATTRIB_FORMAT_16_FLOAT: return "GX2_ATTRIB_FORMAT_16_FLOAT"; // 0x0803
937 case GX2_ATTRIB_FORMAT_16_UINT_TO_FLOAT: return "GX2_ATTRIB_FORMAT_16_UINT_TO_FLOAT"; // 0x0802
938 case GX2_ATTRIB_FORMAT_16_SINT_TO_FLOAT: return "GX2_ATTRIB_FORMAT_16_SINT_TO_FLOAT"; // 0x0a02
939 case GX2_ATTRIB_FORMAT_8_8_UNORM: return "GX2_ATTRIB_FORMAT_8_8_UNORM"; // 0x0004
940 case GX2_ATTRIB_FORMAT_8_8_UINT: return "GX2_ATTRIB_FORMAT_8_8_UINT"; // 0x0104
941 case GX2_ATTRIB_FORMAT_8_8_SNORM: return "GX2_ATTRIB_FORMAT_8_8_SNORM"; // 0x0204
942 case GX2_ATTRIB_FORMAT_8_8_SINT: return "GX2_ATTRIB_FORMAT_8_8_SINT"; // 0x0304
943 case GX2_ATTRIB_FORMAT_8_8_UINT_TO_FLOAT: return "GX2_ATTRIB_FORMAT_8_8_UINT_TO_FLOAT"; // 0x0804
944 case GX2_ATTRIB_FORMAT_8_8_SINT_TO_FLOAT: return "GX2_ATTRIB_FORMAT_8_8_SINT_TO_FLOAT"; // 0x0a04
945 case GX2_ATTRIB_FORMAT_32_UINT: return "GX2_ATTRIB_FORMAT_32_UINT"; // 0x0105
946 case GX2_ATTRIB_FORMAT_32_SINT: return "GX2_ATTRIB_FORMAT_32_SINT"; // 0x0305
947 case GX2_ATTRIB_FORMAT_32_FLOAT: return "GX2_ATTRIB_FORMAT_32_FLOAT"; // 0x0806
948 case GX2_ATTRIB_FORMAT_16_16_UNORM: return "GX2_ATTRIB_FORMAT_16_16_UNORM"; // 0x0007
949 case GX2_ATTRIB_FORMAT_16_16_UINT: return "GX2_ATTRIB_FORMAT_16_16_UINT"; // 0x0107
950 case GX2_ATTRIB_FORMAT_16_16_SNORM: return "GX2_ATTRIB_FORMAT_16_16_SNORM"; // 0x0207
951 case GX2_ATTRIB_FORMAT_16_16_SINT: return "GX2_ATTRIB_FORMAT_16_16_SINT"; // 0x0307
952 case GX2_ATTRIB_FORMAT_16_16_FLOAT: return "GX2_ATTRIB_FORMAT_16_16_FLOAT"; // 0x0808
953 case GX2_ATTRIB_FORMAT_16_16_UINT_TO_FLOAT: return "GX2_ATTRIB_FORMAT_16_16_UINT_TO_FLOAT"; // 0x0807
954 case GX2_ATTRIB_FORMAT_16_16_SINT_TO_FLOAT: return "GX2_ATTRIB_FORMAT_16_16_SINT_TO_FLOAT"; // 0x0a07
955 case GX2_ATTRIB_FORMAT_10_11_11_FLOAT: return "GX2_ATTRIB_FORMAT_10_11_11_FLOAT"; // 0x0809
956 case GX2_ATTRIB_FORMAT_8_8_8_8_UNORM: return "GX2_ATTRIB_FORMAT_8_8_8_8_UNORM"; // 0x000a
957 case GX2_ATTRIB_FORMAT_8_8_8_8_UINT: return "GX2_ATTRIB_FORMAT_8_8_8_8_UINT"; // 0x010a
958 case GX2_ATTRIB_FORMAT_8_8_8_8_SNORM: return "GX2_ATTRIB_FORMAT_8_8_8_8_SNORM"; // 0x020a
959 case GX2_ATTRIB_FORMAT_8_8_8_8_SINT: return "GX2_ATTRIB_FORMAT_8_8_8_8_SINT"; // 0x030a
960 case GX2_ATTRIB_FORMAT_8_8_8_8_UINT_TO_FLOAT: return "GX2_ATTRIB_FORMAT_8_8_8_8_UINT_TO_FLOAT"; // 0x080a
961 case GX2_ATTRIB_FORMAT_8_8_8_8_SINT_TO_FLOAT: return "GX2_ATTRIB_FORMAT_8_8_8_8_SINT_TO_FLOAT"; // 0x0a0a
962 case GX2_ATTRIB_FORMAT_10_10_10_2_UNORM: return "GX2_ATTRIB_FORMAT_10_10_10_2_UNORM"; // 0x000b
963 case GX2_ATTRIB_FORMAT_10_10_10_2_UINT: return "GX2_ATTRIB_FORMAT_10_10_10_2_UINT"; // 0x010b
964 case GX2_ATTRIB_FORMAT_10_10_10_2_SNORM: return "GX2_ATTRIB_FORMAT_10_10_10_2_SNORM"; // 0x020b
965 case GX2_ATTRIB_FORMAT_10_10_10_2_SINT: return "GX2_ATTRIB_FORMAT_10_10_10_2_SINT"; // 0x030b
966 case GX2_ATTRIB_FORMAT_32_32_UINT: return "GX2_ATTRIB_FORMAT_32_32_UINT"; // 0x010c
967 case GX2_ATTRIB_FORMAT_32_32_SINT: return "GX2_ATTRIB_FORMAT_32_32_SINT"; // 0x030c
968 case GX2_ATTRIB_FORMAT_32_32_FLOAT: return "GX2_ATTRIB_FORMAT_32_32_FLOAT"; // 0x080d
969 case GX2_ATTRIB_FORMAT_16_16_16_16_UNORM: return "GX2_ATTRIB_FORMAT_16_16_16_16_UNORM"; // 0x000e
970 case GX2_ATTRIB_FORMAT_16_16_16_16_UINT: return "GX2_ATTRIB_FORMAT_16_16_16_16_UINT"; // 0x010e
971 case GX2_ATTRIB_FORMAT_16_16_16_16_SNORM: return "GX2_ATTRIB_FORMAT_16_16_16_16_SNORM"; // 0x020e
972 case GX2_ATTRIB_FORMAT_16_16_16_16_SINT: return "GX2_ATTRIB_FORMAT_16_16_16_16_SINT"; // 0x030e
973 case GX2_ATTRIB_FORMAT_16_16_16_16_FLOAT: return "GX2_ATTRIB_FORMAT_16_16_16_16_FLOAT"; // 0x080f
974 case GX2_ATTRIB_FORMAT_16_16_16_16_UINT_TO_FLOAT: return "GX2_ATTRIB_FORMAT_16_16_16_16_UINT_TO_FLOAT"; // 0x080e
975 case GX2_ATTRIB_FORMAT_16_16_16_16_SINT_TO_FLOAT: return "GX2_ATTRIB_FORMAT_16_16_16_16_SINT_TO_FLOAT"; // 0x0a0e
976 case GX2_ATTRIB_FORMAT_32_32_32_UINT: return "GX2_ATTRIB_FORMAT_32_32_32_UINT"; // 0x0110
977 case GX2_ATTRIB_FORMAT_32_32_32_SINT: return "GX2_ATTRIB_FORMAT_32_32_32_SINT"; // 0x0310
978 case GX2_ATTRIB_FORMAT_32_32_32_FLOAT: return "GX2_ATTRIB_FORMAT_32_32_32_FLOAT"; // 0x0811
979 case GX2_ATTRIB_FORMAT_32_32_32_32_UINT: return "GX2_ATTRIB_FORMAT_32_32_32_32_UINT"; // 0x0112
980 case GX2_ATTRIB_FORMAT_32_32_32_32_SINT: return "GX2_ATTRIB_FORMAT_32_32_32_32_SINT"; // 0x0312
981 case GX2_ATTRIB_FORMAT_32_32_32_32_FLOAT: return "GX2_ATTRIB_FORMAT_32_32_32_32_FLOAT"; // 0x0813
982 default: return "invalid format";
983 }
984 }
985
DEMOGfxGetSurfaceFormatName(GX2SurfaceFormat format)986 const char *DEMOGfxGetSurfaceFormatName(GX2SurfaceFormat format)
987 {
988 switch(format) {
989 case GX2_SURFACE_FORMAT_INVALID: return "GX2_SURFACE_FORMAT_INVALID"; // 0x0000
990 case GX2_SURFACE_FORMAT_TC_R8_UNORM: return "GX2_SURFACE_FORMAT_TC_R8_UNORM"; // 0x0001
991 case GX2_SURFACE_FORMAT_TC_R8_UINT: return "GX2_SURFACE_FORMAT_TC_R8_UINT"; // 0x0101
992 case GX2_SURFACE_FORMAT_TC_R8_SNORM: return "GX2_SURFACE_FORMAT_TC_R8_SNORM"; // 0x0201
993 case GX2_SURFACE_FORMAT_TC_R8_SINT: return "GX2_SURFACE_FORMAT_TC_R8_SINT"; // 0x0301
994 case GX2_SURFACE_FORMAT_T_R4_G4_UNORM: return "GX2_SURFACE_FORMAT_T_R4_G4_UNORM"; // 0x0002
995 case GX2_SURFACE_FORMAT_TCD_R16_UNORM: return "GX2_SURFACE_FORMAT_TCD_R16_UNORM"; // 0x0005
996 case GX2_SURFACE_FORMAT_TC_R16_UINT: return "GX2_SURFACE_FORMAT_TC_R16_UINT"; // 0x0105
997 case GX2_SURFACE_FORMAT_TC_R16_SNORM: return "GX2_SURFACE_FORMAT_TC_R16_SNORM"; // 0x0205
998 case GX2_SURFACE_FORMAT_TC_R16_SINT: return "GX2_SURFACE_FORMAT_TC_R16_SINT"; // 0x0305
999 case GX2_SURFACE_FORMAT_TC_R16_FLOAT: return "GX2_SURFACE_FORMAT_TC_R16_FLOAT"; // 0x0806
1000 case GX2_SURFACE_FORMAT_TC_R8_G8_UNORM: return "GX2_SURFACE_FORMAT_TC_R8_G8_UNORM"; // 0x0007
1001 case GX2_SURFACE_FORMAT_TC_R8_G8_UINT: return "GX2_SURFACE_FORMAT_TC_R8_G8_UINT"; // 0x0107
1002 case GX2_SURFACE_FORMAT_TC_R8_G8_SNORM: return "GX2_SURFACE_FORMAT_TC_R8_G8_SNORM"; // 0x0207
1003 case GX2_SURFACE_FORMAT_TC_R8_G8_SINT: return "GX2_SURFACE_FORMAT_TC_R8_G8_SINT"; // 0x0307
1004 case GX2_SURFACE_FORMAT_TCS_R5_G6_B5_UNORM: return "GX2_SURFACE_FORMAT_TCS_R5_G6_B5_UNORM"; // 0x0008
1005 case GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM: return "GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM"; // 0x000a
1006 case GX2_SURFACE_FORMAT_TC_R4_G4_B4_A4_UNORM: return "GX2_SURFACE_FORMAT_TC_R4_G4_B4_A4_UNORM"; // 0x000b
1007 case GX2_SURFACE_FORMAT_TC_A1_B5_G5_R5_UNORM: return "GX2_SURFACE_FORMAT_TC_A1_B5_G5_R5_UNORM"; // 0x000c
1008 case GX2_SURFACE_FORMAT_TC_R32_UINT: return "GX2_SURFACE_FORMAT_TC_R32_UINT"; // 0x010d
1009 case GX2_SURFACE_FORMAT_TC_R32_SINT: return "GX2_SURFACE_FORMAT_TC_R32_SINT"; // 0x030d
1010 case GX2_SURFACE_FORMAT_TCD_R32_FLOAT: return "GX2_SURFACE_FORMAT_TCD_R32_FLOAT"; // 0x080e
1011 case GX2_SURFACE_FORMAT_TC_R16_G16_UNORM: return "GX2_SURFACE_FORMAT_TC_R16_G16_UNORM"; // 0x000f
1012 case GX2_SURFACE_FORMAT_TC_R16_G16_UINT: return "GX2_SURFACE_FORMAT_TC_R16_G16_UINT"; // 0x010f
1013 case GX2_SURFACE_FORMAT_TC_R16_G16_SNORM: return "GX2_SURFACE_FORMAT_TC_R16_G16_SNORM"; // 0x020f
1014 case GX2_SURFACE_FORMAT_TC_R16_G16_SINT: return "GX2_SURFACE_FORMAT_TC_R16_G16_SINT"; // 0x030f
1015 case GX2_SURFACE_FORMAT_TC_R16_G16_FLOAT: return "GX2_SURFACE_FORMAT_TC_R16_G16_FLOAT"; // 0x0810
1016 case GX2_SURFACE_FORMAT_D_D24_S8_UNORM: return "GX2_SURFACE_FORMAT_D_D24_S8_UNORM"; // 0x0011
1017 // case GX2_SURFACE_FORMAT_T_R24_UNORM_X8: return "GX2_SURFACE_FORMAT_T_R24_UNORM_X8"; // 0x0011
1018 case GX2_SURFACE_FORMAT_T_X24_G8_UINT: return "GX2_SURFACE_FORMAT_T_X24_G8_UINT"; // 0x0111
1019 case GX2_SURFACE_FORMAT_D_D24_S8_FLOAT: return "GX2_SURFACE_FORMAT_D_D24_S8_FLOAT"; // 0x0811
1020 case GX2_SURFACE_FORMAT_TC_R11_G11_B10_FLOAT: return "GX2_SURFACE_FORMAT_TC_R11_G11_B10_FLOAT"; // 0x0816
1021 case GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM: return "GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM"; // 0x0019
1022 case GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_UINT: return "GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_UINT"; // 0x0119
1023 case GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_SNORM: return "GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_SNORM"; // 0x0219
1024 case GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_SINT: return "GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_SINT"; // 0x0319
1025 case GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM: return "GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM"; // 0x001a
1026 case GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_UINT: return "GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_UINT"; // 0x011a
1027 case GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SNORM: return "GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SNORM"; // 0x021a
1028 case GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SINT: return "GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SINT"; // 0x031a
1029 case GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB: return "GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB"; // 0x041a
1030 case GX2_SURFACE_FORMAT_TCS_A2_B10_G10_R10_UNORM: return "GX2_SURFACE_FORMAT_TCS_A2_B10_G10_R10_UNORM"; // 0x001b
1031 case GX2_SURFACE_FORMAT_TC_A2_B10_G10_R10_UINT: return "GX2_SURFACE_FORMAT_TC_A2_B10_G10_R10_UINT"; // 0x011b
1032 case GX2_SURFACE_FORMAT_D_D32_FLOAT_S8_UINT_X24: return "GX2_SURFACE_FORMAT_D_D32_FLOAT_S8_UINT_X24"; // 0x081c
1033 // case GX2_SURFACE_FORMAT_T_R32_FLOAT_X8_X24: return "GX2_SURFACE_FORMAT_T_R32_FLOAT_X8_X24"; // 0x081c
1034 case GX2_SURFACE_FORMAT_T_X32_G8_UINT_X24: return "GX2_SURFACE_FORMAT_T_X32_G8_UINT_X24"; // 0x011c
1035 case GX2_SURFACE_FORMAT_TC_R32_G32_UINT: return "GX2_SURFACE_FORMAT_TC_R32_G32_UINT"; // 0x011d
1036 case GX2_SURFACE_FORMAT_TC_R32_G32_SINT: return "GX2_SURFACE_FORMAT_TC_R32_G32_SINT"; // 0x031d
1037 case GX2_SURFACE_FORMAT_TC_R32_G32_FLOAT: return "GX2_SURFACE_FORMAT_TC_R32_G32_FLOAT"; // 0x081e
1038 case GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UNORM: return "GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UNORM"; // 0x001f
1039 case GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UINT: return "GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UINT"; // 0x011f
1040 case GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_SNORM: return "GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_SNORM"; // 0x021f
1041 case GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_SINT: return "GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_SINT"; // 0x031f
1042 case GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_FLOAT: return "GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_FLOAT"; // 0x0820
1043 case GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_UINT: return "GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_UINT"; // 0x0122
1044 case GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_SINT: return "GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_SINT"; // 0x0322
1045 case GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_FLOAT: return "GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_FLOAT"; // 0x0823
1046 case GX2_SURFACE_FORMAT_T_BC1_UNORM: return "GX2_SURFACE_FORMAT_T_BC1_UNORM"; // 0x0031
1047 case GX2_SURFACE_FORMAT_T_BC1_SRGB: return "GX2_SURFACE_FORMAT_T_BC1_SRGB"; // 0x0431
1048 case GX2_SURFACE_FORMAT_T_BC2_UNORM: return "GX2_SURFACE_FORMAT_T_BC2_UNORM"; // 0x0032
1049 case GX2_SURFACE_FORMAT_T_BC2_SRGB: return "GX2_SURFACE_FORMAT_T_BC2_SRGB"; // 0x0432
1050 case GX2_SURFACE_FORMAT_T_BC3_UNORM: return "GX2_SURFACE_FORMAT_T_BC3_UNORM"; // 0x0033
1051 case GX2_SURFACE_FORMAT_T_BC3_SRGB: return "GX2_SURFACE_FORMAT_T_BC3_SRGB"; // 0x0433
1052 case GX2_SURFACE_FORMAT_T_BC4_UNORM: return "GX2_SURFACE_FORMAT_T_BC4_UNORM"; // 0x0034
1053 case GX2_SURFACE_FORMAT_T_BC4_SNORM: return "GX2_SURFACE_FORMAT_T_BC4_SNORM"; // 0x0234
1054 case GX2_SURFACE_FORMAT_T_BC5_UNORM: return "GX2_SURFACE_FORMAT_T_BC5_UNORM"; // 0x0035
1055 case GX2_SURFACE_FORMAT_T_BC5_SNORM: return "GX2_SURFACE_FORMAT_T_BC5_SNORM"; // 0x0235
1056 case GX2_SURFACE_FORMAT_T_NV12_UNORM: return "GX2_SURFACE_FORMAT_T_NV12_UNORM"; // 0x0081
1057 default: return "invalid format";
1058 }
1059 }
1060
1061
1062
1063