Skip to content

fix(agc): promote a held import window to its whole allocation - #5870

Merged
adriadam10 merged 1 commit into
boykopovar:mainfrom
Sam-mon7:fix/promote-held-import-window
Oct 15, 2026
Merged

adriadam10 merged 1 commit into
boykopovar:mainfrom
Sam-mon7:fix/promote-held-import-window

Conversation

@Sam-mon7

@Sam-mon7 Sam-mon7 commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

What

Fixes a boot abort in Demon's Souls (PPSA01341) on main, about 30 s in, after 2 frames:

FATAL: an address-based build copies 358 MiB of 1 registered ranges, past 64 MiB (APS5_ADDRESS_COPY_MAX_MIB); the largest: 0x260100000+0x166f0000 (358.9 MiB committed, outside the write-watched arena)
  • Cause: the active recorder holds a 64 MiB import window. That hold refuses the import of the window's whole registered allocation, so the build copies all 358 MiB instead.
  • Fix: while a recorder is active, the containing import of the same allocation may replace the held window. The retired window stays alive through the hold (KeepThroughHold), so pointers the build already took stay valid.

Tested

Windows 11 (26200), WinLibs GCC 15.2.0, Release, RTX 4070.

  1. Demon's Souls on main 63fb0cd92: the abort above.
  2. The same with this PR: no abort. Boot continues into shader preparation, where the next stop is memory (perf(agc): allow shader preparation on first use #5872).
  3. agc_host_import_retire: the new WindowPromotionOutlivesTheHold case fails without the fix ("a held import window could not be promoted to its whole registered range") and passes with it.
  4. ^(agc_|windows_backtrace_): 534 passed, 0 failed, 3 skipped (two udmabuf tests are Linux only; the RTX 4070 has no stencil export).

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
  • Unblocks: PPSA01341 Demon's Souls (PPSA01341) #1283
  • GPUs tested: NVIDIA GeForce RTX 4070, driver 596.21, Windows 11
  • AI-assisted: yes

A 64 MiB import window held by the active recorder blocked the containing import of the same registered allocation, so an address-based build copied the whole range instead. Demon's Souls then stopped after two frames: "an address-based build copies 358 MiB of 1 registered ranges, past 64 MiB".

Allow the containing import when the recorder is active; the retired window stays alive through the hold (KeepThroughHold). Cover promotion, a sync inside the hold and release after the hold's last batch.
@Dextroid17

Copy link
Copy Markdown
Contributor

I ran this PR's test on Linux.

Setup: this PR's diff applied to main at 8cd937e (the PR's base is 464 commits behind it), default CMake build (CMAKE_BUILD_TYPE empty, unoptimized), clean environment. ctest -R '^agc_host_import_retire$', 3 runs each. The test did not open a GPU device, so this is a CPU-only run.

  • with this PR: 3 of 3 pass.
  • with Graphics/src/GuestBufferMemory.cpp put back to main's version (the new test kept): 3 of 3 fail at "FAIL: a held import window could not be promoted to its whole registered range".

So the new test catches the old behaviour here. I did not check Windows, macOS or a real GPU.

AI-assisted: yes

@fdfawef324

Copy link
Copy Markdown
Contributor

Same stop reproduced here, and this PR clears it. Demon's Souls PPSA01342 (ds_enableDebugStartMenu package args), Windows Server 2025, RTX 3060 12 GB (driver 591.86), Ryzen 9 5900X, MinGW GCC 15.2 Release.

  • main 2559e9623 + fix(agc): treat a TYPE 1 T# in a read-only static image slot as null #5828 + a local follow-up for static descriptors: aborts 107 s in, after 2 presents:
    FATAL: an address-based build copies 358 MiB of 1 registered ranges, past 64 MiB (APS5_ADDRESS_COPY_MAX_MIB); the largest: 0x260100000+0x16690000 (358.6 MiB committed, outside the write-watched arena)
  • The same build plus this PR's commit (cherry-picked cleanly): no abort. With a cold shader cache, boot continued to the title's debug start menu at about 450 s.

I only ran this on a cold cache, so I have no timing comparison. agc_host_import_retire wasn't rerun here; Sam-mon7 and Dextroid17 already reported it.

AI-assisted: yes

This was referenced Oct 15, 2026
@github-actions

github-actions Bot commented Oct 15, 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 6499 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp L1057-1059

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 1324 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 1896 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 3891 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 4156 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 4396 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 4397 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 4422 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 4423 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 4424 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 4448 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 4449 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 4520 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 4521 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 4522 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 4523 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 4566 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 4599 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 4718 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 4740 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 4749 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 4760 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 4813 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 5021 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 5372 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 5867 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 6177 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 6222 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 6447 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp

@adriadam10

Copy link
Copy Markdown
Collaborator

Checked on Linux (merged onto current main): build and the libSceAgcDriver ctest scope green except agc_driver_tessellation, which segfaults at Vulkan device creation here independently of this change. agc_host_import_retire passes with the PR and fails when GuestBufferMemory.cpp is reverted, so WindowPromotionOutlivesTheHold covers the fix. The promotion is limited to the same single registered range with an active recorder, and the retired window stays alive through the hold. Also confirmed by @Dextroid17 (Linux ctest) and @fdfawef324 (Demon's Souls on Windows, RTX 3060); merging once the full build is green.

@fdfawef324

Copy link
Copy Markdown
Contributor

Resident Evil 4 (PPSA07411) hits the same abort. The machine is the one from my Demon's Souls comment above. The stack is main 8cd937e + #6126 + earlier heads of #5884 and #6405 + the read-lane variant discussed in #6277 + #5907 at 7ad8cb8 + two local diagnostics that only add detail to geometry-assembly and sample-count refusal messages.

  • Without this PR, cold shader cache: aborts 886 s in. Every frame dump from the run is black.
    FATAL: an address-based build copies 452 MiB of 1 registered ranges, past 64 MiB (APS5_ADDRESS_COPY_MAX_MIB); the largest: 0x250000000+0x1c400000 (452.0 MiB committed, outside the write-watched arena)
    
  • The same build plus this PR's commit (cherry-picked cleanly; same patch as 7b06e75), using the cache the first run filled: no abort. It ran until the harness's timed dump at 2,986 s. Frame dumps show the CAPCOM logo, the brightness calibration screen and the "About the Settings for Sending Play Data" screen.

This is not a clean A/B. Two earlier runs of nearly the same stack without this PR, both with a fully warm cache, ran to the harness's timed dump at 1,485 s and 2,086 s without hitting this abort. Of these runs, only the one that aborted had a cold cache, so whether RE4 reaches the abort may depend on load timing, and one run with the PR does not show that it fixes RE4. I have not yet run the PR with a cold cache.

AI-assisted: yes

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

Labels

agc libSceAgc*

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants