Commit Graph

15 Commits

Author SHA1 Message Date
Matthew Stanley cf2bdbb6fc gte: fov_scale uses scaled H in PGXP clipper, keeps H=0, off in netplay; RTP ring keeps canonical H
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-04 10:55:58 -07:00
Matthew Stanley b6a659ca4a Merge origin/master into review/pr494-fix
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-04 10:43:41 -07:00
Matthew Stanley cd9981cda8 Clip proven native-wide world faces across camera and screen planes 2026-10-03 23:51:14 -07:00
Matthew Stanley d2c8f03e76 Add guarded native draw replay, motion interpolation and stable world filtering 2026-10-03 23:46:25 -07:00
Yves 2ad2725548 gte: add opt-in projection-distance scaling
Adapted from the original feature commits, retaining their author credit:
[82695b75](https://github.com/FractalEngineer/psxrecomp/commit/82695b75d79610ca7a99783adf9dd5195edfcdd0)
[5633e868](https://github.com/FractalEngineer/psxrecomp/commit/5633e86878611a14d3a78e8f9708452a07bc7238)
[bbd01ccf](https://github.com/FractalEngineer/psxrecomp/commit/bbd01ccfc91c1d9ebe199dad071df64e5b13d06d)
[39d478db](https://github.com/FractalEngineer/psxrecomp/commit/39d478db83132815c2c8c593fc719c4bf67301b0)

Source scope and current-master validation: docs/internal/upstream/gte-projection-distance-scale.md

Co-authored-by: Yves <calibratedbeats@gmail.com>
2026-10-04 05:54:03 +08:00
Matthew Stanley 6674024285 Merge master into feat/medievil-native-wide-guards
Reconciled with #470 (PGXP): gpu.c precise vertices take PGXP only under geometry correction and count it, then native-wide edge recovery; the PGXP triangle stat stays PGXP-only. Stubs and tests from both kept; stamps recomputed.
2026-10-02 20:00:23 -07:00
Matthew Stanley 1ed0dfd22d Recover saturated winding at guarded native-wide rendering branches 2026-10-02 16:47:59 -07:00
Shokunin 8630d3a6f8 PGXP: precise culling as a mod option; the mod as a title's one switch
With every drawn vertex precise, a title can still show cracks where the game
culled a face on its integer winding. R4's road emitter runs NCLIP on each
far row and skips rows whose native height rounds to 0. Natively their
neighbours meet at the same integer y. With PGXP they sit at their exact y,
and the skipped row becomes a strip of sky across the road beyond the start
gantry, at 4K and in 2P. tri_mixed cannot see this: the missing face draws
no triangle.

Precise culling (DuckStation's "PGXP culling", minimal footprint):
- While geometry correction is armed, gte_nclip computes the exact
  determinant of the three SXY register shadows (pgxp_gte_nclip_precise:
  live, current words, the GPU's own truncation agreement and tolerance).
  When its sign is nonzero and differs from the integer MAC0's, MAC0 takes
  that sign, with the rounded exact doubled area (at least 1) as magnitude.
  FLAG keeps the integer overflow bits.
- It changes guest-visible MAC0, so it is a `culling` option of
  psx.enhancement.pgxp, false in the builtin, with no [video] key, so netplay
  (which clears every mod) never runs it. It needs geometry correction.
  It is held off in every pass compared against another execution: the
  speculative and replay passes, and the whole overlay shadow diff
  (psx_overlay_shadow_diff_active), interpreter pass included.
- Counters whenever geometry correction is armed: nclip_precise,
  nclip_disagree (exact sign differs: the culled-face crack exposure),
  nclip_corrected. TCP pgxp {"culling":0|1}; env PSX_PGXP_CULLING.

Session arming in one place (src/pgxp_session.cpp, psx_pgxp_session_arm):
main.cpp's renderer setup now calls the same code the test drives. The arming
takes the mod request (reads and clears it), so a session with an empty plan
cannot inherit an earlier session's request even if the reset were skipped.
pgxp_session_test now links the real mod runtime, the builtin plugin and the
builtin manifest, and covers:
- a default-on override;
- a netplay clear, with and without the reset;
- the off switch;
- the options;
- env overrides;
- pgxp_mod_only.

[video] pgxp_mod_only (game.toml, default false): for a title that ships
PGXP through the mod, the mod is the one switch. The [video]
geometry_correction / perspective_texturing / pgxp_cpu_mode values are not
applied, from game.toml or the player's settings.toml. The launcher also
hides its Perspective textures row (has_geometry_precision = 0). That row
showed "off" while a default-on mod corrected textures, and it could keep
texture correction on after the player switched the mod off.

geom_correction also reports texture_correction and the culling switch.

R4, Helter Skelter: 28.7% of NCLIPs disagree in sign. With culling, the
ladder is gone in same-frame 4K captures (1P straight and crest, 2P VS), and
the game emits about 24% more triangles. Its packet buffers peak at 60%.
fp_identity over 12000 frames: stock, PGXP off, and PGXP on with culling off
are IDENTICAL; with culling on, the RAM writes differ from the attract race
on, while cyc/mmio/mc agree throughout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 06:02:52 -07:00
Shokunin dd867215af PGXP: dataflow-only geometry and preserve-projection precision
Two opt-in [video] keys for titles whose build carries the PGXP hooks, both
live-tunable through the TCP pgxp verb. Defaults keep today's behaviour.

pgxp_position_fallback (default true). false skips the position-cache tier
in pgxp_get_precise_vertex and stops gte.cpp filling it. At hook-build
coverage the cache only hands unrelated 3D fractions to CPU-built 2D
polygons (a HUD needle, menus). Beetle and DuckStation leave their vertex
cache off by default.

pgxp_preserve_projection (default false). true makes RTPS/RTPT shadow the
exact projection, from the unshifted MACs and a true divide
(pgxp_project_precise), instead of the GTE's integer-IR one. That removes
the residual wobble of near geometry. Guest SXY, MAC0 and FLAG are
untouched. Only sf=1 vertices with no IR, SZ3 or divide saturation qualify,
and the rest keep the IR path. The exact position can sit a little below the
guest integer or more than a pixel above it, so truncation agreement becomes
the window -4 < precise - native < 5 px, a sanity bound over the IR path's
own error (on R4 every on-screen vertex falls within -1.9 .. +2.6 px). A
packet half at or beyond the GTE saturation limit must still agree exactly.
The tolerance clamp now measures the offset both ways. [widescreen]
precise_nclip reads the same shadows, so in a title that sets both, its
branch sign follows the exact projection too.

Observability: geom_correction reports both switches, ppp_produced, and
geometry-corrected triangles split into all-precise, mixed and native. The
mixed share is the mesh-cracking exposure of G1.1.

Tests: pgxp_test (fallback off, window edges, saturation, two-sided
tolerance, the exact projection and its qualifiers, triangle census);
gte_register_access_test (RTPS/RTPT guest state equals the oracle with the
mode on, and the shadow is the exact projection); video settings test
(defaults, parsing, type check). gpu_gp0_history_guard_test's gpu.c stubs
gain pgxp_note_triangle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 04:24:54 -07:00
Matthew Stanley c564ccd1f1 runtime: route every RAM consumer through one live 2/8 MiB geometry
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 06:31:33 -07:00
Pegasus 5e23de8393 feat: add PS1 conformance harness and fix GTE fidelity
(cherry picked from commit 98d617b5f3)
2026-09-14 17:26:31 +03:00
tetrisgm 5afe95b158 runtime: add title-scoped exact NCLIP branches
(cherry picked from commit 81ebee1346)
2026-08-27 20:44:13 -07:00
Matthew Stanley 2ba74f3b4b pgxp: land clean-room value-propagation engine (phases 0+1, issue #92)
The G1.2/G1.3 mechanism: per-word RAM/scratchpad + per-GPR + per-GTE-reg
shadows carrying sub-pixel projections BY PROVENANCE, validated against
the actual guest word on every read (never guessed from rounded position
- the measured 93.1%-ambiguous G1.4 dead end). Clean-room from psx-spx +
public design docs; vendored duckstation (CC BY-NC-ND) and beetle-psx
(GPL) trees remain black-box oracles only - no code ported.

- runtime/src/pgxp.cpp + pgxp.h: engine, per-vertex GetPreciseVertex
  (dataflow -> ambiguity-gated position cache -> native) with truncation
  agreement + tolerance safeguards; stats; test accessors.
- pgxp_hooks.h: 5-entry hook funnel; PGXP_*() macros no-op unless
  -DPSX_PGXP=1 (codegen-time gate over ONE generated tree); appended
  PGXPHooks* table member in OverlayCallbacks (ABI bump ships with the
  Phase-2 emitter change).
- Both interpreters wired: loads/stores/COP2 + precision-carrying
  arithmetic (moves, add/sub, or-merge, 16-bit shifts, LUI, HI/LO).
- gte.cpp: RTPS feeds the GTE reg shadows; retired s_precise_sxy FIFO,
  hashed s_precision_store, and plain-store invalidation (redundant
  under validate-on-read; store hot path gets 3 calls back).
- gpu.c: prepare_precise_triangle rewritten per-vertex; perspective UVs
  share the same provenance and compose per triangle.
- [video] pgxp_cpu_mode / pgxp_tolerance keys; TCP pgxp verb live-
  toggles geometry/texture/cpu_mode/tolerance; geom_correction census
  grew the pgxp dataflow counters (G1.9 gate metric).
- tests: new pgxp_test (registered); gte_register_access_test updated
  to precise invalidation contract. 33/33 enabled tests green.

Also fixed while landing (both broke a fresh master tree):
- runtime.cmake: once-only psx_game_version.txt stamp (multi-target
  file(GENERATE) collision broke every fresh single-config configure).
- test_overlay_capture_retry: SDL3 rot (SDL_SetMainReady gone, inverted
  SDL_Init check) -> psx_sdl_init.

Tracked as beads-eio.3.48; postmortem + this landing: ENHANCEMENTS.md
G1-G1.10.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-15 18:34:47 -07:00
Matthew Stanley d13bade9ae Speed up exact GTE command marshaling 2026-07-19 14:44:22 -07:00
Matthew Stanley 05f6ef3e02 Optimize GTE fallback and isolate interpreter perf runs 2026-07-19 14:23:36 -07:00