build(release): ship the pipeline state list with every release #1918
No reviewers
Labels
No labels
accessibility
autorelease: pending
autorelease: tagged
bug
dependencies
documentation
duplicate
enhancement
github_actions
good first issue
help wanted
invalid
question
testing wanted
wontfix
No milestone
No assignees
1 participant
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Hookshot!1918
Loading…
Reference in a new issue
No description provided.
Delete branch "ship-pipeline-list"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
A fresh install's first field load washes white for about 6 seconds, because the draws whose pipelines are still compiling are left out; with a pipeline state list beside the game, the first start builds those pipelines before the title and none are left out. Releases v2.0.8 to v2.0.14 shipped no list: I downloaded each release's Windows app part (
HookshotBuilder-app-*.zip, named by itshookshot-setup.txt) and Linux tools part (HookshotLinux-usr-share-hookshot-*.zip, named byhookshot-linux.txt), and theirwork/folders hold onlyhot_funcs.txt,hot_order.txt,hookshot_pieces.prof,image/chunks.txt(and the icon on Windows), with nopipeline_states.bin.Why it went missing
nx2/make_game.py(ship_state_list) andscripts/linux/appimage.shboth shippedwork/pipeline_states.binonly when it happened to be there, and in CI it never is:work/is ignored, and the "Play profile" steps fillwork/from the previous release's app part, which never had one. The Windows package (release_parts.py package) only ever takestools/workfrom the previous release, so even a list in the checkout would not have reached it.What changes
The list lives in
assets/pipeline_states.bin.xz, which is tracked.work/stays local and fully ignored, as CONTRIBUTING says. The file is xz-compressed to keep the repository's history small: 23,840 bytes for the 665,820-byte list. I chose xz over zstd because the AppImage's Python is 3.12, and its standard library haslzmabut notcompression.zstd.What it holds for now: a list recorded from play on my PC, with 1261 pipelines (1186 graphics, 75 mesh) from 977 programs. It will be replaced by a fuller one later.
What the file contains (
nx2/pipeline_states.pyhas the layout). For each pipeline:It contains no game code and no assets. A player's build turns the hashes back into shaders from their own
hookshot_shaders.bin, which is made from their own dump. Unpacked,stringsfinds nothing in it but theHKSTATE1magic.nx2/make_game.pyunpacks the list beside the game ashookshot_pipeline_states_shipped.bin. The game side is unchanged.nx2/pipeline_states.py:--outends in.xz;--checkis the release check: the list must be whole, of this build's format, and not empty.Every release path carries it:
assets/was already copied.appimage.shnow stops if the list is missing.check_player_build.sh(which a tagged release needs to pass) reads the list back with the image's own Python, using--check.release_parts.py packagecopies the list totools/assets/, wheremake_game.py(run fromtools/) looks for it. It stops if the list is missing, damaged, of another format or empty.tools/assetsends up in the app part.Release CI fails without it, with a message that says how to regenerate it. Both checks run on every build, so they run on tags too.
docs/development.md has a new section, "The pipeline state list":
python -I nx2/pipeline_states.py --out assets/pipeline_states.bin.xz assets/pipeline_states.bin.xz <game folder>/hookshot_pipeline_states.bin ...;Tests:
tests/test_ship_state_list.pychecks that:--check;assets/and its check stops without the list;make_game.pyunpacks it from;tests/test_pipeline_states.pyadds the.xzround trip, make_game's unpacking, and a list that does not read being left out.tests/run_all.py: 279 passed, 3 failed. The same 3 fail on main without this change (nx2/test_nup_read_name.py,tests/test_program_cache_cleanup.py,tests/test_wayland_libdecor_hint.py).The first commit put the list in
work/with a.gitignoreexception, and the second commit moves it out again. Please squash on merge, so that the uncompressed 666 KB file does not stay in main's history.A question for you
Are you OK with shipping this file's contents? It is shader hashes and render state: no game code and nothing extracted from the dump. That is the same kind of data as
hot_funcs.txt,hot_order.txtand the play profile (hookshot_pieces.prof), which every release already ships intools/work. Nothing underwork/is committed.Self-review
What I checked, for the whole diff against the base:
AppImage:
cp -a ... assets "$T/"carries the list, andappimage.shnow stops without it.check_player_build.shreads the list back with the image's Python 3.12 (lzmais in its standard library) without writing into the read-only tree.usr/share/hookshotincludesassets/.Windows package:
release_parts.py packagecopies only the tracked gpu/host/nx2/scripts/third_party folders, soassets/was not in it before. The list is now copied explicitly totools/assets/.make_setup_parts.pyputstools/assetsin the app part.make_game.pywithROOT = tools/, sotools/assets/pipeline_states.bin.xzis the path it reads._lzma.pyd.Player build:
make_game.pyunpacks the list tohookshot_pipeline_states_shipped.binwith a.newfile andos.replace, and only rewrites it when the contents differ. The game's reader (state_list_read) is unchanged.Failure modes:
Player lists with a record cut short at the end are still merged; the partial record is dropped, as the game drops it.
Format change (HKSTATE2):
MAGIC/SIZEchange, the committed list stops reading and CI fails until it is regenerated with the new build. That PR has to replaceassets/pipeline_states.bin.xztoo.nx2/pipeline_states.py, so they follow the change.Windows paths: all paths are joined with
os.path.join, and the file is binary.Size: 23,840 bytes in git. An uncompressed list is about 520 bytes per pipeline, and compression brings that to roughly 20 bytes.
Main since the base: main has moved and changed
nx2/make_game.py, but not nearship_state_list, so the merge is clean.What I changed as a result:
.gitattributesmarks*.xzas binary, instead of relying ontext=autoto guess.make_game.pyno longer crashes or ships a list that does not read: it leaves it out and says why.Still open:
work/pipeline_states.bin(666 KB) is not kept in main's history.hookshot_pipeline_states_shipped.binfrom an earlier build is kept when the new list is missing. It is harmless: it is either an earlier list of the same format, or one the game ignores.