Repository navigation
perf(agc): sample comparison-read R32F/R16 surfaces from a GPU depth copy of their storage image - #1619
Conversation
1c0a5b6 to
d4c6be9
Compare
d4c6be9 to
dcffa68
Compare
|
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 |
dcffa68 to
a051e71
Compare
adriadam10
left a comment
There was a problem hiding this comment.
Built and ran this on top of current main: agc_driver_depth_compare_copy passes, and the log shows the new depth copy of storage image path being taken. But I reverted the non-test changes (Texture.hpp/.cpp, ShaderResources.cpp, TechnicalDebt) and the test still passes, so it doesn't pin this change:
tests/execution/DepthCompareCopy.cpp: the snapshot path onmainreturns the same comparison results as the depth copy, so the test can't tell them apart. Make it observable: e.g. assert the lookup returned a texture withIsDepthCopy(), or countRefreshDepthCopy()calls / depth-copy lookups (and that the second store bumpsStorageTexture::Version()and triggers exactly one more refresh). Per CONTRIBUTING, new tests must fail without the change.- Coverage: only R32F, 1 layer, 1 mip. The copy has its own offset/extent math per mip and layer (
Texture.cppRefreshDepthCopy) and a separateR16_UNORM -> D16_UNORMbranch; please add a case with several mips/layers and one for R16. ShaderResources::Revalidaterefresh (ShaderResources.cpp, the new loop at the end): the fast-proof path has no test; a reuse of the same set after a store should show the copy refreshed.
Two things I can't verify here and that you may want to state: the SIGSEGV at ~97 s you mention (please say if it reproduces with APS5_NO_DEPTH_COPY=1 too), and that the copy assumes the storage image is in VK_IMAGE_LAYOUT_GENERAL when read from the transfer.
5efa5b9 to
318469b
Compare
adriadam10
left a comment
There was a problem hiding this comment.
The points from the earlier review are still open on 318469b, and the branch now also conflicts with main in docs/dev/TechnicalDebt.md:
tests/execution/DepthCompareCopy.cpp: still passes with the non-test changes reverted, so it doesn't pin the copy. Assert that the lookup returns a texture withIsDepthCopy(), and that the second store bumpsStorageTexture::Version()and triggers exactly one moreRefreshDepthCopy().- Coverage: add a case with several mips and layers (the per-level offset/extent math in
RefreshDepthCopy) and one forR16_UNORM -> D16_UNORM. ShaderResources::Revalidate(new loop at the end): reuse of the same set after a store should show the refreshed copy.- Please say whether the ~97 s SIGSEGV reproduces with
APS5_NO_DEPTH_COPY=1.
Please rebase on main as well (TechnicalDebt line next to a new one).
318469b to
c7110b3
Compare
|
AI-assisted: yes (Claude Code Fable 5.1 xhigh) |
adriadam10
left a comment
There was a problem hiding this comment.
The points from the previous reviews are still open on c7110b3d, and the branch now conflicts with main:
tests/execution/DepthCompareCopy.cpp: still passes withTexture.hpp,Texture.cppandShaderResources.cppreverted, so it doesn't pin the change. Assert that the lookup returns a texture withIsDepthCopy(), and that the second store bumpsStorageTexture::Version()and triggers exactly one moreRefreshDepthCopy().- Coverage: add cases for several mips and layers (the per-level offset/extent math in
RefreshDepthCopy), forR16_UNORM -> D16_UNORM, and for theRevalidaterefresh. docs/dev/TechnicalDebt.md: conflicts withmain. Rebase, and put the line away from the end of the file, where other open PRs also insert.- The SIGSEGV at ~97 s with the copy on is unexplained, and the TechnicalDebt line mentions an unexplained intermittent boot crash with small surfaces. Please find out whether the copy is involved (e.g. a run with
APS5_NO_DEPTH_COPY=1reproducing it, or a trace of the crash) before this lands.
Happy to look again once these are addressed.
c7110b3 to
ec4b473
Compare
|
@adriadam10 Thanks. Rebased onto
Tested on RTX 5070 Ti (driver 595.91.07): AI-assisted: yes |
…copy of their storage image
…eral mips and layers; drop APS5_NO_DEPTH_COPY
ec4b473 to
bf779b2
Compare
adriadam10
left a comment
There was a problem hiding this comment.
Checked on current main: agc_driver_depth_compare_copy and the rest of the libSceAgcDriver ctest set pass (355/355), the test no longer builds with the non-test changes reverted, and it now pins the copy counts, Version() movement, R16 and the mips/layers case.
Added one commit: moved the TechnicalDebt line off the end of the file (CONTRIBUTING: everyone appends there, so it conflicts).
Merging once the full Build (linux and windows) is green, since the new test opens a Vulkan device.
What
This is the fix from #1133. A comparison-sampled R32_SFLOAT or R16_UNORM surface that a storage image holds is now sampled from a D32_SFLOAT or D16_UNORM image that the GPU refills from the storage image. It no longer stays a CPU snapshot compared against guest memory.
Vulkan only compares depth formats, and this driver reports no depth-comparison sampling on R32_SFLOAT or R16_UNORM, so
cachedTexturekept these lookups (depthCompare) off the storage-image view path. After every GPU write-back, the next lookup flushed, waited for the GPU and compared the whole surface under the GPU mutex. In Demon's Souls that is a 16 MiB shadow map (1024x1024, 4 layers), compared 10-20 times a second on queue 0x30, and queue 0 waits behind it.Texture(context, source, descriptor, components, Texture::DepthCopyTag)makes a depth image of the surface's shape.RefreshDepthCopy()records a copy from the storage image into a device buffer and from there into the depth aspect, with barriers, wheneverStorageTexture::Version()has moved since the last copy.cachedTexturesends adepthComparelookup down this path when the surface is host-imported, R32F or R16 unorm, not 3D, at least 1 MiB, and the storage image has the same format (CanDepthCopyFrom). Everything else stays on the snapshot path as before.ShaderResources::Revalidaterefreshes the depth copies of a set after a successful proof, because the fast proof repeats no lookup.APS5_DEPTH_COPY_MIN_KIB(default 1024) sets the floor. TechnicalDebt has a line for the floor and the 3D exclusion. There is no switch to turn the copies off.New test:
agc_driver_depth_compare_copyhas three cases: R32F 512x512, R16 unorm 1024x512 (theD16_UNORMbranch), and R32F 256x256 with 4 layers and 3 mips, stored and compare-sampled at layer 0 mip 0, layer 2 mip 1 and layer 3 mip 2. Each case writes the surface with a compute store, compare-samples it, stores again and samples it again through the same compiled program, so the second dispatch reuses the cached descriptor set.Texture::TakeDepthCopyCounts()(depth copy textures made, copies refreshed) must read 1 and 1 after the first samples, and 0 and 1 after the second store, which must also moveStorageTexture::Version(). The guest blocks are write-watched so the reuse can take the fast proof.Closes #1133.
Before/after, this change alone
Demon's Souls (PPSA01341 v1.07), boot through the PS Studios movie into the attract movie, 200 s per run. Same build and settings on both sides; the only difference is
APS5_NO_DEPTH_COPY=1on the "before" side (a switch in that local build, removed from this PR since). 3 runs each, interleaved (before, after, before, ...). Each cell is the median of the per-run medians, per 10 s, with the per-run values in brackets.[hooksync])On the "before" side, almost all of those syncs are on ranges of up to 16 MiB (the shadow map). With the copy on, none are.
Presents don't move here. On these runs the title presented at about 10-12 fps on both sides, held by something other than this change. In earlier runs on a different build (in the issue), the attract movie went from 384-407 to 429-439 presents per 10 s with this change.
The build is
mainplus other local fixes and open PRs, not this branch alone. Both sides use that same build. The attract row for "after" has 2 runs: the first "after" run died with SIGSEGV at about 97 s, with no error line in the log and no core dump. 13 earlier runs of the same build with the copy on (it is on by default) had no such crash, so I can't tie it to this change. I'm noting it anyway.Tested
Latest revision (ec4b473), rebased onto
mainaac0f1b, RTX 5070 Ti, driver 595.91.07:ctest -R agc_ -j1: 351 of 352. The one failure,agc_driver_dcc_keys_first_write, fails onmainaac0f1b on this machine too.agc_driver_depth_compare_copywith the non-test changes reverted does not build (TakeDepthCopyCountsis missing). With only theShaderResources.cpplookup change reverted it fails with0 depth copy textures and 0 refreshes, expected 1 and 1. With only the refresh loop at the end ofRevalidateremoved it fails withcomparison sample of the same descriptor set after a second store: thread 2 compared to 1.000000, expected 0.000000.Revalidateloop is only pinned on NVIDIA.Earlier revisions:
Nobara 44 / Linux 7.2, GCC 16.2.1, RTX 5070 Ti, driver 595.91.07. Branch rebased onto
maina29ef59.ctest -R agc_ -j1(SPIRV tools on): 322/323, includingagc_driver_depth_compare_copy. The one failure,agc_driver_dcc_keys_first_write, also fails onmainon this setup.ctest -j1 --timeout 60:agc_driver+guest_agc_driver184/184, includingagc_driver_depth_compare_copy. Full run 463/464; the one failure isguest_dynamic_loader, which also fails on the perf(agc): prove sampled depth surfaces in the fast resource proof #1430 branch on the samemainand is not touched here.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