Skip to content

vk: a mesh fallback program whose compute pipeline failed is not compiled again - #1317

Merged
hckrman101 merged 1 commit into
NotRexed:mainfrom
CiLiBi18:fix/mesh-fallback-failed-pipeline-once
Nov 9, 2026
Merged

hckrman101 merged 1 commit into
NotRexed:mainfrom
CiLiBi18:fix/mesh-fallback-failed-pipeline-once

Conversation

@CiLiBi18

@CiLiBi18 CiLiBi18 commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

fallback_compute_pipelines (gpu/vk/vk_draw.cpp) builds the task and mesh compute pipelines on a program's first fallback draw. When one fails, nothing is kept, so every later draw of that program compiles it again. With a driver that faults on the module, each try is one more fault caught by guarded_compute:

With this change, the failure is remembered by the program's key and variant, and its draws are left out without another try. That is what the first failure already did for that draw. A program the driver can't compile then costs one missing effect instead of the frame rate. The fix behind those faults is the separate #792 port. This change only stops the next bad module from costing the frame rate again.

  • The record is a std::set of (key, variant) under the function's existing mutex, so Program keeps its layout and the program cache's stamp doesn't change.
  • tests/test_mesh_fallback_failed_once.py checks that the record is kept, checked under the lock before guarded_compute, and written before the return. I validated the test by mutation: it fails on main, without the check and without the insert.

hookshot_vk.so builds on Linux with it, and python -I -B tests/run_all.py passes, except nx2/test_nup_read_name.py (zstandard is missing on my machine; it fails the same way on main). It has not been run in game: with #792's fixes, the GTX 1070 no longer reaches this path.

…iled again

fallback_compute_pipelines made the task and mesh stages' compute
pipelines on a program's first fallback draw and kept them. One that
failed kept nothing, so every later draw of the program compiled it
again: with a driver that faults on it, one more fault caught by
guarded_compute each draw. That was 12,160 faults for one program in a
Kokiri Forest run on RADV, the frame down to 2-3 fps (NotRexed#1001). On a
GTX 1070 (NVIDIA 580.178, Linux) the replay stopped presenting after
the first fault.

The failure is now kept by the program's key and variant, and its draws
are left out without another try, as the first failure already left
them out. tests/test_mesh_fallback_failed_once.py checks it.
@hckrman101
hckrman101 merged commit 4841fd9 into NotRexed:main Nov 9, 2026
@CiLiBi18
CiLiBi18 deleted the fix/mesh-fallback-failed-pipeline-once branch November 9, 2026 23:45
rakefire-impala added a commit to rakefire-impala/Hookshot-w-Mesh-Shader-Fallback that referenced this pull request Nov 10, 2026
…ompile

fallback_compute_pipelines made a fallback program's compute pipelines in
its first draw, under one lock. AMD's compiler took up to 12 s on one: every
recording thread stopped behind it and the game froze in the first room
with foliage, then the foliage and the door drew white (RX 5500M, RDNA1,
no VK_EXT_mesh_shader).

- fallback_pipelines_ready: the draw builds them on a worker, as dispatch()
  builds a compute program's pipeline (compute_state 0/1/2, which only
  compute programs used; RX_VK_COMPUTE_SERIAL as there). The draw that
  starts the build waits up to 50 ms for it, which covers NVIDIA's
  compiles; a draw while it still compiles is left out, as a dispatch is.
- fallback_compute_pipelines is the build. Its lock now covers NotRexed#1317's
  failure set and the program's pipelines, not the compiles, so several
  programs compile at once on the workers and in the precompile. A failure
  is still remembered by key and variant before the return, and not tried
  again (tests/test_mesh_fallback_failed_once.py, unchanged, passes).
- precompile_run builds every fallback program's pipelines with the
  compute programs', before play. program_cache_load_some takes a new
  fallbacks flag, which only the precompile sets, and then loads every
  program translated for the fallback (kind 4), not only those the notes
  name, whatever the compute list (NotRexed#1417) says: right after an update is
  when they are cold. Only a GPU without mesh shaders has such programs. The first start
  after a translator change compiles them (minutes on AMD; the precompile's
  stall rule lets the game start and they finish behind it); later starts
  take them from the driver's cache.

tests/test_mesh_fallback.py checks the worker, the draw,
the lock's scope, the precompile and the program cache's load.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rakefire-impala added a commit to rakefire-impala/Hookshot-w-Mesh-Shader-Fallback that referenced this pull request Nov 10, 2026
…ompile

fallback_compute_pipelines made a fallback program's compute pipelines in
its first draw, under one lock. AMD's compiler took up to 12 s on one: every
recording thread stopped behind it and the game froze in the first room
with foliage, then the foliage and the door drew white (RX 5500M, RDNA1,
no VK_EXT_mesh_shader).

- fallback_pipelines_ready: the draw builds them on a worker, as dispatch()
  builds a compute program's pipeline (compute_state 0/1/2, which only
  compute programs used; RX_VK_COMPUTE_SERIAL as there). The draw that
  starts the build waits up to 50 ms for it, which covers NVIDIA's
  compiles; a draw while it still compiles is left out, as a dispatch is.
- fallback_compute_pipelines is the build. Its lock now covers NotRexed#1317's
  failure set and the program's pipelines, not the compiles, so several
  programs compile at once on the workers and in the precompile. A failure
  is still remembered by key and variant before the return, and not tried
  again (tests/test_mesh_fallback_failed_once.py, unchanged, passes).
- precompile_run builds every fallback program's pipelines with the
  compute programs', before play. program_cache_load_some takes a new
  fallbacks flag, which only the precompile sets, and then loads every
  program translated for the fallback (kind 4), not only those the notes
  name, whatever the compute list (NotRexed#1417) says: right after an update is
  when they are cold. Only a GPU without mesh shaders has such programs. The first start
  after a translator change compiles them (minutes on AMD; the precompile's
  stall rule lets the game start and they finish behind it); later starts
  take them from the driver's cache.

tests/test_mesh_fallback.py checks the worker, the draw,
the lock's scope, the precompile and the program cache's load.
NotRexed pushed a commit that referenced this pull request Nov 10, 2026
…ompile (#1512)

fallback_compute_pipelines made a fallback program's compute pipelines in
its first draw, under one lock. AMD's compiler took up to 12 s on one: every
recording thread stopped behind it and the game froze in the first room
with foliage, then the foliage and the door drew white (RX 5500M, RDNA1,
no VK_EXT_mesh_shader).

- fallback_pipelines_ready: the draw builds them on a worker, as dispatch()
  builds a compute program's pipeline (compute_state 0/1/2, which only
  compute programs used; RX_VK_COMPUTE_SERIAL as there). The draw that
  starts the build waits up to 50 ms for it, which covers NVIDIA's
  compiles; a draw while it still compiles is left out, as a dispatch is.
- fallback_compute_pipelines is the build. Its lock now covers #1317's
  failure set and the program's pipelines, not the compiles, so several
  programs compile at once on the workers and in the precompile. A failure
  is still remembered by key and variant before the return, and not tried
  again (tests/test_mesh_fallback_failed_once.py, unchanged, passes).
- precompile_run builds every fallback program's pipelines with the
  compute programs', before play. program_cache_load_some takes a new
  fallbacks flag, which only the precompile sets, and then loads every
  program translated for the fallback (kind 4), not only those the notes
  name, whatever the compute list (#1417) says: right after an update is
  when they are cold. Only a GPU without mesh shaders has such programs. The first start
  after a translator change compiles them (minutes on AMD; the precompile's
  stall rule lets the game start and they finish behind it); later starts
  take them from the driver's cache.

tests/test_mesh_fallback.py checks the worker, the draw,
the lock's scope, the precompile and the program cache's load.
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.

1 participant