Commit Graph
548 Commits
Author SHA1 Message Date
Dean Galvin 258a62c1ea Merge main into pr-6730 via the rebased #6457
# Conflicts:
#	core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
2026-10-20 06:31:06 +13:00
Dean Galvin e42de06845 Merge main into pr-6457
# Conflicts:
#	core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
2026-10-20 06:30:38 +13:00
Adrià Franch 8706cd8a7d docs(agc): keep the title name out of the scan-resistant admission debt entry 2026-10-19 18:44:04 +02:00
Alex ColliniandClaude Sonnet 5.5 c026550122 perf(agc): refuse uncached textures while the sampled cache's least recently used entry is still in use
Over budget but within a quarter over it, the sampled texture cache refused no use of a texture it does not hold, so a cyclic scan over a working set larger than the budget rotated the whole cache and hit almost never. The first use of a key in a present is now refused (used for its draw, never cached) when the least recently used entry was used in this or the previous present. A later use of the key is refused only when that entry was used in this present, so a texture used several times per present is still admitted on a later use. The refusal does not apply past the quarter-over ceiling, so a budget that falls still evicts.

The test lowers the budget through OverrideCacheBudgetForTest instead of the environment. The debt entry records the unmeasured present window, that a texture used more than once still rotates the cache, and the one A-B-A measurement.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-19 18:43:53 +02:00
Longziip ae67e2b7f9 fix(agc): write the reread indirect register list when skipping its invalid entries
When the list read at submission is invalid, the worker now always
executes the copy read again where the packet runs. With
APS5_SKIP_INVALID_INDIRECT_REGISTERS=1 only that copy's invalid entries
are skipped, so the valid entries of a partly updated list are written
instead of the stale ones from submission.

testPartlyUpdatedRegisterListSkipsOnlyItsInvalidEntries submits a list
that is invalid at submission, updates it to a valid entry plus an
invalid one before its packet runs, and reads the register back with
COPY_DATA.
2026-10-19 17:29:53 +01:00
Longziip 557ae22bd1 fix(agc): reread an invalid indirect register list where its packet executes
SET_*_REG_INDIRECT lists are read when the command buffer is submitted.
When that copy holds an offset dword that is no register offset, the
queue worker now reads the list again where the packet executes (as the
console PFP does) and uses that copy if it is valid.

PPSA23566 (UFC 6) intermittently submits a SET_CONTEXT_REG_INDIRECT
whose first entry is 0x038f038f or 0x03900390 in both copies, followed by
180 valid pairs, and the title stopped with "extended register semantics
are not implemented". With APS5_SKIP_INVALID_INDIRECT_REGISTERS=1 the
invalid entries are skipped and the other registers are written; without
it the packet throws as before.
2026-10-19 17:29:53 +01:00
Alexandre Sanchez 98ebc9df1b Merge branch 'main' into fix/agc-cached-image-msaa-guard 2026-10-19 18:12:52 +02:00
Adrià 88a6b34bc5 Merge pull request #6966 from ebosido444-ai/fix/agc-relocated-header
fix(agc): resolve a relocated AGC header whose arrays hold the registered bytes
2026-10-19 17:28:19 +02:00
sussyandClaude Sonnet 5.5 742af5fc8d fix(agc): name both missing features when mesh barycentrics cannot be provided
A pixel shader on the mesh path that reads barycentrics on a device with
neither VK_KHR_fragment_shader_barycentric nor VK_EXT_mesh_shader
reported only the missing mesh shaders. Say that the device has neither,
so reports from such devices are told apart from the case the emulation
covers.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-19 17:26:37 +02:00
sussyandClaude Sonnet 5.5 dd41527ce2 feat(shader): emulate smooth barycentrics on the mesh path
A pixel shader that reads barycentrics on a device without
VK_KHR_fragment_shader_barycentric used to need a vertex shader so a
generated geometry stage could follow it, which a mesh pipeline cannot
have. The mesh program is now compiled a second time with the layout
its pixel shader needs: it writes its clip position as a varying and the
three corner positions of each primitive as per-primitive outputs, and
the pixel shader solves for the weights, for both smooth and linear
interpolation.

The layout is part of the mesh cache key, the stored artifact and the
captured request. Without VK_EXT_mesh_shader the draw still throws, now
saying so. Per-vertex parameters on the mesh path still throw.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-19 17:26:37 +02:00
Rajkamalcode 448cf78c69 fix(agc): skip storage write-back units that lie in no tiled slice
writeBackWindows retiles the kept 64 KiB units through the windows of the
surface's (layer, mip) slices. A unit can lie outside every window: the
tracking grid spans the whole guest range flat, while the slices of a 3D
surface taper in depth (HasLayer), so the upper depth slices' higher-level
blocks belong to no window. The empty window set then sized the retile
linear and scratch buffers at zero, and the zero-sized device buffer threw
'AGC graphics: zero-sized device buffer', aborting the process.

Keep such units as the guest left them: there is no tiled data of the
surface to retile or store. The caller alone accounts for the unit.
2026-10-19 20:54:46 +05:30
plokmklo 9c9128d45c docs(debt): name the pending results that still have no saved guest bytes
Results that land in a unit whose store ran while its blocks were
watched, after those blocks left the watch while nothing was pending,
have neither saved bytes nor a watch: the unwatch hook found nothing to
save and the write-back refuses as before (#7017). The entry named only
the range that leaves the watch without the hook running over it.
2026-10-19 17:01:06 +02:00
plokmklo 1b6419caae fix(agc): run the unwatch hook when a failed collect leaves the write watch
A MarkWritten whose fresh collect fails (a no-access or unwatchable
resident page inside the 64 KiB block span) took the span out of the
write watch without running the unwatch hook, so pending storage-image
results over it kept no saved guest bytes and their write-back refused:
storing storage image results pending over memory outside the write
watch without the guest bytes saved before them is not implemented
(#7017, Palworld PPSA23126 among others).

The hook now runs over the block span before the blocks leave the
watch, as Unwatch and the import fallback do, with the tracker lock
released for it like #6308 does for imports. The debt entry drops the
failed collect from the unsaved cases.

The check makes a collect fail over a no-access arena page and requires
the hook to have covered the block; it needs the WindowsMappings
protection failure, so it runs in the Windows-only section of the write
tracking test.
2026-10-19 17:00:48 +02:00
Dean Galvin 88f64ec265 x
# Conflicts:
#	docs/dev/debt/libSceAgcDriver.md
2026-10-20 03:54:33 +13:00
Dean Galvin 1d8d67f8d3 x
# Conflicts:
#	docs/dev/debt/libSceAgcDriver.md
2026-10-20 03:54:32 +13:00
Dean Galvin f3751e96ad Merge main into pr-6457
# Conflicts:
#	docs/dev/debt/libSceAgcDriver.md
2026-10-20 03:54:07 +13:00
Adrià 73c59b7be6 Merge pull request #6958 from Pipodi/fix/pipeline-cache-save-try-lock
fix(agc): skip a periodic pipeline cache save while a pipeline creation holds the cache
2026-10-19 16:48:06 +02:00
David 63e763f443 Merge remote-tracking branch 'origin/main' into feat/shader-barycentric-tessellation-last-vertex
# Conflicts:
#	docs/dev/debt/shader.md
2026-10-19 18:27:34 +04:00
Gjon Gojcevic a15694eb94 feat(agc): render layered draws into a one-slice surface as an array of its view's slices
A layered draw into a color view of slices 0 to 5 of a 2D surface whose
CB_COLOR_ATTRIB3 declares one slice was refused. The CB clamps the
render target array index to the view's SLICE_MAX, not to the surface's
slice count, so each layer is written one slice pitch further on.
PPSA01317 renders a 512x512 cube map this way. Such a view now renders as
a 2D array of the view's last slice + 1 slices.

AI-assisted: yes
2026-10-19 15:52:35 +02:00
Adrià 85029a00f5 Merge pull request #6762 from simonbronk/fix/stencil-op-value-export
fix(agc): replace with a stencil operation value the pixel shader exports
2026-10-19 15:45:10 +02:00
Adrià 3efab5ed86 Merge pull request #6914 from moong15/pr/queued-index-read-order
fix(agc): order deferred write-backs after queued draws' index reads
2026-10-19 15:39:49 +02:00
Alex ColliniandClaude Opus 5.5 185551c59f docs(debt): record the sampled array window and 2D array read limits
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-19 15:20:58 +02:00
Savvanis SpyrosandClaude Opus 5.5 c5dbdf1fde fix(agc): name the RELEASE_MEM system counter instead of GDS data
A RELEASE_MEM with DATA_SEL 4 was refused as "GDS RELEASE_MEM data".
amdgpu's GFX10 packet header gives 4 as the 64-bit system counter and 5
as GDS data. Validation now refuses 4 as the system counter, whose
console frequency and epoch are not known, 5 as GDS data and 6 or 7 as
reserved, and the debt file records the system counter.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-19 16:18:13 +03:00
XairRrR 3f0d75025f docs(agc): keep the depth planes debt entry under the length limit
State the gap first and drop the mechanism details the code and the
pull request already carry.

AI-assisted: yes
2026-10-19 14:51:51 +02:00
xXPBSXxandClaude Sonnet 5.5 2368691a9e docs(debt): add the Radeon 860M symptom of the CMASK clear pass
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-19 14:43:05 +02:00
ebosido444-ai 943b7007c9 fix(agc): resolve a relocated AGC header whose arrays hold the registered bytes
A title can relocate a registered shader header, and the register, special and
semantic arrays it points at, into memory of its own and resolve the ABI with
that copy (Astro's Playroom, PPSA01325, #2914). SameHeader accepted such a copy
only while every pointer inside it stayed put, so a moved array left the
resolution throwing "refers to a replaced shader header".

Accept the copy when every array it names still holds the registered bytes: the
registered header then decodes what the copy describes, nothing is copied and
ShaderSnapshot stays immutable. A copy whose arrays differ or are unreadable
still throws.
2026-10-19 14:36:11 +02:00
milescovielloandClaude Opus 5.5 74a6bdaa01 feat(agc): take a full DCC fill of a resident multisampled target as its fast clear
A multisampled DCC color target imports its uniform DCC fast clear on
first use and then refuses any later change to its color, DCC or CMASK
memory. Titles built on the PS5 Mesa stack fast-clear such a target
every frame with two buffer fills, the CMASK to 0xcc (FMASK cleared,
color expanded) and the DCC to a uniform clear key, so the second
frame stopped on "writes to a resident multisampled DCC target or its
metadata are not implemented".

The fills of a resident DCC target's metadata are now noted. When a
fill covered the whole DCC range since the last use and the range holds
its key once pending writes land (LandedUniformMetadataByte, which
reads the bytes directly rather than through the resident read guard),
the next use clears every sample to that key's color, as the import
does, and takes the new DCC and CMASK generations. A CMASK written
since must have been filled whole too. Partial fills, other keys,
CMASK-only writes and any write to the color memory are still refused.
Fills of a DCC target's CMASK no longer go to the CMASK-only fast-clear
tracker, which refused the expanded code 0xcc.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-19 12:23:44 +00:00
Alex ColliniandClaude Opus 5.5 1d8acd1eda fix(agc): skip a periodic pipeline cache save while a pipeline creation holds the cache
The saver thread took the snapshot lock with a blocking exclusive lock. Behind
a pipeline creation that runs for minutes (an NVIDIA compile of a 1.5M-word
compute pipeline), the queued writer made the shared_mutex hold every later
pipeline creation on every queue until the compile ended. The periodic save now
tries the lock and waits for the next interval when it is busy; SaveNow and the
teardown save still wait.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-19 13:57:50 +02:00
Adrià 87aee045df Merge pull request #6821 from JJenkx/fix/point-context-sdk-defaults
fix(agc): initialize point size and limits from SDK defaults
2026-10-19 13:45:12 +02:00
xXPBSXxandClaude Sonnet 5.5 0b8c849f55 docs(agc): record the queue 0x20 label wait that holds another slot's address
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-19 13:32:36 +02:00
xXPBSXxandClaude Sonnet 5.5 7d5089a7fb docs(debt): record the CMASK clear pass fault on AMD without pipeline libraries
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-19 13:31:58 +02:00
milescovielloandClaude Opus 5.5 1f63ba35af docs(agc): say where PS_ITER_SAMPLE alone still throws and which memory accesses can differ
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-19 11:28:30 +00:00
Adrià f6eeca4f5f Merge pull request #6786 from fdfawef324/claude/agc-indirect-args-stale
fix(agc): wait for address-based writers before reading indirect dispatch arguments
2026-10-19 13:16:24 +02:00
milescovielloandClaude Opus 5.5 c2764f31f2 fix(agc): draw a PS_ITER_SAMPLE program once per pixel into a one-sample depth target
A one-sample depth target under a multisampled rasterizer without
MSAA_ENABLE is drawn as a one-sample draw at the pixel center, but a pixel
program that runs with PS_ITER_SAMPLE threw. Ghost of Tsushima (PPSA02225)
draws its depth-only pass this way (2x PA_SC_AA_CONFIG, PA_SC_MODE_CNTL_1
0x06030000, KILL_ENABLE, no sample index or coverage input) and stops on it.

Every sample is taken to be at the pixel center on this path, so
invocations per sample would get the same inputs and give the same depth,
kill and color results, and the target keeps sample 0's. Such a program is
now drawn once per pixel, without sample shading. ANCILLARY and
SAMPLE_COVERAGE inputs still throw. The debt entry notes that only the
memory writes of such a program can differ.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-19 11:05:02 +00:00
Adrià Franch 45d012ed3d docs(agc): merge the storage write-back debt lines and state what the hold counters report 2026-10-19 12:57:59 +02:00
umangandClaude Opus 5.5 00053a3f60 fix(agc): hold queued draws' vertex and DMA source reads and retry the stores they refused
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-19 12:57:48 +02:00
umangandClaude Opus 5.5 c9af5d9f4b fix: order deferred write-backs after queued draws' index reads
A pipelined draw read its index buffer from guest memory at commit time,
after the packets behind it had run, so a later dispatch's deferred
storage-image write-back could land in the bytes first. Stellar Blade
recycles its full-screen quad's index buffer for a 66x66 image when the
menu loads, and aborted with "vertex fetch exceeds descriptor record count".
Deferred write-backs now wait while a queued draw still holds a read of the
range. APS5_NO_QUEUED_DRAW_READ_ORDER=1 restores the old order; [draw]
reports held read ranges and stores.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-19 12:57:48 +02:00
simonbronkandClaude Opus 5.5 7563b4a480 fix(agc): replace with a stencil operation value the pixel shader exports
With DB_SHADER_CONTROL.STENCIL_OP_VAL_EXPORT_ENABLE the pixel shader
supplies the value that REPLACE_OP and the add and subtract operations
use in place of DB_STENCILREFMASK.STENCILOPVAL. The bit was refused as a
whole, which stopped Onimusha: Way of the Sword (PPSA27836) at a
DB_SHADER_CONTROL 0x45 draw with DB_STENCIL_CONTROL 0x40040 (REPLACE_OP
on depth pass, both faces), write mask 0xff and compare ALWAYS.

The export is accepted with the 32_GR and 32_ABGR Z formats. When no
reachable operation through a non-zero write mask reads the value, it
cannot change the result and is ignored. Without a test value export, a
reachable REPLACE_OP becomes REPLACE with the exported value as
FragStencilRefEXT (or the bounded replay on devices without the
extension), provided both faces compare without the test value and use
no ONES or REPLACE_TEST; early tests throw. The add and subtract
operations, and REPLACE_OP with a test value export, still throw.

The value is read from bits 8-15 of the second MRTZ channel: the
title's pixel shader shifts it left by 8 right before exp mrtz
(v_lshlrev_b32 v0, 8, v0). That is the only evidence for the layout and
it is listed as technical debt. The pixel stage info carries the new
flag into the cache key, the draw keys and request serialization
version 31.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-19 12:53:13 +02:00
Adrià 118266aec2 Merge pull request #6760 from Ondra97/codex/fix-f64-minmax-denormals
fix(shader): honor f64 min and max input denormal mode
2026-10-19 12:27:39 +02:00
Adrià 8e3d8b9bd8 Merge pull request #6723 from Tripchipp/fix/debt-file-unlinked-entries
fix(tools): keep debt entries without a core link in the index
2026-10-19 12:09:51 +02:00
Alexandre Sanchez 67c7190223 fix(agc): preserve image table semantics in cached MSAA guards
Mark described image-table ranges explicitly and apply the eager color-target guard only to ordinary image bindings. Cover native multisample table validation and record the separate table registration gap.
2026-10-19 11:41:30 +02:00
Dean 7f37d45ed3 Merge pull request #6451 from EagleBearerYS/fix/agc-sample-location-grid-fallback
fix(agc): fall back to pixel (0,0)'s sample locations where the device has no 2x2 grid
2026-10-19 22:22:04 +13:00
Dean Galvin 3b68e8c19e Merge main into pr-6730
# Conflicts:
#	docs/dev/debt/libSceAgcDriver.md
2026-10-19 22:12:19 +13:00
Dean Galvin f879cd713c Merge main into pr-6479
# Conflicts:
#	core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp
#	docs/dev/debt/libSceAgcDriver.md
2026-10-19 22:12:19 +13:00
Dean Galvin a48e28a632 Merge main into pr-6457
# Conflicts:
#	docs/dev/debt/libSceAgcDriver.md
2026-10-19 22:12:18 +13:00
Adrià f161098d3b Merge pull request #6563 from notaxeltv/feat/agc-msaa-enable-rect-list
fix(agc): allow MSAA_ENABLE single-sample rect lists
2026-10-19 10:44:32 +02:00
f6c8e8474f fix(agc): wait for address-based writers before reading indirect dispatch arguments
A CPU read of DISPATCH_INDIRECT arguments waited only through the flush
hook, which waits for the ranges recorded work noted as pending writes.
An address-based store (FLAT/GLOBAL, or through a descriptor the
recompiler cannot resolve to a static buffer) is not recorded as a
pending write: its batch leases the registered allocations, and only the
guest pin waiter finished that batch. So the thread-dimension,
misaligned and disabled paths, the fill-kernel path and the device's CPU
fallback read the arguments from before an address-based producer ran.
GTA V (PPSA04264) dies loading Story on such a read: a 64-thread clear
kernel read {160, 288, 0xffffffff} as thread dimensions
(3x288x4294967295 groups), bytes its 1-thread setup kernel had not yet
overwritten with {n, 1, 1}, and threw "workgroup count
3x288x4294967295 exceeds device limits".

Every CPU read of dispatch arguments at execution now first finishes the
recorder up to the newest batch recorded with a lease
(Graphics::FinishLeaseWork). The group read-ahead still reads without
waiting; a dispatch it resolved is adopted only when the execution-time
read gives the same counts, and one that differs is dropped and counted
in the [groupcap] line. The device limit error names the argument
address and cpuReason, and the driver adds the queue, path and
read-ahead outcome. The [indirect] read time includes the lease wait,
and the [recorder] sync-site table records the offset of
FinishLeaseWork's caller. The CPU reads that still miss address-based
writes (indirect draw arguments and count, the copy kernel's count
record, the awaits-title checks) are listed in the technical debt.

IndirectArgumentsPendingProducer covers the execution-time CPU argument
reads on compute queues and the pending-label CPU fallback in the Vulkan
device. Its sixth case records a real argument label behind a host Vulkan
event in an earlier batch and an address-based producer in the later open
batch. The event releases only after that producer batch is submitted;
a bounded watchdog releases for cleanup but fails the case. It requires
a deferred producer lease, an unsubmitted producer at the argument
decision, cpuReason 2 and the fresh arguments and counter result. Small
valid stale counts keep a broken-wait control finite on every driver.
Exact CPU-reason and watchdog diagnostics identify the failing path. This
replaces a spinning workload whose earlier label could retire before
the fallback decision on lavapipe, allowing a false green with cpuReason 0.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Codex <[email protected]>
2026-10-19 10:18:11 +02:00
Adrià b715404323 Merge pull request #6646 from EagleBearerYS/fix/agc-heap-mirror-replan-unwatched
fix(agc): plan a heap again when its mirror's range has left the write watch
2026-10-19 10:15:31 +02:00
Adrià 9a5726cc18 Merge pull request #6601 from Amoenus/codex/feat-msaa-sampled-readback
feat(agc): read individual multisample image samples
2026-10-19 10:14:12 +02:00
Dean Galvin a53c89fee8 Merge main into pr-6730 via the rebased #6457
# Conflicts:
#	core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
#	docs/dev/debt/libSceAgcDriver.md
2026-10-19 21:02:18 +13:00