engine/rr: run dec0_1's translated tail on two waves

dec0_1's translated output tail ran on wave 0 while the block's other three
waves had finished. It is a prologue (y = r + MLP * s2 and the shuffles that
give each lane its two pixels) followed by the same per-pixel code twice.

gen_rr2_enc0.py --tail-waves N gives each of N waves its own copy of the
tail with only its N-th of the stores (in order: the first pixel's six, then
the second's), and the compiler drops what a copy's stores do not need.
Every stored value comes from the same instructions on the same values as on
one wave. With one window per workgroup, the window index no longer adds
gl_SubgroupID (it was 0 for the only valid wave).

compile_rr2.py uses two waves (D4R_RR2_TAIL_WAVES=1 for one): 120 -> 96
vector registers, 12 -> 16 waves per SIMD; RX 9070 XT, 720p -> 1440p:
dec0_1 565 -> 474 us. Four waves, splitting each pixel's stores, is slower
(529 us). Every image byte-identical on the replay inputs (also robustness2,
no robust access and the split gather build).

Signed-off-by: itchyfeetleech <[email protected]>
This commit is contained in:
itchyfeetleech committed 2026-10-18 22:03:34 +13:00
1 parent 69a4f6ae2f
commit c29076b38f
3 files changed
+31 -5

No files matched your search

+7
View File
@@ -557,6 +557,13 @@ registers to the waves its shared memory leaves room for (enc1 needed 97 vector
so the check there is the whole instruction mix: only `v_and_or_b32` / `v_or` / `v_perm` / shifts go (post -16
VALU, down -9, downp -73), every `v_fma_f32` / `v_mul_f32` / `v_add_f32` / conversion / `v_exp` / `v_log` count is
unchanged (post moves 5 of its 57 mixes from the low to the high half of their registers). Output 673 -> 665 us.
- **dec0_1's translated tail on two waves** (`gen_rr2_enc0.py --tail-waves 2`). The tail ran on wave 0 while the
block's other three waves had nothing left to do; it is a prologue (y = r + MLP * s2 and the shuffles that give each
lane its two pixels) and then the same per-pixel code twice. Each of two waves now runs its own copy of the tail with
only one pixel's stores (the first six, the last six), and the compiler drops what a copy's stores do not need:
every stored value comes from the same instructions on the same values. 120 -> 96 vector registers, 12 -> 16 waves
per SIMD; dec0_1 565 -> 474 us. Four waves (each pixel's stores split in two) is slower, 529 us: the per-pixel work
the parts share is then done twice. `D4R_RR2_TAIL_WAVES=1` builds the single-wave tail.
- **One unsigned comparison per axis in the translation's bounds-checked fetch** (`ptx2rr.py` `fetch0`: a negative
coordinate is above every size): 231 instructions fewer in enc0, whose gather fetches 102 times, its scalar spills
200 -> 176; enc0 745 -> 738 us.