Files
NX2navi/runtime/stutter_map.h
chrg6 a473e763b2 Tie the stutter map's cause count to perf.c's at compile time, and rewrap the comment that lists the causes.
The review of d84aa5fb and c05e6528 found that nothing at compile time tied perf.c FT_C_N to stutter_map.c SM_CAUSES:
they sit in different translation units, perf.c ft_frame passes stutter_frame n = FT_C_N, and the areas' by_cause
counts and cause_short are indexed against SM_CAUSES, so a cause added on one side only would mislabel the map without
an error (tests/stutter_hitch_check.c checks only its own names[]). stutter_map.h now defines STUTTER_CAUSES,
stutter_map.c sizes SM_CAUSES from it, and perf.c asserts FT_C_N == STUTTER_CAUSES beside the FT_C_* list. With
STUTTER_CAUSES set to 11 the assertion stops perf.c's compile.

The review also found that the header comment line of stutter_map.c listing the causes ran to 142 columns, where the
file wraps at 120; the paragraph is rewrapped without a change of words.

No change to what runs. perf.c, stutter_map.c and the other files that include stutter_map.h (romfs.c, vk_exec_draw.c,
vk_pipeline.c) compile with the dev flags, perf.c and stutter_map.c add no -Wall -Wextra warnings, and
stutter_hitch_check and stutter_map_check pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 18:41:39 -05:00

31 lines
2.2 KiB
C

// The stutter map (NX2NAVI_STUTTER_MAP=1, stutter_map.c): for a play session, which frames hitched, in which area, what
// the frame waited for, and which pipelines and shaders draws met missing, so the next pipeline list and shader
// preparation can take them in.
#pragma once
#include <stdint.h>
extern int stutter_map_on; // set once at start (stutter_map_init); every hook below returns at once while it is 0
void stutter_map_init(void);
// An area's load (perf.c perf_scene, from romfs.c): hitches from here on are counted in that area, and those within
// SM_LOAD_NS of the load apart from play.
void stutter_area(const char *name);
// The texture pool began or ended making an area's textures (vk_exec_draw.c pool_loading): frames within SM_LOAD_NS of
// it count as an area load's too, in the area of the last stutter_area.
void stutter_load(void);
// A draw met its pipeline (shader 0) or one of its shaders (shader 1) missing and the replay thread spent ns on it
// before it was bound or skipped (vk_exec_draw.c, beside wait_note). vi, fi: the vertex (or mesh) and fragment shaders'
// input ids, NULL when not known (still translating, or no fragment stage).
void stutter_miss(int shader, int mesh, const uint8_t *vi, const uint8_t *fi, uint64_t ns, int skipped);
// A pipeline a draw missed became usable ms after the miss (vk_pipeline.c ready_note): recorded 1 when pipeline-keys.bin
// (or the seed list) named it, fresh 1 when one of its shaders was translated in this session (not prepared).
void stutter_ready(int mesh, const uint8_t *vi, const uint8_t *fi, double ms, int recorded, int fresh, int fast);
// Every present (perf.c ft_frame): d the frame's interval, part the time it went to by cause (names[i], n of them;
// the last one is the part nothing recorded explains), cause the one the frame is charged to.
// STUTTER_CAUSES: the number of causes, perf.c's FT_C_N (perf.c asserts it), which stutter_map.c cause_short and the
// areas' counts are sized by; n is that many.
#define STUTTER_CAUSES 10
void stutter_frame(uint64_t frame, uint64_t now, uint64_t d, const uint64_t *part, const char *const *names, int n,
int cause);
void stutter_report(const char *tag); // the map so far; every 5 minutes of play, at a focus loss in play and at exit