From fe7ddc0acadf7ff752371525155feeab9fde6073 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Sat, 12 Nov 2022 13:43:58 +1000 Subject: [PATCH] Introduce an easier way to do profiling --- src/game/lv.c | 2 +- src/include/constants.h | 13 ++++ src/include/lib/profile.h | 1 + src/lib/main.c | 8 +- src/lib/profile.c | 154 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 175 insertions(+), 3 deletions(-) diff --git a/src/game/lv.c b/src/game/lv.c index 9b9a11d54..c9c54d445 100644 --- a/src/game/lv.c +++ b/src/game/lv.c @@ -946,7 +946,7 @@ Gfx *lvPrint(Gfx *gdl) #ifdef PROFILING if (joyGetButtonsPressedThisFrame(0, R_JPAD)) { - g_LvStatsPage = (g_LvStatsPage + 1) % 2; + g_LvStatsPage = (g_LvStatsPage + 1) % 3; } #endif diff --git a/src/include/constants.h b/src/include/constants.h index 47e8f1391..2e2504be2 100644 --- a/src/include/constants.h +++ b/src/include/constants.h @@ -3424,10 +3424,23 @@ #ifdef PROFILING #define PROFILE(marker, code) \ + void profileStart(s32 arg0); \ + void profileEnd(s32 arg0); \ profileStart(marker); \ code; \ profileEnd(marker); +#define PROFILESTART() \ + { \ + s32 _line = __LINE__; \ + void profileStartDynamic(char *file, s32 line); \ + profileStartDynamic(__FILE__, _line) + +#define PROFILEEND() \ + void profileEndDynamic(char *file, s32 line); \ + profileEndDynamic(__FILE__, _line); \ + } + #define PROFILE_MAINTICK_END 0x10000 #define PROFILE_RSP_END 0x10001 #define PROFILE_RDP_END 0x10002 diff --git a/src/include/lib/profile.h b/src/include/lib/profile.h index d0f5d8325..ec6ac10b5 100644 --- a/src/include/lib/profile.h +++ b/src/include/lib/profile.h @@ -16,5 +16,6 @@ void profileHandleRspEvent(s32 event); #endif Gfx *profileRender(Gfx *gdl); +Gfx *profileRenderDynamic(Gfx *gdl); #endif diff --git a/src/lib/main.c b/src/lib/main.c index 768186593..ebeaca502 100644 --- a/src/lib/main.c +++ b/src/lib/main.c @@ -646,8 +646,12 @@ void mainTick(void) profileEnd(PROFILEMARKER_CPU); #if PROFILING - if (g_LvShowStats && g_LvStatsPage == 1) { - gdl = profileRender(gdl); + if (g_LvShowStats) { + if (g_LvStatsPage == 1) { + gdl = profileRender(gdl); + } else if (g_LvStatsPage == 2) { + gdl = profileRenderDynamic(gdl); + } } #endif diff --git a/src/lib/profile.c b/src/lib/profile.c index ce0dda392..4caaefc09 100644 --- a/src/lib/profile.c +++ b/src/lib/profile.c @@ -17,6 +17,19 @@ u32 g_ProfileAudStart = 0; u32 g_ProfileAudTicks[NUM_SAMPLES]; u32 g_ProfileGfxTicks[NUM_SAMPLES]; u32 g_ProfileGfxTally; +struct profileslot *g_ProfileCurrentSlot; + +struct profileslot { + char *file; + s32 line; + s32 ticks; + s32 startticks; + s32 numiterations; + struct profileslot *parent; + bool recursion; +}; + +struct profileslot g_ProfileSlots[30]; void profileReset(void) { @@ -28,6 +41,74 @@ void profileReset(void) g_ProfileMarkers[g_ProfileIndex][i][0] = 0; g_ProfileMarkers[g_ProfileIndex][i][1] = 0; } + + for (i = 0; i < ARRAYCOUNT(g_ProfileSlots); i++) { + g_ProfileSlots[i].file = NULL; + g_ProfileSlots[i].parent = NULL; + } + + g_ProfileCurrentSlot = NULL; +} + +void profileStartDynamic(char *file, s32 line) +{ + s32 i; + struct profileslot *emptyslot = NULL; + struct profileslot *slot = NULL; + + for (i = 0; i < ARRAYCOUNT(g_ProfileSlots); i++) { + if (!emptyslot && g_ProfileSlots[i].file == NULL) { + emptyslot = &g_ProfileSlots[i]; + } else if (g_ProfileSlots[i].file == file && g_ProfileSlots[i].line == line) { + slot = &g_ProfileSlots[i]; + break; + } + } + + if (slot) { + // Another iteration on an existing slot + if (slot->startticks) { + slot->recursion = true; + } else { + slot->numiterations++; + slot->startticks = osGetCount(); + } + + g_ProfileCurrentSlot = slot; + } else if (emptyslot) { + // New slot + slot = emptyslot; + + slot->file = file; + slot->line = line; + slot->parent = g_ProfileCurrentSlot; + slot->ticks = 0; + slot->numiterations = 1; + slot->recursion = false; + slot->startticks = osGetCount(); + + g_ProfileCurrentSlot = slot; + } +} + +void profileEndDynamic(char *file, s32 line) +{ + s32 i; + struct profileslot *slot = NULL; + + for (i = 0; i < ARRAYCOUNT(g_ProfileSlots); i++) { + if (g_ProfileSlots[i].file == file && g_ProfileSlots[i].line == line) { + slot = &g_ProfileSlots[i]; + break; + } + } + + if (slot) { + slot->ticks = osGetCount() - slot->startticks; + slot->startticks = 0; + + g_ProfileCurrentSlot = slot->parent; + } } void profileStart(s32 marker) @@ -245,4 +326,77 @@ Gfx *profileRender(Gfx *gdl) return gdl; } + +Gfx *profileRenderDynamicSlot(Gfx *gdl, s32 x, s32 *y, s32 index) +{ + char buffer[64]; + struct profileslot *slot = &g_ProfileSlots[index]; + s32 childticks = 0; + s32 textwidth; + s32 textheight; + s32 x2 = x; + s32 i; + + if (slot->recursion) { + sprintf(buffer, "%s:%d *RECURSION*\n", slot->file, slot->line); + gdl = textRender(gdl, &x2, y, buffer, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0x00ff00a0, 0x000000a0, viGetWidth(), viGetHeight(), 0, 0); + } else { + // Render this slot + sprintf(buffer, "%s:%d", slot->file, slot->line); + gdl = textRender(gdl, &x2, y, buffer, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0x00ff00a0, 0x000000a0, viGetWidth(), viGetHeight(), 0, 0); + + sprintf(buffer, "%dus", (u32) OS_CYCLES_TO_USEC(slot->ticks)); + textMeasure(&textheight, &textwidth, buffer, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0); + + x2 = 160 - textwidth; + gdl = textRender(gdl, &x2, y, buffer, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0x00ff00a0, 0x000000a0, viGetWidth(), viGetHeight(), 0, 0); + + sprintf(buffer, "%d\n", slot->numiterations); + x2 = 170; + gdl = textRender(gdl, &x2, y, buffer, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0x00ff00a0, 0x000000a0, viGetWidth(), viGetHeight(), 0, 0); + + // Render child slots + for (i = 0; i < ARRAYCOUNT(g_ProfileSlots); i++) { + if (g_ProfileSlots[i].file && g_ProfileSlots[i].parent == slot) { + gdl = profileRenderDynamicSlot(gdl, x + 5, y, i); + childticks += g_ProfileSlots[i].ticks; + } + } + + // Render child "other" slot + if (childticks > 0) { + x2 = x + 5; + gdl = textRender(gdl, &x2, y, "other", g_CharsHandelGothicXs, g_FontHandelGothicXs, 0x00ff00a0, 0x000000a0, viGetWidth(), viGetHeight(), 0, 0); + + sprintf(buffer, "%dus\n", (u32) OS_CYCLES_TO_USEC(slot->ticks - childticks)); + textMeasure(&textheight, &textwidth, buffer, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0); + + x2 = 160 - textwidth; + gdl = textRender(gdl, &x2, y, buffer, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0x00ff00a0, 0x000000a0, viGetWidth(), viGetHeight(), 0, 0); + } + } + + return gdl; +} + +Gfx *profileRenderDynamic(Gfx *gdl) +{ + if (g_FontHandelGothicXs) { + s32 x = 10; + s32 y = 10; + s32 i; + + gdl = text0f153628(gdl); + + for (i = 0; i < ARRAYCOUNT(g_ProfileSlots); i++) { + if (g_ProfileSlots[i].file && g_ProfileSlots[i].parent == NULL) { + gdl = profileRenderDynamicSlot(gdl, x, &y, i); + } + } + + gdl = text0f153780(gdl); + } + + return gdl; +} #endif