Repository navigation
feat(shader): implement image_atomic_fmin, fmax and fcmpswap - #562
Conversation
…buffer atomics
buffer_atomic_inc, buffer_atomic_dec, buffer_atomic_cmpswap_x2 and
buffer_atomic_{add,sub,smin,umin,smax,umax,and,xor}_x2 threw in the decoder.
The 64-bit ones use native 64-bit SPIR-V atomics like the existing
swap_x2/or_x2; inc and dec wrap at the data operand through the existing
compare-exchange helpers.
Co-Authored-By: Claude <noreply@anthropic.com>
buffer_atomic_fcmpswap, fcmpswap_x2, fmin_x2, fmax_x2, inc_x2 and dec_x2 are compare-and-swap loops on the dword or qword. fcmpswap compares as floats (-0 equals +0, NaN equals nothing) and fmin/fmax are IEEE minNum/maxNum with -0 < +0, a quieted result for a signalling NaN and the other operand for a quiet one, all with integer ops so the driver's float controls do not matter. The existing 32-bit fmin/fmax kept the old value whenever a NaN or two zeros were involved; it now uses the same rule. Co-Authored-By: Claude <noreply@anthropic.com>
The three MIMG float atomics threw as unknown opcodes. They now run as a compare-and-swap loop on the 32-bit texel with the bit-level rules the float buffer atomics already use (NaN, signed zero and sNaN quieting as measured on RDNA2), so no float atomic feature is needed from the driver. Co-Authored-By: Claude <noreply@anthropic.com>
Progress report (d7f0c49 → d1f7710)📈 GPU shader instructions: 81.99% (+1.72%, +20 implemented instructions) ✅ 20 implemented
|
|
Thanks. I checked the encodings with llvm-mc for gfx1013: image_atomic_fcmpswap, image_atomic_fmin and image_atomic_fmax are MIMG opcodes 0x1d, 0x1e and 0x1f, and the RDNA2 ISA guide gives the same semantics you measured (fcmpswap stores src when The first two commits are patch-identical to #321 and #332, so this lands after them. Image atomics are still only accepted on 32_UINT views, and float-format textures keep throwing in the materializer, which is the right place to stop for now.
One note for the merge order: #506 also edits This only adds encodings that main refused, so it's ready to merge from my side once #321 and #332 are in. |
…mics On RDNA2 the image, buffer and global float atomics (fmin, fmax, fcmpswap and the _x2 forms) flush both operands to a signed zero when bit 0 of the shader's denormal field is clear, as the LDS forms do: the f32 field for the 32-bit forms, the f16/f64 field for _x2. Only the LDS forms flushed here. floatAtomicFlush (was sharedFloatFlush) now sets MemoryInfo::flushDenormals for every float atomic, and AtomicFloatBits applies it in minMax and compareSwap. The float atomic tests from boykopovar#332, boykopovar#506 and boykopovar#562 were measured with denormals kept, so they now set FLOAT_MODE 0xf0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What
This implements the three MIMG float atomics, which threw as unknown opcodes. The ISA sweep found them.
image_atomic_fcmpswap(0x1d)texel = (texel == cmp) ? src : texel, compared as floats: −0 equals +0, NaN equals nothing.vdata[0]= src,vdata[1]= cmp, dmask must be 0x3 likeimage_atomic_cmpswapimage_atomic_fmin(0x1e) /image_atomic_fmax(0x1f)These are the same rules the float buffer atomics follow in #332. On the hardware the image forms gave the same results as the buffer forms (800/800 rows), and the same results on a
32_UINTand a32_FLOATT#. Withoutglcthe data VGPR is left untouched, as for the other image atomics.Implementation:
AtomicUpdate's compare-exchange loop on the existing u32 texel pointer, asimage_atomic_inc/decalready do. The value is computed on the raw bits through feat(shader): implement the float and 64-bit inc/dec buffer atomics #332'sAtomicFloatBits, which is reached through two helpers,AtomicFloatMinMaxandAtomicFloatCompareSwap. So the driver's float controls (denormals, NaN payloads) don't matter, and no Vulkan float-atomic feature is needed.32_UINTtextures (ResourceMaterializer, "atomic image descriptor uses an unsupported format"). A float-format texture keeps throwing there. Accepting one needs a uint view of a float texture in the driver, which belongs in a separate PR.Tested
Arch Linux, RDNA2 iGPU (Radeon 660M), RADV and lavapipe. No title.
New execution test
agc_driver_image_atomics_float_tests(ImageAtomicsFloat.cpp):cmp = srcand once withcmp = old.glc, and fmin withoutglc. Everything is compared bit for bit. The emitted code only uses integer ops on the bits, so NVIDIA's NaN canonicalisation doesn't apply.ComputeTarget(32)).The test fails without the change in each of these cases (each checked separately):
Release build: full ctest passes except
agc_driver_pixel_helper_lanes, which also fails onmainon local RADV.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt.mdfiles or images added to the repository (attach them to this PR)