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.
The variable is read by the log copy in libc; the row gives its kind,
that an empty value counts as unset, the appending behaviour and the
startup error.
The opening paragraph of docs/dev/ENVIRONMENT.md lists the calls through
which the code reads environment names, and so the reads that the
Conventions check holds to a row. It omits _wgetenv with a wide literal.
tools/env_reference.py has recognised that form since 65da8ac106, and the
code reads nine names through it on Windows, among them
ANYPS5_SHADER_CACHE_DIR, ANYPS5_SCREENSHOTS and APS5_DUMP_SUBMITS. The
paragraph now names _wgetenv beside GetEnvironmentVariableW.
AI-assisted: yes
List the controller vibration strength variable in the libScePad table with its default of 100, the paths it covers, the adaptive trigger effects it does not, and the error an invalid value raises.
A set-but-invalid value, including an empty one, a non-finite number, a
number outside -60 to 0 or trailing text, stops the title with an error
naming the variable and the value instead of silently keeping 0 dB. The
gain is parsed once when the AudioOut2 context is created, kept in the
context and passed to the mix loop, so the audio thread never reads the
environment.
The one-read rule is pinned end to end: a play that changes the variable
to a value that would stop the title after the context was created keeps
the parsed fold and never re-reads the environment.
Add APS5_PAD_SPEAKER_FALLBACK_DB for AudioOut2 controller-speaker ports
folded into the main mix when no controller speaker is present. The
default 0 dB keeps the existing unity mix; mute removes the fallback
copy so a title's own main-port copy is heard instead.
cacheDrawStages never admitted a draw an indirect packet runs on the CPU
path, so a title whose draws are mostly DRAW_INDEX_INDIRECT packets with
a patched user word the vertex program reads as a value missed the draw
cache on nearly every lookup whatever its size. On Demon's Souls 97 % of
the draw packets are such draws and the hit rate stayed at 9 % with
APS5_DRAW_CACHE_ENTRIES=32768.
APS5_DRAW_CACHE_INDIRECT admits them. A hit reuses the fragment stage
and skips the first vertex pass; the stage whose user word the record
patches is still re-materialized per record, as the hit path already
provided for.
Tested: agc_driver_draw_cache_reuse_indirect (three DRAW_INDIRECT draws
patching an unfolded user word: one insert and one hit with the knob,
none without), the other draw_cache_reuse, key_miss, register_key and
draw_cache_relocation tests on lavapipe and an RTX 5070 Ti.
A comma-separated list of hex program addresses (optional 0x prefix) now
writes only those programs' requests, so one expensive shader can be
captured without serializing every request a title prepares. Any other
value, such as 1, keeps writing every request. A filtered-out program
returns no name, so diagnostics never point at a file that was not
written, and it stays eligible for a later list.
Co-Authored-By: Claude Opus 5.5 <[email protected]>