The resource materializer refused every atomic image descriptor whose
format was not 32_UINT. RDNA2 image atomics act on the raw dword and
the numeric format only affects addressing, so 32_SINT and 32_FLOAT
surfaces are now accepted with the Uint numeric class and run through
the existing integer atomics and float compare-exchange loops. Other
formats still throw, and the message now names the format.
DescriptorBinding gains imageAtomic, carried through the shader disk
cache (format version 4) and the resource content key. The driver
binds those elements through a cached R32_UINT view of R32_SINT and
R32_SFLOAT storage images.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
EmitDppTargetLane threw "DPP control 336 is not supported" for the
DPP16 row_share controls 0x150-0x15f. row_share:sel now reads lane
sel of the reading lane's own row, (lane & ~15) | sel, as the RDNA2
ISA defines it. The source never leaves the row, so the target is
always valid and an inactive source follows the existing fi and
bound_ctrl rule, as for row_xmask.
The new agc_driver_dpp16_row_share_xmask execution test covers
v_mov_b32, v_add_nc_u32, v_sub_nc_u32 and v_max_f32 with row_share
and row_xmask under a partial exec mask, with fi, bound_ctrl and
row/bank masks, as wave32 and wave64; row_xmask had no test before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GLOBAL opcode 0x34 subtracts the data register from a global dword and
clamps the result to zero, returning the previous value. It only exists
in the global segment, so the flat form throws in the decoder, and the
form without glc throws like buffer_atomic_csub does. The clamped
subtract is now a shared helper used by both opcodes.
The address operands of a MIMG instruction are laid out by its own DIM
field: the decoder counts them that way. The SPIR-V emitter located the
gradients, the LOD, the LOD clamp, the mip level and the sample index
after the coordinate count of the bound T# instead, so an array
instruction on a non-array texture took the slice as its LOD.
An instruction that addresses fewer coordinates than its image has is
refused instead of reading the next address component as a coordinate.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Decode FLAT opcode 0x17 in the global segment and store the data VGPR of
each active lane at the SGPR pair base plus the signed offset plus four
times the lane id, sharing the address path of global_load_dword_addtid.
Co-Authored-By: Claude <noreply@anthropic.com>
Stages without workgroup memory keep LDS in a per-invocation Function
array. With the array sized to the addresses it reaches (#586),
PPSA21564's intro pixel shader still takes 864 bytes of local memory
per thread on NVIDIA: its accesses are lane * 4 + {0, 256, 512}, so
the index stays dynamic and the 192-dword array lives in local memory.
When every LDS access's address is lane * stride + constant (lane id,
constants, adds, multiplies and left shifts), with one stride, a whole
number of dwords, for all of them and no wrap (the bound analysis
already proves that), the emitter now addresses each access by its
constant plus its instruction offset. The lane id is the same for
every access of an invocation, so taking lane * stride out maps the
addresses one to one, keeps which accesses alias and keeps every
access in bounds; the array sees only constant indices and the driver
keeps it in registers. Shaders with any other address form are
emitted as before.