tools: validate the program cache's SPIR-V offline (scripts/validate_spirv.py) #1508

Merged
rakefire-impala merged 1 commit from tools/validate-program-cache-spirv into main 2026-11-10 05:48:07 +00:00
rakefire-impala commented 2026-11-10 05:43:31 +00:00 (Migrated from github.com)

A developer tool: runs spirv-val offline over every program in hookshot_programs.bin, and checks workgroup limits that spirv-val doesn't. No game code changes.

Part of splitting up #1023.

Why

The mesh fallback's SPIR-V bugs that #1314 fixed showed up on an RX 5500M only as driver crashes or silent failures at pipeline creation. Validating the program cache offline found every one of them at once, with no game session needed:

  • the payload address read by byte offset instead of member index;
  • PhysicalStorageBuffer accesses without Aligned;
  • a Function variable outside the first block;
  • a bool stored into a u32.

With those fixes: 1347 mesh-as-compute programs, 0 failed stages (--uniform-buffer-standard-layout --scalar-block-layout, as Lichii validates).

What it does

python -I scripts/validate_spirv.py <hookshot_programs.bin> [--all | --key <hex>]

  • Walks the cache's records: the mesh-as-compute ones (kind 4) by default, every program with --all, or one program with --key.
  • Runs each stage through the Vulkan SDK's spirv-val (--target-env vulkan1.3 by default; --val-arg passes more).
  • Checks a workgroup's invocations and workgroup memory against the GPU's limits (--max-invocations, --max-shared; RDNA1 defaults 1024 and 64 KB).
  • Writes each failing stage out as .spv, .spvasm (via spirv-dis) and .txt with the reasons, and groups the errors by message in a summary.

Tests

tests/test_validate_spirv.py (new) builds a small cache with one valid module over the workgroup-memory limit and one invalid module, and checks that both are found.

Risk

None to the game: one script and one test.

A developer tool: runs `spirv-val` offline over every program in `hookshot_programs.bin`, and checks workgroup limits that `spirv-val` doesn't. No game code changes. Part of splitting up #1023. ## Why The mesh fallback's SPIR-V bugs that #1314 fixed showed up on an RX 5500M only as driver crashes or silent failures at pipeline creation. Validating the program cache offline found every one of them at once, with no game session needed: - the payload address read by byte offset instead of member index; - PhysicalStorageBuffer accesses without `Aligned`; - a Function variable outside the first block; - a bool stored into a u32. With those fixes: 1347 mesh-as-compute programs, 0 failed stages (`--uniform-buffer-standard-layout --scalar-block-layout`, as Lichii validates). ## What it does `python -I scripts/validate_spirv.py <hookshot_programs.bin> [--all | --key <hex>]` - Walks the cache's records: the mesh-as-compute ones (kind 4) by default, every program with `--all`, or one program with `--key`. - Runs each stage through the Vulkan SDK's `spirv-val` (`--target-env vulkan1.3` by default; `--val-arg` passes more). - Checks a workgroup's invocations and workgroup memory against the GPU's limits (`--max-invocations`, `--max-shared`; RDNA1 defaults 1024 and 64 KB). - Writes each failing stage out as `.spv`, `.spvasm` (via `spirv-dis`) and `.txt` with the reasons, and groups the errors by message in a summary. ## Tests `tests/test_validate_spirv.py` (new) builds a small cache with one valid module over the workgroup-memory limit and one invalid module, and checks that both are found. ## Risk None to the game: one script and one test.
Commenting is not possible because the repository is archived.
No description provided.