On a new knote EV_FORCEONESHOT is dropped from the flags; on an
existing one it sets EV_ONESHOT and fires the knote, as
kqueue_register does at l.1339-1341. A modify no longer ORs
EV_ONESHOT, EV_CLEAR or EV_DISPATCH into the knote.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
A knote registered or modified with EV_DISABLE stays registered but is
not polled, fired or reported until an EV_ENABLE change re-arms it, as
kern_event.c does with KN_DISABLED. EV_DISPATCH reports an event once
and then disables the knote, and EV_FORCEONESHOT registers as oneshot.
A negative nevents fails with EINVAL instead of throwing.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Account id 0 or a null output returns SCE_NP_ERROR_INVALID_ARGUMENT;
otherwise the always signed-out NP returns SCE_NP_ERROR_SIGNED_OUT, as
sceNpGetAccountIdA does. PPSA14632 imports it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
With the GS traps in WindowsTlsBuilder::Build, GCC 15.2 inlines this
vector insert differently and reports eight -Wstringop-overflow false
positives at it. resize appends the same four zero bytes and builds without
them.
LargestDeviceLocalHeap now calls ShaderResources.cpp's private
largestDeviceLocalHeap instead of replacing it, so the file's callers
stay as they are on main and other changes that call the private helper
still build with this one.
For each of the five: the size query, the value, a short buffer (ENOMEM, the copied prefix kept), a new value (EPERM) and a trailing name component (ENOTDIR).
uname reads kern.ostype, kern.hostname, kern.osrelease, kern.version and
hw.machine through sysctl. Super Mario Sunshine (PPSA99312) stopped on the
first, "sysctl_nid_postfix: unsupported MIB 1.1". sysctl now serves the five
as read-only strings: FreeBSD 11.4-RELEASE's values for the type, release and
version, the host name gethostname reports, and amd64. A new value returns
EPERM as for the other read-only names, and a trailing name component returns
ENOTDIR.
Since #5056, sceNetCtlGetInfo throws for every info code it does not
model. Ghost of Yotei (PPSA26344) asks for code 12, the DHCP host name,
during boot and now aborts one second in.
The configuration #5056 reports (wired, DHCP, HTTP proxy off) sets no
DHCP host name, no PPPoE user name and no proxy server, so codes 12, 13
and 20 now return 0 with an empty string. The Wi-Fi codes (5-10) and
the proxy port (21) still throw. GuestNetCtl checks the three empty
answers and keeps the throw check for the rest; the libSceNetCtl debt
line says the same.
agc_shader_memory and agc_shader_bindless: an invalid selected T# is
poisoned with its words without changing the artifact; a key past the
heap selects a null image without reading the heap; an unmapped selected
record is Unmapped poison and is not read; a key loaded from a constant
buffer at an SRT offset selects its record, and one that cannot be read
faults the table instead of throwing; a key loaded from a buffer the
shader writes keeps the whole table; a key chosen per lane keeps the
table; a record past the 65,536-key cap is selected; and a selected
record whose second load carries past 32 bits is OffsetCarry poison while
the record past the wrap is read.
agc_driver_image_table: a dispatch keyed from a constant buffer at an SRT
offset samples three records exactly as their direct bindings do, with
one module and one bound image; samples zeros for a key past the table;
does not fault for an invalid record under a clear EXEC; reports the
invalid record's address, words and reason when it selects it; and faults
when it stores over its selected record.
agc_shader_disk_cache: a selected column round-trips in the hand-built
plan, a fixture plans one and materializes it after a round trip, and a
selection past the sources is rejected.
The relative vector addressing entry still said every window register
lives in one function-scope array. It now describes the array of the
bounded slots, the per-slot variables, the OpSwitch fallback and
APS5_NO_WINDOW_NARROWING, with the RTX 3060 measurement.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Uzy15wqYTt6iWyxYXEzUWo
For an indirect draw, whose counts only the GPU knows, the driver copies
the whole range a vertex buffer descriptor covers, records * stride from
the descriptor's address. The last record's element ends sooner when the
attribute sits at an offset in its record, and the fetch can read at most
(records - 1) * stride plus the element.
Forspoken (PPSA03984) draws instances from a 48 MiB buffer of 96-byte
records with six attributes at offsets 0 to 0x50 in each record. The copy
for the attribute at 0x50 ran 0x50 bytes past the buffer into the
unmapped page after it, and the draw stopped with "guest memory is not
readable".
VertexBufferExtent now ends at the last record's element, as
VertexBufferReadSize does for the last record of a direct draw.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Since registered shaders are prepared in the background (#2583),
PlanRegistered keeps the decoded RDNA program in the
RegisteredPreparation it queues for the preparation pool. Only
PlanRegistered reads it, for the s_swappc_b64 check, so each queued
shader holds its decoded program until a pool worker has prepared it.
During the registration burst of Borderlands 4 (PPSA01494) these
programs held 638 MiB.
Decode into a local again, as before #2583.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
DMA_DATA on queue 0 joins the draw pipeline unless APS5_NO_PIPELINE_DMA is set. A copy that does not overlap uncommitted draws, a SET_PREDICATION, and a NOP other than a dispatch reset leave the queue in place. The source bytes are snapshotted in packet order, an immediate fill still notes depth and color metadata, and a predication that reads an uncommitted range waits for it. Marker push and pop no longer allocate a string per packet.
main's StorageTextureBudget calls largestDeviceLocalHeap, the helper this branch made public as LargestDeviceLocalHeap for the overlay's VRAM line. The merge renames that call, so the merged tree builds.
The [image-table] line under APS5_PROFILE_DRAW now splits the skipped
narrowings by reason: a value key that cannot be evaluated, a key
descriptor that is not a buffer, a key buffer with more positions than
APS5_IMAGE_TABLE_KEY_SCAN (with the most positions seen), pending GPU
writes over the key buffer, and an unmapped key page. Selected records
never narrow, so the line counts them apart.
The pipelined label path treated every nonzero RELEASE_MEM INT_SEL as an end-of-pipe interrupt;
main's PacketMemory excludes 3 (send data after write confirm). agc_driver failed on it with
APS5_PIPELINED_DRAWS=1 ("release with INT_SEL send data after write confirm raised an interrupt").
Co-Authored-By: TheAggie <[email protected]>
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
DrawWriteRanges decoded every written storage image element, and DecodeTextureResource refuses a zero
base address, so a draw with a null storage image bound failed (PPSA01317) instead of skipping it.
The element is now skipped by the binder's own null rule (base address words zero) before it is
decoded. agc_driver_draw_write_ranges binds a null image next to a written one.
Co-Authored-By: Gjon Gojcevic <[email protected]>
Co-Authored-By: SleglJan <[email protected]>
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
With APS5_PIPELINED_DRAWS=1, queue 0's worker decodes, captures and recompiles a draw and hands it to
a committer thread that records it (Graphics::Draw under the GPU lock), so the two run in parallel
instead of one after the other. Work the committer has not reached yet is tracked by the guest ranges
it will write; a later packet that reads or writes them, or one the pipeline cannot order, drains it.
Ordered as commit items instead of drains:
- labels (WRITE_DATA, RELEASE_MEM) and same-queue waits on them; APS5_PIPELINE_DRAIN_LABELS=1 drains;
- the end of a queue-0 submission and a released REWIND tail; APS5_PIPELINE_DRAIN_SUBMISSIONS=1 drains;
- the title's buffer fill kernels; APS5_PIPELINE_DRAIN_FILLS=1 drains;
- DMA_DATA immediates and copies (APS5_PIPELINE_DMA=1).
A draw's write ranges include the storage images it writes and its exact color and depth target
ranges (APS5_EXACT_DRAW_WRITES=1), not estimates.
Draw-path costs the pipeline exposed:
- ShaderMemory moves, so a commit owns its capture's pages;
- a submission made before the worker's current collect epoch began keeps the epoch, so a worker
behind a queue of submissions walks a surface once per catch-up (APS5_SUBMISSION_EPOCH_EACH=1 bumps
at every submission); a thread remembers the ranges it walked for the whole epoch;
- the pipeline signals only threads that wait; the pending-image and unit-shadow registries take a
spinning slim lock instead of std::mutex (winpthreads contention was kernel events); ScanPending skips
the registry walk when no pending image can overlap;
- fewer heap allocations per recorded draw (reused descriptor sets and scratch vectors, buffer pool
size classes kept).
GTA V Performance mode, prologue bank interior, RTX 5080: 11.7 -> about 20 fps together with the cheaper
captures below it.
Off by default here; the follow-up turns it on.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Co-Authored-By: Gjon Gojcevic <[email protected]>
Since #757, a T# loaded from a buffer heap at a runtime offset is an
image table column, and every capture snapshots the whole heap, up to
65,536 records, even when user data or an SRT read fixes the offset.
When the T#'s eight dwords and its offset are runtime values the SRT
walker evaluates, the column is now selected: the offset is kept as a
descriptor source, the shader indexes entry 0, and the snapshot reads
only the record at the evaluated offset, with the heap base moved to
that record.
The column keeps a table's semantics. An invalid T#, an unmapped record
or an offset that carries past 32 bits is poison that faults only when a
lane selects it; an offset the walker cannot read faults the table
instead of throwing; the record's mode is picked per entry, so no
pipeline variant is added; and a dispatch that writes the record faults
it as written by its dispatch. Dwords past the heap read zeros, as the
scalar loads would, and a record past the key cap is read rather than
poisoned.
A column stays a whole table when its offset is chosen per lane, or when
the shader may write the memory the offset is read from at run time: the
buffer it is read from (by V#), or any memory when the read or a write
goes through a pointer or a GPU-only descriptor. Samplers are unchanged:
an S# the walker evaluates is already a direct sampler. The plan stores
the selection, so the disk cache format is 36.
Five agc_shader_memory and agc_shader_bindless checks asserted the old
planning and now assert the selected record:
- "image table SRT key": a key read through the SRT narrowed a 4-key
table to records 0 and 2. It now selects record 2 alone, captures no
other record, and a changed key moves the capture without changing the
module or its disk key.
- "image table key union" and "image table late key": two keys of one
heap shared one column with two value key domains. Each key now
selects its own record, as two one-record tables.
- "image table unkeyed access": a read keyed through the SRT shared a
whole column with a read keyed per lane. The first now selects its
record; the second keeps the whole, unnarrowed table.
- "uniform table image": the T# at a user data offset was one key of a
full table. It is now the one selected record, and the record the user
data does not select is not read.
A value key domain only arises for a key the walker evaluates, so it no
longer narrows an image column; key buffer domains (keys loaded per
lane) still do.
prepareBuffer and queueAudio computed frames * channels * bytesPerSample
in 32-bit arithmetic. A large samplesNum from sceAudioOutOpen (which
only rejects len == 0) wraps the product, so buf.resize allocates a
truncated buffer while the mixing loops write frames * channels samples
past it. Compute the size in 64 bits and throw past INT32_MAX, which
also keeps the downstream int casts well-defined.
Return the RLIMIT_NOFILE soft limit that getrlimit reports, capped at INT_MAX: FreeBSD sys_getdtablesize returns the smaller of that limit and maxfilesperproc, and the guest limit never exceeds the hard limit that bounds it here. The guest test now asserts the value instead of the throw, and the debt entry records the semantics.
A draw with PA_SC_AA_CONFIG.MSAA_NUM_SAMPLES 2 (4x) and MSAA_ENABLE
clear into a 4x depth/stencil and color pair threw "multisampled
targets rasterized without MSAA_ENABLE are unsupported for points,
lines, a depth target or alpha-to-coverage", which stops METAL GEAR
SOLID: Peace Walker (PPSA18216) at its first presentation (draw B on
#5268). A depth target with the same sample count now gets the same
pixel center samples as the color targets, so each depth and stencil
sample is tested and written with the depth at the pixel center, as GL
allows when multisampling is disabled.
DB_EQAA Z interpolation or overrasterization and a sample-mask export
with a depth target throw on this path.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
materializeRegisterClear clears the resident image to CB_COLOR_CLEAR_WORD
when the target's DCC keys read as the register clear code. Most of the
time those keys come from a key store the driver recorded itself
(NoteKeysFillOnGpu) and the GPU has not run it yet, so FillClear refused
with "keys pending" and the fallback waited for that store (SyncThrough).
The wait buys nothing when the newest recorded writer of the whole key
range is the noted store: ProvedCurrentDccKeys already answered from the
same memo (PendingStoreKeys), so the keys the GPU will hold are known and
are the code this clear stands for. The image clear and the
"uncompressed" key store after it are recorded into the same queue behind
that store and land after it, the order the wait gave.
KnownPendingDccKeys exposes that proof, and the register clear passes it
as FillClear's allowRegisterClear, which skips only the "keys pending"
refusal; the key scan still runs. Any other pending writer (a title
kernel, a later partial or wider write, a shadowed range) keeps the wait.
Tests: the proof answers only for a pending noted store covering the
range, and a clear recorded behind a pending register clear key store
leaves the clear word in memory and uncompressed keys.
Another open change adds a line at the start of the draw-packet branch in Driver::execute. The overlay's draw count now follows landPendingWaits instead, which counts the same packets.