perf(vk): GCN (RX 400/500): f16 lowered where the GPU has none; no VRAM mirrors or batched submits by default (from hookshot-k10) #2343

Merged
NotRexed merged 3 commits from port/k10-gcn-f16-mirrors into main 2026-11-11 21:27:49 +00:00
NotRexed commented 2026-11-11 15:17:12 +00:00 (Migrated from github.com)

Ported from deadlynch/hookshot-k10 commit e09059c1, credited as co-author. That fork carries the fixes that got an RX 580 under RADV to play.

  • f16 only where the GPU has f16 shaders. RADV gives Polaris (RX 400/500) shaderFloat16 = false, yet the translator always emitted f16, and Kokiri Forest drew as coloured noise. f16 is now lowered to f32 there, as Pascal (GTX 10xx, also without f16) needs too. The f16 networks fall back to the linear stand-in, and these programs are kept apart in the program cache (disk_stamp), so other GPUs keep theirs.
  • GCN: VRAM mirrors and batched submits off by default. That applies on a GPU that pins no stage to 32 lanes and runs wider. An RX 580 ran Kokiri Forest at 20 fps with either on and 24.5 with both off; an RX 590 played with them off in #1001. RX_VK_MIRROR / RX_VK_BATCH still choose.

GPUs with f16 shaders and 32-lane stages (RTX, RDNA) take exactly the same path as before.

Checked

  • Applied cleanly onto main; the three files compile.
  • Tested on an RX 580 by the fork's author.
  • Not yet run here (RTX 4060 Ti, where it changes nothing): a run follows before merging.

🤖 Generated with Claude Code

Ported from [deadlynch/hookshot-k10](https://github.com/deadlynch/hookshot-k10) commit e09059c1, credited as co-author. That fork carries the fixes that got an RX 580 under RADV to play. - **f16 only where the GPU has f16 shaders.** RADV gives Polaris (RX 400/500) `shaderFloat16 = false`, yet the translator always emitted f16, and Kokiri Forest drew as coloured noise. f16 is now lowered to f32 there, as Pascal (GTX 10xx, also without f16) needs too. The f16 networks fall back to the linear stand-in, and these programs are kept apart in the program cache (`disk_stamp`), so other GPUs keep theirs. - **GCN: VRAM mirrors and batched submits off by default.** That applies on a GPU that pins no stage to 32 lanes and runs wider. An RX 580 ran Kokiri Forest at 20 fps with either on and 24.5 with both off; an RX 590 played with them off in #1001. `RX_VK_MIRROR` / `RX_VK_BATCH` still choose. GPUs with f16 shaders and 32-lane stages (RTX, RDNA) take exactly the same path as before. ### Checked - Applied cleanly onto main; the three files compile. - Tested on an RX 580 by the fork's author. - Not yet run here (RTX 4060 Ti, where it changes nothing): a run follows before merging. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
hckrman101 (Migrated from github.com) reviewed 2026-11-11 16:29:22 +00:00
hckrman101 (Migrated from github.com) left a comment

Thanks for porting this. The gating looks right to me for the cards that matter most: on RTX and RDNA, sg32_stages is non-zero (minSubgroupSize <= 32 with subgroup size control), so gcn is false and mirrors and batching stay as before. Intel and NVIDIA report 32-lane subgroups, so they're excluded too. The f16 change only applies where shaderFloat16 is false, and the nf16 stamp is only added there, so caches on f16 cards don't change. Nothing has been posted on the thread yet, so these are first notes.

The one blocker is CI. tests/test_amd_subgroup_profiles.py fails on Linux and Windows because of this PR. It copies disk_stamp() from const uint32_t lanes[] to // (the records keep Shader::Info, and the new nf16 block falls inside that slice. The fixture's dev stub has no vk12 (no member named 'vk12'), and its add stub expects every call to be 5 words. The simplest fix is to move the block below the abi[] add, outside the slice. If you'd rather keep it where it is, give the stub a vk12 and let check_stamp accept the extra word. The other red jobs (Python checks part 1/2 on Ubuntu, SPIR-V fixtures, appimage) died in apt with Temporary failure resolving 'azure.archive.ubuntu.com', so a re-run should clear them.

Things to be aware of, but not blocking:

  • The f16 lowering also turns on by default on any other card without shaderFloat16, including GTX 10xx going by the description. The existing comment at host_info() says Eden's lowering on its own drew Kokiri as noise on an RTX card. Pascal now gets that lowering, the linear stand-in for the networks, and a fresh program cache, and it hasn't been tested yet. A run on a 10xx before merging would be worth it, or at least a line in the description saying Pascal changes too.
  • The gcn test also matches Vega (the comment says so) and Vega/GCN APUs on RADV, where batching now turns off. The numbers come from an RX 580 (and an RX 590 in #1001), so for Vega and the APUs this is an assumption. That's probably fine since RX_VK_MIRROR / RX_VK_BATCH still override.

Good to merge once the subgroup-profile test is fixed and CI is green, plus the RTX 4060 Ti run you mentioned.

Thanks for porting this. The gating looks right to me for the cards that matter most: on RTX and RDNA, `sg32_stages` is non-zero (`minSubgroupSize <= 32` with subgroup size control), so `gcn` is false and mirrors and batching stay as before. Intel and NVIDIA report 32-lane subgroups, so they're excluded too. The f16 change only applies where `shaderFloat16` is false, and the `nf16` stamp is only added there, so caches on f16 cards don't change. Nothing has been posted on the thread yet, so these are first notes. The one blocker is CI. `tests/test_amd_subgroup_profiles.py` fails on Linux and Windows because of this PR. It copies `disk_stamp()` from `const uint32_t lanes[]` to `// (the records keep Shader::Info`, and the new `nf16` block falls inside that slice. The fixture's `dev` stub has no `vk12` (`no member named 'vk12'`), and its `add` stub expects every call to be 5 words. The simplest fix is to move the block below the `abi[]` add, outside the slice. If you'd rather keep it where it is, give the stub a `vk12` and let `check_stamp` accept the extra word. The other red jobs (Python checks part 1/2 on Ubuntu, SPIR-V fixtures, appimage) died in apt with `Temporary failure resolving 'azure.archive.ubuntu.com'`, so a re-run should clear them. Things to be aware of, but not blocking: - The f16 lowering also turns on by default on any other card without `shaderFloat16`, including GTX 10xx going by the description. The existing comment at `host_info()` says Eden's lowering on its own drew Kokiri as noise on an RTX card. Pascal now gets that lowering, the linear stand-in for the networks, and a fresh program cache, and it hasn't been tested yet. A run on a 10xx before merging would be worth it, or at least a line in the description saying Pascal changes too. - The `gcn` test also matches Vega (the comment says so) and Vega/GCN APUs on RADV, where batching now turns off. The numbers come from an RX 580 (and an RX 590 in #1001), so for Vega and the APUs this is an assumption. That's probably fine since `RX_VK_MIRROR` / `RX_VK_BATCH` still override. Good to merge once the subgroup-profile test is fixed and CI is green, plus the RTX 4060 Ti run you mentioned.
@ -186,8 +186,10 @@ bool batch_on() {
p2.pNext = &dp;
if (dev.physical) vkGetPhysicalDeviceProperties2(dev.physical, &p2), radv = dp.driverID == VK_DRIVER_ID_MESA_RADV;
const char* e = getenv("RX_VK_BATCH");
hckrman101 (Migrated from github.com) commented 2026-11-11 16:29:22 +00:00

Nit: sg32_stages is also 0 when RX_VK_NO_SUBGROUP_PIN is set, so on RDNA that debug switch now also turns batching (and VRAM mirrors) off, which could confuse an A/B test. It would also catch an RDNA driver without subgroup size control. Neither is a big deal. Maybe say it in the comment, or work out GCN from minSubgroupSize instead.

Nit: `sg32_stages` is also 0 when `RX_VK_NO_SUBGROUP_PIN` is set, so on RDNA that debug switch now also turns batching (and VRAM mirrors) off, which could confuse an A/B test. It would also catch an RDNA driver without subgroup size control. Neither is a big deal. Maybe say it in the comment, or work out GCN from `minSubgroupSize` instead.
hckrman101 (Migrated from github.com) commented 2026-11-11 16:29:22 +00:00

This also changes Pascal (and any other card without shaderFloat16) by default, not only Polaris. The comment just above says this lowering on its own gave noise on an RTX card. It would be good to have a GTX 10xx run, or at least to say in the description that Pascal changes too.

This also changes Pascal (and any other card without `shaderFloat16`) by default, not only Polaris. The comment just above says this lowering on its own gave noise on an RTX card. It would be good to have a GTX 10xx run, or at least to say in the description that Pascal changes too.
hckrman101 (Migrated from github.com) commented 2026-11-11 16:29:22 +00:00

This sits inside the slice tests/test_amd_subgroup_profiles.py takes from disk_stamp() (const uint32_t lanes[] up to // (the records keep Shader::Info). The fixture's dev has no vk12, so it fails to compile on both platforms. Even with one, its add stub asserts bytes == 5 * sizeof(uint32_t). Moving this block after the abi[] add avoids both problems.

This sits inside the slice `tests/test_amd_subgroup_profiles.py` takes from `disk_stamp()` (`const uint32_t lanes[]` up to `// (the records keep Shader::Info`). The fixture's `dev` has no `vk12`, so it fails to compile on both platforms. Even with one, its `add` stub asserts `bytes == 5 * sizeof(uint32_t)`. Moving this block after the `abi[]` add avoids both problems.
Joey-Magnus (Migrated from github.com) approved these changes 2026-11-11 21:23:01 +00:00
Joey-Magnus (Migrated from github.com) left a comment

The stub now sets vk12.shaderFloat16 = true. test_amd_subgroup_profiles and test_shader_stamp_cache pass locally. The gate sg32_stages == 0 && subgroup_size > 32 is false on RTX, RDNA, Intel and Arc, and the nf16 stamp word is only added without shaderFloat16, so caches on f16 GPUs stay valid.

Side effect: setting RX_VK_NO_SUBGROUP_PIN on RDNA now also matches GCN and loses mirrors and batching (RX_VK_MIRROR/RX_VK_BATCH still override).

This changes vk_shader.cpp, as do #2309, #2306, #2442 and #2457. Shipping them in one release means players re-prepare once.

The stub now sets `vk12.shaderFloat16 = true`. `test_amd_subgroup_profiles` and `test_shader_stamp_cache` pass locally. The gate `sg32_stages == 0 && subgroup_size > 32` is false on RTX, RDNA, Intel and Arc, and the `nf16` stamp word is only added without `shaderFloat16`, so caches on f16 GPUs stay valid. Side effect: setting `RX_VK_NO_SUBGROUP_PIN` on RDNA now also matches GCN and loses mirrors and batching (`RX_VK_MIRROR`/`RX_VK_BATCH` still override). This changes `vk_shader.cpp`, as do #2309, #2306, #2442 and #2457. Shipping them in one release means players re-prepare once.
Commenting is not possible because the repository is archived.
No description provided.