Skip to content

feat(recompiler): implement 64-bit image atomics - #896

Merged
adriadam10 merged 2 commits into
boykopovar:mainfrom
alfalfa-star:feat/image-atomic-64
Oct 7, 2026
Merged

adriadam10 merged 2 commits into
boykopovar:mainfrom
alfalfa-star:feat/image-atomic-64

Conversation

@alfalfa-star

Copy link
Copy Markdown
Contributor

What

Implement 64-bit integer image atomics. image_atomic_* with a two-dword data mask (0x3, or 0xf for cmpswap) is the 64-bit form of an integer image atomic, and the decoder rejected it with invalid MIMG data mask.

PPSA14632 (LEGO Horizon Adventures, Unreal Engine) updates a 32_32 surface with six 64-bit image_atomic_umax in a compute shader during its first frames, and stops there on main.

  • Decoder: swap, add, sub, smin, umin, smax, umax, and, or, xor and cmpswap with the 64-bit data mask decode with dataBits = 64.
  • IR: new ImageAtomic*64 opcodes take and return U64, read from and written to register pairs as the 64-bit buffer atomics are.
  • Resources and bindings: an image updated by them is marked atomic64 and gets its own descriptor binding range (five bindings after the 32-bit atomic ones), declared as an R64ui image of 64-bit integers. The descriptor must be 32_32 UINT, SINT or FLOAT. The flag reaches the driver as DescriptorBinding::imageAtomic64 and is stored in the shader disk cache.
  • SPIR-V: OpImageTexelPointer to a 64-bit texel and the 64-bit atomic opcodes, with Int64, Int64Atomics, Int64ImageEXT and SPV_EXT_shader_image_int64. When the target does not list Int64ImageEXT, recompiling throws 64-bit image atomics need VK_EXT_shader_image_atomic_int64.
  • Driver: VulkanDevice enables shaderImageInt64Atomics when the device offers it and advertises Int64ImageEXT. StorageTexture::Atomic64View binds an R64_UINT view of the surface; storage images are already created with MUTABLE_FORMAT and EXTENDED_USAGE, and R64_UINT is in the 64-bit compatibility class of R32G32_*.

Not covered, and listed in TechnicalDebt: 64-bit image_atomic_inc/dec and the float atomics still throw, as does any other access in the same shader to an image it updates with 64-bit atomics.

Tested

  • Arch Linux, GCC 16.2, Release, RX 9070 XT (RADV GFX1201, shaderImageInt64Atomics = true).
  • New agc_driver_image_atomics64: each of the 11 operations on 32_32 UINT, SINT and FLOAT surfaces, checking the returned and stored values for every thread against edge cases across the dword boundary (carry, borrow, sign bit, high word deciding min/max). Turning 64-bit umax into umin in the emitter makes it fail. Full ctest: 360/360.
  • PPSA14632: the shader recompiles to 36653 words with six OpAtomicUMax %ulong on an R64ui image, spirv-val accepts it, and the title runs on to an unrelated sceAgcCbBranch: null or misaligned address 0x0.
  • Windows not built or tested.

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

@alfalfa-star

Copy link
Copy Markdown
Contributor Author

A note on overlaps with open pull requests, for whichever lands second:

@github-actions github-actions Bot added shader core/shader docs agc libSceAgc* labels Oct 6, 2026
@github-actions github-actions Bot added needs rebase Conflicts with main, rebase needed labels Oct 6, 2026
@github-actions github-actions Bot added needs rebase Conflicts with main, rebase needed and removed needs rebase Conflicts with main, rebase needed labels Oct 7, 2026
image_atomic_* with a two-dword data mask (four for cmpswap) is the
64-bit form of an integer image atomic. The decoder rejected it with
"invalid MIMG data mask". PPSA14632 (Unreal Engine) uses
image_atomic_umax this way in a compute shader during its first frames.

Swap, add, sub, signed and unsigned min/max, and, or, xor and cmpswap
now decode with 64-bit data and translate to new ImageAtomic*64 IR
opcodes. An image updated by them gets its own descriptor binding
range, declared as an R64ui image of 64-bit integers, and the module
uses Int64ImageEXT from SPV_EXT_shader_image_int64. The driver enables
shaderImageInt64Atomics when the device offers it and binds an
R64_UINT view of the 32_32 UINT, SINT or FLOAT surface. Without the
feature, recompiling such a shader throws.

64-bit inc, dec and the float atomics still throw, as does any other
access in the same shader to an image it updates with 64-bit atomics.

The new agc_driver_image_atomics64 test runs every operation on 32_32
UINT, SINT and FLOAT surfaces and checks the returned and stored values
against edge cases across the dword boundary.

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

Copy link
Copy Markdown
Collaborator

Measured all 11 operations (cmpswap with equal and different comparator) on 32_32 UINT/SINT/FLOAT surfaces on RDNA2 hardware (gfx1035) with carry/sign edge rows plus random rows: returned and stored values match this PR's model bit for bit (5760 cells, 0 mismatches). The test passes on RADV and on CI's lavapipe, and fails without the change. Rebased on main (only conflict: the DescriptorBinding size assert, now 448, and the new imageUnnormalized/imageSamplers lines next to imageAtomic64); full ctest green after the rebase. Merging once CI is green.

@adriadam10
adriadam10 force-pushed the feat/image-atomic-64 branch from 3e02fc7 to 9df5929 Compare October 7, 2026 08:25
A pixel or vertex shader with a 64-bit image atomic declares Int64Atomics,
Int64ImageEXT and SPV_EXT_shader_image_int64, which graphics shader
validation rejected ("SPIR-V requires unsupported device capability"),
so the draw was dropped. Compute dispatches are not validated this way.

The device records whether it enabled shaderImageInt64Atomics
(imageInt64Atomics in the device state and the graphics Context), and
ValidateShaders accepts the two capabilities and the extension when it
did.

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
#944 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp L1071

@alfalfa-star

Copy link
Copy Markdown
Contributor Author

A second commit makes draws work too. In PPSA14632, a pixel shader with a 64-bit image atomic was rejected by graphics shader validation (SPIR-V requires unsupported device capability 5016); compute dispatches are not validated this way. The device now records imageInt64Atomics, and ValidateShaders accepts Int64Atomics, Int64ImageEXT and SPV_EXT_shader_image_int64 when it is set. A test in agc_driver_graphics covers both capabilities. ctest: 387 of 387 pass.

#1074 does the same for 64-bit buffer atomics (bufferInt64Atomics) and touches the same ValidateShaders signature; whichever lands second needs a small rebase.

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 7, 2026
@adriadam10

Copy link
Copy Markdown
Collaborator

Re-checked the second commit: graphics validation now accepts Int64Atomics, Int64ImageEXT and SPV_EXT_shader_image_int64 only when the device enabled shaderImageInt64Atomics, and the new agc_driver_graphics case fails if that acceptance is removed. Full ctest green (387/387) merged onto main. #1074 changes the same ValidateShaders signature, so whichever lands second needs a small rebase. Merging once CI is green.

@adriadam10
adriadam10 merged commit 46f2050 into boykopovar:main Oct 7, 2026
3 checks passed
@alfalfa-star
alfalfa-star deleted the feat/image-atomic-64 branch October 7, 2026 09:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* docs shader core/shader

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants