Capture costly compute builds and restore matching recipes after checking
full recipes, driver fingerprints and Vulkan compatibility keys. Add size
and time thresholds, opt-out, atomic persistence and corruption/rejection
fallback.
Remember below-threshold recipes in separate files so competing decisions
cannot overwrite captured binaries. Prefer saved binaries and retry
capture when the time threshold is lowered.
Cover compatibility, fallback, deterministic competing writers and
cross-process capture, restore and corruption.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Before a label, a pending linear or small storage image that shares no page
with another pending or storing image now gets a write-watch read trap
instead of its store. The first access to its pages stores it through the
host-read hook; any other store releases the trap first.
APS5_NO_LABEL_READ_TRAP=1 keeps the store at the label.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The mode is read once, the first time it is needed, and an unset
variable means off. Any other value, including an empty one, throws an
error that names the variable and the value. The variable is added to
the libScePad table of ENVIRONMENT.md. Nothing reads the mode yet, so
no pulse is sent by this commit.
Null buffer descriptors still split modules on unused specialization
fields after buffer presence moved to run time. Learn the first valid
bound fields per slot and use them for absent descriptors, retaining
actual runtime presence and independent bound formats.
Snapshot the learned fields once for result memo keys and materialization
so identical null captures cannot retain a module made before learning.
Cover direct, captured and prepared calls, null stores, and changed formats.
Keep the process-local table and an off switch for main's module selection.
AI-assisted: yes
Culprit-adjacent #12862; failing run 41237240415 (linux agc_driver_frame_replay,
frame_capture_eop, frame_replay_*). The recorder stops with 'less than 4 GiB free
on the capture volume' and writes zero frames when the shared runner disk is
nearly full. APS5_FRAME_CAPTURE_MIN_FREE_BYTES overrides the threshold (default
unchanged); the tests set 0.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
libSceAgcDriver decides per 64 KiB block whether a pending storage image
keeps the CPU's bytes. A window that ran into the next block marked it
CPU-written and dropped the GPU results there (agc_storage_write_back,
agc_idle_publish_wait, array layer and depth plane tests).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A guest thread that writes a large watched range in order takes one
write-watch fault per page. Under Rosetta 2 each fault is a Mach
exception round trip. When the two pages before the faulting one were
written since the last collection, the handler now unprotects up to 32
pages from it that have the same protection and records them as
written. APS5_WRITE_WATCH_FAULT_AHEAD sets the count; 0 or 1 keeps one
page per fault.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Add the row for the mode that shows a notice when a PlayStation Network
dialog opens, with its unset and invalid behaviour. The row is in its own
libSceIme section because the variable is read in that library.
Staging a swept write-only element (#7618) costs a copy-in and a
copy-back per use. In PPSA03912's town that saves GPU time, but in its
main menu the 202 MiB element is faster in place (73 vs 91 ms of GPU
time per frame), so the menu lost about a fifth of its frames.
Decide per element by measurement. The busiest element is probed in
its current mode, the other mode and its current mode again; the other
mode is kept when its frames are faster by more than twice the
standard error. A repeated answer doubles the wait for the next probe
from 20 s up to 160 s, and a jump of the frame GPU time by more than a
quarter (a scene change) probes again at once. The frame GPU time comes
from the whole-batch timestamps, which the first probe turns on.
Resource builds made under the other decision are not reused.
APS5_NO_ADAPTIVE_STAGING=1 stages every eligible element, as before.
The policy is in AdaptiveStaging.hpp, fed by the caller with frame
counts and time; agc_adaptive_staging covers keeping the faster mode,
frame noise, the back-off cap, a scene change and the share threshold.
AI-assisted. Tested by me on my own machine.
The volume, mute and focus state that libSceAudioOut applies and libSceVideoOut changes now lives in libScePad, which both libraries already link, instead of in libSceAudioOut. The tests that compile the state directly and the environment reference follow the file.
The row names the variable, its values (1 shows the controller status
panel for 4 s on a connect, a disconnect or a battery drop to a lower
class; unset or 0 never shows it by itself) and that any other value is
refused, as the environment reference requires for every name the code
reads.
On NVIDIA's proprietary driver, function arrays that live in local memory
and are read under a data-dependent branch return wrong values in
subgroups 1-3 of a mesh workgroup; subgroup 0 is correct. A wave64
geometry program whose relative addressing keeps its VGPRs in the vector
window therefore loses register writes in every wave but the first. In
the clipping geometry program of Sony's PS5 PSP emulator (PPSA07550) the
empty waves never cleared their candidate primitive slots and wrote
degenerate triangles over wave 0's, so the 3D menu drew spikes.
On that driver a mesh program's window now lives in a device-local
storage buffer of 256 workgroup slots of 65536 dwords, claimed through a
per-slot lock and released after the final barrier. The pool is created
before the first draw that uses it records anything, and its header is
zeroed in a batch of its own that is submitted and waited for; the pool
is published only after that wait, and a failure releases it. Direct
register accesses keep one function variable per register; a direct
store also writes the buffer when a buffer read can see it, relative
reads load the buffer, relative writes store only to it, and a direct
read that may follow a relative write loads the buffer and refreshes the
variable. A buffer entry is zeroed only when a buffer read can see it
before a write. APS5_NO_MESH_WINDOW_BUFFER=1 keeps the arrays.