perf(build): keep unchanged button prompts in packaged builds too #314

Open
gab9281 wants to merge 3 commits from gab9281/Longshot:perf/prompt-cache-packaged into main
Member

Why

Every build from a packaged builder (the launcher's, players' builds) drew the button prompts of the other controllers again, even when nothing they are made from changed: about two minutes of the finish stage, each time. Source-checkout builds already kept them (46780503).

What changed

  • build: nx2/make_game.py passes --incremental to prompt_assets.py in every build, packaged or not.
  • prompts: prompt_key() in nx2/prompt_assets.py also covers:
    • host/prompts.c, the game's side that makes the runtime files from the prompts. A kept set now keeps those runtime files too, and they are no longer removed under a game running from the folder.
    • the builder's release (builder_release(): version.txt, or the AppImage's VERSION; none in a source checkout). The first build after a builder update draws them again, whatever the input list misses.
  • prompts: the reason printed for a run without --incremental is now "a direct run of prompt_assets.py".
  • tests: tests/test_prompt_skip.py:
    • kept originals and runtime files;
    • the builder's release draws them again;
    • a failed drawing removes the prompts;
    • every build asks for --incremental.
  • docs: docs/development.md (when the prompts are kept), and two rows in docs/tested-configurations.md.

Flags and settings

None. LONGSHOT_FORCE_PROMPTS=1 still draws them again, as before.

Measurements

main: 514591a3 (2026-11-13)
this PR: perf/prompt-cache-packaged @ b7faba3f (6c16f8da, the head, adds only the docs rows)
Hardware: NVIDIA GeForce RTX 3060 Laptop GPU (6 GB), NVIDIA 620.70.06, AMD Ryzen 7 6800H, 15 GB, CachyOS (Linux 7.3.3), KDE Wayland
Scene: no game. A packaged builder: the AppImage's AppRun stand-in, LONGSHOT_TOOLS set. An --update of a built game folder with nothing changed, --no-prepare-shaders.
Method:

  • Each side first got one warm-up build. On this PR, that build drew the prompts once, because no stamp existed yet.
  • Then 2 builds per side, interleaved main, PR, main, PR.
  • The numbers are the finish stage from the builder's where the time went lines.

How to reproduce: build a game folder with each commit's packaged builder, then run make_game.py --update on it twice with nothing changed. Read the prompts: line and the finish stage.

main @ 514591a3 this PR @ b7faba3f
Finish stage, run 1 148 s 12 s
Finish stage, run 2 191 s 11 s
Median 170 s 11.5 s
The prompts drawn again every build kept
main-1   finish 148 s | prompts: regenerated (packaged or direct build)
branch-1 finish 12 s  | prompts: unchanged, kept
main-2   finish 191 s | prompts: regenerated (packaged or direct build)
branch-2 finish 11 s  | prompts: unchanged, kept
(warm-up, this PR: prompts: regenerated (source changed))

Testing

Tested:

  • python -I -B tests/run_all.py on Linux: 517 passed, 1 failed, 15 skipped (with the Vulkan and SPIR-V headers; the skips are Windows-only checks and one needing an offscreen Vulkan 1.3 device). test_menu_i18n fails on main @ 514591a3 too.
  • tests/test_prompt_skip.py: 41 tests pass.
  • The packaged-builder builds above on Linux: kept with nothing changed, and drawn again after an update.
  • In the game, on Linux, from the kept folder: the button prompts row changed in play through the control bridge (Switch, Xbox, PS4, PS5). The log shows each face's textures and the icons in texts made again (prompts: now <face> textures … icons in texts). The game ran on the lightest settings, because this 15 GB laptop ran out of memory twice on the default ones.

Not tested:

  • A packaged build on Windows (the launcher's Windows builder). The same code runs there: version.txt is next to nx2/.
  • Whether the HUD's R1/R2 item hints follow a live face change. In these shots they stayed R1/R2 after the change, after 5 s, after the pause menu, and after a map change. This PR doesn't change what is drawn, only whether unchanged files are drawn again. The same check on main needed a shader preparation that was not practical here.

Needs other testers:

  • Windows, the launcher's packaged builder: a second build with nothing changed. Expected: prompts: unchanged, kept and a finish stage under 20 s, then the faces still switch in the game (T-Z5M2).

Screenshots

Nothing on screen: the prompts drawn are the same files; only when they are drawn changes.

Risk and rollback

A kept set could be stale if something the prompts are made from is missing from the stamp. The builder's release in the stamp limits that to one builder release. LONGSHOT_FORCE_PROMPTS=1 draws them again. Reverting the commits is enough.

Reviewer notes

Start with prompt_key() and make_prompts() in nx2/prompt_assets.py. One thing is unchanged on purpose: on a miss, the inputs are hashed again after drawing (a few seconds against a minute or two of drawing), so an input that changed during the drawing is never stamped.

Issues

None: a follow-up to 46780503, which kept them in source-checkout builds.

Checklist

For everyone

  • One topic.
  • The title is a Conventional Commit (type(scope): description).
  • Rebased on current main.
  • python -I -B tests/run_all.py run and passing (any failure that also fails on main is named above).
  • Tested in the game, or what wasn't is named under Testing.
  • Testing filled in: what was tested, what wasn't, and what needs other testers (with test requests).
  • Measured: main and this PR at named commits, on the same PC, scene and settings, at least 2 interleaved runs each, the median reported.
  • No game files, dumps, build output or generated files.
  • third_party/ untouched (a new folder with a PROVENANCE.md instead).
  • The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled.

If applicable

  • AI assistance recorded with Assisted-by: / Co-Authored-By: trailers.
  • A row in docs/tested-configurations.md for each measured run.
  • A check under tests/ that reads changed source updated in this PR, not weakened.
  • Docs updated.

🤖 Generated with Claude Code

https://claude.ai/code/session_015KgSKoUqUvce5UXG89NBgi

## Why Every build from a packaged builder (the launcher's, players' builds) drew the button prompts of the other controllers again, even when nothing they are made from changed: about two minutes of the finish stage, each time. Source-checkout builds already kept them (46780503). ## What changed - build: `nx2/make_game.py` passes `--incremental` to `prompt_assets.py` in every build, packaged or not. - prompts: `prompt_key()` in `nx2/prompt_assets.py` also covers: - `host/prompts.c`, the game's side that makes the runtime files from the prompts. A kept set now keeps those runtime files too, and they are no longer removed under a game running from the folder. - the builder's release (`builder_release()`: `version.txt`, or the AppImage's `VERSION`; none in a source checkout). The first build after a builder update draws them again, whatever the input list misses. - prompts: the reason printed for a run without `--incremental` is now "a direct run of prompt_assets.py". - tests: `tests/test_prompt_skip.py`: - kept originals and runtime files; - the builder's release draws them again; - a failed drawing removes the prompts; - every build asks for `--incremental`. - docs: `docs/development.md` (when the prompts are kept), and two rows in `docs/tested-configurations.md`. ## Flags and settings None. `LONGSHOT_FORCE_PROMPTS=1` still draws them again, as before. ## Measurements main: 514591a3 (2026-11-13) this PR: perf/prompt-cache-packaged @ b7faba3f (6c16f8da, the head, adds only the docs rows) Hardware: NVIDIA GeForce RTX 3060 Laptop GPU (6 GB), NVIDIA 620.70.06, AMD Ryzen 7 6800H, 15 GB, CachyOS (Linux 7.3.3), KDE Wayland Scene: no game. A packaged builder: the AppImage's AppRun stand-in, `LONGSHOT_TOOLS` set. An `--update` of a built game folder with nothing changed, `--no-prepare-shaders`. Method: - Each side first got one warm-up build. On this PR, that build drew the prompts once, because no stamp existed yet. - Then 2 builds per side, interleaved main, PR, main, PR. - The numbers are the finish stage from the builder's `where the time went` lines. How to reproduce: build a game folder with each commit's packaged builder, then run `make_game.py --update` on it twice with nothing changed. Read the `prompts:` line and the finish stage. | | main @ 514591a3 | this PR @ b7faba3f | |---|---|---| | Finish stage, run 1 | 148 s | 12 s | | Finish stage, run 2 | 191 s | 11 s | | Median | 170 s | 11.5 s | | The prompts | drawn again every build | kept | ``` main-1 finish 148 s | prompts: regenerated (packaged or direct build) branch-1 finish 12 s | prompts: unchanged, kept main-2 finish 191 s | prompts: regenerated (packaged or direct build) branch-2 finish 11 s | prompts: unchanged, kept (warm-up, this PR: prompts: regenerated (source changed)) ``` ## Testing **Tested:** - `python -I -B tests/run_all.py` on Linux: 517 passed, 1 failed, 15 skipped (with the Vulkan and SPIR-V headers; the skips are Windows-only checks and one needing an offscreen Vulkan 1.3 device). `test_menu_i18n` fails on main @ 514591a3 too. - `tests/test_prompt_skip.py`: 41 tests pass. - The packaged-builder builds above on Linux: kept with nothing changed, and drawn again after an update. - In the game, on Linux, from the kept folder: the button prompts row changed in play through the control bridge (Switch, Xbox, PS4, PS5). The log shows each face's textures and the icons in texts made again (`prompts: now <face> textures … icons in texts`). The game ran on the lightest settings, because this 15 GB laptop ran out of memory twice on the default ones. **Not tested:** - A packaged build on Windows (the launcher's Windows builder). The same code runs there: `version.txt` is next to `nx2/`. - Whether the HUD's R1/R2 item hints follow a live face change. In these shots they stayed R1/R2 after the change, after 5 s, after the pause menu, and after a map change. This PR doesn't change what is drawn, only whether unchanged files are drawn again. The same check on main needed a shader preparation that was not practical here. **Needs other testers:** - Windows, the launcher's packaged builder: a second build with nothing changed. Expected: `prompts: unchanged, kept` and a finish stage under 20 s, then the faces still switch in the game (T-Z5M2). ## Screenshots Nothing on screen: the prompts drawn are the same files; only when they are drawn changes. ## Risk and rollback A kept set could be stale if something the prompts are made from is missing from the stamp. The builder's release in the stamp limits that to one builder release. `LONGSHOT_FORCE_PROMPTS=1` draws them again. Reverting the commits is enough. ## Reviewer notes Start with `prompt_key()` and `make_prompts()` in `nx2/prompt_assets.py`. One thing is unchanged on purpose: on a miss, the inputs are hashed again after drawing (a few seconds against a minute or two of drawing), so an input that changed during the drawing is never stamped. ## Issues None: a follow-up to 46780503, which kept them in source-checkout builds. ## Checklist ### For everyone - [x] One topic. - [x] The title is a Conventional Commit (`type(scope): description`). - [x] Rebased on current `main`. - [x] `python -I -B tests/run_all.py` run and passing (any failure that also fails on `main` is named above). - [x] Tested in the game, or what wasn't is named under Testing. - [x] Testing filled in: what was tested, what wasn't, and what needs other testers (with test requests). - [x] Measured: main and this PR at named commits, on the same PC, scene and settings, at least 2 interleaved runs each, the median reported. - [x] No game files, dumps, build output or generated files. - [x] `third_party/` untouched (a new folder with a `PROVENANCE.md` instead). - [x] The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled. ### If applicable - [x] AI assistance recorded with `Assisted-by:` / `Co-Authored-By:` trailers. - [x] A row in `docs/tested-configurations.md` for each measured run. - [x] A check under `tests/` that reads changed source updated in this PR, not weakened. - [x] Docs updated. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_015KgSKoUqUvce5UXG89NBgi
#2698 kept the button prompts between source-checkout builds but left
packaged builders (the launcher's, players' builds) drawing them again
on every build: about a minute of the finish stage each time. The stamp
already covers what could differ there: prompt_assets.py and the prompt
tables by content, the packages and their native libraries, Python, the
game's files. A builder update changes those, so its first build still
draws them again.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015KgSKoUqUvce5UXG89NBgi
- The stamp has the builder's release (version.txt, or the AppImage's
  VERSION): each builder update draws the prompts again once, whatever the
  input list misses. A source checkout has none, as before.
- host/prompts.c is in the stamp: the runtime files the game makes from the
  prompts were made by the same code, so a kept set keeps them too, and a
  game running from the folder no longer has them removed under it.
- The regenerated reason without --incremental says a direct run.
- Tests: the builder's release, kept runtime files, every build asks for
  --incremental; the packaged parameter that no longer reached the code is
  gone.

Not changed: on a miss, the inputs are hashed again after drawing (a few
seconds against the minute or two of the drawing), which is what keeps an
input changed during the drawing from being stamped.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015KgSKoUqUvce5UXG89NBgi
docs(build): the measured finish stage in docs/tested-configurations.md
All checks were successful
CI / Conventional Commit title (pull_request) Successful in 4s
CI / Workflow lint (actionlint) (pull_request) Successful in 6s
Third-party parts / As their notes say (pull_request) Successful in 5s
Website / Website on Cloudflare (pull_request_target) Has been skipped
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been skipped
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been skipped
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been skipped
Third-party parts / The same as upstream (pull_request) Has been skipped
PR description / Description follows the template (pull_request_target) Successful in 3s
6c16f8daad
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015KgSKoUqUvce5UXG89NBgi
gab9281 changed title from WIP: perf(build): keep unchanged button prompts in packaged builds too to perf(build): keep unchanged button prompts in packaged builds too 2026-11-13 21:54:36 +00:00
mooki left a comment

Read head 6c16f8da, all five changed files, the packaging paths and runtime prompt readers; ran the cache tests on this head and against main cf605c85, the font-mapping check with GCC and Clang, and the AppImage-font and guide-line checks. No game or full build was run.

What's good

  • The cost is real: main leaves out --incremental when it installs a packaged launcher. This change reaches the existing cache path rather than adding a second one. Both package formats carry host/prompts.c and the release file where the new key looks for them.
  • The input and output checks, failed-generation fallback and before/after input comparison remain intact. The runtime still chooses textures and layouts from the current face and bindings; the font and merged size table are made for each process.
  • The focused cache check reports 41 tests, with 2 Windows-only skips. Against current main, the same check fails in the four expected places: the release key, packaged incremental flag, host/prompts.c invalidation and retained runtime files. The tests distinguish the change from main.
  • The reported build comparison names both commits, the laptop, warm-ups and two alternating runs per side. From the quoted finish times, the medians are 169.5 s and 11.5 s; 170 s is reasonable rounding. The ranges are 148–191 s and 11–12 s. That supports a large reduction for these warm, unchanged updates, not a gameplay speed claim.

Needed before it can merge

  1. Resolve the run-table conflict using main's new run-file format. docs/tested-configurations.md lines 17–18 are the only conflicting hunk against main cf605c85: both sides inserted results at the start of the table. Main has also frozen that table and moved new results to docs/tested/. Rebase, leave the existing rows and catalogue links intact, and put these four measured builds in separate self-contained run files following docs/tested/README.md, without as above. A clean merge and a passing tests/test_tested_configurations.py would settle this. The Python changes merge without a textual conflict; I found no separate functional defect in them.

Smaller points

  • The Windows request's “finish stage under 20 s” is not established for another PC. Use prompts: unchanged, kept as the expected cache result and ask the tester to report the time. The finish stage also copies the built files and does other work.
  • Please keep the skips visible in the test result: here it is 39 passed and 2 skipped, not 41 executed passes. The missing NumPy dependency on my first guide-line invocation was resolved with the existing dependency environment; that check then passed.

Not checked

No packaged Windows build, game, real controller, live face change or full suite was run here. The source-check jobs on this head were skipped, not passed: https://git.magicbean.dev/MagicBeanDev/Longshot/actions/runs/2673. The Windows request remains useful, especially for the version.txt path and a second build of the same folder.

I checked the measurement arithmetic, not the original build logs or machine load. The description's unresolved R1/R2 observation cannot establish a regression without the same check on main. The reason for requesting changes is the merge and run-record migration above, not an observed prompt-rendering failure.

Read head `6c16f8da`, all five changed files, the packaging paths and runtime prompt readers; ran the cache tests on this head and against main `cf605c85`, the font-mapping check with GCC and Clang, and the AppImage-font and guide-line checks. No game or full build was run. ### What's good - The cost is real: main leaves out `--incremental` when it installs a packaged launcher. This change reaches the existing cache path rather than adding a second one. Both package formats carry `host/prompts.c` and the release file where the new key looks for them. - The input and output checks, failed-generation fallback and before/after input comparison remain intact. The runtime still chooses textures and layouts from the current face and bindings; the font and merged size table are made for each process. - The focused cache check reports 41 tests, with 2 Windows-only skips. Against current main, the same check fails in the four expected places: the release key, packaged incremental flag, `host/prompts.c` invalidation and retained runtime files. The tests distinguish the change from main. - The reported build comparison names both commits, the laptop, warm-ups and two alternating runs per side. From the quoted finish times, the medians are 169.5 s and 11.5 s; 170 s is reasonable rounding. The ranges are 148–191 s and 11–12 s. That supports a large reduction for these warm, unchanged updates, not a gameplay speed claim. ### Needed before it can merge 1. **Resolve the run-table conflict using main's new run-file format.** `docs/tested-configurations.md` lines 17–18 are the only conflicting hunk against main `cf605c85`: both sides inserted results at the start of the table. Main has also frozen that table and moved new results to `docs/tested/`. Rebase, leave the existing rows and catalogue links intact, and put these four measured builds in separate self-contained run files following `docs/tested/README.md`, without `as above`. A clean merge and a passing `tests/test_tested_configurations.py` would settle this. The Python changes merge without a textual conflict; I found no separate functional defect in them. ### Smaller points - The Windows request's “finish stage under 20 s” is not established for another PC. Use `prompts: unchanged, kept` as the expected cache result and ask the tester to report the time. The finish stage also copies the built files and does other work. - Please keep the skips visible in the test result: here it is 39 passed and 2 skipped, not 41 executed passes. The missing NumPy dependency on my first guide-line invocation was resolved with the existing dependency environment; that check then passed. ### Not checked No packaged Windows build, game, real controller, live face change or full suite was run here. The source-check jobs on this head were skipped, not passed: https://git.magicbean.dev/MagicBeanDev/Longshot/actions/runs/2673. The Windows request remains useful, especially for the `version.txt` path and a second build of the same folder. I checked the measurement arithmetic, not the original build logs or machine load. The description's unresolved R1/R2 observation cannot establish a regression without the same check on main. The reason for requesting changes is the merge and run-record migration above, not an observed prompt-rendering failure.
All checks were successful
CI / Conventional Commit title (pull_request) Successful in 4s
CI / Workflow lint (actionlint) (pull_request) Successful in 6s
Third-party parts / As their notes say (pull_request) Successful in 5s
Website / Website on Cloudflare (pull_request_target) Has been skipped
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been skipped
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been skipped
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been skipped
Third-party parts / The same as upstream (pull_request) Has been skipped
PR description / Description follows the template (pull_request_target) Successful in 3s
This pull request has changes conflicting with the target branch.
  • docs/tested-configurations.md
View command line instructions

Manual merge helper

Use this merge commit message when completing the merge manually.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u 'perf/prompt-cache-packaged:gab9281-perf/prompt-cache-packaged'
git switch 'gab9281-perf/prompt-cache-packaged'
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
MagicBeanDev/Longshot!314
No description provided.