Repository navigation
perf(agc): skip the depth plane copy when no slice changed - #2491
oneandonlydean merged 2 commits into
Conversation
|
Tested on a second title and vendor: Sonic Origins Plus (PPSA05324), Linux, Radeon R9 380 2 GB (RADV, Mesa 26.0.8), 960x540 render size. Its main menu draws a 4-slice 1024x1024 D32 shadow cascade array once per frame and samples it in 43 draws. Main menu, 10 s windows with
One note for the rebase: with #454 in the same tree, |
|
Additional platform validation on standalone PR head Windows: passed — Windows 11, supported WinLibs GCC 15.2.0 UCRT/POSIX/SEH r7; CMake 4.3.1 / Ninja. Release / Tests: Reproduce after building the test targets: Vulkan: native AMD RX 6900 XT, driver 32.0.21045.5002. Integration limitation: a local merge against main |
8085dda to
1360f6f
Compare
1360f6f to
ae3b551
Compare
…opies only for changed layers and slices) into integ/head Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ae3b551 to
dcd0b74
Compare
Sampling a depth surface as a 2D array, a cube or its integer bits copies its planes into a per-use image. Each use read every slice no depth surface holds from guest memory and detiled it again, even when nothing had written it since: in one level of a heavier title that was about 165,000 layer reads, about 650 GiB, in a five-minute run. A slice read from guest memory now stays in the copy's staging buffer with the write generation it was read at. The next use reads and detiles it again only when its address, size or tiling changed, the write tracker reports a write since, or recorded GPU work writes the range; a slice a depth surface held in between is read again. Without write watching every use reads, as before.
dcd0b74 to
e691d03
Compare
|
Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.
|
|
@oneandonlydean #4873 overlaps this PR in This PR keeps the same tight-slice assumption in
Growing the staging buffer does not affect this PR's partial copy: every copied layer rewrites its part of the staging buffer before the image copy, and unchanged layers are kept in the image, not in the staging buffer. Happy to rebase #4873 onto this one if it lands first, or the other way around. |
Sampling a depth array, cube or R16_UINT view of depth surfaces went through DepthPlaneCopy::Refresh on every use. Each use copied every slice a depth surface holds into the staging buffer and the whole staging buffer into the copy image, with three ALL_COMMANDS barriers, although nothing had written the slices since the previous use. Each depth surface now carries a write serial, bumped when a draw binds it as its depth target and when a pending fast clear is applied. The copy keeps the image and serial of every slice it copied. A use copies only the slices whose surface or serial changed and the guest layers that changed (as before), and records nothing when none did. A slice whose surface is the depth target of the latest depth draw is copied at every use until another depth target is bound, since that draw may still be recorded after the copy. Test: agc_driver_depth_plane_guest_layers counts the recorded slice copies and copy fills; a second use with nothing written records none (it records one of each without this change), a draw to a slice's surface or a CPU write to a guest layer copies only that layer.
e691d03 to
50e5f08
Compare
|
Windows RTX 5070 Ti cross-test completed for the #2490/#2491 port, now Native guest-layer/copy-count, depth compare-copy, fast-clear, fast-clear-submit, storage-reuse, last-writer and full mocked graphics: 7/7 passed initially (7.50 s). I also imported Michon's sampled-value fixture dc0c2cf preserving authorship. It exposed a pre-existing integration omission: the extracted planesAccepted helper lost upstream's depth-bits alternative. Both this port and production baseline 861fe25 failed the D16 depth-bits array refusal identically. Restoring the same upstream gate made all eight checks pass (8.05 s). Then I removed only #2491's production change, keeping #2490, the restored format gate and both fixtures: copy-count fails with 1 depth surface copy + 1 plane fill where 0 + 0 are expected; sampled-value control passes. Restored and rebuilt: 8/8 passed (7.98 s), without skips (ANYPS5_REQUIRE_VULKAN=1). Final fixture-only comment cleanup follows this integration's conventions; rebuilt sampled-value test passes again. Scoped conventions/diff checks pass. The integration also has storage-to-depth write-back, so Transfer(..., false, ...) bumps the new write serial as required; retired-surface/address filters and TakeWrites are preserved. No game performance claim yet. The new game comparison stages only patched graphics, with libc/kernel unchanged, normal asynchronous draws, the same warm cache/profile/cache and memory limits as 861fe25. Graphics SHA256 FCB1B8FBE97FD95D817653C882B307D2296D81EEA04C913F3474C056016DF166. AI-assisted (Codex). No title code, captures or assets uploaded. |
What
Follow-up to #425. Stacked on #2490 (keep unchanged guest layers of a depth plane copy), which this builds on; the first commit here is #2490's.
DepthPlaneCopykeeps the image and serial of every slice it copied. A use copies only the slices whose surface or serial changed, plus the guest layers that changed (as before), and records nothing at all when none did.GENERALto transfer and back instead of fromUNDEFINED).#425 is merged, so this head is rebased onto
main1c5e628, on top of #2490's new headaf716047. Both commits applied without conflicts and the change is the same.DepthSurfaceView(draws) andApplyFastClearonmain, HTILE and memory value fills included (they set the pending clear), so the serial covers every writer.written = ++depthWrites;after itscopyPlane(plane, stencil, false)); whichever lands second needs that one line.It cannot merge before #2490.
Why
Every sampled use of a depth array, cube or
R16_UINTview copied every slice a depth surface holds into the staging buffer and the whole staging buffer into the copy image, behind threeALL_COMMANDSbarriers, although nothing had written the slices since the previous use. A title that renders its shadow cascades once per frame and samples them a few hundred times spent most of its GPU frame in these copies.Tested
Linux (CachyOS, GCC 16.2.1, Release with CI's configure flags and
ANYPS5_ENABLE_SPIRV_TOOLS=ON, full build andlibs), RTX 4090, NVIDIA 610.57.04.ctest -R "agc|shader"(--parallel 4,ANYPS5_REQUIRE_VULKAN=1): 462/462 on this head (e691d032), 462/462 on perf(agc): keep unchanged guest layers of a depth plane copy #2490af716047, 461/461 onmain1c5e628.tools/check_conventions.py --base origin/mainandtools/check_test_registration.pypass.The seven
agc_driver_depth*tests underVK_LAYER_KHRONOS_validation: pass, no validation message.agc_driver_depth_plane_guest_layerscounts the recorded slice copies (vkCmdCopyImageToBuffer) and copy fills (vkCmdCopyBufferToImage):sampling the depth planes with nothing written since recorded 1 depth surface copies and 1 plane copy fills, expected 0 and 0;It passes with the change (5 of 5 runs).
A 2D title we test with, on this head: 220 s through the menu into the second room, picture checks pass, no error line. It does not sample depth planes this way, so this is a regression check only.
A 3D title we test with stops on
mainbefore its title scene without feat(libSceAgcDriver): storage image access to depth surfaces #4500, so it was measured onmain1c5e628 + feat(libSceAgcDriver): storage image access to depth surfaces #4500, with perf(agc): keep unchanged guest layers of a depth plane copy #2490 and this together: frames per second in the title scene and in the menu after it.main1c5e628 + feat(libSceAgcDriver): storage image access to depth surfaces #4500Without the two changes the title scene runs at 0.6 to 0.9 fps from its first frame on (74 frames in 90 s); with them the run goes on into the first level. One run each; caches warm for the second row. In the second row feat(libSceAgcDriver): storage image access to depth surfaces #4500's store-back also bumps the write serial (the line named under What).
Not measured on this base: the level numbers of the earlier base (0.174 fps without, 2.275 fps with, on
main99c1c26 + #425's earlier head + #454). Not tested on Windows or on AMD.Checklist
main(1c5e628, the merge of feat(agc): depth planes sampled as 2D arrays, cubes and integer views #425); no other open PR changesDepthPlaneCopy(feat(agc): retain and refresh sampled depth array storage #1368 samples depth arrays with its own storage, separately)NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)