mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
2d2f4aebb4
Root cause (proven via the new present ring + gl_coh_ring correlation): flush_cpu_upload() merged all pending CPU->VRAM writes into ONE union bounding box. A frame with two disjoint uploads (sprite column + tile row — routine MMX6 texture streaming) produced a union spanning the display framebuffers, which the flush painted from the STALE CPU VRAM mirror (the FBO is authoritative under GL) — stomping live frames with black for exactly two presents (one per double-buffer parity). Scene-dependence of the uploads made it look config/timing dependent; the software renderer is immune because its CPU array is authoritative. Fix: exact pending-rect list (16 rects; merges only when zero uncovered pixels are added — containment or same-band extension; wrap-aware GP0(A0) transfers split into up to 4 exact rects instead of the old "wrapped: take all" full-VRAM union; overflow -> order-preserving flush-all; pre-context union retained where the CPU array is authoritative). Merge rule verified by a 20k-randomized-rect host test (0 stale / 0 missing painted pixels). Observability (always-on): gl_present_ring records every SwapWindow (path, src/letterbox rects, drained glGetError, wall-ms, backbuffer + blit-source pixel samples) — the instrument that gave the 1:1 black-capture correlation. debug_server_send_fmt now heap-formats responses >64KB (they previously truncated into unparseable JSON, breaking large ring dumps). (debug_server.c also carries the Vulkan screenshot_file sync hunk from the concurrent VK bring-up; see the next commit.) Validated: ~18-min MMX6 GL attract soak, ~1600 window captures across 3+ attract cycles — zero isolated black frames, zero GL errors (pre-fix: 19/40 captures black at the intro). Tomba1 build-gl boots clean; its full attract soak follows. ENHANCEMENTS.md added (framework enhancement ledger, R1 OpenGL / R2 Vulkan state). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>