Commit Graph

1503 Commits

Author SHA1 Message Date
Shokunin 0b8453e770 Queue native-wide mirrors on the full-VRAM surface
Each mirrored batch switched to the wide surface and back, ending two
Metal render passes over the hr (10240x5120 at 10x) and wide surfaces;
cost grew with the allocation, so dynamic resolution's down steps did not
lower it. Mirrors now ride the windowed mode's queue (one pass per wide
surface, at the same sync points: uploads, pack, clears, stencil
rebuilds, render-pass copies, presents and dumps). GL_LINES mirrors (1x)
flush it and draw at once. Queue entries carry their scissor and palette
texture.

PSX_GL_WIDE_QUEUE=0 and PSX_GL_WIDE_STENCIL_FULL=1 restore the previous
paths for A/B; gl_scale_invariance_test gains a "wmask" mode (wide mask
stencil, centre splice on/off) and checks native VRAM, frame at S and the
wide surface are identical with either off, for wmask, lines, twin and
the scene at 1x/3x/9x and in the window mode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:25:57 -07:00
Shokunin 39216d1875 Rebuild only the stale part of native-wide mask stencils
At S > 1 every GP0(E6h) mask-check enable after an unchecked opaque draw
rebuilt each native-wide surface's whole stencil from alpha, tiled. At a
10x allocation that is many render passes over 4270x5120 surfaces per
enable; R4 2P VS enables the check several times a frame and spent ~85%
of its emulation thread waiting on Metal command buffers there (16:9 at
10x: 17.7 guest Hz).

Track per wide surface the rect where the stencil may differ from alpha
(unchecked mirror draws by bbox, the centre splice, scale-step rescales,
render-pass restores) and rebuild only that. While the centre is spliced
from hr at every present its stencil is never observed, so the centre
part is left stale and rebuilt only if a mask-checked mirror draw meets it
with the splice off. Native (1x) keeps the whole-surface rebuild.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:25:57 -07:00
Shokunin b15667423b Dynamic resolution: scale guards follow the present wrappers; refuse in windowed mode
gl_internal_scale_guards checks the hr-window handling where it now lives
(present_vram_impl, present_wide_fbo_impl, the float present_target_quad);
dyn_apply refuses outright in the windowed high-resolution mode, which
dyn_eligible already excludes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:25:56 -07:00
Shokunin 3152a44429 Keep one owned GL swap with dynres telemetry 2026-10-07 14:25:56 -07:00
Shokunin e0c6abe5e3 Round-trip dynamic resolution through launcher settings 2026-10-07 14:25:56 -07:00
Shokunin 108962248c Add the opt-in dynamic resolution controller, config and telemetry
A step controller (dynamic_resolution.c) lowers or raises the GL internal scale from frame-time telemetry between a floor and the configured ceiling; off unless a title or the player enables it. Tested by dynamic_resolution_test (synthetic load) and the real-GL gl_scale_invariance_test step modes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:25:56 -07:00
Shokunin c5d945b0e1 Change the GL internal scale at run time (opt-in)
gl_renderer_set_dynamic_resolution(1) keeps the hr surface and the
native-wide surfaces allocated at the scale context init gave them (the
ceiling) and lets the internal scale step to any integer level from 1 to
it while the game runs. A lower level renders into the surfaces'
lower-left VRAM*S corner; every viewport, scissor, pack, copy and capture
already takes the scale at use, so only allocation and the present's
normalised UVs read the allocated size. Off (the default) nothing is
allocated differently and no step can run.

A step runs after a present, never inside a render pass:
- it takes the top-left sample of every native block of the old surface
  (the sample the pack reads) into a 1x image and reseeds the new corner
  from it, so the guest-visible VRAM is unchanged byte for byte;
- it rescales the displayed rect and the draw area from their old pixels,
  so neither the frame on screen nor the one being drawn shows 1x blocks;
- it rescales the native-wide margins in place, in row bands ordered so
  no source row is overwritten before it is read;
- it marks the mask stencil stale (rebuilt at once while mask checking is
  on) and drops the render-pass backup and images.

Reallocating per step instead measured 30-106 ms at 7x-10x on an Apple
M4, mostly the first touch of the new surface. Steps are not offered in
the windowed high-resolution mode or with dual raster.

gl_scale_invariance_test gains "steps" runs: rendering after a step into
a ceiling-sized surface equals the fixed-scale run at that level; a chain
of steps (9x down to 1x and back, 5x) leaves the native VRAM unchanged at
every step, the two rects and the wide margins exact nearest rescales of
their old pixels, everything else the old top-left samples, and mask
checking right after a step correct; the window mode refuses steps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:25:56 -07:00
Matthew Stanley ed398cc37e Improve DuckStation texture capture and replacement fidelity 2026-10-07 13:40:57 -07:00
Matthew Stanley 62d5277174 Add guarded screen-space and tiled-strip widescreen tags 2026-10-07 12:06:57 -07:00
Matthew Stanley 3a11aea16d Refresh netplay validation against master retaining audited startup cache and local views 2026-10-07 11:59:16 -07:00
Matthew Stanley 9a1bfdcee2 Merge PR 554 for local netplay validation; clear new peer state on rematch 2026-10-07 11:21:55 -07:00
Matthew Stanley 7d0a18ebc6 Integrate netplay pad and own-view stack without dropping current-master behavior
Preserve negotiated content and dual-raster pass gates. Retain both fixture assertion sets and HD-off seams. Regenerate both BIOS with actual native emitter. Fix type-only rollback corrections and exclude extra-pad changes from digital-only promote gates.
2026-10-07 11:06:57 -07:00
Matthew Stanley dea71f2261 Integrate verified duplicate LOAD guard into current netplay validation bundle 2026-10-07 10:52:06 -07:00
Matthew Stanley 62ee64d0a3 Merge reviewed validated warm startup cache (PR555)
# Conflicts:
#	runtime/src/mod_packages.cpp
#	runtime/src/mod_runtime.cpp
#	runtime/tests/test_mod_runtime.cpp
2026-10-07 10:51:41 -07:00
Matthew Stanley 14001565cf Merge reviewed launcher worker capability opt-in (PR553) 2026-10-07 10:49:04 -07:00
Matthew Stanley ee140c9519 Merge reviewed sky scheduler opt-in (PR552) 2026-10-07 10:48:55 -07:00
Matthew Stanley a99ad54763 Merge reviewed host launch timing scopes (PR551)
# Conflicts:
#	runtime/src/mod_runtime.cpp
2026-10-07 10:48:55 -07:00
Matthew Stanley 5549b2d426 Merge reviewed UNC path preservation (PR550) 2026-10-07 10:48:22 -07:00
Matthew Stanley c51f191c0b Merge reviewed render provenance and sky scheduler fix (PR546) 2026-10-07 10:48:15 -07:00
Matthew Stanley c6b089b896 Combine controller stack with validated PGXP fixes and current master; regenerate both BIOS backends 2026-10-07 10:01:37 -07:00
Matthew Stanley d5d9a65889 Integrate current master retaining strict GP0 fixture guards 2026-10-07 09:55:51 -07:00
Matthew Stanley 29a9e8d598 Contain best-effort preload failures and isolate audited cache tests 2026-10-07 09:30:57 -07:00
Matthew Stanley c124f6ba52 Wire warm preboot readiness and cover cache invalidation contracts 2026-10-07 09:25:56 -07:00
Matthew Stanley 0fb60d2617 Keep cached digest reads restricted to audited titles 2026-10-07 09:15:17 -07:00
Matthew Stanley 6e54d0f462 Reuse audited launcher preparation with validated dependency tickets 2026-10-07 09:14:22 -07:00
Shokunin b4a700d7a6 netplay rollback: tip-extend rereplay is deterministic on every seat
A tip-extend made each seat reload some ring snap between load and the new
prefer tick: the initiator one it had just saved mid-frame during the
replay, a follower still short of prefer a pre-episode live snap. Neither
restore is cycle-exact with a straight run, so seats drifted apart (R4
2-peer under load: POST / resim core diverge after FOLLOW rereplays).

- A seat still replaying and not past prefer just continues to the raised
  target: every tick it finished ran on unchanged rows.
- A seat past prefer replays again from the episode load (the pinned
  frame-boundary baseline every seat matched).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 09:02:39 -07:00
Shokunin c37b827e97 netplay rollback: every seat answers the episode handshake
The episode kept one peer-baseline / ready / POST latch, so with three or
four seats the first reply answered for everyone, and the one early
BASELINE stash was overwritten by the next seat's. In R4's 4-peer run with
the host loaded every frame, two guests replayed a light-tip episode and
resumed while the host had not opened it; host and guests then waited on
each other (pcap_freeze / wire_hole) until the stall timeout.

- BASELINE, ready-ACK and POST go through rnet_rb_quorum: the episode moves
  on only when every other occupied seat has answered, and a digest from
  any seat that differs fails the comparison. Early BASELINEs stash per
  seat. Two seats behave as before.
- Light tip skips the ready RTT only with one peer; with more, every seat's
  ready is how the others know it rolled back to the same load.
- A follower that has not simulated the load tick yet defers and joins when
  it gets there (no NACK, no zombie-load refusal for that join).
- Seal, ready and verify timeouts restart while a seat still owing a reply
  advances its input tip: they fire only when nothing moves.
- psx_netplay_peer_seats(); pins recomp-net rb_quorum.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 08:09:13 -07:00
Shokunin 465f926ecf netplay: confirm against every peer, shed the own view when behind, progress-based stall timeout
Four-peer rollback desynced under load (R4, host behind): the guests
predicted the slow host's pad, hash-confirmed the tick among themselves
through the one shared peer ring, then promoted the host's real pad into
history only (hc-silent promote) while the host simulated it. The host
stayed forked; its recovery episode was then refused as a "zombie load"
behind the guests' (wrongly) agreed tip.

- Hash confirm is a quorum over every occupied peer seat
  (rnet_hc_set_peer_mask / note_peer_from, recomp-net) for three or more
  seats; two seats keep the one-peer chain.
- A peer more than 4 ticks behind the others' inputs sheds its own view
  (psx_mod_render_local_view status FAST_FORWARD, held 60 ticks), so the
  presentation-only pass goes before the simulation slips.
  PSX_NET_LOCAL_VIEW_SHED=0 keeps it.
- The admit-stall watchdog counts time without progress: a remote input tip
  that advances restarts it, so a slow peer is waited for.
  PSX_NET_ADMIT_STALL_MS (20000) and PSX_NET_LIVENESS_MS (1500) configure it.
- Pins recomp-net fix/rollback-span-stall.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 06:59:03 -07:00
Matthew Stanley 72622466f8 Allow audited titles to opt into worker-safe launcher preparation 2026-10-06 23:32:26 -07:00
Matthew Stanley bceadc6124 Add DuckStation-compatible texture pack mod and gameplay dumping
Load modern texpage/texupload PNG replacements independently of DuckStation source. Integrate pack folders and options with mods, preserve native VRAM, and validate GL rendering, format matching, dump safety, and upload invalidation.
2026-10-06 23:24:47 -07:00
Matthew Stanley e4b6ddc99a Require measured host credit before admitting render replay 2026-10-06 23:03:48 -07:00
Matthew Stanley 8ba237ccf5 Retain host launch and mod commit stage timings for TCP diagnostics 2026-10-06 22:46:05 -07:00
Matthew Stanley 6e154bcf03 Preserve Windows UNC roots when persisting launcher paths
Use native path spelling for settings and BIOS/disc sidecars. Add save/reopen regressions for UNC selections.

Beads: beads-eio.3.286
2026-10-06 21:52:36 -07:00
Shokunin 5f72282fa5 Merge remote-tracking branch 'origin/feat/title-rewind-block' into feat/netplay-input-transform
# Conflicts:
#	generated/OpenBIOS.emitter.sha
#	runtime/src/debug_server.c
2026-10-06 19:37:46 -07:00
Shokunin 6f62f560bf netplay: input transforms stay per player online; rollback rows carry rx/ry
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:37:35 -07:00
Shokunin 12c5512218 Merge remote-tracking branch 'origin/feat/pad-transform-stage' into feat/netplay-input-transform 2026-10-06 19:35:45 -07:00
Matthew Stanley d66401751e Integrate controller input stack for review with current command index and both BIOS backends 2026-10-06 19:21:51 -07:00
Matthew Stanley 8f126c595b Integrate PR 513 retaining current COP2 hooks and regenerate both BIOS backends 2026-10-06 19:13:37 -07:00
Matthew Stanley 85d4888352 Merge commit 'refs/review/20261006/pr506' into review/pr502-wave-20261006 2026-10-06 19:04:48 -07:00
Matthew Stanley 58ccacc228 Restore GPU presentation provenance after render passes 2026-10-06 18:34:39 -07:00
Shokunin 33b842e97f netplay: per-player own-view mods, widescreen only inside the local view
A [[plugin]] may declare netplay = "local_view": it only changes what one
player sees. A netplay session now keeps the player's own features whose every
contribution is such a plugin (no writes, overlays or derived discs) instead of
clearing them, without saving state.toml. They activate as usual, but their
hooks run only inside psx_mod_render_local_view (psx_mod_local_view_scope) and
their vblank/savestate callbacks not at all. With such a plan the widescreen
cull margin is the stock 0 in the shared game and this peer's own margin only
inside the sandboxed own-view draw; squash is not used. The canonical frame,
snapshots and digests stay identical on every peer whatever each player chose,
so nothing is negotiated, and each keeps their own aspect.

Tests: netplay_view_mods_test (flag, plan filter, parked hooks, no vblank,
state.toml untouched), ws_local_view_margin_test (margin scope), render-pass
sandbox asserts the scope around a local view.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 14:17:26 -07:00
Matt Stanley 7b2539415a Merge pull request #544 from RetroPortingToolKit/fix/ape-pgxp-terrain-seams
PGXP: carry precision through GTE-as-multiplier arithmetic and unaligned word copies
2026-10-06 14:01:53 -07:00
Matthew Stanley f9c7bb0a1c PGXP: carry precision through GTE-as-multiplier arithmetic and lwl/lwr word copies
Fixes Ape Escape terrain seams: CPU-built subdivision midpoints and lwl/lwr-copied
grid corners drew native next to precise neighbours. Adds pgxp_tri_ring/pgxp_store_ring.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-06 13:35:43 -07:00
Matthew Stanley 458e6ece8d Skip the wide centre copy in render-pass captures while a camera view is active
pass_capture_into copied the unshifted canonical frame over an anchored wide
surface: interpolated frames showed stale margins and a displaced, flickering centre.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-06 12:53:03 -07:00
Matthew Stanley afc9d87367 Restore the GL readback fixture build; reject short capture pitch
The fixture no longer compiled (poisoned s_scale, duplicate psx_cycle_count),
and gl_renderer_capture_display_hires fell back to a write that ignored pitch.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-06 12:53:02 -07:00
Shokunin f379771c93 netplay: let a title present its own sandboxed local view
psx_mod_render_local_view() runs a title's draw code in the render-pass
sandbox on a forward netplay frame and keeps the drawn display rect in the
OpenGL presenter's surface only. The authoritative CPU VRAM, guest RAM,
rollback snapshots and digests keep the canonical frame; the presenter shows
this peer's own image. A committed image cancels any local-view crop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 11:24:17 -07:00
Matt Stanley d95eed86c2 Merge pull request #541 from RetroPortingToolKit/feat/mod-uncharged-guest-call
Add uncharged guest calls: run a guest function in zero guest time
2026-10-06 11:13:08 -07:00
Matthew Stanley 49fe052a3e Add uncharged guest calls: run a guest function in zero guest time
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-06 09:53:08 -07:00
Shokunin c4215396e3 netplay: present a title-chosen local view for each peer
A title whose netplay mode draws every seat's view into one frame (so all
peers keep identical guest state) can now ask the present path to show only
this peer's rectangle of the display: psx_netplay_present_local_view(x, y,
w, h), usually picked from psx_netplay_local_slot(). The GL dual-raster
present shows it from the internal-resolution surface, the software present
crops its staged frame, both at 4:3, and the headless present-image ring
records the same rectangle. The request is host-only (never serialized or
guest-visible), lapses PSX_NETPLAY_LOCAL_VIEW_HOLD ticks after its last
renewal so menus fall back to the full frame, survives rollback replays
without moving its stamp backwards, and is ignored offline. It wins over
[netplay] local_viewport.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 01:05:14 -07:00
Shokunin 3654593e16 Add a rewind_status debug command
Reports whether local Rewind is enabled and open, the title block
(psx_mod_set_rewind_blocked) and the snapshots held, so scripted headless runs
can check that a blocked title captures no history and refuses to open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 23:49:55 -07:00