Skip to content

fix(agc): keep RADV's descriptor pool overrun inside the pool's pages - #1065

Merged
adriadam10 merged 1 commit into
boykopovar:mainfrom
alfalfa-star:fix/radv-descriptor-pool-tail
Oct 8, 2026
Merged

adriadam10 merged 1 commit into
boykopovar:mainfrom
alfalfa-star:fix/radv-descriptor-pool-tail

Conversation

@alfalfa-star

Copy link
Copy Markdown
Contributor

What

The descriptor cache's chain pools are created with two more storage buffer descriptors than a set may take (ChainPoolCreateSizes). This keeps a RADV overrun inside the pool's pages. A TechnicalDebt line records the workaround.

RADV (Mesa 26.0 and later, since 849d41db "radv: implement a new descriptor sets allocator") sets up a FREE_DESCRIPTOR_SET pool's allocator with

util_vma_heap_init(&pool->bo_heap, RADV_POOL_HEAP_OFFSET, bo_size + RADV_POOL_HEAP_OFFSET);

util_vma_heap_init takes a start and a size, so the heap ends 32 bytes past the pool's buffer, and a set can be placed up to 32 bytes past its end. Mesa main still has this. The chain pools come out at exactly 0x26000 bytes, a page multiple, so those 32 bytes are an unmapped page:

  • On the GPU, a shader's scalar load of a descriptor in the set's last 32 bytes raises a gfxhub page fault (SQC (data)). The gfx ring times out and is reset, and the recorder then waits on a fence that never signals. In PPSA14632, Unreal aborts after 120 s with GameThread timed out waiting for RenderThread. A RADV_DEBUG=hang dump shows a 160-byte set at offset 0x25f80, with an s_load_b128 of its storage buffer descriptor at 0x26000.
  • On the CPU, vkUpdateDescriptorSets can write there. Under GPU-assisted validation this segfaulted in radv_write_sampler_descriptor, with the destination exactly at the end of a 0x26000-byte /dev/dri/renderD128 mapping.

With two more storage buffers the pool is 0x26020 bytes. The 16-byte slack RADV adds per set is already capped by maxSets, so the only change is the 32 bytes. The buffer then spans 0x27000 bytes and the overrun stays in mapped memory. The other pools in the driver are linear (no FREE_DESCRIPTOR_SET), and RADV bounds those correctly.

Standalone repro on RADV, no AnyPS5 needed: a pool for four sampled images (128 bytes, maxSets 1).

Set linear pool FREE_DESCRIPTOR_SET pool
4 images (128 bytes) 0 0
5 images (160 bytes) VK_ERROR_OUT_OF_POOL_MEMORY 0
6 images (192 bytes) VK_ERROR_OUT_OF_POOL_MEMORY VK_ERROR_FRAGMENTED_POOL

Tested

Linux 7.2.9 (Arch), Mesa 26.2.4 RADV, RX 9070 XT (RDNA4).

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 in TechnicalDebt
  • 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
  • AI-assisted: yes

🤖 Generated with Claude Code

RADV (Mesa 26.0 and later) initialises a FREE_DESCRIPTOR_SET pool's
allocator with bo_size + RADV_POOL_HEAP_OFFSET as its size, so a set can
be placed up to 32 bytes past the pool's buffer. The chain pools are
0x26000 bytes, a page multiple, so a set at the end of a full pool has
its last descriptors on an unmapped page: the CPU descriptor write
faults, or the shader's scalar load raises a GPU page fault and the ring
is reset.

Two more storage buffer descriptors make the pool 0x26020 bytes; the
buffer's last page then holds those 32 bytes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 7, 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
#1051 docs/dev/TechnicalDebt.md L255
#1184 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp L2155-2156
#1237 docs/dev/TechnicalDebt.md L255

@adriadam10

Copy link
Copy Markdown
Collaborator

Checked: build + ctest on the merge with current main (415/415), CI green, and the RADV util_vma_heap_init(bo_size + RADV_POOL_HEAP_OFFSET) claim against Mesa main (radv_descriptor_pool.c). The pool size arithmetic (0x26000 → 0x26020) matches, and ChainPoolSizes still drives the capacity check. Merging.

Note for #1184: it rewrites the same poolInfo lines in ShaderResources.cpp, so whichever lands second needs a rebase.

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

Labels

agc libSceAgc* docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants