diff --git a/Makefile b/Makefile index ca93850d6..1cf4fe0d9 100644 --- a/Makefile +++ b/Makefile @@ -68,6 +68,13 @@ ROMALLOCATION_GAME = 0x0d0000 ROM_SIZE := 32 +# PROFILING +# +# If enabled (1), press L to show frate stats followed by D-right to toggle +# profiling information. + +PROFILING = 0 + ################################################################################ # The VERSION constant is used in the source to handle version-specific code. @@ -164,6 +171,10 @@ DEFINES := \ C_DEFINES := $(foreach d,$(DEFINES),-D$(d)) AS_DEFINES := $(foreach d,$(DEFINES),--defsym $(d)) --defsym _LANGUAGE_ASSEMBLY=1 +ifeq ($(PROFILING),1) + C_DEFINES += -DPROFILING +endif + A_DIR := src/assets/$(ROMID) B_DIR := build/$(ROMID) E_DIR := extracted/$(ROMID) diff --git a/src/game/lv.c b/src/game/lv.c index b86a43d97..d779ffcbd 100644 --- a/src/game/lv.c +++ b/src/game/lv.c @@ -91,6 +91,7 @@ #include "lib/memp.h" #include "lib/mtx.h" #include "lib/music.h" +#include "lib/profile.h" #include "lib/rng.h" #include "lib/sched.h" #include "lib/snd.h" @@ -944,7 +945,8 @@ void lvFindThreats(void) } } -u8 g_LvShowRates = 0; +u8 g_LvShowStats = 0; +u8 g_LvStatsPage = 0; u8 g_LvAntialias = 1; u8 g_LvRateIndex = 59; u8 g_LvOom = 0; @@ -1015,6 +1017,9 @@ Gfx *lvPrintRateGraph(Gfx *gdl) return gdl; } +u32 g_LvBefore = 0; +u32 g_LvAfter = 0; + Gfx *lvPrintRateText(Gfx *gdl) { if (g_FontHandelGothicXs) { @@ -1082,7 +1087,7 @@ Gfx *lvPrintRateText(Gfx *gdl) Gfx *lvPrint(Gfx *gdl) { if (joyGetButtonsPressedThisFrame(0, L_TRIG)) { - g_LvShowRates = 1 - g_LvShowRates; + g_LvShowStats = 1 - g_LvShowStats; } if (joyGetButtonsPressedThisFrame(0, U_JPAD)) { @@ -1090,9 +1095,15 @@ Gfx *lvPrint(Gfx *gdl) viUpdateMode(); } +#ifdef PROFILING + if (joyGetButtonsPressedThisFrame(0, R_JPAD)) { + g_LvStatsPage = (g_LvStatsPage + 1) % 2; + } +#endif + lvRecordRate(); - if (g_LvShowRates) { + if (g_LvShowStats && g_LvStatsPage == 0) { g_ScaleX = g_ViRes == VIRES_HI ? 2 : 1; gdl = text0f153628(gdl); @@ -1295,6 +1306,7 @@ Gfx *lvRender(Gfx *gdl) gSPDisplayList(gdl++, &var80061380); } + profileStart(PROFILEMARKER_LVR_PREPARE); viSetViewPosition(g_Vars.currentplayer->viewleft, g_Vars.currentplayer->viewtop); viSetFovAspectAndSize(g_Vars.currentplayer->fovy, g_Vars.currentplayer->aspect, g_Vars.currentplayer->viewwidth, g_Vars.currentplayer->viewheight); @@ -1305,7 +1317,9 @@ Gfx *lvRender(Gfx *gdl) gdl = vi0000b1d0(gdl); gdl = currentPlayerScissorToViewport(gdl); artifactsClear(); + profileEnd(PROFILEMARKER_LVR_PREPARE); + profileStart(PROFILEMARKER_LVR_BONDGUN); if ((g_Vars.stagenum != STAGE_CITRAINING || (var80087260 <= 0 && g_MenuData.root != MENUROOT_MPSETUP)) && g_Vars.lvframenum <= 5 && !g_Vars.normmplayerisrunning @@ -1322,6 +1336,7 @@ Gfx *lvRender(Gfx *gdl) && var8009dfc0 == 0) { g_Vars.currentplayer->gunctrl.unk1583_06 = bgun0f09eae4(); } + profileEnd(PROFILEMARKER_LVR_BONDGUN); if (g_Vars.lockscreen) { gdl = bviewDrawMotionBlur(gdl, 0xffffffff, 255); @@ -1332,7 +1347,7 @@ Gfx *lvRender(Gfx *gdl) mtx00016748(1); if (g_Vars.currentplayer->menuisactive) { - gdl = menuRender(gdl); + PROFILE(PROFILEMARKER_LVR_MENU, gdl = menuRender(gdl)); } } else { if (var80075d60 == 2) { @@ -1340,16 +1355,17 @@ Gfx *lvRender(Gfx *gdl) } gdl = viRenderViewportEdges(gdl); - gdl = skyRender(gdl); - bgTick(); - lightsTick(); - propsTickPlayer(islastplayer); - scenarioTickChr(NULL); - propsSort(); - autoaimTick(); - handsTickAttack(); + PROFILE(PROFILEMARKER_LVR_SKY1, gdl = skyRender(gdl)); + PROFILE(PROFILEMARKER_LVR_BGTICK, bgTick()); + PROFILE(PROFILEMARKER_LVR_LIGHTS, lightsTick()); + PROFILE(PROFILEMARKER_LVR_PROPS, propsTickPlayer(islastplayer)); + PROFILE(PROFILEMARKER_LVR_SCENARIOCHR, scenarioTickChr(NULL)); + PROFILE(PROFILEMARKER_LVR_PROPSSORT, propsSort()); + PROFILE(PROFILEMARKER_LVR_AUTOAIM, autoaimTick()); + PROFILE(PROFILEMARKER_LVR_HANDS, handsTickAttack()); // Calculate lookingatprop + profileStart(PROFILEMARKER_LVR_LOOKINGAT); if (PLAYERCOUNT() == 1 || g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0 @@ -1384,7 +1400,9 @@ Gfx *lvRender(Gfx *gdl) } else { g_Vars.currentplayer->lookingatprop.prop = NULL; } + profileEnd(PROFILEMARKER_LVR_LOOKINGAT); + profileStart(PROFILEMARKER_LVR_TRACKEDPROPS); if (gsetHasFunctionFlags(&g_Vars.currentplayer->hands[0].gset, FUNCFLAG_THREATDETECTOR)) { lvFindThreats(); } else if (weaponHasFlag(bgunGetWeaponNum(HAND_RIGHT), WEAPONFLAG_AIMTRACK)) { @@ -1405,6 +1423,7 @@ Gfx *lvRender(Gfx *gdl) } } } + profileEnd(PROFILEMARKER_LVR_TRACKEDPROPS); // Handle eyespy Z presses if (g_Vars.currentplayer->eyespy @@ -1451,20 +1470,20 @@ Gfx *lvRender(Gfx *gdl) currentPlayerInteract(true); } - propsTestForPickup(); - gdl = bgRender(gdl); + PROFILE(PROFILEMARKER_LVR_PICKUP, propsTestForPickup()); + PROFILE(PROFILEMARKER_LVR_BG, gdl = bgRender(gdl)); chr0f028498(var80075d68 == 15 || g_AnimHostEnabled); - gdl = propsRenderBeams(gdl); - gdl = shardsRender(gdl); - gdl = sparksRender(gdl); - gdl = weatherRender(gdl); + PROFILE(PROFILEMARKER_LVR_BEAMS, gdl = propsRenderBeams(gdl)); + PROFILE(PROFILEMARKER_LVR_SHARDS, gdl = shardsRender(gdl)); + PROFILE(PROFILEMARKER_LVR_SPARKS, gdl = sparksRender(gdl)); + PROFILE(PROFILEMARKER_LVR_WEATHER, gdl = weatherRender(gdl)); if (g_NbombsActive) { - gdl = nbombsRender(gdl); + PROFILE(PROFILEMARKER_LVR_NBOMBS, gdl = nbombsRender(gdl)); } if (var80075d60 == 2) { - gdl = playerRenderHud(gdl); + PROFILE(PROFILEMARKER_LVR_HUD, gdl = playerRenderHud(gdl)); #if VERSION == VERSION_NTSC_BETA || VERSION == VERSION_PAL_BETA gdl = lvRenderManPosIfEnabled(gdl); @@ -1742,8 +1761,8 @@ Gfx *lvRender(Gfx *gdl) } #if VERSION >= VERSION_NTSC_1_0 - gdl = scenarioRenderHud(gdl); - gdl = lvRenderFade(gdl); + PROFILE(PROFILEMARKER_LVR_SCENARIO, gdl = scenarioRenderHud(gdl)); + PROFILE(PROFILEMARKER_LVR_FADE, gdl = lvRenderFade(gdl)); #else gdl = lvRenderFade(gdl); gdl = scenarioRenderHud(gdl); @@ -1785,12 +1804,12 @@ Gfx *lvRender(Gfx *gdl) #endif } - gdl = sky0f1274d8(gdl); - gdl = amRender(gdl); + PROFILE(PROFILEMARKER_LVR_SKY2, gdl = sky0f1274d8(gdl)); + PROFILE(PROFILEMARKER_LVR_ACTIVEMENU, gdl = amRender(gdl)); mtx00016748(1); if (g_Vars.currentplayer->menuisactive) { - gdl = menuRender(gdl); + PROFILE(PROFILEMARKER_LVR_MENU, gdl = menuRender(gdl)); } mtx00016748(g_Vars.currentplayerstats->scale_bg2gfx); @@ -1804,7 +1823,7 @@ Gfx *lvRender(Gfx *gdl) } } - artifactsTick(); + PROFILE(PROFILEMARKER_LVR_ARTIFACTS, artifactsTick()); if ((g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0) #if VERSION >= VERSION_NTSC_1_0 @@ -2274,7 +2293,7 @@ void lvTick(void) g_Vars.lvupdate60freal = PALUPF(g_Vars.lvupdate60f); bgunTickBoost(); - hudmsgsTick(); + PROFILE(PROFILEMARKER_LVT_HUDMSGS, hudmsgsTick()); if ((joyGetButtonsPressedThisFrame(0, 0xffff) != 0 || joyGetStickX(0) > 10 @@ -2446,41 +2465,47 @@ void lvTick(void) langTick(); } else { lvUpdateCutsceneTime(); - vtxstoreTick(); + PROFILE(PROFILEMARKER_LVT_VTXSTORE, vtxstoreTick()); lvUpdateSoloHandicaps(); - roomsTick(); + PROFILE(PROFILEMARKER_LVT_ROOMS, roomsTick()); skyTick(); - casingsTick(); - shardsTick(); - sparksTick(); - wallhitsTick(); - splatsTick(); + PROFILE(PROFILEMARKER_LVT_CASINGS, casingsTick()); + PROFILE(PROFILEMARKER_LVT_SHARDS, shardsTick()); + PROFILE(PROFILEMARKER_LVT_SPARKS, sparksTick()); + PROFILE(PROFILEMARKER_LVT_WALLHITS, wallhitsTick()); + PROFILE(PROFILEMARKER_LVT_SPLATS, splatsTick()); + profileStart(PROFILEMARKER_LVT_WEATHER); if (g_WeatherActive) { weatherTick(); } + profileEnd(PROFILEMARKER_LVT_WEATHER); + profileStart(PROFILEMARKER_LVT_NBOMBS); if (g_NbombsActive) { nbombsTick(); } + profileEnd(PROFILEMARKER_LVT_NBOMBS); - lvUpdateMiscSfx(); - sndTick(); - pakExecuteDebugOperations(); - lightingTick(); - modelmgrPrintCounts(); - boltbeamsTick(); - amTick(); - menuTick(); - scenarioTick(); + PROFILE(PROFILEMARKER_LVT_MISCSFX, lvUpdateMiscSfx()); + PROFILE(PROFILEMARKER_LVT_SND, sndTick()); + PROFILE(PROFILEMARKER_LVT_PAK, pakExecuteDebugOperations()); + PROFILE(PROFILEMARKER_LVT_LIGHTING, lightingTick()); + PROFILE(PROFILEMARKER_LVT_MODELMGR, modelmgrPrintCounts()); + PROFILE(PROFILEMARKER_LVT_BOLTBEAMS, boltbeamsTick()); + PROFILE(PROFILEMARKER_LVT_ACTIVEMENU, amTick()); + PROFILE(PROFILEMARKER_LVT_MENU, menuTick()); + PROFILE(PROFILEMARKER_LVT_SCENARIO, scenarioTick()); + profileStart(PROFILEMARKER_LVT_PROPS); if (!g_MainIsEndscreen) { propsTick(); } + profileEnd(PROFILEMARKER_LVT_PROPS); - musicTick(); + PROFILE(PROFILEMARKER_LVT_MUSIC, musicTick()); langTick(); - propsTickPadEffects(); + PROFILE(PROFILEMARKER_LVT_PADEFFECTS, propsTickPadEffects()); if (mainGetStageNum() == STAGE_CITRAINING) { struct trainingdata *trainingdata = dtGetData(); diff --git a/src/include/constants.h b/src/include/constants.h index 90cd76133..72bf4365d 100644 --- a/src/include/constants.h +++ b/src/include/constants.h @@ -3424,6 +3424,12 @@ #define PRESETANIM_GUNJAM 254 #define PRESETANIM_TALKRANDOM 255 +#ifdef PROFILING +#define PROFILE(marker, code) \ + profileStart(marker); \ + code; \ + profileEnd(marker); + #define PROFILE_MAINTICK_END 0x10000 #define PROFILE_RSP_END 0x10001 #define PROFILE_RDP_END 0x10002 @@ -3434,6 +3440,81 @@ #define PROFILE_RDP_START1 0x40001 #define PROFILE_AUDIOFRAME_END 0x60000 +enum profilemarker { + PROFILEMARKER_CPU, + PROFILEMARKER_AUD, + PROFILEMARKER_GFX, + PROFILEMARKER_AUDIO, + PROFILEMARKER_LVTICK, + PROFILEMARKER_LVTICKPLAYERS, + PROFILEMARKER_LVRENDER, + PROFILEMARKER_LVT_HUDMSGS, + PROFILEMARKER_LVT_VTXSTORE, + PROFILEMARKER_LVT_ROOMS, + PROFILEMARKER_LVT_CASINGS, + PROFILEMARKER_LVT_SHARDS, + PROFILEMARKER_LVT_SPARKS, + PROFILEMARKER_LVT_WALLHITS, + PROFILEMARKER_LVT_SPLATS, + PROFILEMARKER_LVT_WEATHER, + PROFILEMARKER_LVT_NBOMBS, + PROFILEMARKER_LVT_MISCSFX, + PROFILEMARKER_LVT_SND, + PROFILEMARKER_LVT_PAK, + PROFILEMARKER_LVT_LIGHTING, + PROFILEMARKER_LVT_MODELMGR, + PROFILEMARKER_LVT_BOLTBEAMS, + PROFILEMARKER_LVT_ACTIVEMENU, + PROFILEMARKER_LVT_MENU, + PROFILEMARKER_LVT_SCENARIO, + PROFILEMARKER_LVT_PROPS, + PROFILEMARKER_LVT_MUSIC, + PROFILEMARKER_LVT_PADEFFECTS, + PROFILEMARKER_LVR_PREPARE, + PROFILEMARKER_LVR_BONDGUN, + PROFILEMARKER_LVR_SKY1, + PROFILEMARKER_LVR_BGTICK, + PROFILEMARKER_LVR_LIGHTS, + PROFILEMARKER_LVR_PROPS, + PROFILEMARKER_LVR_SCENARIOCHR, + PROFILEMARKER_LVR_PROPSSORT, + PROFILEMARKER_LVR_AUTOAIM, + PROFILEMARKER_LVR_HANDS, + PROFILEMARKER_LVR_LOOKINGAT, + PROFILEMARKER_LVR_TRACKEDPROPS, + PROFILEMARKER_LVR_PICKUP, + PROFILEMARKER_LVR_BG, + PROFILEMARKER_LVR_BEAMS, + PROFILEMARKER_LVR_SHARDS, + PROFILEMARKER_LVR_SPARKS, + PROFILEMARKER_LVR_WEATHER, + PROFILEMARKER_LVR_NBOMBS, + PROFILEMARKER_LVR_HUD, + PROFILEMARKER_LVR_SCENARIO, + PROFILEMARKER_LVR_FADE, + PROFILEMARKER_LVR_SKY2, + PROFILEMARKER_LVR_ACTIVEMENU, + PROFILEMARKER_LVR_MENU, + PROFILEMARKER_LVR_ARTIFACTS, + PROFILEMARKER_TMP, + NUM_PROFILEMARKERS +}; + +enum rspevent { + RSPEVENT_AUD_START, + RSPEVENT_AUD_FINISH, + RSPEVENT_GFX_START, + RSPEVENT_GFX_PAUSE, + RSPEVENT_GFX_RESUME, + RSPEVENT_GFX_FINISH +}; +#else +#define PROFILE(marker, code) code +#define profileStart(marker) +#define profileEnd(marker) +#define profileHandleRspEvent(event) +#endif + #define PROJECTILEFLAG_AIRBORNE 0x00000001 #define PROJECTILEFLAG_00000002 0x00000002 #define PROJECTILEFLAG_STICKY 0x00000004 diff --git a/src/include/lib/profile.h b/src/include/lib/profile.h index 6d732dd37..d0f5d8325 100644 --- a/src/include/lib/profile.h +++ b/src/include/lib/profile.h @@ -8,7 +8,13 @@ void profileInit(void); void profileTick(void); void profileReset(void); void profile00009a98(void); -void profileSetMarker(u32 arg0); + +#ifdef PROFILING +void profileStart(s32 arg0); +void profileEnd(s32 arg0); +void profileHandleRspEvent(s32 event); +#endif + Gfx *profileRender(Gfx *gdl); #endif diff --git a/src/include/lib/sched.h b/src/include/lib/sched.h index f38910a9f..4dafd676a 100644 --- a/src/include/lib/sched.h +++ b/src/include/lib/sched.h @@ -10,7 +10,7 @@ void __scHandleRSP(OSSched *sc); void __scHandleRDP(OSSched *sc); void __scHandleTasks(OSSched *sc); void __scAppendList(OSSched *sc, OSScTask *t); -void __scExec(OSSched *sc, OSScTask *sp, OSScTask *dp); +void __scExec(OSSched *sc, OSScTask *sp, OSScTask *dp, s32 resuming); void __scMain(void *arg); void __scYield(OSSched *sc); void schedInitArtifacts(void); diff --git a/src/lib/audiomgr.c b/src/lib/audiomgr.c index d0409744a..d5afe8346 100644 --- a/src/lib/audiomgr.c +++ b/src/lib/audiomgr.c @@ -193,12 +193,12 @@ void amgrMain(void *arg) switch (*msg) { case OS_SC_RSP_MSG: var80091588 = osGetTime(); - profileSetMarker(PROFILE_AUDIOFRAME_START); + profileStart(PROFILEMARKER_AUDIO); amgrHandleFrameMsg(g_AudioManager.audioInfo[g_AdmaCurFrame % 3], info); admaReceiveAll(); count++; - profileSetMarker(PROFILE_AUDIOFRAME_END); + profileEnd(PROFILEMARKER_AUDIO); var80091590 = osGetTime(); var80091570 = var80091590 - var80091588; diff --git a/src/lib/main.c b/src/lib/main.c index 25a5bbbff..e2940092f 100644 --- a/src/lib/main.c +++ b/src/lib/main.c @@ -71,6 +71,9 @@ #include "data.h" #include "types.h" +extern u8 g_LvShowStats; +extern u8 g_LvStatsPage; + bool var8005d9b0 = false; s32 g_StageNum = STAGE_TITLE; u32 g_MainMemaHeapSize = 1024 * 300; @@ -1708,12 +1711,12 @@ void mainTick(void) frametimeCalculate(); profile00009a98(); profileReset(); - profileSetMarker(PROFILE_MAINTICK_START); func000034d8(); joyDebugJoy(); schedSetCrashEnable2(false); if (g_MainGameLogicEnabled) { + profileStart(PROFILEMARKER_CPU); gdl = gdlstart = gfxGetMasterDisplayList(); gDPSetTile(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, 0, 0x0000, G_TX_LOADTILE, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD); @@ -1729,7 +1732,9 @@ void mainTick(void) } #endif - lvTick(); + PROFILE(PROFILEMARKER_LVTICK, lvTick()); + + profileStart(PROFILEMARKER_LVTICKPLAYERS); playermgrShuffle(); if (g_StageNum < STAGE_TITLE) { @@ -1747,7 +1752,10 @@ void mainTick(void) } } - gdl = lvRender(gdl); + profileEnd(PROFILEMARKER_LVTICKPLAYERS); + + PROFILE(PROFILEMARKER_LVRENDER, gdl = lvRender(gdl)); + func000034e0(&gdl); #if VERSION == VERSION_NTSC_BETA || VERSION == VERSION_PAL_BETA @@ -1765,9 +1773,13 @@ void mainTick(void) dhudClear(); #endif - if (debug0f11ed70() >= 2) { + profileEnd(PROFILEMARKER_CPU); + +#if PROFILING + if (g_LvShowStats && g_LvStatsPage == 1) { gdl = profileRender(gdl); } +#endif #if VERSION == VERSION_NTSC_BETA || VERSION == VERSION_PAL_BETA if (g_MainIsDebugMenuOpen) { @@ -1789,7 +1801,6 @@ void mainTick(void) g_MainNumGfxTasks++; memaPrint(); func0f16cf94(); - profileSetMarker(PROFILE_MAINTICK_END); #if VERSION == VERSION_PAL_BETA debug0f119a80nb(); diff --git a/src/lib/profile.c b/src/lib/profile.c index 27dfd3fc0..a63006fd9 100644 --- a/src/lib/profile.c +++ b/src/lib/profile.c @@ -2,8 +2,12 @@ #include "constants.h" #include "bss.h" #include "data.h" +#include "game/game_1531a0.h" +#include "lib/vi.h" #include "types.h" +#define NUM_SAMPLES 32 + void profileInit(void) { // empty @@ -14,17 +18,249 @@ void profileTick(void) // empty } -void profileReset(void) -{ - // empty -} - void profile00009a98(void) { // empty } -void profileSetMarker(u32 value) +#ifdef PROFILING +// [x][x][0] is the current ticks tally (for multiple start + stops within one frame) +// [x][x][1] is the start time +u32 g_ProfileMarkers[NUM_SAMPLES][NUM_PROFILEMARKERS][2]; +s32 g_ProfileIndex = 0; +u32 g_ProfileAudTicks[NUM_SAMPLES]; +u32 g_ProfileGfxTicks[NUM_SAMPLES]; +u32 g_ProfileGfxTally; + +void profileReset(void) +{ + s32 i; + + g_ProfileIndex = (g_ProfileIndex + 1) % NUM_SAMPLES; + + for (i = 0; i < NUM_PROFILEMARKERS; i++) { + g_ProfileMarkers[g_ProfileIndex][i][0] = 0; + g_ProfileMarkers[g_ProfileIndex][i][1] = 0; + } +} + +void profileStart(s32 marker) +{ + g_ProfileMarkers[g_ProfileIndex][marker][1] = osGetCount(); +} + +void profileEnd(s32 marker) +{ + g_ProfileMarkers[g_ProfileIndex][marker][0] += osGetCount() - g_ProfileMarkers[g_ProfileIndex][marker][1]; +} + +u32 profileReadCounters(void) +{ + u32 buf = IO_READ(DPC_BUFBUSY_REG); + u32 tmm = IO_READ(DPC_TMEM_REG); + u32 bus = IO_READ(DPC_PIPEBUSY_REG); + u32 max; + + max = buf > tmm ? buf : tmm; + max = bus > max ? bus : max; + + return max; +} + +void profileHandleRspEvent(s32 event) +{ + switch (event) { + case RSPEVENT_AUD_START: + osDpSetStatus(DPC_CLR_CMD_CTR | DPC_CLR_PIPE_CTR | DPC_CLR_TMEM_CTR); + break; + case RSPEVENT_AUD_FINISH: + g_ProfileAudTicks[g_ProfileIndex] = profileReadCounters(); + break; + case RSPEVENT_GFX_START: + osDpSetStatus(DPC_CLR_CMD_CTR | DPC_CLR_PIPE_CTR | DPC_CLR_TMEM_CTR); + break; + case RSPEVENT_GFX_PAUSE: + g_ProfileGfxTally += profileReadCounters(); + break; + case RSPEVENT_GFX_RESUME: + osDpSetStatus(DPC_CLR_CMD_CTR | DPC_CLR_PIPE_CTR | DPC_CLR_TMEM_CTR); + break; + case RSPEVENT_GFX_FINISH: + g_ProfileGfxTicks[g_ProfileIndex] = g_ProfileGfxTally + profileReadCounters(); + break; + } +} + +Gfx *profileRenderRspLine(Gfx *gdl, s32 x, s32 *y, char *label, u32 *ticksarray) +{ + char buffer[64]; + s32 percent; + u32 colour; + u32 microseconds; + s32 textwidth; + s32 textheight; + s32 x2; + u32 ticks = 0; + s32 i; + + for (i = 0; i < NUM_SAMPLES; i++) { + ticks += ticksarray[i]; + } + + ticks /= NUM_SAMPLES; + + percent = ticks * 100 / (62500000 / 60); + microseconds = ticks * 10 / 625; + + if (percent >= 100) { + colour = 0xff0000a0; + } else if (percent >= 80) { + colour = 0xffff00a0; + } else { + colour = 0x00ff00a0; + } + + x2 = x; + gdl = textRender(gdl, &x2, y, label, g_CharsHandelGothicXs, g_FontHandelGothicXs, colour, 0x000000a0, viGetWidth(), viGetHeight(), 0, 0); + + sprintf(buffer, "%d", microseconds); + textMeasure(&textheight, &textwidth, buffer, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0); + + x2 = x + 100 - textwidth; + gdl = textRender(gdl, &x2, y, buffer, g_CharsHandelGothicXs, g_FontHandelGothicXs, colour, 0x000000a0, viGetWidth(), viGetHeight(), 0, 0); + + sprintf(buffer, "%d%%\n", percent); + textMeasure(&textheight, &textwidth, buffer, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0); + + x2 = x + 130 - textwidth; + gdl = textRender(gdl, &x2, y, buffer, g_CharsHandelGothicXs, g_FontHandelGothicXs, colour, 0x000000a0, viGetWidth(), viGetHeight(), 0, 0); + + return gdl; +} + +Gfx *profileRenderCpuLine(Gfx *gdl, s32 x, s32 *y, char *label, s32 marker) +{ + char buffer[64]; + u32 ticks = 0; + s32 percent; + u32 colour; + u32 microseconds; + s32 textwidth; + s32 textheight; + s32 x2; + s32 i; + + for (i = 0; i < NUM_SAMPLES; i++) { + ticks += g_ProfileMarkers[i][marker][0]; + } + + ticks /= NUM_SAMPLES; + + percent = 100 * ticks / (OS_CPU_COUNTER / 60); + microseconds = OS_CYCLES_TO_USEC(ticks); + + if (percent >= 100) { + colour = 0xff0000a0; + } else if (percent >= 80) { + colour = 0xffff00a0; + } else { + colour = 0x00ff00a0; + } + + x2 = x; + gdl = textRender(gdl, &x2, y, label, g_CharsHandelGothicXs, g_FontHandelGothicXs, colour, 0x000000a0, viGetWidth(), viGetHeight(), 0, 0); + + sprintf(buffer, "%d", microseconds); + textMeasure(&textheight, &textwidth, buffer, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0); + + x2 = x + 100 - textwidth; + gdl = textRender(gdl, &x2, y, buffer, g_CharsHandelGothicXs, g_FontHandelGothicXs, colour, 0x000000a0, viGetWidth(), viGetHeight(), 0, 0); + + sprintf(buffer, "%d%%\n", percent); + textMeasure(&textheight, &textwidth, buffer, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0); + + x2 = x + 130 - textwidth; + gdl = textRender(gdl, &x2, y, buffer, g_CharsHandelGothicXs, g_FontHandelGothicXs, colour, 0x000000a0, viGetWidth(), viGetHeight(), 0, 0); + + return gdl; +} + +Gfx *profileRender(Gfx *gdl) +{ + if (g_FontHandelGothicXs) { + s32 x = 10; + s32 y = 10; + + gdl = text0f153628(gdl); + gdl = profileRenderRspLine(gdl, x, &y, "AUD", g_ProfileAudTicks); + gdl = profileRenderRspLine(gdl, x, &y, "GFX", g_ProfileGfxTicks); + gdl = profileRenderCpuLine(gdl, x, &y, "CPU", PROFILEMARKER_CPU); + gdl = profileRenderCpuLine(gdl, x, &y, " audio", PROFILEMARKER_AUDIO); + gdl = profileRenderCpuLine(gdl, x, &y, " lvTick", PROFILEMARKER_LVTICK); + gdl = profileRenderCpuLine(gdl, x, &y, " hudmsgs ", PROFILEMARKER_LVT_HUDMSGS ); + gdl = profileRenderCpuLine(gdl, x, &y, " vtxstore ", PROFILEMARKER_LVT_VTXSTORE ); + gdl = profileRenderCpuLine(gdl, x, &y, " rooms ", PROFILEMARKER_LVT_ROOMS ); + gdl = profileRenderCpuLine(gdl, x, &y, " casings ", PROFILEMARKER_LVT_CASINGS ); + gdl = profileRenderCpuLine(gdl, x, &y, " shards ", PROFILEMARKER_LVT_SHARDS ); + gdl = profileRenderCpuLine(gdl, x, &y, " sparks ", PROFILEMARKER_LVT_SPARKS ); + gdl = profileRenderCpuLine(gdl, x, &y, " wallhits ", PROFILEMARKER_LVT_WALLHITS ); + gdl = profileRenderCpuLine(gdl, x, &y, " splats ", PROFILEMARKER_LVT_SPLATS ); + gdl = profileRenderCpuLine(gdl, x, &y, " weather ", PROFILEMARKER_LVT_WEATHER ); + gdl = profileRenderCpuLine(gdl, x, &y, " nbombs ", PROFILEMARKER_LVT_NBOMBS ); + gdl = profileRenderCpuLine(gdl, x, &y, " miscsfx ", PROFILEMARKER_LVT_MISCSFX ); + gdl = profileRenderCpuLine(gdl, x, &y, " snd ", PROFILEMARKER_LVT_SND ); + gdl = profileRenderCpuLine(gdl, x, &y, " pak ", PROFILEMARKER_LVT_PAK ); + gdl = profileRenderCpuLine(gdl, x, &y, " lighting ", PROFILEMARKER_LVT_LIGHTING ); + gdl = profileRenderCpuLine(gdl, x, &y, " modelmgr ", PROFILEMARKER_LVT_MODELMGR ); + gdl = profileRenderCpuLine(gdl, x, &y, " boltbeams ", PROFILEMARKER_LVT_BOLTBEAMS ); + gdl = profileRenderCpuLine(gdl, x, &y, " activemenu", PROFILEMARKER_LVT_ACTIVEMENU); + gdl = profileRenderCpuLine(gdl, x, &y, " menu ", PROFILEMARKER_LVT_MENU ); + gdl = profileRenderCpuLine(gdl, x, &y, " scenario ", PROFILEMARKER_LVT_SCENARIO ); + gdl = profileRenderCpuLine(gdl, x, &y, " props ", PROFILEMARKER_LVT_PROPS ); + gdl = profileRenderCpuLine(gdl, x, &y, " music ", PROFILEMARKER_LVT_MUSIC ); + gdl = profileRenderCpuLine(gdl, x, &y, " padeffects", PROFILEMARKER_LVT_PADEFFECTS); + gdl = profileRenderCpuLine(gdl, x, &y, " lvTickPlayers", PROFILEMARKER_LVTICKPLAYERS); + + x = 170; + y = 10; + + gdl = profileRenderCpuLine(gdl, x, &y, " lvRender", PROFILEMARKER_LVRENDER); + gdl = profileRenderCpuLine(gdl, x, &y, " prepare ", PROFILEMARKER_LVR_PREPARE ); + gdl = profileRenderCpuLine(gdl, x, &y, " bondgun ", PROFILEMARKER_LVR_BONDGUN ); + gdl = profileRenderCpuLine(gdl, x, &y, " sky1 ", PROFILEMARKER_LVR_SKY1 ); + gdl = profileRenderCpuLine(gdl, x, &y, " bgtick ", PROFILEMARKER_LVR_BGTICK ); + gdl = profileRenderCpuLine(gdl, x, &y, " lights ", PROFILEMARKER_LVR_LIGHTS ); + gdl = profileRenderCpuLine(gdl, x, &y, " props ", PROFILEMARKER_LVR_PROPS ); + gdl = profileRenderCpuLine(gdl, x, &y, " scenariochr ", PROFILEMARKER_LVR_SCENARIOCHR ); + gdl = profileRenderCpuLine(gdl, x, &y, " propssort ", PROFILEMARKER_LVR_PROPSSORT ); + gdl = profileRenderCpuLine(gdl, x, &y, " autoaim ", PROFILEMARKER_LVR_AUTOAIM ); + gdl = profileRenderCpuLine(gdl, x, &y, " hands ", PROFILEMARKER_LVR_HANDS ); + gdl = profileRenderCpuLine(gdl, x, &y, " lookingat ", PROFILEMARKER_LVR_LOOKINGAT ); + gdl = profileRenderCpuLine(gdl, x, &y, " trackedprops", PROFILEMARKER_LVR_TRACKEDPROPS); + gdl = profileRenderCpuLine(gdl, x, &y, " pickup ", PROFILEMARKER_LVR_PICKUP ); + gdl = profileRenderCpuLine(gdl, x, &y, " bg ", PROFILEMARKER_LVR_BG ); + gdl = profileRenderCpuLine(gdl, x, &y, " beams ", PROFILEMARKER_LVR_BEAMS ); + gdl = profileRenderCpuLine(gdl, x, &y, " shards ", PROFILEMARKER_LVR_SHARDS ); + gdl = profileRenderCpuLine(gdl, x, &y, " sparks ", PROFILEMARKER_LVR_SPARKS ); + gdl = profileRenderCpuLine(gdl, x, &y, " weather ", PROFILEMARKER_LVR_WEATHER ); + gdl = profileRenderCpuLine(gdl, x, &y, " nbombs ", PROFILEMARKER_LVR_NBOMBS ); + gdl = profileRenderCpuLine(gdl, x, &y, " hud ", PROFILEMARKER_LVR_HUD ); + gdl = profileRenderCpuLine(gdl, x, &y, " scenario ", PROFILEMARKER_LVR_SCENARIO ); + gdl = profileRenderCpuLine(gdl, x, &y, " fade ", PROFILEMARKER_LVR_FADE ); + gdl = profileRenderCpuLine(gdl, x, &y, " sky2 ", PROFILEMARKER_LVR_SKY2 ); + gdl = profileRenderCpuLine(gdl, x, &y, " activemenu ", PROFILEMARKER_LVR_ACTIVEMENU ); + gdl = profileRenderCpuLine(gdl, x, &y, " menu ", PROFILEMARKER_LVR_MENU ); + gdl = profileRenderCpuLine(gdl, x, &y, " artifacts ", PROFILEMARKER_LVR_ARTIFACTS ); + gdl = profileRenderCpuLine(gdl, x, &y, "tmp", PROFILEMARKER_TMP); + gdl = text0f153780(gdl); + } + + g_ProfileGfxTally = 0; + + return gdl; +} +#else +void profileReset(void) { // empty } @@ -33,3 +269,4 @@ Gfx *profileRender(Gfx *gdl) { return gdl; } +#endif diff --git a/src/lib/sched.c b/src/lib/sched.c index 543dc15fe..1826db8ad 100644 --- a/src/lib/sched.c +++ b/src/lib/sched.c @@ -56,7 +56,7 @@ void __scHandleRDP(OSSched *s); void __scAppendList(OSSched *s, OSScTask *t); OSScTask *__scTaskReady(OSScTask *t); s32 __scTaskComplete(OSSched *s,OSScTask *t); -void __scExec(OSSched *sc, OSScTask *sp, OSScTask *dp); +void __scExec(OSSched *sc, OSScTask *sp, OSScTask *dp, s32 resuming); void __scYield(OSSched *s); s32 __scSchedule(OSSched *sc, OSScTask **sp, OSScTask **dp, s32 availRCP); @@ -279,7 +279,7 @@ void schedAppendTasks(OSSched *sc, OSScTask *t) state = ((sc->curRSPTask == 0) << 1) | (sc->curRDPTask == 0); if (__scSchedule(sc, &sp, &dp, state) != state) { - __scExec(sc, sp, dp); + __scExec(sc, sp, dp, false); } } @@ -360,7 +360,7 @@ void __scHandleTasks(OSSched *sc) state = ((sc->curRSPTask == 0) << 1) | (sc->curRDPTask == 0); if (__scSchedule(sc, &sp, &dp, state) != state) { - __scExec(sc, sp, dp); + __scExec(sc, sp, dp, false); } } @@ -411,12 +411,12 @@ void __scHandleRSP(OSSched *sc) t = sc->curRSPTask; sc->curRSPTask = 0; - profileSetMarker(PROFILE_RSP_END); - if ((t->state & OS_SC_YIELD) && osSpTaskYielded(&t->list)) { t->state |= OS_SC_YIELDED; if ((t->flags & OS_SC_TYPE_MASK) == OS_SC_XBUS) { + profileHandleRspEvent(RSPEVENT_GFX_PAUSE); + // Push the task back on the list t->next = sc->gfxListHead; sc->gfxListHead = t; @@ -433,7 +433,7 @@ void __scHandleRSP(OSSched *sc) state = ((sc->curRSPTask == 0) << 1) | (sc->curRDPTask == 0); if (__scSchedule(sc, &sp, &dp, state) != state) { - __scExec(sc, sp, dp); + __scExec(sc, sp, dp, true); } } } @@ -555,7 +555,6 @@ void __scHandleRDP(OSSched *sc) schedConsiderScreenshot(); } - profileSetMarker(PROFILE_RDP_END); osDpGetCounters(g_SchedDpCounters); t = sc->curRDPTask; @@ -567,7 +566,7 @@ void __scHandleRDP(OSSched *sc) state = ((sc->curRSPTask == 0) << 1) | (sc->curRDPTask == 0); if (__scSchedule(sc, &sp, &dp, state) != state) { - __scExec(sc, sp, dp); + __scExec(sc, sp, dp, false); } } } @@ -603,6 +602,12 @@ extern u8 g_LvAntialias; */ s32 __scTaskComplete(OSSched *sc, OSScTask *t) { + if (t->list.t.type == M_AUDTASK) { + profileHandleRspEvent(RSPEVENT_AUD_FINISH); + } else { + profileHandleRspEvent(RSPEVENT_GFX_FINISH); + } + if ((t->state & OS_SC_RCP_MASK) == 0) { if (t->list.t.type == 1 && (t->flags & OS_SC_SWAPBUFFER) @@ -693,7 +698,7 @@ void __scAppendList(OSSched *sc, OSScTask *t) t->state = t->flags & OS_SC_RCP_MASK; } -void __scExec(OSSched *sc, OSScTask *sp, OSScTask *dp) +void __scExec(OSSched *sc, OSScTask *sp, OSScTask *dp, s32 resuming) { if (sp) { if (sp->list.t.type == M_AUDTASK) { @@ -704,11 +709,16 @@ void __scExec(OSSched *sc, OSScTask *sp, OSScTask *dp) osDpSetStatus(DPC_STATUS_CMD_BUSY | DPC_STATUS_CBUF_READY | DPC_STATUS_DMA_BUSY | DPC_STATUS_END_VALID); } - if (sp->list.t.type == M_AUDTASK) { - profileSetMarker(PROFILE_RSP_START); + if (resuming) { + if (sp->list.t.type != M_AUDTASK) { + profileHandleRspEvent(RSPEVENT_GFX_RESUME); + } } else { - profileSetMarker(PROFILE_RDP_START1); - profileSetMarker(PROFILE_RDP_START2); + if (sp->list.t.type == M_AUDTASK) { + profileHandleRspEvent(RSPEVENT_AUD_START); + } else { + profileHandleRspEvent(RSPEVENT_GFX_START); + } } sp->state &= ~(OS_SC_YIELD | OS_SC_YIELDED);