fix(spirv): implement 8- and 16-bit global stores #536

Merged
nicholasgower merged 1 commit from fix/global-narrow-writes into main 2026-11-08 09:55:22 +00:00
nicholasgower commented 2026-11-08 09:02:23 +00:00 (Migrated from github.com)

What

The SPIR-V backend still threw NotImplementedException for WriteGlobalU8/S8/U16/S16. A mesh program that uses STG.U8/S8/U16/S16 therefore failed to translate. This is the same failure class as the LoadGlobalS16 crash reported in #192: the program is left out and the game goes on to dereference a null resource (CRASH: ... read 0x100000000150, guest 0x150).

The load half (LoadGlobalU8/S8/U16/S16) is already in main from c3459dc. This change completes the store half: the aligned 32-bit word is changed in place with a compare-exchange loop, as the storage buffers' narrow stores already do. A plain load/store pair would lose another invocation's half of the word; the console's byte-enabled store does not.

Test

tests/global_load_16_ir.cpp now emits signed and unsigned 8/16-bit stores at offsets 0, 2, 3 and at a page end, and checks the compare-exchange loop, the bit-field insert and the helper call. The fixture also keeps the existing load cases.

  • Pre-fix (HEAD before this commit): the fixture aborts with Shader::NotImplementedException: SPIR-V Instruction is not implemented (WriteGlobalS16) is not implemented.
  • With this change: all cases pass, and every emitted module passes spirv-val --target-env vulkan1.3.

Not AMD-specific

The LoadGlobalS16 failure in #192/#351 appears on NVIDIA as well; the owner confirmed it in #351. The RX 580/570 in #192 also lacks mesh shaders, which is a separate rendering limitation (507b95b warns about it). The crash signature in the attached log is the shader-translation failure, not a vendor-specific GPU path. The later report of VRAM exhaustion after ~10 seconds is a separate issue (#105).

Refs #192.

## What The SPIR-V backend still threw `NotImplementedException` for `WriteGlobalU8/S8/U16/S16`. A mesh program that uses `STG.U8/S8/U16/S16` therefore failed to translate. This is the same failure class as the `LoadGlobalS16` crash reported in #192: the program is left out and the game goes on to dereference a null resource (`CRASH: ... read 0x100000000150, guest 0x150`). The load half (`LoadGlobalU8/S8/U16/S16`) is already in main from c3459dc. This change completes the store half: the aligned 32-bit word is changed in place with a compare-exchange loop, as the storage buffers' narrow stores already do. A plain load/store pair would lose another invocation's half of the word; the console's byte-enabled store does not. ## Test `tests/global_load_16_ir.cpp` now emits signed and unsigned 8/16-bit stores at offsets 0, 2, 3 and at a page end, and checks the compare-exchange loop, the bit-field insert and the helper call. The fixture also keeps the existing load cases. - Pre-fix (HEAD before this commit): the fixture aborts with `Shader::NotImplementedException: SPIR-V Instruction is not implemented (WriteGlobalS16) is not implemented`. - With this change: all cases pass, and every emitted module passes `spirv-val --target-env vulkan1.3`. ## Not AMD-specific The `LoadGlobalS16` failure in #192/#351 appears on NVIDIA as well; the owner confirmed it in #351. The RX 580/570 in #192 also lacks mesh shaders, which is a separate rendering limitation (507b95b warns about it). The crash signature in the attached log is the shader-translation failure, not a vendor-specific GPU path. The later report of VRAM exhaustion after ~10 seconds is a separate issue (#105). Refs #192.
nicholasgower commented 2026-11-08 09:30:47 +00:00 (Migrated from github.com)

The appimage check fails on main too (the packaging workflow's AppImage step), so it is not from this change. The relevant checks are green: Game-free source regressions on Ubuntu and Windows, and the SPIR-V global narrow load/store lowering job (real IR, spirv-val, and the new store cases). This is the store half of the narrow-global family for #192; the load half is already in main at c3459dc.

The `appimage` check fails on `main` too (the packaging workflow's AppImage step), so it is not from this change. The relevant checks are green: `Game-free source regressions` on Ubuntu and Windows, and the `SPIR-V global narrow load/store lowering` job (real IR, `spirv-val`, and the new store cases). This is the store half of the narrow-global family for #192; the load half is already in `main` at `c3459dc`.
Commenting is not possible because the repository is archived.
No description provided.