Build: prepare the shaders at the end of the build, not at the first start #819

Closed
klimovich008 wants to merge 2 commits from prepare-shaders-at-build into main
klimovich008 commented 2026-11-08 22:26:52 +00:00 (Migrated from github.com)

What

make_game.py now runs hookshot --prepare-shaders as its last step, so shader preparation happens during the build, under the builder's progress bar, instead of at the game's first start.

  • Relaying the output. The game's @@stage and @@progress lines go on to the builder unchanged. Its own @@done shaders and @@error ... lines go on as plain text, because both builders read those as the build itself finishing or failing.
  • Failures don't fail the build. If there's no usable Vulkan (exit 3), the game is missing, or anything else goes wrong, the build still succeeds. The game then prepares at its first start, as it does today.
  • Opt-out. Both builders have a "Prepare shaders now" tick, on by default. Unticked, they pass the new make_game.py --no-prepare-shaders and the game prepares at its first start, as today. The choice is remembered and used for updates. HOOKSHOT_NO_PREPARE=1 also skips the step.
  • Builder UI. The Windows builder gets a "Prepare the shaders" row and a share of the progress bar. The Linux builder already shows the stage's own text, so it needs no change.

Why

hookshot --prepare-shaders has been in the game since PR #320, but nothing runs it: not make_game.py, the Windows builder or the Linux builder. So every player gets the preparation at their first start, as minutes of a black game window. Its progress only shows in a console window that can open behind the game, which is why it looks like a hang (#26, #711, the "stuck at 99%" reports behind #701).

On my PC (RX 9070 XT, Ryzen 7 5700X3D), the first start after a fresh v2.0.3 build took 197 s before the first frame; it was 302 s on v2.0.2. A warm start takes 5.5–7.5 s. With this change, those minutes move into the build, where the player expects to wait and can see progress.

This PR doesn't change what gets prepared. It runs the same prepare_run the first start runs, so it neither fixes nor worsens the compute-layout bug that #772 fixes. #701, #702 and #772 change how the preparation works, not when it runs, so this combines with them.

Testing

  • New test, tests/test_prepare_at_build.py (4 cases):
    • a child that prints stage, progress and @@done: the first two are relayed, and @@done comes through as plain text;
    • a child that prints @@error and exits 3: no @@ line reaches the builder, the function returns 3, and the message says the game will prepare at first start;
    • a missing game exe: the build isn't failed;
    • an order check in main(): it runs after the game folder is swapped in, the shader list is written and the pipeline seed is copied, and before @@done.
  • Existing tests pass: test_finish_output.py, test_builder_status.py, test_build_log.py.
  • Windows piping: on Windows, hookshot.exe --prepare-shaders run with its stdout piped printed its @@progress and @@done shaders lines and exited 0. That confirms the relay gets the lines on Windows too.
  • Not tested: I haven't run a full builder build with this change or seen the new row in the Windows builder. The row only adds one entry to the existing Stages and Weight tables.

🤖 Generated with Claude Code

## What `make_game.py` now runs `hookshot --prepare-shaders` as its last step, so shader preparation happens during the build, under the builder's progress bar, instead of at the game's first start. - **Relaying the output.** The game's `@@stage` and `@@progress` lines go on to the builder unchanged. Its own `@@done shaders` and `@@error ...` lines go on as plain text, because both builders read those as the build itself finishing or failing. - **Failures don't fail the build.** If there's no usable Vulkan (exit 3), the game is missing, or anything else goes wrong, the build still succeeds. The game then prepares at its first start, as it does today. - **Opt-out.** Both builders have a **"Prepare shaders now"** tick, on by default. Unticked, they pass the new `make_game.py --no-prepare-shaders` and the game prepares at its first start, as today. The choice is remembered and used for updates. `HOOKSHOT_NO_PREPARE=1` also skips the step. - **Builder UI.** The Windows builder gets a "Prepare the shaders" row and a share of the progress bar. The Linux builder already shows the stage's own text, so it needs no change. ## Why `hookshot --prepare-shaders` has been in the game since PR #320, but nothing runs it: not `make_game.py`, the Windows builder or the Linux builder. So every player gets the preparation at their first start, as minutes of a black game window. Its progress only shows in a console window that can open behind the game, which is why it looks like a hang (#26, #711, the "stuck at 99%" reports behind #701). On my PC (RX 9070 XT, Ryzen 7 5700X3D), the first start after a fresh v2.0.3 build took **197 s** before the first frame; it was 302 s on v2.0.2. A warm start takes 5.5–7.5 s. With this change, those minutes move into the build, where the player expects to wait and can see progress. This PR doesn't change what gets prepared. It runs the same `prepare_run` the first start runs, so it neither fixes nor worsens the compute-layout bug that #772 fixes. #701, #702 and #772 change how the preparation works, not when it runs, so this combines with them. ## Testing - **New test, `tests/test_prepare_at_build.py`** (4 cases): - a child that prints stage, progress and `@@done`: the first two are relayed, and `@@done` comes through as plain text; - a child that prints `@@error` and exits 3: no `@@` line reaches the builder, the function returns 3, and the message says the game will prepare at first start; - a missing game exe: the build isn't failed; - an order check in `main()`: it runs after the game folder is swapped in, the shader list is written and the pipeline seed is copied, and before `@@done`. - **Existing tests pass:** `test_finish_output.py`, `test_builder_status.py`, `test_build_log.py`. - **Windows piping:** on Windows, `hookshot.exe --prepare-shaders` run with its stdout piped printed its `@@progress` and `@@done shaders` lines and exited 0. That confirms the relay gets the lines on Windows too. - **Not tested:** I haven't run a full builder build with this change or seen the new row in the Windows builder. The row only adds one entry to the existing `Stages` and `Weight` tables. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
hckrman101 commented 2026-11-08 22:44:08 +00:00 (Migrated from github.com)

Let's add a checkbox so that this can either be done during build or on first load. Let's have it enabled by default (so it's during build)

Let's add a checkbox so that this can either be done during build or on first load. Let's have it enabled by default (so it's during build)
klimovich008 commented 2026-11-09 02:22:33 +00:00 (Migrated from github.com)

Done: both builders now have a "Prepare shaders now" tick, on by default.

  • Ticked: as before in this PR. The build ends with hookshot --prepare-shaders under its own "Prepare the shaders" row.
  • Unticked: the builder passes the new make_game.py --no-prepare-shaders, and the game prepares at its first start, as it does today. (HOOKSHOT_NO_PREPARE=1 still works too.)
  • Remembered: the choice is saved (builder-settings.json on Windows, builder.ini on Linux) and applied to updates as well.
  • Where it is: on Windows, under "Build workers" on the files page; on Linux, under Language.

Checks: tests/test_prepare_at_build.py has a new case for the flag and both builders' build and update paths. The other builder tests pass, and the Windows builder compiles with 0 errors and 0 warnings (dotnet build -c Release). I haven't looked at the new tick on screen. The failing Python source check is the existing tests/test_mem_trim.py failure on main (fixed by #799), not this change.

Done: both builders now have a **"Prepare shaders now"** tick, on by default. - **Ticked:** as before in this PR. The build ends with `hookshot --prepare-shaders` under its own "Prepare the shaders" row. - **Unticked:** the builder passes the new `make_game.py --no-prepare-shaders`, and the game prepares at its first start, as it does today. (`HOOKSHOT_NO_PREPARE=1` still works too.) - **Remembered:** the choice is saved (`builder-settings.json` on Windows, `builder.ini` on Linux) and applied to updates as well. - **Where it is:** on Windows, under "Build workers" on the files page; on Linux, under Language. Checks: `tests/test_prepare_at_build.py` has a new case for the flag and both builders' build and update paths. The other builder tests pass, and the Windows builder compiles with 0 errors and 0 warnings (`dotnet build -c Release`). I haven't looked at the new tick on screen. The failing Python source check is the existing `tests/test_mem_trim.py` failure on `main` (fixed by #799), not this change.
NotRexed commented 2026-11-09 05:37:14 +00:00 (Migrated from github.com)

Thank you for adding the tick! On current main tests/test_linux_builder_jobs.py fails with this branch (7 errors, in CI too). Closing to keep the queue clear — please rebase on current main, fix that test, and reopen; thanks!

Thank you for adding the tick! On current main tests/test_linux_builder_jobs.py fails with this branch (7 errors, in CI too). Closing to keep the queue clear — please rebase on current main, fix that test, and reopen; thanks!
klimovich008 commented 2026-11-09 06:53:33 +00:00 (Migrated from github.com)

Rebased on current main and fixed tests/test_linux_builder_jobs.py (its harness window now has the new tick; plus a case for the unticked path). GitHub won't reopen this PR after the rebase, so it continues as #1026.

Rebased on current main and fixed `tests/test_linux_builder_jobs.py` (its harness window now has the new tick; plus a case for the unticked path). GitHub won't reopen this PR after the rebase, so it continues as #1026.
Commenting is not possible because the repository is archived.
No description provided.