docs: antialiasing_mode, supersample and the post_aa command

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Shokunin
2026-10-07 21:19:40 -07:00
parent 14feec22bf
commit a090a4b83f
2 changed files with 39 additions and 0 deletions
+2
View File
@@ -55,6 +55,7 @@ Columns: **N** = native, **D** = DuckStation oracle.
| `screenshot_wide_hires` | ✓ | | `path`, `base_x` | The displayed band of the native-wide surface at internal resolution (`wide_w×S` by `height×S`). `present_shot` is capped at the window; this checks a widescreen + internal-resolution combination at full size |
| `present_shot` | ✓ | | `path` | PNG of the **composed present surface** — the frame after the backend fits the display buffer to the window, so it carries the presented aspect. ⚠ every other capture resolves the display buffer *before* that fit: on a 508×256 display in a 4:3 window they answer 508×256 while the player sees 640×480. Use this one for anything aspect-shaped (widescreen, letterbox), where a pre-fit buffer would hide the very stage the change touches. Staged and fulfilled on the next present, so the ack means *queued* — poll `present_shot_seq`. Unavailable headless and on the Vulkan backend (its swapchain has no readback hook) |
| `present_shot_seq` | ✓ | | — | Completion counter for `present_shot`, plus `wrote` (1 = that completion produced a PNG). Sample before staging, poll until `seq` moves. Advances on success *and* failure, so the poll always terminates |
| `post_aa` | ✓ | | `mode` (optional: 0 off, 1 fxaa, 2 fxaa_hq) | Read or set post-process anti-aliasing live (`[video] antialiasing_mode`). Replies `mode`, `passes` (filtered presents so far) and `gpu_us`: the mean pass time since the last query when the run has `PSX_POST_AA_TIME=N` (N passes per present between `glFinish` fences, a measurement mode), else 0 |
| `hd_textures` | ✓ | | optional `replacements`, `dump` (0 or 1), `reload` (1) | HD pack root, switches, backend support, replacement count, matched/ready/applied draw counts, and queued dump count. Optional controls update the configured host pack on the emulation thread; no configured root is an error. Reload retains unchanged upload identities. OpenGL displays replacements; software/Vulkan retain original artwork. Pair with `present_shot` for visual evidence and native VRAM probes for architectural data |
| `gl_interp` | ✓ | | — | OpenGL frame-rate presenter ([FRAME_RATE.md](FRAME_RATE.md)): enabled/suspended, host and target Hz, swaps, `source` (`vblank`/`flip`), `flip_period`, `captures` (new source frames) and `duplicates` (VBlanks that re-presented the same frame) |
| `render_pass_stats` | ✓ | | — | Render passes ([RENDER_PASSES.md](RENDER_PASSES.md)): plans, phases wanted/planned (shedding), passes, rollbacks (`nesting_repairs`: watchdog aborts whose skipped frame exits the restore undid), dropped device stores by class, `verify_mismatch` under `PSX_RENDER_PASS_VERIFY=1`, host-time split per pass, smoothed pass cost (`cost_us`; `cost_rewarms`: estimates no pass had run on for a while, measured again), presents made from pass images (`late_presents`: held past the frame's planned end because the next flip was late; `expired`: frames whose images stopped showing after several frame lengths without a flip), pass image textures allocated (`image_textures`, `image_bytes`), `status` (`psx_mod_render_pass_status`: 0 ready, 1 no presenter, 2 backend, 3 disabled, 4 session, 5 fast-forward, 6 busy), `backups_reused` (passes that reused the previous pass's VRAM backup), `spans` / `span_failures` and the last failure `span_fail` (`psx_mod_run_guest_span`: reason, exit PC, `$ra`, PC after a call that did not return) |
@@ -711,6 +712,7 @@ Regenerate with `python tools/gen_tcp_commands.py`; `--check` fails if this bloc
| `phase_hot` | ✓ | | |
| `phase_profile` | ✓ | | ✓ |
| `ping` | ✓ | ✓ | ✓ |
| `post_aa` | ✓ | | |
| `present_image_ring_get` | ✓ | | |
| `present_image_ring_stats` | ✓ | | |
| `present_ring` | ✓ | | |
+37
View File
@@ -604,6 +604,43 @@ the pixels to show it. Native keeps the window exactly as before.
downsamples to the window. It accepts 1 to 32 in both `game.toml` and the
player's `settings.toml`; 1 (the default) is native and unchanged.
### Anti-aliasing (`antialiasing_mode`, `supersample`)
Both are opt-in and change nothing unless set.
```toml
[video]
supersample = 1.5 # 1.0..4.0, default 1.0
antialiasing_mode = "fxaa" # off (default) | fxaa | fxaa_hq
```
`supersample` multiplies the target of a line preset or Match display before
it becomes a scale: Match display on a 1080 px monitor with 2.0 asks for 2160
lines (S = 9) and the present's area resolve brings it back to 1080, which is
ordered-grid SSAA of everything, 2D included. Native and the legacy
`supersampling` factor are left alone. Dynamic resolution takes the result as
its ceiling and steps under it as before. `PSX_SUPERSAMPLE=<factor>` overrides
it for one run.
`antialiasing_mode` filters the composed game image on OpenGL: after the game
quad (4:3, native-wide, Smooth motion and generated frames alike) and before
hold-last capture, the OSD, screenshots and the swap. It reads only output
pixels, so guest VRAM, readbacks, render passes and the Smooth motion sources
are untouched; the bezel and OSD stay sharp; 24-bit FMV frames are not
filtered. `fxaa` is one copy and one full-screen pass (about 0.1 ms at 1080p
on an M4); `fxaa_hq` lowers the contrast threshold and searches further along
long edges. `PSX_AA_MODE=off|fxaa|fxaa_hq` overrides it for one run and the
`post_aa` TCP command switches it live. The older boolean `antialiasing` key is
unrelated: it is the linear present filter the launcher already persists.
Not offered: MSAA. The hi-res surface *is* guest VRAM (texture pages, CLUTs,
VRAM copies, readbacks and the mask stencil all sample or copy it between
draws), so a multisampled target would need a resolve before every one of
those and the mask/semi-transparency rules would have to run per sample; that
is a renderer redesign, not an option. SMAA needs its area/search lookup
textures and three passes; on an image that is already area-resolved from a
higher internal resolution it buys little over FXAA, so it is left for later.
The runtime clamps N per backend:
- Software and Vulkan stop at 4.