Repository navigation
perf(agc): read a fast-cleared surface's guest bytes only when the import is compared - #2699
Conversation
…port is compared boykopovar#2096 keeps a copy of a storage image's guest bytes so that Refresh can compare memory the write watch does not cover. The host-import upload path takes that copy only when the range is unwatched, but the DCC fast-clear path took it on every upload. Reading the whole surface goes through the flush hook, so each 64 KiB block of a surface that a unit shadow covers recorded a publish and waited for the GPU. The clear path now resolves the surface's host import first (the import can unwatch the range, as a compared host-pointer import does) and takes the copy only when the range is then unwatched, like the import path. Write-watched memory, such as direct memory behind a dma-buf import, skips it; a range that is unwatched later re-uploads instead of comparing, as before boykopovar#2096. agc_driver_dcc_keys_first_write checks that a fast-cleared upload keeps the copy exactly when its range is unwatched at that point. PPSA14632 (LEGO Horizon Adventures) on Linux, RX 9070 XT: the flush hook waited ~60,000 times per 10 s for these publishes (6.4 s), now ~3,500, and presents rise from ~24 to ~100 per 10 s. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Native Windows run, since no Windows results were posted. Setup: Windows 10 (19045), RTX 3060 Laptop (NVIDIA 616.92), MinGW-w64 GCC 15.2.0 (WinLibs r7), Release. Head
No title was run. 🤖 Addressed by Claude Code |
|
The one failing job, |
|
Tested on Windows with a second title, Hollow Knight: Silksong (PPSA12544). Setup: Windows 11 Pro (26300), i7-11800H, RTX 3060 Laptop (driver 617.42), WinLibs GCC 15.2.0 r7, Release. Guest memory reads (
Over the whole 250 s, reads went from 99,548 MiB in 14.7 s to 14,470 MiB in 3.3 s.
🤖 Generated with Claude Code |
|
Checked the diff, the build and ctest of libSceAgcDriver on Linux ( |
…ched memory range is write-watched. Since boykopovar#2984, Refresh turns a BlockMaybeWritten unit into BlockUnchanged only through compareUntracked, which needs that copy. Where a host import leaves its range watched and making it stamps the imported pages (the probe's writtenAtImport, 4 of 4 on NVIDIA's Linux driver), the import window stamps the surface, so a pending fast-cleared image counted as changed again and agc_driver_dcc_keys_first_write failed on main (boykopovar#3179). HostImports now keeps whether making each kind of import stamped the probe's pages, and WatchedImportsStampPages reports whether an import that leaves its range watched can stamp it. The clear path skips the copy only when no such import can, as oneandonlydean proposed in boykopovar#3179. Devices whose probe saw no pages written at the import, devices without host imports and Windows (whose alias imports don't disarm the guest views) keep boykopovar#2699's saving. An unprobed watch (APS5_WRITE_WATCH_IMPORTS=watch) keeps the copy. The fast-clear check in agc_driver_dcc_keys_first_write now expects the copy exactly when the range is unwatched or such a stamp is possible. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ched memory range is write-watched. Since #2984, Refresh turns a BlockMaybeWritten unit into BlockUnchanged only through compareUntracked, which needs that copy. Where a host import leaves its range watched and making it stamps the imported pages (the probe's writtenAtImport, 4 of 4 on NVIDIA's Linux driver), the import window stamps the surface, so a pending fast-cleared image counted as changed again and agc_driver_dcc_keys_first_write failed on main (#3179). HostImports now keeps whether making each kind of import stamped the probe's pages, and WatchedImportsStampPages reports whether an import that leaves its range watched can stamp it. The clear path skips the copy only when no such import can, as oneandonlydean proposed in #3179. Devices whose probe saw no pages written at the import, devices without host imports and Windows (whose alias imports don't disarm the guest views) keep #2699's saving. An unprobed watch (APS5_WRITE_WATCH_IMPORTS=watch) keeps the copy. The fast-clear check in agc_driver_dcc_keys_first_write now expects the copy exactly when the range is unwatched or such a stamp is possible. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What
#2096 keeps a copy of a storage image's guest bytes so that
Refreshcan compare memory the write watch doesn't cover. Its host-import upload path takes that copy only when the range is unwatched (GuestMemory::Watched). The DCC fast-clear path, however, takes it on every upload:originalValid = falsebecame an unconditionalcaptureGuestBytes(nullptr).Reading the whole surface goes through the flush hook. For a surface a unit shadow covers, every 64 KiB block records a publish and waits for the GPU (
FlushForAccess→PublishShadowsOnly→SyncThrough). Stack from PPSA14632, sampled at those waits:Driver::dispatch→ShaderResources::Revalidate→cachedStorageTexture→StorageTexture::Refresh→upload→captureGuestBytes→ReadCommitted→FlushForAccess.The clear path now resolves the surface's host import first, because creating it can unwatch the range (a compared host-pointer import does). It takes the copy only when the range is unwatched after that, like the import path. Write-watched memory, such as Linux direct memory behind a dma-buf import (which keeps write protection), skips the read. A range that becomes unwatched only later re-uploads instead of comparing, as it did before #2096.
agc_driver_dcc_keys_first_writenow checks that a fast-cleared upload keeps the copy exactly when its range is unwatched at that point. In the default run, the test block's host-pointer import is compared, so it covers the case #2096 needs. WithAPS5_WRITE_WATCH_IMPORTS=watchthe check fails without this change ("a fast-cleared upload of write-watched memory read its guest bytes"). That mode then stops at the existing "an unchanged pending image was uploaded again" check, onmainas well, so it isn't a ctest variant.Tested
Linux (Arch), RX 9070 XT, RADV, Release:
mainb5f5362 plus fix(guest-arena): place guest address space in the PS5 window on Linux #861 (Linux guest arena, needed to boot it), udmabufsize_limit_mb1024. Values per 10 s, steady state:mainHow I narrowed it down: on that setup, the merge right before #639 (2b29784) has about 230 such waits per 10 s, and #2347, the first later merge that boots the title, has about 61,900. Reverting #425, #1309's backing write, #1310, #1410/#1411 or #2575 on
maindidn't change the count. The stack above leads to this line.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt.mdfiles or images added to the repository (attach them to this PR)🤖 Generated with Claude Code