Skip to content

fix(agc): bound the sampled depth-plane copies - #7705

Open
AnthonyClemens wants to merge 2 commits into
boykopovar:mainfrom
AnthonyClemens:fix/agc-bound-depth-plane-copies
Open

AnthonyClemens wants to merge 2 commits into
boykopovar:mainfrom
AnthonyClemens:fix/agc-bound-depth-plane-copies

Conversation

@AnthonyClemens

@AnthonyClemens AnthonyClemens commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

What

A depth plane copy (a depth surface sampled as several slices, an integer view or a cube) stayed in planeCopies() until the device went away. Each copy also kept a staging buffer the size of the copy. A staging buffer it outgrew was moved into retiredStaging and never freed. So every depth surface a scene ever sampled this way kept its copy, and device memory grew with each new scene.

With this change:

  • Each copy shares its image ownership with the views it hands out, through the existing OwnedImage owner of the depth-plane Texture constructor. A copy can leave the cache while a draw or a cached resource set still samples it.
  • The recorder keeps the image and the staging buffer until the recorded copy has run. A copy evicted in the meantime, or a staging buffer it outgrew, never frees memory still in use.
  • Once the copies pass APS5_DEPTH_PLANE_COPY_MIB (default 256; 0 keeps every copy), the least recently used ones leave the cache. A copy made again refills from the depth surface and guest memory, as a new copy does.

DepthPlaneCopyCount() returns the number of cached copies, for the test.

In Resident Evil 2 (PPSA04288), these were the peak depth plane copy allocations under APS5_VK_MEMORY_TRACK:

Build Peak depth plane copy
Before the change 1228 MiB (two runs)
With the change 164–188 MiB (three runs)

The scene rendered the same either way. Without the bound, the staging buffers of the same size added roughly as much again under device buffer.

Tested

Windows 11 Pro (10.0.26200), AMD Radeon RX 9070 XT, WinLibs GCC 15.2.0, Release, on main 85029a0.

  • New: agc_driver_depth_plane_sampling_evicting. It runs the depth-plane sampling cases with APS5_DEPTH_PLANE_COPY_MIB=1 and --evicting. Every copy but the newest leaves the cache, so later cases rebuild evicted copies and must read the same values. It then requires one copy left in the cache.
  • Control (jotitadev's point). The same binary with APS5_DEPTH_PLANE_COPY_MIB=0, which keeps every copy as main does, fails: 8 depth plane copies were kept with a 1 MiB budget, expected only the newest.
  • Unchanged and passing: depth_plane_sampling, depth_plane_guest_layers, depth_plane_fill, depth_compare_copy, depth_storage, depth_storage_dispatch, depth_storage_reuse, depth_surface_from_storage, depth_bits_guest_memory.
  • Rebased onto current main. As MaxLikesCode noted, the prepared_shaders_abi_deferred_* failures came from the old base.
  • Conventions. The code comments the conventions check flagged were removed. Their content is in this description.

Thanks to MaxLikesCode, savvaniss and jotitadev for the NVIDIA, Intel/AMD and MoltenVK runs.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: PPSA04288 (device memory growth across scenes)
  • GPUs tested: AMD Radeon RX 9070 XT, Windows 11 (others in the comments: RTX 4090, Intel UHD 770, Apple M2 Max/MoltenVK)
  • AI-assisted: yes (Claude Code)

@github-actions

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 1341 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 1368 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
PR 1395 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
PR 5021 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 5371 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 5426 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 5431 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 5499 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
PR 5656 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 5925 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6044 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6146 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
PR 6185 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6186 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6187 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6188 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6192 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6209 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6280 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6292 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
PR 6300 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
PR 6457 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6479 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6501 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6588 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6611 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6615 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
PR 6636 docs/dev/ENVIRONMENT.md
PR 6642 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6683 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
PR 6718 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6727 core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
PR 6730 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6747 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6788 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6808 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
PR 6820 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6868 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6887 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6924 docs/dev/ENVIRONMENT.md
PR 6937 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6941 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6946 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 6947 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 6965 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6973 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6977 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
PR 6987 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6989 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6995 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7002 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7048 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7085 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7201 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
PR 7223 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7233 core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
PR 7256 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
PR 7332 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 7395 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7417 docs/dev/ENVIRONMENT.md
PR 7427 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 7446 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7449 core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
PR 7457 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 7484 docs/dev/ENVIRONMENT.md
PR 7505 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7514 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7604 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 7642 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 7683 docs/dev/ENVIRONMENT.md
PR 7800 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp

@jotitadev jotitadev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apple GPU / MoltenVK run. agc_driver_depth_plane_sampling_evicting and the depth-plane tests pass on Metal. Two of the tests listed as unchanged, depth_plane_guest_layers and depth_storage, are skipped on macOS on main. With a loader patch they run and pass with this PR.

Machine: Apple M2 Max, macOS 27.2, x86-64 build under Rosetta. Head 0258a05, PR diff applied cleanly. Drivers: MoltenVK 1.4.2 (Vulkan SDK 1.4.363.0) and MoltenVK main + SPIRV-Cross #2704.

Tested: the tree is main a373e85 + mugurc's macOS series (ci/macos-series-2) + the PRs needed to build on macOS (#6667, #6668, #7524, #6969, and two files of #7332), not plain main (it doesn't build on macOS yet). Also in the same build: #7707, #7698, #7687, #7691 and #7705 (they touch different files and applied cleanly together), plus a test-only patch that lets nine AGC fixtures load the Vulkan loader on macOS (branch jotitadev:fix/agc-tests-vulkan-loader-macos). Base on that tree: 40 ^agc failures with MoltenVK 1.4.2 and 26 with MoltenVK main + #2704.

  • agc_driver_depth_plane_sampling_evicting (APS5_DEPTH_PLANE_COPY_MIB=1), depth_plane_sampling, depth_plane_fill, depth_plane_guest_layers, depth_storage, depth_compare_copy, depth_surface_from_storage and depth_bits_guest_memory: all pass 3 of 3 on both drivers. depth_storage_dispatch and depth_storage_reuse also pass in the full-suite runs.
  • DepthPlaneGuestLayers.cpp and DepthStorage.cpp load libvulkan.so.1 themselves, without portability enumeration. Without the loader patch they print skipped, no usable Vulkan device on macOS, so they don't cover this change there.
  • Full ^agc suite with the stack: 42 of 730 fail on MoltenVK 1.4.2 and 28 of 730 on MoltenVK main + #2704. That is the base failures plus agc_driver_pooled_buffer_range and agc_performance_overlay, which only run because of the loader patch and fail for unrelated reasons. No new failure from this PR.

I didn't do a without-the-fix control. Without the fix, the evicting test's variable does nothing, so the test would pass anyway.

GPUs tested: Apple M2 Max (MoltenVK 1.4.2; MoltenVK main + SPIRV-Cross #2704)

Written with AI assistance (Claude Code). I ran the builds and tests above on my machine.

@MaxLikesCode

Copy link
Copy Markdown

NVIDIA data: GeForce RTX 4090, driver 617.42, Windows 11 Pro 26200, WinLibs GCC 15.2.0 r7, Release, BUILD_TESTING=ON with every execution test built. Head 0258a05, which already contains main 79d7d26.

AI-assisted: yes (Claude Code)

@savvaniss

Copy link
Copy Markdown
Contributor

Windows regression check on an Intel UHD 770 and an AMD RX 9070 XT: no new failures in the full CTest results.

Windows 11 Pro 26300, WinLibs GCC 15.2.0 r7, Release, every execution test built. Intel UHD Graphics 770 (8086:a780), driver 32.0.101.7088. AMD Radeon RX 9070 XT (1002:7550), driver 32.0.31041.1004, with VkCache emptied first. This head 0258a057b merged into main 6b8228b2b.

This PR adds no test, so I ran full CTest (--parallel 4, 1606 tests) with it merged:

AI-assisted: yes (Claude Code)

AnthonyClemens and others added 2 commits October 19, 2026 09:48
A depth plane copy (a depth surface sampled as several slices, an integer view or a cube) was
kept until the device went away, with a staging buffer of its own size, and a staging buffer it
outgrew was never freed. Every depth surface a scene ever sampled this way held its copy, so
device memory grew with each new scene (0.4-1.2 GB in RE2 after a level load).

The copies now share their image's ownership with the views they hand out, the recorder keeps
the image and the staging buffer until the recorded copy has run, and past
APS5_DEPTH_PLANE_COPY_MIB (default 256; 0 keeps every copy) the least recently used copies
leave the cache. A copy made again refills from the surface and guest memory as a new one does.
agc_driver_depth_plane_sampling_evicting runs the plane sampling cases with a 1 MiB budget.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…est copy

agc_driver_depth_plane_sampling_evicting passes --evicting, and the test then requires a single
depth plane copy left in the cache (DepthPlaneCopyCount) after the cases. With
APS5_DEPTH_PLANE_COPY_MIB=0, which keeps every copy, it fails with "8 depth plane copies were kept
with a 1 MiB budget, expected only the newest". The explanatory comments move to the pull request.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@AnthonyClemens
AnthonyClemens force-pushed the fix/agc-bound-depth-plane-copies branch from 0258a05 to f440e3b Compare October 19, 2026 14:06
@github-actions github-actions Bot added the unblocks title Names a title ID on the Unblocks line label Oct 19, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* build docs unblocks title Names a title ID on the Unblocks line

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants