Files
psxrecomp/runtime/include
Shokunin d22ebac9a4 Host-timed render passes for true in-between frames
psx_mod_render_pass_plan() / psx_mod_render_pass() let a trusted plugin
redraw its game between two logic ticks with the game's own draw code. A
pass is a sandboxed nested guest call:

- time is frozen: cycles are counted (GTE and mult/div deadlines keep
  working) but no device advances, no VBlank or device event fires and no
  interrupt is delivered; GPU linked-list DMA and delayed completions finish
  synchronously (psx_cycles freeze, interrupts, dma);
- stores go straight to RAM/scratchpad, bypassing code-page tracking,
  overlay watch and write traces; MMIO is an allow-list (GP0, GP1 DMA mode /
  info, GPU and OTC DMA, I_STAT/I_MASK) and SPU, CD, timer and other device
  stores are dropped and counted (memory.c);
- afterwards CPU (with the GTE), RAM, scratchpad, I-cache tags, interrupt,
  timer, DMA and GPU registers are restored exactly (render_pass.c, a GPU
  register checkpoint without savestate side effects), with a guest-cycle
  watchdog that rolls a runaway pass back;
- on OpenGL the declared display rect (hr colour + mask stencil, raw mirror,
  native-wide band, CPU VRAM rows) is backed up, drawn, captured and rolled
  back; writes outside it are journaled and restored, or refused.

The presenter keeps two generations of images (the game's own frame plus
one image per pass phase), promotes one when the flip-aware source sees the
display flip to its rect, and shows the newest image at each output
deadline's phase, crossfading across gaps when passes were shed. Presents
that fall due while passes run are made between them. The plan predicts the
output deadlines of the coming frame and sheds passes to fit a host-time
budget learnt from the presenter's idle time (PSX_RENDER_PASS_BUDGET).

PSX_MOD_FRAME_INTERPOLATION_HOLD repeats the newest frame where no pass
image applies, so a pass-driven title never shows anything later than stock.

Default off: nothing runs unless a plugin calls the API, and the plan
refuses in netplay, rollback, rewind, turbo, self-check resimulation, while
suspended (FMV) or without GL flip-aware interpolation. Pass writes are kept
out of frame_fingerprint. Debug: render_pass_stats, render_pass_dump,
PSX_RENDER_PASS_VERIFY=1 (state + VRAM hashes around every pass).

The freeze API lives in the runtime-only psx_cycle_freeze.h. psx_cycles.h is
part of the overlay codegen hash and stays byte-identical, so titles that
never use passes keep their overlay caches and savestates.

Tests: render_pass_plan_test (deadline-exact phases per rate, shedding,
selection), render_pass_freeze_test (10^6 frozen cycles, exact restore,
watchdog), render_pass_guards (sandbox choke points; the codegen-hashed headers stay
free of the pass API).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 21:02:47 -07:00
..
2026-07-29 03:18:10 -04:00
2026-08-07 16:42:43 -04:00
2026-08-03 05:26:37 -04:00
2026-08-07 18:11:35 -04:00
2026-08-03 05:26:37 -04:00
2026-07-31 17:14:35 -04:00
2026-07-31 17:14:35 -04:00
2026-07-29 03:18:10 -04:00
2026-07-31 17:14:35 -04:00
2026-07-29 03:18:10 -04:00
2026-07-29 03:18:10 -04:00
2026-07-29 03:18:10 -04:00