Skip to content

fix(agc): drop stale depth-plane results whose guest memory was unmapped - #9406

Merged
adriadam10 merged 3 commits into
boykopovar:mainfrom
JJenkx:fix/depth-plane-unmapped
Oct 24, 2026
Merged

adriadam10 merged 3 commits into
boykopovar:mainfrom
JJenkx:fix/depth-plane-unmapped

Conversation

@JJenkx

@JJenkx JJenkx commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

What

A depth plane that a draw wrote is marked stale and stored to guest memory later, when something overlaps it or the device stores idle results. If the title has unmapped that memory in the meantime, the store creates a StorageTexture over pages that are no longer committed, and the driver stops:

[gpu] driver failure: AGC graphics: storage texture has no committed guest pages

The path is:

Driver::run -> VulkanDevice::StoreIdleResults -> StorageTexture::FlushPending -> FlushDepthPlanes -> StorageTexture::Create

Wobbly Life (PPSA29413) hits this about 108 s in: it unmaps the memory of a 64 MiB 4096x4096 D32 depth target (64 KiB Z swizzle) after drawing to it, before the plane is stored.

FlushDepthPlanes now checks for readable committed pages before storing a stale plane. A readable plane without write permission retains the existing unsupported-store failure and its pending results; it is not treated as unmapped. When none are left, it does not store the plane: the pending depth is dropped, the surface is no longer stale, and a one-time warning names the plane. The discard path is used only when the readable committed-range query is empty. The debt file records the behaviour, and what the console does with such a store is not known.

Tested

Protected-memory regression correction. The former writable-only guard also discarded pending depth for a readable mapping protected against writes, and printed that it was unmapped. A CPU/mock probe using a real PROT_READ mapping confirms the difference: the pinned main rejects the store and keeps pending depth (rejected=1, pending=1); the original #9406 rebased onto that same main silently drops it (rejected=0, pending=0). The correction queries readable ranges before discarding. The new cross-platform TestReadOnlyStalePlaneFlush requires the original rejection and pending state to survive. The unchanged extended mock fixture fails its specific rejection assertion with the original #9406 libraries and passes with the corrected depth implementation. These initial results use separately compiled objects relinked with the pinned main object set; they are supplemental CPU/mock evidence, not the coherent full-source Vulkan comparison. The coherent Release build also passes. Main a19e7f6f and corrected head f4c543528e each pass agc_driver_graphics and agc_driver_graphics_maps_fallback three times (six runs per arm). The exact coherent corrected fixture fails the readable-protection assertion against the original rebased #9406 libraries in both query paths. These binaries use a mock device and do not establish Vulkan-layer coverage. Coherent paired hardware validation also passes on main a19e7f6fdc5475c538e2a9135aa45880503ef377 and head f4c543528eb339d059f9472b02cae9475e5d81e8: five focused checks per arm (host-import mock, graphics mock, depth-plane partial store, depth storage and prepared exports). Vulkan required, shader cache disabled, actual Khronos insertion confirmed in each of the three hardware cases. Both arms have the same pre-existing VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605; the change adds no VUID types. This does not claim zero validation errors. Conventions and whitespace pass; merge-tree is clean against newer main ad19afc31e, which was not the test baseline. Pinned raw hardware/mock logs, negative-control results and source review. A Windows exact-head mock check has been requested separately and is not claimed here.

Independent macOS report, historical head. @imellag reports Planet of Lana PPSA19450 on Apple M4 Pro, macOS 27.0.1 under Rosetta 2 and MoltenVK 1.4.2. The tester identifies the same unmapped 64 MiB D32 depth-plane flush path with a backtrace and preceding memory-unmap trace. Four runs without this PR stopped; two with historical head 1855089a95 reached gameplay and the 200-second limit, logging the drop warning. This was a macOS integration containing #8658 and several other patches, not stock main, and has not been rerun with the protected-memory correction. It is attributed external correctness evidence; no FPS gain or console equivalence is inferred.

Independent same-base repeat, 2026-10-23: @xXPBSXx reports PPSA25936 on main ba1b117cec6caa95fb6e0c46b4392baa0ce2d11c versus that exact main plus this PR head 1855089a95e9ab865a4b50d952c6e72044e3f9c4 (local merge 1478b1c4642184969a9e5439e28f73402ece13bb). Two 600-second runs per arm on each of AMD Radeon RX 6400 and NVIDIA RTX 4080 SUPER: the storage-texture/no-committed-pages stop occurs in both main runs on each GPU and in neither change run on either GPU. The tester reports unchanged non-AGC libraries and relinker between arms. This is attributed external evidence, not a local rerun; n=2 per arm/GPU does not establish an intermittent-failure rate, other-title coverage, gameplay correctness, console equivalence or an FPS gain. The common base is deliberately older than the then-current main. This repeat replaces that tester's earlier comparison between different main revisions.

Linux 7.2.9, Ryzen 9 7950X, Radeon RX 6650 XT, RADV Mesa 26.2.4, Release.

New test. TestUnmappedStalePlaneFlush in agc_driver_graphics (DepthSurfaceReuse.cpp, mock device) draws to a mirrorable D32 plane at an unmapped address, then flushes it. It requires that the flush does not throw, stores nothing and clears the stale state.

  • With the change: passes.
  • With DepthSurface.cpp restored to main and the test kept: fails, because the flush throws (rechecked on b27924d851).

Independent Linux regression report. On head 1855089a9 merged onto main 7e2ba73e4, Dextroid17 reports that both agc_driver_graphics and agc_driver_graphics_maps_fallback pass 6/6 runs each; restoring main's DepthSurface.cpp while keeping the regression test makes both fail 6/6. This exercises both Linux PROCMAP_QUERY and /proc/self/maps paths. These focused binaries use a mock device and do not load the Vulkan loader or ICD; setting VK_INSTANCE_LAYERS for them does not establish validation-layer coverage. The actual Vulkan comparison is the separate full-suite report below. These are independently reported results on CachyOS, not a local rerun (report).

Full ctest -j8. Run on main b27924d851 and on this change rebased onto it (1855089a95), with VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation (the loader inserted the layer; no was not found but was requested line), ANYPS5_REQUIRE_VULKAN=1 and ANYPS5_NO_SHADER_CACHE=1. Both runs have 1827 tests with the same 4 failures and the same 25 skips. The failures are:

  • guest_named_shm_concurrency;
  • agc_idle_publish_wait;
  • agc_driver_image_array_window_past_layer_limit;
  • agc_driver_tessellation (segfault).

The VUID- sets and counts are identical:

VUID Count
VkWriteDescriptorSet-descriptorType-00337 32
VkPipelineColorBlendStateCreateInfo-pAttachments-00605 26
VkImageMemoryBarrier-image-03320 12
VkImageViewCreateInfo-usage-02275 6
vkCmdCopyBuffer-srcBuffer-00118 2

With DepthSurface.cpp restored to b27924d851 and the test kept, agc_driver_graphics fails under the same environment, because the flush throws. The same comparisons on the earlier bases 0c6a5bd593 (1813 tests) and b3c0f48bdd (1806 tests) also matched.

PPSA29413, natively. Same scripted input (Cross every 15 to 20 s):

Build Runs Result
main cecb540a63 2 stops at about 108 s with the error above
main 0c6a5bd593 1 stops at about 108 s with the error above
this change, before the rebase 2 runs to the 300 s limit
this change, after the rebase 2 runs to the 300 s limit

The runs with the change reach the play menu, the tutorial prompt and the intro comic at about 120 FPS. Each printed the drop warning once for the title's 64 MiB depth plane, and none caused a GPU fault in the kernel log.

Rebase. Main's per-unit depth-plane stores (#9026) now store only the overlapped units. The check sits in that path, before SyncFromMemory, and clears every stale unit of an unmapped plane. The PPSA29413 rows below are on the earlier bases; the title was not rerun on b27924d851.

Overlap. #1368 and #1395 also change DepthSurface.cpp, and #1368 changes DepthSurfaceReuse.cpp. Neither changes FlushDepthPlanes or handles a plane whose memory is unmapped: #1368 adds 2D-array depth storage and only sets maxImageArrayLayers in RunDepthSurfaceReuseTests, and #1395 adds an alternative array-storage path. Both conflict with current main, so a merge with this PR was not tested; whichever lands second must keep this check and test. This PR does not depend on either.

  • Independent Windows data points on head 8e6bbb3a2d merged onto current main: agc_driver_graphics passes 3 of 3 and fails 3 of 3 with main's DepthSurface.cpp restored. One ran on an RTX 5070 Ti and an AMD RDNA2 iGPU (comment); the other did not record its GPU (comment).

Other titles (reports by others in this PR):

  • Biped (PPSA24589), Windows, RTX 5070 Ti: on main, opening the pause menu stops with this error; with the PR the pause menu, resume and return to the main menu work over a 900 s session, and the drop warning is printed (comment).
  • Hamster Playground (PPSA06652), Linux: loading a house stops about 2 s later on 0c6a5bd593 in 3 of 3 runs; see the comment for the runs with the PR (comment).

Not verified:

  • what the console does when a title unmaps memory that holds pending depth;
  • other titles.

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: PPSA29413 (Wobbly Life (PPSA29413) #2211), PPSA24589 (Biped (PPSA24589) #9376), PPSA06652
  • GPUs tested: AMD Radeon RX 6650 XT, RADV Mesa 26.2.4, Linux 7.2.9-arch1-1
  • AI-assisted: yes

🤖 Generated with Claude Code

@github-actions github-actions Bot added unblocks title Names a title ID on the Unblocks line needs rebase Conflicts with main, rebase needed labels Oct 21, 2026
@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

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.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 9159 docs/dev/debt/libSceAgcDriver.md L93

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 1368 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
core/libs/prx/libSceAgcDriver/tests/DepthSurfaceReuse.cpp
PR 1395 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
PR 2434 docs/dev/debt/libSceAgcDriver.md
PR 4448 docs/dev/debt/libSceAgcDriver.md
PR 5058 docs/dev/debt/libSceAgcDriver.md
PR 5372 docs/dev/debt/libSceAgcDriver.md
PR 5925 docs/dev/debt/libSceAgcDriver.md
PR 6146 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6186 docs/dev/debt/libSceAgcDriver.md
PR 6194 docs/dev/debt/libSceAgcDriver.md
PR 6223 docs/dev/debt/libSceAgcDriver.md
PR 6273 docs/dev/debt/libSceAgcDriver.md
PR 6280 docs/dev/debt/libSceAgcDriver.md
PR 6300 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6412 docs/dev/debt/libSceAgcDriver.md
PR 6481 docs/dev/debt/libSceAgcDriver.md
PR 6548 docs/dev/debt/libSceAgcDriver.md
PR 6549 docs/dev/debt/libSceAgcDriver.md
PR 6804 docs/dev/debt/libSceAgcDriver.md
PR 6808 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6867 docs/dev/debt/libSceAgcDriver.md
PR 6977 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7201 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
PR 7256 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7449 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7604 docs/dev/debt/libSceAgcDriver.md
PR 7642 docs/dev/debt/libSceAgcDriver.md
PR 7668 docs/dev/debt/libSceAgcDriver.md
PR 7910 docs/dev/debt/libSceAgcDriver.md
PR 8014 docs/dev/debt/libSceAgcDriver.md
PR 8223 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 8319 docs/dev/debt/libSceAgcDriver.md
PR 8592 docs/dev/debt/libSceAgcDriver.md
PR 9356 docs/dev/debt/libSceAgcDriver.md
PR 9387 docs/dev/debt/libSceAgcDriver.md
PR 9393 docs/dev/debt/libSceAgcDriver.md
PR 9401 docs/dev/debt/libSceAgcDriver.md
PR 9431 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9432 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9533 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9592 docs/dev/debt/libSceAgcDriver.md
PR 9672 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9673 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9674 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9675 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9676 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9700 docs/dev/debt/libSceAgcDriver.md
PR 9717 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9742 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9842 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9891 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9892 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9893 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9895 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9898 docs/dev/debt/libSceAgcDriver.md
PR 9904 docs/dev/debt/libSceAgcDriver.md
PR 9905 docs/dev/debt/libSceAgcDriver.md
PR 9906 docs/dev/debt/libSceAgcDriver.md
PR 10049 docs/dev/debt/libSceAgcDriver.md
PR 10193 docs/dev/debt/libSceAgcDriver.md
PR 10233 docs/dev/debt/libSceAgcDriver.md
PR 10420 docs/dev/debt/libSceAgcDriver.md
PR 10472 docs/dev/debt/libSceAgcDriver.md
PR 10581 docs/dev/debt/libSceAgcDriver.md

@wachi35676

Copy link
Copy Markdown
Contributor

This needs a rebase: head ecb2220 no longer merges onto main a6dcea927. git merge-tree reports conflicts in Graphics/src/DepthSurface.cpp and docs/dev/debt/libSceAgcDriver.md. #9026 (f57bbc936, "store only the depth plane units a flush overlaps") rewrote FlushDepthPlanes. The surface->memoryStale = false; … SyncFromMemory … stored.emplace_back(...) block the check was inserted into no longer exists. Main now stores per-unit through StaleUnitsIn/StoreDepthPlane(resource, units)/ClearStale(units).

Is the bug still on main? I applied only the PR's TestUnmappedStalePlaneFlush to main a6dcea927 (Windows 11, WinLibs GCC 15.2.0, Release; mock-device test, run with both the RTX 5070 Ti and the Radeon iGPU selected). agc_driver_graphics fails:

flushing a depth plane whose guest memory is not mapped must drop its results: AGC graphics: guest storage texture format 100 cannot be used as a storage image

So the flush still tries to store the unmapped plane on main. In the mock it now fails on the storage-format check, before the storage texture has no committed guest pages check in Texture.cpp. The rebased check needs to go before SyncFromMemory/StoreDepthPlane in the new overlapped-units branch. It also needs to clear the stale units there, so that DepthPlanesStale() turns false.

Nit: the diff adds #include <cstdio> while the file already includes it three lines below.

AI-assisted: yes (Claude Code); results above were run on this machine.

@JJenkx
JJenkx force-pushed the fix/depth-plane-unmapped branch 2 times, most recently from ecb2220 to 8e6bbb3 Compare October 21, 2026 23:17
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 21, 2026
@JJenkx

JJenkx commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

Thanks, and for confirming the bug on main with the mock test. The PR head is now 8e6bbb3a2d, rebased onto 0c6a5bd593 (after #9026), and git merge-tree against current main is clean.

  • The check now sits in the overlapped-units branch, before SyncFromMemory/StoreDepthPlane. For a plane without writable committed pages it calls surface->ClearStale(), so DepthPlanesStale() turns false, and continues.
  • DepthSurface.cpp includes <cstdio> once; the duplicate came from main's file during the rebase and is gone.
  • The revalidation after the rebase is in the description:
    • matched full ctest with Khronos validation on main 0c6a5bd593 and on the PR: 1813 tests, same failures, same VUIDs;
    • PPSA29413: main crashes at 109 s; two runs with the PR run to the 300 s limit.

@wachi35676

Copy link
Copy Markdown
Contributor

Re-checked 8e6bbb3a2 merged onto current main (clean) on Windows 11, WinLibs GCC 15.2.0, Release, ANYPS5_REQUIRE_VULKAN=1:

  • agc_driver_graphics passes 3/3 on the RTX 5070 Ti and 3/3 on the AMD RDNA2 iGPU (ANYPS5_GPU=AMD). That includes TestUnmappedStalePlaneFlush.
  • Negative control: with DepthSurface.cpp from main, it fails with flushing a depth plane whose guest memory is not mapped must drop its results: ... guest storage texture format 100 cannot be used as a storage image, which is the failure from my earlier comment.
  • The rebase onto perf(agc): store only the depth plane units a read overlaps #9026's FlushDepthPlanes and the single <cstdio> include look right.

AI-assisted: yes (Claude Code); results above were run on this machine.

@github-actions github-actions Bot added docs agc libSceAgc* labels Oct 22, 2026
@xXPBSXx

xXPBSXx commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

Windows data point for 8e6bbb3a2 merged onto main 6ef5a1c4c (clean, git merge-tree rc 0): Windows 10.0.19045, MinGW-w64 GCC 15.2.0, Release. ctest -N -R '^agc_driver_graphics$' lists exactly that one test; ctest --no-tests=error -R '^agc_driver_graphics$' was run three times per tree. The GPU was not recorded in these logs, so no device is claimed.

  • With the PR: passes 3 of 3 (11-15 s).
  • Same tree with core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp restored to main (the new test cases kept): fails 3 of 3 (ordinary test failure, not a crash).
    Not tested: other platforms, a title run.
    AI-assisted (Claude Code).

@MarcZX10 MarcZX10 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.

The reported failure is reproducible in the mock regression, and the change places the unmapped-memory check before synchronization and storage. The author’s paired Vulkan validation-layer runs, title negative control, and independent Windows positive/negative runs are useful evidence. git diff --check also passes on the current head.

I’m requesting changes for the remaining repository requirements:

  • The branch is still based on 0c6a5bd593, while current main is 4a17c71757. Please rebase onto current main, resolve any conflicts, and refresh the focused AGC validation runs on that base. AGC changes require the same focused tests on main and the change with the validation layer and Vulkan-required environment, comparing VUIDs and naming the GPU.
  • The current overlap scan cannot compare this branch against #1368 (shared DepthSurface.cpp and DepthSurfaceReuse.cpp) or #1395 (shared DepthSurface.cpp) because those branches conflict with current main. Both PRs modify the depth-surface implementation. Please manually establish whether the changed behavior overlaps, coordinate the order with their authors where it does, and update Depends on: accordingly. The scan also identifies uncomparable shared debt-file edits; please refresh that check after rebasing and resolve any actual same-entry overlap with the authors.

The recorded Linux full-suite and title runs are on base 0c6a5bd593, not current main; the external Windows checks are valuable independent reports but do not replace the required refreshed paired validation. No local AGC test was run in this review environment: it has no /dev/dri device or existing build tree. Hosted product jobs on this PR are skipped; the conventions check, eligibility, labels, and report checks pass.

@JJenkx

JJenkx commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

A second title for this fix, and it reproduces on demand: Hamster Playground (PPSA06652) 01.009.000, Unity. Linux 7.2.9, Radeon RX 6650 XT, RADV Mesa 26.2.4, GCC Release.

Trigger: from a save that already has a house, Cross at 25/40 s clears the disclaimer, Down at 55 s moves to PLAY on "Select your house", Cross at 58 s loads the house. On main the driver stops about 2 s later, at 60.3 s, every time I've run it that way:

[gpu] driver failure: AGC graphics: storage texture has no committed guest pages

Stack (GDB on main 38d3c0858a, breaking at _Unwind_RaiseException in libc.prx): the first throw is this PR's path:

AgcDriver::Graphics::Require(bool, char const*)
AgcDriver::Graphics::StorageTexture::StorageTexture(...)
AgcDriver::Graphics::StorageTexture::Create(...)
AgcDriver::Graphics::FlushDepthPlanes(unsigned long, unsigned long)
AgcDriver::Graphics::StorageTexture::FlushPending(...)
AgcDriver::VulkanDevice::StoreIdleResults(bool)
AgcDriver::DriverDetail::Driver::run(unsigned int)

The presenter thread only reports it afterwards ([videoout] presentation failed).

Before/after: this PR's base 0c6a5bd593 against its head 8e6bbb3a2d. Only libSceAgcDriver.prx differs (sha256 prefixes d850c2947bd5d79c and 64a871bf7952ae3b); every other library is the same set, and the title is relinked against each. Same input schedule, same restored save before every run.

side runs result
base 0c6a5bd593 3 all stop at 60.3 s with storage texture has no committed guest pages
this PR 8e6bbb3a2d 3 all run to the end (152.6–153.3 s), no driver failure

Two of the pairs come from a launch that restored the same save before every run. The third pair is from the run right after the one that created the house.

With this PR the house loads: the in-game tutorial notebook over the 3D room, then the "Skip Tutorial" dialog. The log has this PR's warning in place of the stop:

[gpu] depth plane 0x277050000+0x1fe0000 was unmapped with GPU results pending; they are dropped

followed by four storage image ...+0x1fe0000: memory no longer registered; 510 pending ranges dropped lines.

Logs and reports of all six runs, the two screenshots, and the GDB log with its script: 20261022-pr9406-PPSA06652.tar.gz (sha256 c99e6e173cb370faf87a79077eeac4fcff160bafdefd6331879a09f5a6100de2).

AI-assisted testing and report: yes, Claude Code.

@JJenkx
JJenkx force-pushed the fix/depth-plane-unmapped branch from 8e6bbb3 to 1855089 Compare October 22, 2026 06:31
@JJenkx

JJenkx commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

@MarcZX10 thanks. Addressed:

  • Rebase. Now on main b27924d851 as 1855089a95; it applied without conflicts. tools/check_conventions.py --base origin/main passes. The debt change is one new bullet after "Depth planes in guest memory" and edits no existing entry.

  • Paired validation on that base. Full ctest -j8 on b27924d851 and on 1855089a95, run on a Radeon RX 6650 XT (RADV Mesa 26.2.4, Linux 7.2.9). Environment: VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation (the loader inserted the layer, with no was not found line), ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1. Results:

    • both runs have 1827 tests, the same 4 failures and the same 25 skips;
    • the VUID- sets and counts are identical; the table is in the body.
  • Negative control on that base. With DepthSurface.cpp restored to b27924d851 and the test kept, agc_driver_graphics fails under the same environment: "flushing a depth plane whose guest memory is not mapped must drop its results".

  • Overlap with feat(agc): retain and refresh sampled depth array storage #1368 and feat(agc): add experimental depth clear and copy recognition #1395. I compared their patches. Neither changes FlushDepthPlanes or handles a plane whose memory is unmapped:

    So Depends on: none stays. Both conflict with current main, so I could not test either combined with this PR. Whichever lands second has to keep this check and its test; I've noted that in the body and will ping their authors.

The title runs in the body are still from the earlier bases; Wobbly Life was not rerun on b27924d851.

@THEMANnt

Copy link
Copy Markdown

Windows Biped (PPSA24589), content version 01.000.002, 2026-10-22 retest for discussion #9376.

Compared unmodified main 7e2ba73e4c8c26b5d632b0d2f46166ffc1b8a29d against PR head 1855089a95e9ab865a4b50d952c6e72044e3f9c4 merged cleanly onto it (local merge 61bdb4b103c37455dab895304c87b4bf35e30f96). Windows 11 Pro build 26200, Ryzen 7 7800X3D, 32 GB RAM, RTX 5070 Ti 16 GB, NVIDIA 616.92, GCC 15.2 Release.

  • Main: gameplay was reachable. Opening the pause menu with Esc produced AGC graphics: storage texture has no committed guest pages and SIGABRT at about 170 seconds. The harness subsequently stopped the failing process at 172.08 seconds when available RAM fell below 5 GiB; its recorded stop reason is memory_watchdog, not a natural crash exit.
  • With fix(agc): drop stale depth-plane results whose guest memory was unmapped #9406: I verified opening the pause menu, resuming and returning to the main menu without that crash. Recording lasted 900.69 seconds total, including startup, menus and user-controlled play; stop reason duration_limit. No storage-texture driver failure or SIGABRT captured. The PR's new path was exercised:
[gpu] depth plane 0x268950000+0x1000000 was unmapped with GPU results pending; they are dropped

Both runs reused the same source assets and the same pre-run save snapshot, with isolated frozen runtime-library copies. The native game executable was identical. No game patch, metadata override or scripted controller input. Candidate minimum sampled available RAM was 5.14 GiB; available commit 21.79 GiB.

Focused tests: agc_driver_graphics, agc_driver_depth_fast_clear, agc_driver_depth_storage passed 3/3 on both trees, with ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1, and VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, verbose CTest output. Both logs have zero VUID- matches and no missing-layer warning; the Vulkan test selected the RTX 5070 Ti. Candidate graphics coverage includes TestUnmappedStalePlaneFlush. An initial depth-test attempt skipped because the build selection omitted those sources; they were enabled, rebuilt and run successfully for the comparison above.

Remaining: main-menu music is still absent; gameplay music works (verified with the PR). The earlier cutscene-audio issue was not rechecked. Save reload and full-game/long-term stability are not established by this bounded run. These mixed-scene FPS samples are not a performance comparison.

The title was sitting in a menu midway through the candidate session; I then resumed gameplay. The total recording duration is not continuous gameplay duration.

Near the end, I confirmed that gameplay after resuming remained responsive, without another freeze or visible graphics problem.

AI-assisted: yes (Codex prepared the builds/logging and checked results; I controlled and visually tested the game).

@Dextroid17

Copy link
Copy Markdown
Contributor

Linux data point for 1855089a9 on main 7e2ba73e4 (local merge 44ddd9d81, git merge-tree clean): CachyOS, kernel 7.2.11, GCC 16.2.1, CMake 4.4.3, Ninja, Release, ANYPS5_NO_SHADER_CACHE=1, ANYPS5_REQUIRE_VULKAN=1, -j1. ctest -N -R '^agc_driver_graphics' lists two tests here: agc_driver_graphics and the Linux-only agc_driver_graphics_maps_fallback (APS5_NO_PROCMAP_QUERY=1), which the Windows runs above cannot cover: the new GuestMemory::CommittedRanges call in FlushDepthPlanes goes through describePages, which on Linux takes the PROCMAP_QUERY ioctl or, with that variable set, the /proc/self/maps scan (on Windows, VirtualQuery).

Head. Both tests pass 6 of 6 runs each (3 plain, 3 with VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, which changes nothing here, see below); each test's output has the new [gpu] depth plane 0xa0000000+0x40000 was unmapped with GPU results pending; they are dropped line, on the ioctl path and on the /proc/self/maps fallback alike.

Negative control. Graphics/src/DepthSurface.cpp from 7e2ba73e4, the PR's DepthSurfaceReuse.cpp kept: both tests fail 6 of 6, always flushing a depth plane whose guest memory is not mapped must drop its results: AGC graphics: guest storage texture format 100 cannot be used as a storage image, the line @wachi35676 reported on Windows in #9406 (comment); the was unmapped message does not appear.

One note for anyone adding a validation-layer arm here: agc_driver_graphics_tests is a mock-device binary and loaded no Vulkan loader or ICD on this host (LD_DEBUG=libs lists no libvulkan.so.1; VK_LOADER_DEBUG=all prints nothing), so VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation cannot apply to it and no GPU name attaches to its result.

AI-assisted: yes (Claude Code); results above were run on this machine.

@JJenkx

JJenkx commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

Additional native crash-regression evidence: Outer Wilds (PPSA08102), Linux/RADV, same machine and the same three-file starting-save manifest in both arms.

  • Main d6e7ab42dfe191818721c6c5ad9aee4070b434aa: aborts, exit 134, at 184.16 s with AGC graphics: storage texture has no committed guest pages.
  • That main plus only this PR (local 507f040c0f652cf1ed341688c75c8a949f4bd691, replaying the changes at PR head 1855089a95e9ab865a4b50d952c6e72044e3f9c4; no perf(shader): reuse an evicted memo result's bindings for the next miss #9049): the storage-texture failure is absent. The run remains alive through the scheduled window close at 535 s and exits 0 at 537.10 s. It logs once: [gpu] depth plane 0x218c30000+0x1fe0000 was unmapped with GPU results pending; they are dropped.

The candidate's 330 s capture has a black “Wake Up” screen; at 510 s it shows an outdoor first-person scene with “Look Around” / “Move” prompts. That scene is very dark, so this establishes progress past the reproducible abort, not correct brightness or gameplay responsiveness. The test started from the saved checkpoint, sent Cross at 100 s and 170 s, and sent held Circle at 230 s and 330 s; the original runtime/save/configuration were restored afterward.

This is one baseline and one candidate on the frozen d6e7ab42 base, not latest-main coverage, a matched-scene performance result, or native validation-layer coverage. Full logs, save hashes, executable hash and captures are retained locally; the focused validation results already recorded above are separate evidence.

@xXPBSXx

xXPBSXx commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Correction (please disregard the comparison below): the run without this PR and the runs with it were built on different main bases (b3e42bd1eb against 513ca7e558 plus this PR, 36 commits apart, 35 of them touching AGC files), so the two states are not comparable and the comparison does not show what this PR changes. I am repeating it with one base for both states and will post the result here.


Title data point (Windows, AMD Radeon RX 6400), PPSA25936, two 600 s runs per state; libs rebuilt for each state.

  • GPU, every run: Selected GPU name=AMD Radeon RX 6400 vendor=0x1002 device=0x743f (run_*.out).
  • Without this PR (fresh upstream/main b3e42bd1eb): both runs stop with AGC graphics: storage texture has no committed guest pages, after about 2 minutes each (run_113625 line 1713, run_113912 line 1797).
  • With this PR (the same main plus fix(agc): drop stale depth-plane results whose guest memory was unmapped #9406 merged locally, head 1855089a95): no run shows that message. The first run (run_122646) goes on for the whole 600 s. The second (run_123824) ends after about 5 minutes with a different failure, a game-side access violation (0xc0000005 on UnityGfxDeviceWorker, write of 0x18); I do not know whether this PR plays any part in it.

This is n=2 per state on one GPU, and the debt entry describes the stop as intermittent (an earlier run of this title on an RTX 4080 SUPER, run_115620, Selected GPU name=NVIDIA GeForce RTX 4080 SUPER vendor=0x10de device=0x2702, also stopped there), so n=2 per state shows absence here, not a rate. PPSA15065 was run the same way (two runs per state, same GPU): no storage-texture stop in any of the four runs, so it says nothing about this PR. Run folders (file names only): PPSA25936_rNT/run_113625, run_113912, run_122646, run_123824.

AI-assisted (Claude Code).

@xXPBSXx

xXPBSXx commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Repeat of the PPSA25936 data point, with both states built from the same main. This replaces the earlier comment, whose two states were built from different main commits (that is the correction noted there).

Build: A = upstream/main ba1b117cec6caa95fb6e0c46b4392baa0ce2d11c, all libs built. B = A plus #9406 head 1855089a95e9ab865a4b50d952c6e72044e3f9c4, merged locally (merge commit 1478b1c4642184969a9e5439e28f73402ece13bb, first parent A; the merge changes the 3 files of this PR, +27 lines); only the AGC driver and what depends on it was rebuilt for B, the other libs and the relinker are the same files as in A. main has moved on by 35 commits since; both states use the older common base on purpose.

Runs: PPSA25936, 600 s each. The stop counted is AGC graphics: storage texture has no committed guest pages.

State GPU (from Selected GPU in each run's .out) Runs Stop in
A (main) AMD Radeon RX 6400 (vendor=0x1002 device=0x743f) run_145027, run_145241 2 of 2, after about 2 minutes
B (main + #9406) AMD Radeon RX 6400 run_152322, run_153522 0 of 2, no abort
A (main) NVIDIA GeForce RTX 4080 SUPER (vendor=0x10de device=0x2702) run_142708, run_142926 2 of 2, after about 2 minutes
B (main + #9406) NVIDIA GeForce RTX 4080 SUPER run_154659, run_155847 0 of 2, no abort

n=2 per state and GPU shows that the stop is absent with this PR in these runs, not a rate; the debt entry describes the stop as intermittent. The earlier B run that ended in a game-side access violation (on main 513ca7e558 plus #9406) did not repeat here (no abort in four B runs). No other title was run; no console source.

AI-assisted (Claude Code).

@imellag

imellag commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Tested on macOS with Planet of Lana (PPSA19450, 01.010.000, Unity), which hits this stop on every run about 8 s after choosing New Game on slot 1:

[gpu] driver failure: AGC graphics: storage texture has no committed guest pages

A local print at the throw shows the same case the PR describes: a 4096x4096 D32 depth plane (tile mode 4, 64 MiB) at 0x30fa90000, with no mapped pages left. With APS5_TRACE_MEMORY=1, the title releases the physical memory and unmaps 0x30fa80000+0x4040000 just before the throw. The backtrace is the PR's path:

StorageTexture::StorageTexture <- StorageTexture::Create <- DepthSurface::Mirror <- DepthSurface::StoreDepthPlane
<- FlushDepthPlanes <- StorageTexture::FlushPending <- StorageTexture::FlushAllPending
<- VulkanDevice::StoreIdleResults <- Driver::run

Apple M4 Pro, macOS 27.0.1, x86-64 under Rosetta 2, MoltenVK 1.4.2. main does not build on macOS yet, so this ran on #8658 (e1b9724391) with #8477, #9263, #9193, #9746, #9737, #10062 and #6926 merged. Every run starts a new save and presses cross at 55, 72 and 90 s:

Runs Stopped
without this PR 4 4, at about 98 s
this PR (head 1855089a95) merged 2 0; each run reaches gameplay and runs to the 200 s limit, logging once depth plane 0x30f8d0000+0x4000000 was unmapped with GPU results pending; they are dropped

Three of the runs without the PR, and both with it, also carried a local print on the throw path (it only prints there). In the village after the intro, the run with this PR held 27.9 fps (p50 35 ms). An older macOS build from before #7154, which does not have FlushDepthPlanes, ran the same sequence at 26.9 fps without stopping.

@JJenkx
JJenkx force-pushed the fix/depth-plane-unmapped branch from 1855089 to f4c5435 Compare October 23, 2026 18:55
@JJenkx

JJenkx commented Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto main a19e7f6fdc5475c538e2a9135aa45880503ef377, final head f4c543528eb339d059f9472b02cae9475e5d81e8. This also fixes an overbroad original guard: a readable, write-protected mapping was incorrectly classified as unmapped and its pending depth discarded. The guard now checks readable ranges, preserving main’s explicit unsupported-store rejection and pending state for protected readable memory. A new cross-platform mock regression fails with the original guard and passes with the correction.

Full coherent build passes. Main and change each pass both Linux graphics mock query paths3x (6runs/arm), with expected exact-fixture negatives against the original guard in both paths. Matched RX6650XT/RADV hardware comparison passes5/5 per arm; Khronos loads in each3 hardware cases, Vulkan required/cacheoff. Both have the same existing independentBlend00605 VUID; no new VUID types, not a zero-error claim. Fresh conventions/whitespace and clean merge-tree against mainad19afc31e.

#1368 and #1395 heads remain unchanged from the manual overlap review: neither edits FlushDepthPlanes; #1368’s fixture edit sets maxImageArrayLayers. Existing merge-order coordination is on #1368; no feature dependency was introduced and neither conflicted branch was integrated or claimed tested. The description retains attributed Windows and macOS reports on their original pins.

Exact source pins, raw hardware/mock logs and negative controls. No fresh native-title or FPS claim.

@iamthehimansh

Copy link
Copy Markdown
Contributor

Tested on an Apple M2 Pro, macOS, x86_64 Release under Rosetta 2, MoltenVK 1.4.2, applied on top of #8658's feat/macos-port (27abf7e4b) together with #8477, #9263, #9746 and #9406. I built the whole tree and ran the full suite (1,962 tests), then ran any new failure 3x on its own with each PR alone.

AI-assisted: yes (Cana)

@adriadam10
adriadam10 dismissed MarcZX10’s stale review October 24, 2026 10:21

Dismissing a stale review: the requested changes were addressed after it (new head and/or updated description with the asked-for runs) and the merge queue blocks on it. Please request changes again if anything is still open.

@adriadam10
adriadam10 merged commit af45c30 into boykopovar:main Oct 24, 2026
12 checks passed
@adriadam10

Copy link
Copy Markdown
Collaborator

Re-checked f4c543528e against current main (merges cleanly; the new DB depth copy commit doesn't touch FlushDepthPlanes or the store paths): the readable-committed-ranges check sits before SyncFromMemory, only a plane with no readable pages is dropped, TestUnmappedStalePlaneFlush fails with main's DepthSurface.cpp, and TestReadOnlyStalePlaneFlush pins the protected case; merged.

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

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants