Skip to content

fix(libSceAgcDriver): normalize reserved bit 30 in guest buffer descriptors - #7089

Merged
oneandonlydean merged 1 commit into
boykopovar:mainfrom
pushkarreddyy:fix/agc-driver-buffer-descriptor-reserved-bit
Oct 18, 2026
Merged

oneandonlydean merged 1 commit into
boykopovar:mainfrom
pushkarreddyy:fix/agc-driver-buffer-descriptor-reserved-bit

Conversation

@pushkarreddyy

Copy link
Copy Markdown
Contributor

What

Normalizes reserved bit 30 of word 1 (words[1] & 0x40000000u) to zero when building ShaderBufferResource in ShaderResources::addGuestBuffer, instead of requiring it to be clear.

On RDNA hardware, bit 30 in word 1 of a buffer resource descriptor is reserved and ignored by buffer sampling/resource hardware. While PR #5049 normalized bit 30 for scalar-only buffer resources before binding, non-scalar and compute buffers reaching ShaderResources::addGuestBuffer previously threw with buffer descriptor has reserved bits set.

Unblocks Code Violet (PPSA26528, Unreal Engine 5.5) which aborts at compute shader 0x147b9e400 with reserved bit 30 set (#7051).

Tested

  • Unit test in core/libs/prx/libSceAgcDriver/tests/execution/BufferDescriptorRuntime.cpp updated: verifies that vector and mixed buffer accesses with bit 30 set in word 1 are accepted and produce identical dispatch outputs as untouched descriptors.
  • Conventions check: python tools/check_conventions.py --base origin/main passed cleanly with 0 findings.
  • Technical debt documented in docs/dev/debt/libSceAgcDriver.md.

Checklist

@github-actions

github-actions Bot commented Oct 17, 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 6636 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp L3802-3803

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 1395 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 2434 docs/dev/debt/libSceAgcDriver.md
PR 4040 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 4448 docs/dev/debt/libSceAgcDriver.md
PR 4650 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 5058 docs/dev/debt/libSceAgcDriver.md
PR 5372 docs/dev/debt/libSceAgcDriver.md
PR 5441 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 5499 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 5500 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 5925 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 5998 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 5999 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6054 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6082 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6177 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6188 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6192 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6194 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6222 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6223 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6235 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6273 docs/dev/debt/libSceAgcDriver.md
PR 6292 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6297 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6300 docs/dev/debt/libSceAgcDriver.md
PR 6320 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6373 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6412 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6414 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6472 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6481 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6529 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6535 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6548 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6563 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6612 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6615 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6727 docs/dev/debt/libSceAgcDriver.md
PR 6741 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6783 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6786 docs/dev/debt/libSceAgcDriver.md
PR 6801 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6808 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6867 docs/dev/debt/libSceAgcDriver.md
PR 6868 docs/dev/debt/libSceAgcDriver.md
PR 6946 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6947 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6972 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6977 docs/dev/debt/libSceAgcDriver.md
PR 7250 docs/dev/debt/libSceAgcDriver.md
PR 7332 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7426 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7432 docs/dev/debt/libSceAgcDriver.md
PR 7505 docs/dev/debt/libSceAgcDriver.md

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

Two tests fail with this PR on both devices I have. Both failures come from test expectations, not from the fix.

Machine: Ubuntu 26.04, i7-8700, GCC 15.2, Release, BUILD_TESTING=ON. NVIDIA GeForce RTX 3070 (driver 595.99.02) and lavapipe (Mesa 26.0.3, LLVM 21.1.8) on the same host. Head 2c7d0bf0d merged onto main 47a266cf9 (clean). ANYPS5_NO_SHADER_CACHE=1, -j1 --timeout 30.

Run RTX 3070 lavapipe
agc_driver_buffer_descriptor_runtime, PR head fails 3/3: vector or mixed buffer read changed with reserved bit 30 set same failure
same, ShaderResources.cpp from main fails: buffer descriptor has reserved bits set same
PR head, last check changed as below pass pass
^agc (649 tests), PR vs main 647/649: agc_driver_buffer_descriptor_runtime and agc_driver_graphics fail (expected graphics rejection: reserved bits); main passes 649/649 same two failures; main 649/649

The last loop in ScalarReads compares every lane with expected, which is the dword at Input + 4 (the scalar load's value). For the vector-only program Code, lane N stores the dword at Input + 4 * N, the same layout Run checks. So only lane 1 can match. Printed on the 3070 with bit 30 set:

vector lane 0 out 7e552c03 scalarExpected 22f9d0a7 perLane 7e552c03
vector lane 1 out 22f9d0a7 scalarExpected 22f9d0a7 perLane 22f9d0a7
vector lane 2 out c79e754c scalarExpected 22f9d0a7 perLane c79e754c

With the vector-only program checked against Input + 4 * lane and the mixed program kept on expected, all 32 lanes match on both devices and the test passes. In mixedCode the second store (v3 = s8) goes to the same lane address as the vector result, so that case only checks the scalar value. The vector load with bit 30 set is checked only by the vector-only program.

agc_driver_graphics still expects the old rejection at tests/Graphics.cpp:4552: expectSingleFailure(changed([](auto& binding) { binding.guestDescriptor[1] |= 0x40000000u; }), "reserved bits");. With bit 30 now cleared, that binding is accepted, so this line needs to expect acceptance or be removed.

The CI Linux and Windows jobs were skipped on this head, so neither failure showed up there.

Not run: Windows, AMD, Code Violet or any title.

GPUs tested: NVIDIA GeForce RTX 3070 (595.99.02) and lavapipe (Mesa 26.0.3), Ubuntu 26.04

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

@pushkarreddyy

pushkarreddyy commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks @jotitadev for the testing reproduction and for pointing out the lane indexing expectation in BufferDescriptorRuntime.cpp and the graphics test expectation at core/libs/prx/libSceAgcDriver/tests/Graphics.cpp:4552. I will update both test expectations to match the normalized descriptor semantics.

As a quick note on repository workflow: please do not submit formal GitHub Review decisions unless you are a designated project maintainer with write or merge permissions on �oykopovar/AnyPS5. If you have testing results or observations to share, please post them strictly as regular discussion comments on the PR thread rather than formal reviews.

@Neithennn

Copy link
Copy Markdown
Contributor

Windows NVIDIA run, since GPUs tested is n/a: two tests fail with this PR and pass on main.

Windows 11 Pro 26200, NVIDIA GeForce RTX 4080 (driver 617.42), AMD Ryzen 7 5800X, WinLibs GCC 15.2.0 r7, Ninja, Release, bundled dependencies, BUILD_TESTING=ON, ANYPS5_NO_SHADER_CACHE=1. Head 2c7d0bf0d merged onto main f51724078; full build succeeds. Unchanged main on the same machine: 1398/1398.

  1. agc_driver_buffer_descriptor_runtime (this PR's test) fails 7/7 (targeted, full suite and 5 serial runs):
AGC graphics: vector or mixed buffer read changed with reserved bit 30 set

That is the new check at BufferDescriptorRuntime.cpp:145: with input[1] |= 0x40000000u the dispatch output on the RTX 4080 differs from the untouched descriptor's.

  1. agc_driver_graphics fails 6/6 (full suite and 5 serial runs) at the existing check Graphics.cpp:4589, which expects a graphics binding with guestDescriptor[1] |= 0x40000000u to be rejected:
expected graphics rejection: reserved bits

With this change bit 30 is accepted, so that expectation needs updating if accepting it is intended.

The other buffer tests (agc_driver_buffer_load_store, agc_driver_buffer_format, agc_driver_buffer_unaligned_base, the atomics) pass. Full ctest -j 8: 1396/1398, the two above being the only failures. I have not checked AMD or lavapipe, so I cannot say whether the first failure is NVIDIA-specific.

AI-assisted: yes (runs done with Claude Code).

@pushkarreddyy
pushkarreddyy force-pushed the fix/agc-driver-buffer-descriptor-reserved-bit branch from 2c7d0bf to df02f8b Compare October 17, 2026 17:24
@pushkarreddyy

Copy link
Copy Markdown
Contributor Author

Thanks @Neithennn for running the full hardware suite on Windows / RTX 4080 and catching both test discrepancies!

Fixed in updated commit df02f8b4c (rebased on latest main):

  1. agc_driver_buffer_descriptor_runtime (BufferDescriptorRuntime.cpp):

    • The test was comparing all lanes against a single scalar value (value == expected), which failed for the 32-lane vector load (Code) and mixed load.
    • Updated to capture the untouched descriptor's exact dispatch output as baseline, then verify that dispatching with input[1] |= 0x40000000u produces identical results across all lanes (Require(Output == baseline)).
  2. agc_driver_graphics (Graphics.cpp):

    • Updated the expectation at line 4589 from expectSingleFailure ("reserved bits") to expectSingleAccepted(..., "a V# with reserved bit 30"), matching the normalization behavior.

@MarcZX10

Copy link
Copy Markdown
Contributor

I checked the current head df02f8b4c and its hosted checks. The earlier NVIDIA/lavapipe runs are on 2c7d0bf0d; the updated head changes the buffer test to compare bit-30-set output against the clear-bit baseline, and the Windows/Linux jobs on df02f8b4c were skipped. Could you confirm that agc_driver_buffer_descriptor_runtime and agc_driver_graphics both pass on a real GPU with this exact head? That would verify the final test expectation and acceptance path rather than only the prior revision.

@Neithennn

Copy link
Copy Markdown
Contributor

@MarcZX100 @pushkarreddyy Rerun of the exact head df02f8b4c on the RTX 4080: both pass now.

Windows 11 Pro 26200, NVIDIA GeForce RTX 4080 (driver 617.42), WinLibs GCC 15.2.0 r7, Ninja, Release, bundled dependencies, BUILD_TESTING=ON, ANYPS5_NO_SHADER_CACHE=1, ANYPS5_REQUIRE_VULKAN=1. The head is one commit on main 66702f1cf, built as is.

  • agc_driver_buffer_descriptor_runtime: passes (targeted, full suite and 3 serial runs); it failed 7/7 on 2c7d0bf0d.
  • agc_driver_graphics: passes (same runs); it failed 6/6 at the reserved-bits rejection on 2c7d0bf0d.
  • The other buffer tests (load/store, format, unaligned base, atomics): pass.
  • Full ctest -j 8: 1399/1399.

No title run.

AI-assisted: yes (runs done with Claude Code).

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 17, 2026
@pushkarreddyy
pushkarreddyy force-pushed the fix/agc-driver-buffer-descriptor-reserved-bit branch from df02f8b to e62b037 Compare October 18, 2026 02:40
@pushkarreddyy

Copy link
Copy Markdown
Contributor Author

Thank you @Neithennn for the Windows 11 / RTX 4080 verification and test run!

Rebased cleanly on latest origin/main (b39d90bf1) with the conflict resolved in ShaderResources.cpp (guestBufferBytes & addGuestBuffer). All pre-flight convention checks pass cleanly.

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 18, 2026
@pushkarreddyy
pushkarreddyy force-pushed the fix/agc-driver-buffer-descriptor-reserved-bit branch from e62b037 to 64fa204 Compare October 18, 2026 10:28
@pushkarreddyy

Copy link
Copy Markdown
Contributor Author

@oneandonlydean Cleanly rebased onto latest origin/main (64fa204f8).

All hardware test discrepancies were resolved, and @Neithennn confirmed on Windows 11 / RTX 4080 that full suite tests (agc_driver_buffer_descriptor_runtime and agc_driver_graphics) pass 1399/1399 cleanly. Ready for review when convenient!

@oneandonlydean

Copy link
Copy Markdown
Collaborator

Thanks, the change is right. One naming point: on GFX10 (gfx1013), bit 30 of V# word 1 is CACHE_SWIZZLE (Mesa's gfx10-rsrc.json: STRIDE [29:16], CACHE_SWIZZLE [30], SWIZZLE_ENABLE [31]), a cache-bank hint with no effect on the address or data, rather than a reserved bit. Could the debt entry say that, so that it is clearly a dropped hint and not an unknown bit? "Console equivalence is unmeasured" can then go: the bit has no addressing effect to measure. And could the entry leave out the title (the PR and #7051 already record Code Violet)?

@pushkarreddyy
pushkarreddyy force-pushed the fix/agc-driver-buffer-descriptor-reserved-bit branch from 64fa204 to c3c400a Compare October 18, 2026 11:09
@pushkarreddyy

Copy link
Copy Markdown
Contributor Author

@oneandonlydean Updated the technical debt entry in docs/dev/debt/libSceAgcDriver.md as suggested:

  • Renamed the section to [Buffer descriptor CACHE_SWIZZLE hint].
  • Explicitly documented bit 30 on GFX10 (gfx1013) as CACHE_SWIZZLE (STRIDE [29:16], CACHE_SWIZZLE [30], SWIZZLE_ENABLE [31]), a cache-bank hint with no addressing effect that is dropped during descriptor binding.
  • Removed the unmeasured equivalence and title mentions from the debt entry.
  • Rebased cleanly onto latest origin/main.

@oneandonlydean
oneandonlydean merged commit 0d078f7 into boykopovar:main Oct 18, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* docs fix error Closes an issue (Fixes #N)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Code Violet (PPSA26528): abort at compute shader 0x147b9e400, "buffer descriptor has reserved bits set", new between d92a8dad3 and 51acb79ac

5 participants