feat(vk): built-in shaders from a folder with RX_VK_SHADER_DIR #2878

Open
github-sync wants to merge 1 commit from github/pr/2878 into main
Owner

@jordanella opened this pull request on GitHub · 2026-11-12 18:18 UTC · original

Trying an edit to one of the renderer's own shaders (the texture decoders, the upscalers, frame generation, the write-back diff) takes a renderer build today, because their SPIR-V is compiled in. With RX_VK_SHADER_DIR set, the renderer takes each of them from a folder when the file is there, so an edit is a glslang run and a restart. This is the dev-loop proposal's B2 (#2636), the Vulkan side of what RX_WGSL_OVERRIDE does for WebGPU.

Change

  • The switch: RX_VK_SHADER_DIR=<folder>. Each built-in shader is taken from <folder>/<name>.spv when that file is SPIR-V, and the log names it once:

    vk: built-in shader wb_diff_comp from <folder>/wb_diff_comp.spv (6248 bytes; compiled in: 6248) (RX_VK_SHADER_DIR)
    

    <name> is the header's: clear_vert.spv for clear_vert_spv.h. A missing file means the compiled-in words, without a log line. A file that isn't SPIR-V (its length, or its first word) is named in the log with the reason, and the compiled-in words are used.

  • One lookup: gpu/vk/vk_builtin_spv.{h,cpp}, builtin_spv(name, words, bytes), behind a BUILTIN_SPV(ARRAY) macro. A file is read once and kept for the process, as the compiled-in words are. It serves all 52 compiled-in arrays the renderer uses, in vk_draw, vk_framegen, vk_fsr3, vk_fsr3fi, vk_fsr3_inputs, vk_memory, vk_reactive, vk_temporal and vk_texture. The two FSR 3 pass tables carry each array's name for it.

  • Unset, nothing changes: the lookup returns the compiled-in words before looking at anything else.

  • Not from a shared hookshot_env.txt: a folder of shader code is a _DIR switch, so env_line_allowed already refuses it there. Only the environment the game is started with sets it.

  • The headers stay generated from the sources, as before. The folder is for iteration only.

In the game

Windows 11, RTX 3080 (NVIDIA 621.14), this branch built with the Builder's steps, headless through the control bridge from a save, in Kokiri Forest:

  • A folder of the built-in shaders' own words (each written from its header): in play, 24–28 fps, nothing in the log about a lost device or a crash. Four shaders were made from the folder in that scene: astc_decoder_comp, bc_encoder_comp, block_linear_unswizzle_2d_comp and wb_diff_comp, each logged once with the same size as the compiled-in one.
  • The same with wb_diff_comp.spv two bytes too long: in play, 22–29 fps, and vk: built-in shader wb_diff_comp: <folder>/wb_diff_comp.spv is not a whole number of words, or shorter than SPIR-V's header; the compiled-in one is used.

An edited shader wasn't tried: there is no glslang on this PC. The files were the shipped words, so the run shows the path works, not a visible change.

Testing

  • tests/test_builtin_spv.py (new, game-free):
    • builds the lookup as C++ with a stand-in log and runs it with the folder unset, the file missing, a SPIR-V file, one cut short and one with the wrong first word, in a folder with a space in its name;
    • checks that every compiled-in array of gpu/vk/shaders and host_shaders that gpu/vk uses goes through the lookup (52 here; on main it stops at vk_draw.cpp's seven);
    • checks that RX_VK_SHADER_DIR isn't taken from hookshot_env.txt.
  • Three fixtures that compile pieces of vk_framegen.cpp (upscale_independent_test.cpp, framegen_resources_test.cpp, present_source_crop_test.cpp) define BUILTIN_SPV_ARGS beside their stand-in arrays, as the lookup is with the folder unset, so their pointer checks still hold.
  • Every check that reads the changed files (159), through run_all.py on Windows, rebased on today's main: 157 pass; nx2/test_bc_storage_views.py and tests/test_linux_driver_fault_guard.py fail the same way on main here.
  • Not tested: Linux. The lookup is standard C++, and paths are fopen's, which is UTF-8 on Windows through the manifest.

See #2636 (B2).

🤖 Generated with Claude Code

> [@jordanella](https://github.com/jordanella) opened this pull request on GitHub · 2026-11-12 18:18 UTC · [original](https://github.com/NotRexed/Hookshot/pull/2878) Trying an edit to one of the renderer's own shaders (the texture decoders, the upscalers, frame generation, the write-back diff) takes a renderer build today, because their SPIR-V is compiled in. With `RX_VK_SHADER_DIR` set, the renderer takes each of them from a folder when the file is there, so an edit is a glslang run and a restart. This is the dev-loop proposal's B2 (#2636), the Vulkan side of what `RX_WGSL_OVERRIDE` does for WebGPU. ## Change - **The switch:** `RX_VK_SHADER_DIR=<folder>`. Each built-in shader is taken from `<folder>/<name>.spv` when that file is SPIR-V, and the log names it once: ``` vk: built-in shader wb_diff_comp from <folder>/wb_diff_comp.spv (6248 bytes; compiled in: 6248) (RX_VK_SHADER_DIR) ``` `<name>` is the header's: `clear_vert.spv` for `clear_vert_spv.h`. A missing file means the compiled-in words, without a log line. A file that isn't SPIR-V (its length, or its first word) is named in the log with the reason, and the compiled-in words are used. - **One lookup:** `gpu/vk/vk_builtin_spv.{h,cpp}`, `builtin_spv(name, words, bytes)`, behind a `BUILTIN_SPV(ARRAY)` macro. A file is read once and kept for the process, as the compiled-in words are. It serves all 52 compiled-in arrays the renderer uses, in `vk_draw`, `vk_framegen`, `vk_fsr3`, `vk_fsr3fi`, `vk_fsr3_inputs`, `vk_memory`, `vk_reactive`, `vk_temporal` and `vk_texture`. The two FSR 3 pass tables carry each array's name for it. - **Unset, nothing changes:** the lookup returns the compiled-in words before looking at anything else. - **Not from a shared `hookshot_env.txt`:** a folder of shader code is a `_DIR` switch, so `env_line_allowed` already refuses it there. Only the environment the game is started with sets it. - **The headers stay generated** from the sources, as before. The folder is for iteration only. ## In the game Windows 11, RTX 3080 (NVIDIA 621.14), this branch built with the Builder's steps, headless through the control bridge from a save, in Kokiri Forest: - **A folder of the built-in shaders' own words** (each written from its header): in play, 24–28 fps, nothing in the log about a lost device or a crash. Four shaders were made from the folder in that scene: `astc_decoder_comp`, `bc_encoder_comp`, `block_linear_unswizzle_2d_comp` and `wb_diff_comp`, each logged once with the same size as the compiled-in one. - **The same with `wb_diff_comp.spv` two bytes too long:** in play, 22–29 fps, and `vk: built-in shader wb_diff_comp: <folder>/wb_diff_comp.spv is not a whole number of words, or shorter than SPIR-V's header; the compiled-in one is used`. An edited shader wasn't tried: there is no glslang on this PC. The files were the shipped words, so the run shows the path works, not a visible change. ## Testing - **`tests/test_builtin_spv.py` (new, game-free):** - builds the lookup as C++ with a stand-in log and runs it with the folder unset, the file missing, a SPIR-V file, one cut short and one with the wrong first word, in a folder with a space in its name; - checks that every compiled-in array of `gpu/vk/shaders` and `host_shaders` that `gpu/vk` uses goes through the lookup (52 here; on `main` it stops at `vk_draw.cpp`'s seven); - checks that `RX_VK_SHADER_DIR` isn't taken from `hookshot_env.txt`. - **Three fixtures that compile pieces of `vk_framegen.cpp`** (`upscale_independent_test.cpp`, `framegen_resources_test.cpp`, `present_source_crop_test.cpp`) define `BUILTIN_SPV_ARGS` beside their stand-in arrays, as the lookup is with the folder unset, so their pointer checks still hold. - **Every check that reads the changed files (159), through `run_all.py` on Windows, rebased on today's `main`:** 157 pass; `nx2/test_bc_storage_views.py` and `tests/test_linux_driver_fault_guard.py` fail the same way on `main` here. - **Not tested:** Linux. The lookup is standard C++, and paths are `fopen`'s, which is UTF-8 on Windows through the manifest. See #2636 (B2). 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- github-sync:item:2878 -->
With RX_VK_SHADER_DIR=<folder>, each of the renderer's built-in shaders
is taken from <folder>/<name>.spv (clear_vert.spv for clear_vert_spv.h)
when that file is SPIR-V, and the log names it; otherwise, and unset,
the compiled-in words. A shader edit can then be tried by compiling it
into the folder and starting the game again, without a renderer build.
The dev-loop proposal's B2 (#2636).

One lookup (gpu/vk/vk_builtin_spv.h, BUILTIN_SPV) serves the 52
compiled-in arrays the renderer uses; the FSR 3 tables carry each
array's name. The folder is not taken from hookshot_env.txt (a _DIR
switch). tests/test_builtin_spv.py builds the lookup and runs it against
made-up files, and checks that no array is used around it.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Commenting is not possible because the repository is archived.
No description provided.