Skip to content

fix(vk): keep impossible depth-integer compute variants out of the seed - #894

Closed
easymod0 wants to merge 1 commit into
NotRexed:mainfrom
easymod0:fix/seed-compute-depth-integer-variants
Closed

easymod0 wants to merge 1 commit into
NotRexed:mainfrom
easymod0:fix/seed-compute-depth-integer-variants

Conversation

@easymod0

@easymod0 easymod0 commented Nov 9, 2026

Copy link
Copy Markdown

What this fixes

On a fresh install with Mesa 26.2.6 (RADV, RX 9070 XT, Linux), the first start crashes in the shader warm-up, and the next two crash in the precompile before it gives up for one start:

CRASH: exception 0xc0000005 (write 0x40) at libvulkan_radeon.so+0x15b67d

seed_compute tries every answer to a compute program's texture questions. When a texture that is depth-compared gets the answer "integer format", the SPIR-V samples a uint image for a float compare result. spirv-val rejects it, Mesa's spirv_to_nir returns NULL, and RADV dereferences that.

No bound texture can give that answer, because a depth compare needs a depth format. The variant was still saved to hookshot_programs.bin, so precompile_run compiled it again on later starts, and the warm-up and precompile markers only skip those steps temporarily.

Change

  • seed_compute now treats a variant with a texture that is both is_depth and is_integer as failed, so it is never compiled or saved.
  • Only the seed's trial variants are affected. Programs translated in play are unchanged.
  • vk_shader.cpp is part of the shader stamp, so caches that already hold these variants are rebuilt.

Testing

On the RX 9070 XT with Mesa 26.2.6, using the v2.0.5 game with this branch's hookshot_vk.so:

Start Before After
First, empty cache Crash in the warm-up Preparation finishes (38,809 programs, 132.9 s), 10,083 compute pipelines built, window opens, ~60 fps
Second Crash in the precompile Window opens, ~59 fps, nothing rebuilt
  • Mesa's MESA_SPIRV_FAIL_DUMP_PATH wrote no rejected shaders during either start. Before the fix it wrote the failing shader.
  • I fed the suspect compute shaders from a full v2.0.5 cache to the driver one at a time. All 216 with a depth compare on an integer texture were rejected by spirv_to_nir. The other 194 passed it, including 190 valid gathers on integer textures and 4 with a mismatched image format, so the check does not need to be broader.
  • tests/test_seed_compute_depth_integer.py is new and game-free. It fails without the change. tests/run_all.py: 100 passed, 0 failed, 12 skipped (missing headers on this machine).

Only the opening screens were run, about 15 seconds per start. I did not test gameplay, other GPUs or Windows.

Related

seed_compute tries every answer to a compute program's texture questions. A depth compare answered with an integer format gives SPIR-V that samples a uint image for a float compare result. No bound texture can give that answer, but the variant was kept in hookshot_programs.bin and compiled at start, where RADV's compiler crashes on it.
@tickernelz

Copy link
Copy Markdown
Contributor

Confirmed on an RX 6800 XT (RADV NAVI21, Mesa 26.2.6, Fedora 44, kernel 7.2.15) with the v2.0.5 game and this branch's hookshot_vk.so from the Linux AppImage build of 0e396a7.

Fresh cache, no hookshot_programs.bin:

vk: prepared 38809 shader programs (46502 new, 165 failed, 0 stage libraries; 10083 compute variants, 752 programs with texture variants, 65 at the limit) in 59.4 s
vk: precompile: 10083 programs, 0 graphics and 10083 compute pipelines in 1295 ms
vk: 4200 presents, 60.0 fps; ... GPU-bound wait 0.0 ms

Ten minutes of frames afterwards, no CRASH. The same folder and procedure with the v2.0.5 hookshot_vk.so instead crashes in under a minute at libvulkan_radeon.so+0x14a7d2, which is the report's signature.

Cache validation, spirv-val --target-env vulkan1.3 over every unique module the cache holds:

cache modules rejected depth-compare + integer sampled type
v2.0.5, as shipped 50,824 222 216
this branch, rebuilt from empty 50,800 6 0

The six that remain are two other classes and are not this patch's: four compute modules with an R32ui storage image declared with a float sampled type (the same class as #848), and two fragment modules where an SBlock value does not dominate its use. Neither crashes RADV in the runs above.

One caveat on my side: the run renders offscreen (no window, no display in the session I ran it from), so I can confirm the warm-up and the precompile that used to kill the process now complete and the game holds 60 fps, but not that the window opens on this card.

@NotRexed

NotRexed commented Nov 9, 2026

Copy link
Copy Markdown
Owner

Closing to keep the queue clear — please rebase on current main and reopen; thanks!

@NotRexed NotRexed closed this Nov 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants