From 14feec22bf2efbd755c872071b3c684a2f1e2d21 Mon Sep 17 00:00:00 2001 From: Shokunin <30949000+tetrisgm@users.noreply.github.com> Date: Wed, 7 Oct 2026 21:15:17 -0700 Subject: [PATCH] post_aa debug command: time the pass (PSX_POST_AA_TIME=N) Co-Authored-By: Claude Opus 5.5 --- runtime/include/gpu_gl_renderer.h | 1 + runtime/src/debug_server.c | 5 ++-- runtime/src/gpu_gl_renderer.c | 44 +++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/runtime/include/gpu_gl_renderer.h b/runtime/include/gpu_gl_renderer.h index 2e5e243f..0f978a76 100644 --- a/runtime/include/gpu_gl_renderer.h +++ b/runtime/include/gpu_gl_renderer.h @@ -184,6 +184,7 @@ enum { GL_POST_AA_OFF = 0, GL_POST_AA_FXAA = 1, GL_POST_AA_FXAA_HQ = 2 }; int gl_renderer_set_post_aa(int mode); int gl_renderer_post_aa(void); uint64_t gl_renderer_post_aa_passes(void); +double gl_renderer_post_aa_gpu_us(void); /* debug builds, PSX_POST_AA_TIME=N: mean pass time (us), resets */ /* Clear to black + swap (display-disabled frame). */ void gl_renderer_present_blank(void); diff --git a/runtime/src/debug_server.c b/runtime/src/debug_server.c index 700337d0..97434388 100644 --- a/runtime/src/debug_server.c +++ b/runtime/src/debug_server.c @@ -8563,8 +8563,9 @@ static void handle_post_aa(int id, const char *json) { int mode = json_get_int(json, "mode", -1); if (mode >= 0) (void)gl_renderer_set_post_aa(mode); - send_fmt("{\"id\":%d,\"ok\":true,\"mode\":%d,\"passes\":%llu}", id, - gl_renderer_post_aa(), (unsigned long long)gl_renderer_post_aa_passes()); + send_fmt("{\"id\":%d,\"ok\":true,\"mode\":%d,\"passes\":%llu,\"gpu_us\":%.1f}", id, + gl_renderer_post_aa(), (unsigned long long)gl_renderer_post_aa_passes(), + gl_renderer_post_aa_gpu_us()); } static void handle_frame_perf(int id, const char *json) diff --git a/runtime/src/gpu_gl_renderer.c b/runtime/src/gpu_gl_renderer.c index e7c322ca..ba6b72a9 100644 --- a/runtime/src/gpu_gl_renderer.c +++ b/runtime/src/gpu_gl_renderer.c @@ -1392,6 +1392,16 @@ static GLuint s_paa_prog = 0, s_paa_tex = 0; static int s_paa_tw = 0, s_paa_th = 0, s_paa_failed = 0; static GLint s_paa_uTex = -1, s_paa_uRcp = -1, s_paa_uUvRect = -1, s_paa_uQuality = -1; static uint64_t s_paa_passes = 0; +#ifndef PSX_NO_DEBUG_TOOLS +/* Cost of the pass (debug server post_aa), only with PSX_POST_AA_TIME=N: the + * pass runs N times (1..64; N > 1 re-filters the frame and amortizes the + * fence) bracketed by glFinish and timed on the host clock. That serializes + * the GPU, so it is a measurement mode, never on by default. (Timestamp + * queries read 0 on Apple's GL.) */ +static int s_paa_time = -1; +static double s_paa_gpu_us_sum = 0.0; +static uint64_t s_paa_gpu_n = 0, s_paa_t0 = 0; +#endif static const char *POST_AA_FS = "#version 330\n" @@ -1489,6 +1499,19 @@ static void post_aa_apply(int lx, int ly, int lw, int lh) { } else { glBindTexture(GL_TEXTURE_2D, s_paa_tex); } +#ifndef PSX_NO_DEBUG_TOOLS + if (s_paa_time < 0) { + const char *e = getenv("PSX_POST_AA_TIME"); + s_paa_time = e ? atoi(e) : 0; + if (s_paa_time < 0) s_paa_time = 0; + if (s_paa_time > 64) s_paa_time = 64; + } + if (s_paa_time) { glFinish(); s_paa_t0 = SDL_GetPerformanceCounter(); } + const int reps = s_paa_time > 1 ? s_paa_time : 1; +#else + const int reps = 1; +#endif + for (int r = 0; r < reps; r++) { p_glBindFramebuffer(PSXGL_READ_FRAMEBUFFER, 0); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, lx, ly, lw, lh); p_glBindFramebuffer(PSXGL_FRAMEBUFFER, 0); @@ -1503,10 +1526,31 @@ static void post_aa_apply(int lx, int ly, int lw, int lh) { glDrawArrays(GL_TRIANGLES, 0, 3); p_glBindVertexArray(0); p_glUseProgram(0); + } glBindTexture(GL_TEXTURE_2D, 0); +#ifndef PSX_NO_DEBUG_TOOLS + if (s_paa_time) { + glFinish(); + s_paa_gpu_us_sum += (double)(SDL_GetPerformanceCounter() - s_paa_t0) * 1e6 / + (double)SDL_GetPerformanceFrequency() / (double)reps; + s_paa_gpu_n++; + } +#endif s_paa_passes++; } +/* Mean microseconds per pass since the last call (debug builds with + * PSX_POST_AA_TIME=N; 0 otherwise). Resets the mean. */ +double gl_renderer_post_aa_gpu_us(void) { +#ifndef PSX_NO_DEBUG_TOOLS + double m = s_paa_gpu_n ? s_paa_gpu_us_sum / (double)s_paa_gpu_n : 0.0; + s_paa_gpu_us_sum = 0.0; s_paa_gpu_n = 0; + return m; +#else + return 0.0; +#endif +} + /* Present sampling. u_sharp==0 is the historical behaviour: sample straight at * v_uv, so the texture's own filter (NEAREST or LINEAR) decides everything. *