API Design

/* Profiler zones — named time spans measured per frame. */

#define SH_PROF_MAX_ZONES 32

typedef struct {
    const char *name;
    uint64_t    start_ns;
    uint64_t    total_ns;       /* Accumulated this frame */
    uint64_t    worst_ns;       /* Worst single measurement this frame */
    uint32_t    call_count;     /* Times entered this frame */
} sh_prof_zone_t;

typedef struct {
    sh_prof_zone_t  zones[SH_PROF_MAX_ZONES];
    int             zone_count;

    /* Per-frame totals */
    uint64_t        frame_start_ns;
    uint64_t        frame_total_ns;
    uint32_t        frame_count;

    /* Rolling averages (last 60 frames) */
    uint64_t        frame_times[60];
    int             frame_idx;

    /* Hardware counters (optional, uses PRFC1 since PRFC0 = timer) */
    perf_cntr_event_t hw_event;
    uint64_t        hw_count_this_frame;

    /* Output */
    int             enabled;
    int             overlay_enabled;    /* Draw on-screen stats */
} sh_profiler_t;


/* Initialize profiler. hw_event = what to count on PRFC1 (or PMCR_INIT_NO_MODE to skip). */
void sh_prof_init(sh_profiler_t *prof, perf_cntr_event_t hw_event);

/* Call at frame start. */
void sh_prof_frame_begin(sh_profiler_t *prof);

/* Call at frame end. Records frame time, advances rolling average. */
void sh_prof_frame_end(sh_profiler_t *prof);

/* Register a named zone (call once at init). Returns zone index. */
int sh_prof_zone_register(sh_profiler_t *prof, const char *name);

/* Enter a zone. */
void sh_prof_zone_begin(sh_profiler_t *prof, int zone_idx);

/* Exit a zone. */
void sh_prof_zone_end(sh_profiler_t *prof, int zone_idx);

/* Scoped zone helper (GCC cleanup attribute). */
#define SH_PROF_ZONE(prof, idx) \
    int _sh_prof_zone_##idx __attribute__((cleanup(_sh_prof_zone_cleanup))) = idx; \
    sh_prof_zone_begin(prof, idx); \
    (void)_sh_prof_zone_##idx

/* Get average frame time in microseconds (last 60 frames). */
float sh_prof_avg_frame_us(const sh_profiler_t *prof);

/* Get FPS (based on rolling average). */
float sh_prof_fps(const sh_profiler_t *prof);

/* Get a zone's last-frame time in microseconds. */
float sh_prof_zone_us(const sh_profiler_t *prof, int zone_idx);

/* Print all zones to dcload console. */
void sh_prof_print(const sh_profiler_t *prof);

/* Dump full report to file (via dcload /pc/ path). */
void sh_prof_dump(const sh_profiler_t *prof, const char *path);

/* Enable/disable overlay (renders to PVR2 as text overlay). */
void sh_prof_overlay(sh_profiler_t *prof, int enabled);


/* --- Common Zone Indices (convention) --- */
#define SH_ZONE_UPDATE      0
#define SH_ZONE_TRANSFORM   1
#define SH_ZONE_SUBMIT      2
#define SH_ZONE_RENDER      3
#define SH_ZONE_AUDIO       4
#define SH_ZONE_DISC_IO     5
#define SH_ZONE_AI          6
#define SH_ZONE_PHYSICS     7