mirror of
https://github.com/HackerN64/HackerOoT.git
synced 2026-01-21 10:37:37 -08:00
102 lines
3.4 KiB
C
102 lines
3.4 KiB
C
#ifndef PROFILER_INLINE_H
|
|
#define PROFILER_INLINE_H
|
|
|
|
#include "profiler.h"
|
|
#include "../variables.h"
|
|
|
|
extern void Profiler_RecordEventWithTime(u8 type, OSTime time);
|
|
extern void Profiler_RecordEvent(u8 type);
|
|
|
|
// These are all inline functions because they're only called once. They would
|
|
// have just been directly included in the calling code, but this approach lets
|
|
// their functionality be separated visually, and lets this get ported to other
|
|
// projects more easily.
|
|
|
|
static inline void Profiler_RSPStart(u32 type, bool isFirstStartOfMainGfxTask){
|
|
OSTime t = osGetTime();
|
|
u8 eventType;
|
|
if(isFirstStartOfMainGfxTask){
|
|
activeProfilerState->traceEndTime = t;
|
|
|
|
{
|
|
u32 prevInt = __osDisableInt();
|
|
// Atomically swap last and active, and reset the important counter.
|
|
ProfilerState* temp = activeProfilerState;
|
|
activeProfilerState = lastProfilerState;
|
|
lastProfilerState = temp;
|
|
activeProfilerState->numEvents = 0;
|
|
__osRestoreInt(prevInt);
|
|
}
|
|
|
|
#if ENABLE_F3DEX3
|
|
activeProfilerState->f3dex3Version = gLoadedF3DEX3Version;
|
|
#endif
|
|
activeProfilerState->traceStartTime = t;
|
|
|
|
osDpSetStatus(DPC_CLR_CLOCK_CTR | DPC_CLR_CMD_CTR | DPC_CLR_PIPE_CTR | DPC_CLR_TMEM_CTR);
|
|
|
|
eventType = PROFILER_EVENT_TYPE_MAINGFXSTART;
|
|
}else if(type == M_AUDTASK){
|
|
eventType = PROFILER_EVENT_TYPE_RSPAUDIOSTART;
|
|
}else if(type == M_GFXTASK){
|
|
eventType = PROFILER_EVENT_TYPE_RSPGFXSTART;
|
|
}else{
|
|
eventType = PROFILER_EVENT_TYPE_RSPOTHERSTART;
|
|
}
|
|
activeProfilerState->lastRSPStartTime = t;
|
|
Profiler_RecordEventWithTime(eventType, t);
|
|
}
|
|
|
|
static inline void Profiler_RSPDone(u32 type){
|
|
u8 eventType;
|
|
if (type == M_AUDTASK) {
|
|
eventType = PROFILER_EVENT_TYPE_RSPAUDIOEND;
|
|
}else if(type == M_GFXTASK){
|
|
eventType = PROFILER_EVENT_TYPE_RSPGFXEND;
|
|
}else{
|
|
eventType = PROFILER_EVENT_TYPE_RSPOTHEREND;
|
|
}
|
|
Profiler_RecordEvent(eventType);
|
|
}
|
|
|
|
static inline void Profiler_RSPDoneNotYield(u32 flags){
|
|
if((flags & OS_SC_NEEDS_RDP)){
|
|
// This is the main graphics task, and it's done with the RSP
|
|
Profiler_RecordEvent(PROFILER_EVENT_TYPE_RSPGFXLASTEND);
|
|
#if ENABLE_F3DEX3
|
|
// Get F3DEX3 perf counters
|
|
F3DEX3YieldDataFooter* footer = (F3DEX3YieldDataFooter*)(
|
|
(u8*)gGfxSPTaskYieldBuffer +
|
|
OS_YIELD_DATA_SIZE - sizeof(F3DEX3YieldDataFooter));
|
|
osInvalDCache(footer, sizeof(F3DEX3YieldDataFooter));
|
|
bcopy(footer, &activeProfilerState->footer, sizeof(F3DEX3YieldDataFooter));
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static inline void Profiler_RDPDone(){
|
|
activeProfilerState->rdpTmemCount = IO_READ(DPC_TMEM_REG);
|
|
activeProfilerState->rdpPipeCount = IO_READ(DPC_PIPEBUSY_REG);
|
|
activeProfilerState->rdpCmdCount = IO_READ(DPC_BUFBUSY_REG);
|
|
activeProfilerState->rdpClockCount = IO_READ(DPC_CLOCK_REG);
|
|
Profiler_RecordEvent(PROFILER_EVENT_TYPE_RDPEND);
|
|
}
|
|
|
|
static inline void Profiler_TaskAllDone(u32 flags){
|
|
if((flags & OS_SC_NEEDS_RDP)){
|
|
Profiler_RecordEvent(PROFILER_EVENT_TYPE_MAINGFXEND);
|
|
}
|
|
}
|
|
|
|
static inline bool Profiler_GfxIsHung(){
|
|
OSTime t = osGetTime();
|
|
return OS_CYCLES_TO_USEC(t - activeProfilerState->lastRSPStartTime) > 1000000
|
|
|| OS_CYCLES_TO_USEC(t - activeProfilerState->traceStartTime) > 1000000;
|
|
}
|
|
|
|
extern void Profiler_Init();
|
|
extern void Profiler_Draw(GraphicsContext* gfxCtx);
|
|
extern void Profiler_Destroy();
|
|
|
|
#endif
|