mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
2e4badfc3f
The OSD query at the two present-skip sites now goes through ov_needs_present(), which falls through to host_osd_needs_present() unless the render thread is replaying a present with its recorded overlay state. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
48 lines
2.3 KiB
Python
48 lines
2.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Every GL present-skip site must be gated on the vsync-cadence query.
|
|
|
|
The renderer may elide a swap whose front buffer is unchanged. The frontend
|
|
calls present once per guest vblank, so eliding a swap also elides whatever
|
|
that swap was blocking on. When driver vsync owns the guest cadence the
|
|
wall-clock pacer is deliberately not run (they are XOR), which makes the swap
|
|
block the ONLY throttle -- and an elided frame is then unthrottled. A game that
|
|
presents every other vblank (BoF3, and any other 30 Hz-presenting title) ran at
|
|
exactly 2x on a ~60 Hz panel until each skip site consulted this query.
|
|
"""
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
RENDERER = (ROOT / "runtime" / "src" / "gpu_gl_renderer.c").read_text(
|
|
encoding="utf-8"
|
|
)
|
|
MAIN = (ROOT / "runtime" / "src" / "main.cpp").read_text(encoding="utf-8")
|
|
PACING = (ROOT / "runtime" / "include" / "frame_pacing.h").read_text(
|
|
encoding="utf-8"
|
|
)
|
|
|
|
# The skip sites are the branches that increment the probe skip counter and
|
|
# return without reaching SDL_GL_SwapWindow. Both consult the OSD, the
|
|
# interpolation-cadence owner, and the vsync-cadence owner.
|
|
skips = RENDERER.count("s_probe_skip++;")
|
|
assert skips >= 2, "expected the VRAM and wide-FBO present-skip sites"
|
|
assert RENDERER.count("!psx_present_vsync_owns_cadence() &&") == skips, (
|
|
"every present-skip site must be gated on psx_present_vsync_owns_cadence(); "
|
|
"an ungated skip lets the guest free-run when driver vsync owns cadence"
|
|
)
|
|
# The OSD query goes through ov_needs_present(), which is host_osd_needs_present()
|
|
# except when the render thread replays a present recorded with its own copy
|
|
# of the overlay state (docs/RENDER_THREAD.md).
|
|
assert RENDERER.count("!ov_needs_present() &&") == skips
|
|
assert ": host_osd_needs_present();" in RENDERER
|
|
assert RENDERER.count("!gl_renderer_interpolation_owns_cadence()) {") == skips
|
|
|
|
# The query is declared beside the pacer it is the XOR partner of, and defined
|
|
# in the frontend that owns the cadence decision.
|
|
assert "int psx_present_vsync_owns_cadence(void);" in PACING
|
|
assert 'extern "C" int psx_present_vsync_owns_cadence(void) {' in MAIN
|
|
assert "return present_vsync_owns_cadence();" in MAIN
|
|
|
|
print("present-skip cadence guard passed (%d skip sites gated)" % skips)
|