fix: switches that behave as players expect, and dead ones removed #2042
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!2042
Loading…
Reference in a new issue
No description provided.
Delete branch "knobs-cleanup"
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?
Several switches did things a player would not expect: a test run's
RX_VK_PACE=1stayed inhookshot_options.inifor good, a line inhookshot_env.txtbeat a switch set for one launch, and switches that change the shader translation did nothing on a PC that already had a program cache. This PR fixes those, removes switches left over from mkw-recomp and TOTK, makes the AMD ASTC workaround a menu row, and makes=0mean off for every on/off switch. The V-Sync row is #2041.It is a series of commits, one per part, in this order.
1. Bug fixes
Environment overrides last for their run.
RX_VK_FRAMEGEN_MULT,RX_VK_PACE,RX_VK_UPSCALE,HOS_REALTIME_STEP,HOS_DYNRESandHOS_OUTPUT_RESwere copied into their rows inmenu_init, and the next change of any row saved them. They now apply to the run only:save()writes the player's own value until the player changes that row (env_override,saved_valueinvk_menu.cpp; a custom output size of the player's is kept too).tests/test_menu_env_overrides.pycompiles the realsave()and the overrides' part ofmenu_init.Translation switches are in the program cache's stamp.
RX_VK_NO_CBUF_LOAD_RULE,RX_VK_PTR_SPLIT_FALLBACK,RX_VK_ALL_GLOBAL_PROGS,RX_VK_NO_EXTREGS,RX_VK_NO_DRAW_PARAMS, and the miss log'sRX_VK_MISS_LOGandRX_VK_BLOCK_PROBE, each change what the translator makes (checked at each read) but were not indisk_stamp's list.tests/test_program_stamp_knobs.pyreads everyRX_VK_switch the translator reads and fails when one is missing (two that only log are listed as such). Nothing changes for a run that sets none of them.Rows no preset sets keep the Quality preset. Changing Reflex, Anti-Lag 2, Output resolution, Anisotropic filtering, Ultrawide, Ultrawide menus, Robust buffers, Mesh shaders, Text speed, Text size, Controller in background, Layout preset, Descriptor reuse or Sampler cache turned the preset to Custom. They are
preset_exemptnow;tests/test_preset_exempt.pyderives the rule fromapply_preset. The Upscaler stays as it was, because changing it moves Render resolution to the upscaler's own steps.The environment goes over
hookshot_env.txt. The file usedsetenv(..., 1), so a switch set for one launch (HOS_FULLSCREEN=0 ./hookshot, a launcher's or a script's own) lost to the saved line. A name already set when the game starts now keeps its value, and the log says the file's line was left out; within the file a later line still replaces an earlier one.tests/test_env_file.pycovers it. The readme and the development guide now give the order: the environment, thenhookshot_env.txt, then the menu's saved rows.2. Dead switches removed, duplicates merged
Each removal was checked against the code, tests, scripts, workflows, the builders and the docs first.
RX_BACKEND=eden: it loadedmkw_eden.dll, which nothing builds, then fell back to WebGPU.gpu/vk/VULKAN.mdandvk_api.hnow namehookshot_vk.dll.HOS_FIX_RESandHOS_SCENE_NATIVE, withnx2/oot_native_resolution.py, the lift patch they switched (off since #849). The lift changes, so the next build lifts again.RX_VK_FOLLOW_MESH("tried for the foliage, which it did not bring back").TOTK_MINIMAL_LAYOUT, andTOTK_in the nameshookshot_env.txtaccepts.RX_VK_OOT_VISUAL,RX_VK_OOT_FOG,RX_VK_OOT_EXPOSUREand the Orchid fog and exposure workaround (off since 11-07; its factors were tuned against bugs since fixed). The NaN guard that shared its header is now inir_opt/fragment_output_guard.h. The readme's credits say what Orchid's workaround was used for, and the license line no longer lists Orchid's code.nx2/build.py --lib,--only,--optand--no-polls: nothing passes them.--dllstays (nx2/test_dll.pyandnx2/dllmap.pyuse it).RX_VK_DESC_SLOTGEN,RX_VK_NO_DESC_REUSEandRX_VK_DESC_REUSE_DGENare now one switch,RX_VK_DESC_REUSE=0/1/never(the row's values:0is its Off, the global check;1is its On, by slot, the default;neverturns reuse off), which goes over the Descriptor reuse row. The DGEN switch only turned off issue 1126's fix and is gone.RX_VK_NAN_GUARD=0turns off both NaN guards;RX_VK_NO_NAN_GUARDis gone.nx2/bake_ds's copy of the stamp's list matches the live one again, and the stamp check now compares them.RX_VK_FRAMELOG(pictures) andRX_VK_FRAME_LOG(frame times),RX_VK_PRESENT_AHEAD(frame generation's copies) andRX_VK_PRESENTS_AHEAD(the replay's queue depth). Renaming them would break scripts that use them for little gain.Looked at and left in place:
HOS_FPS_MAXis not a duplicate of the Game frame rate cap row: it takes any rate (75, 100, 180 Hz screens) where the row has steps, andtests/test_frame_rate_cap_step.pydrives the cap through it. Its comment no longer calls it a test.RX_JOBSis no longer inmake_game.py; the Linux builder still honours it deliberately (tests/test_linux_builder_jobs.py), andthird_party/a64-kitreads it.RX_VK_SPARSE_IDLEturns on the stricter ordering of sparse binds, which was left off for MKW's sake. Whether OoT should have it on is a measurement, not a removal.3. Menu rows
The Debug tab's Developer section, with Robust buffers and then ASTC as RGBA8 selected (headless capture, 1600x900, RTX 3090, Linux):
hookshot_env.txt(#57, #1006). Its help says what it is for and that it takes far more video memory.RX_VK_ASTC_RGBA8still goes over it for a run. It does not turn itself on for any GPU: #993's report says it took effect on a 9070 XT and did not help, so there is no clear set of cards to turn it on for.4. One rule for on/off switches
About 230 switches read as on whenever they were set, so
RX_VK_NO_PROGRAM_CACHE=0orHOS_HEADLESS=0turned the feature on.env_on(name)(gpu/vk/compat/hookshot_env.h, for bothhost/andgpu/vk) is off when the variable is unset, empty,0,false,offorno, and on otherwise. Every check that only asked whether a switch was set now uses it;=1works as before.host/andgpu/vk(the translator's own switches included) now use it. A switch that some other place reads for a value is left exactly as it was: 25 of them, such asRX_VK_WARP64=0,HOS_FULLSCREEN=0, the lists and the sizes, where0already means something.nx2/kit.pyhas the same rule asenv_on()for the build'sRX_VK_ONLY.nx2/build.pycounts the header in the runtime's object keys, as it doesdlss_math.h. The AppImage now packs headershost/includes from belowgpu/vk/.tests/test_env_on.pychecks the rule in C, C++ and Python, and fails if a switch is read the old way again. Checks that compile code cut out of the changed files now force-include the header (theirgetenvstand-ins passenv_onthrough them). The checks that look for a switch's read by its text now look forenv_on.test_display_startup_failure'sHOS_HEADLESS=0case andtest_program_answer_domains'RX_VK_REGISTER_AT_ONCE=0case now expect off.RX_VK_FIFOandRX_VK_IMMEDIATEkeep their old reads here because #2041 (the V-Sync row) replaces them.tests/,scripts/,.github/, the builders or the docs set any of the converted switches to0or empty to turn it on (checked by grep).This part touches many files that other PRs also edit (
vk_draw.cppabove all). Most of it is a mechanical rewrite, done by a script that only rewrites presence checks whose value is not read on the same line, so on a conflict it is simplest to drop this commit and run the rewrite again on the new base.Testing
python -I -B tests/run_all.pyon the branch, rebased onmain667ba79: 342 passed, 13 skipped. The three failures are the same as onmain:nx2/test_nup_read_name.py,tests/test_builder_log_read_only.pyandtests/test_wayland_libdecor_hint.py, all failing on this machine without these changes. New checks:test_menu_env_overrides,test_program_stamp_knobs,test_preset_exempt,test_env_on; extended:test_env_file,test_menu_keys.hookshot_vk.so, its exported-symbol check clean, the shaders prepared), and after it a build ofhookshot_vk.so(exported-symbol check clean); a headless run with the Insert menu drawn into the shots: the Debug tab's Developer rows show and change. The log hasrx: renderer: Vulkanand robust buffer access on (Auto), as before.For the maintainer to decide (not changed here)
gpu/render, about 226 switches). It is reached only whenhookshot_vkfails to load or start, and the builders still shipwgpu-native. It could be dropped, or frozen with its switches cut to a handful.RX_VK_NO_PARTIAL,RX_VK_NO_STATE_LIST,RX_VK_PUSH_ALL,RX_VK_PUSH_STATE_OLD,RX_VK_UB_CUR_ONLY,RX_VK_POOL_END_IMPORTED,RX_VK_MIRROR_KEEP,RX_VK_READBACK_NO_CATCHUP,RX_VK_FORCE_LINEAR,RX_VK_UPLOAD_ALL,RX_VK_NO_TABLE_SHRINKand others). One policy that would work: an A/B switch lives for one release after its default flips, then goes.I read through this one and found nothing that blocks it. Two things need fixing before it can merge, plus a few small ones. I only read the code and haven't run the tests locally. CI hasn't run them either, since GitHub skips the test workflows while the PR has conflicts.
Before merge
Conflicts with main in
gpu/vk/vk_menu.cppandgpu/vk/vk_menu.h. All of them are small:ur::snaptour::snap_renderdescriptor_reusecomment changed on both sidesAfter the rebase, Mesh shaders probably needs
preset_exemptas well (apply_presetdoesn't set it).test_preset_exemptshould flag it.Restart on Windows ignores changes to
hookshot_env.txt.relaunch()inhost/hos_relaunch.cpassesNULLfor the environment toCreateProcessW. The new process therefore inherits this one's environment, which already holds every value_putenvset from the file. With the environment now going first, the restarted game skips each line of the file, so edits made while the game runs are lost. The log also reports every line as "set in the environment, which goes first". Linux doesn't have this problem, because it execs with/proc/self/environ, the environment the game started with. A fix: saveGetEnvironmentStringsW()inmainbeforeload_hookshot_env(), then pass that block, withHOS_RESTART_OFadded andCREATE_UNICODE_ENVIRONMENT.Minor
host/posix/display_sdl.c:SDL_VIDEODRIVERandSDL_VIDEO_DRIVERare now read withenv_on. They're SDL's own variables and hold a driver name, not an on/off value, sogetenvfits them better. These are the only two converted names outsideRX_,HOS_,HOOKSHOT_,EDEN_andNVN_.RX_VK_NO_DESC_REUSE=1orRX_VK_NO_NAN_GUARD=1. If those are in someone'shookshot_env.txt, they now do nothing, and nothing says so. A log line that names the replacement (RX_VK_DESC_REUSE=0,RX_VK_NAN_GUARD=0) would help bug reports.load_hookshot_envtracks at most 64 names, each under 96 characters. Past that, a later line for an untracked name is skipped as if it came from the environment. Harmless in practice, but worth a comment or a higher limit.Checked and looks right
env_onisn't read for its value anywhere else. I also checked that nothing inscripts/,builder/,.github/or the tests sets one to0to turn it on, apart from theRX_VK_REGISTER_AT_ONCE=0case this PR updates.env_overrideandsaved_value: a run's override stays out ofhookshot_options.iniuntil the player changes the row, and a custom Output resolution size is kept.RX_VK_DESC_REUSElevels match the old switches: row Off is 1, row On is 2, and 0 is the oldRX_VK_NO_DESC_REUSE. The removedRX_VK_OOT_*,HOS_FIX_RESandHOS_SCENE_NATIVEwere already off by default.Suggestion: part 4 (the
env_onrule) carries most of the risk, and the description already says it may need redoing after conflicts. It could go in a PR of its own, so the bug fixes in parts 1 to 3 don't wait on it.I went through all six commits against the description. Most of it holds up. The removed switches really are gone: nothing in head reads
RX_BACKEND=eden/mkw_eden,HOS_FIX_RES,HOS_SCENE_NATIVE,oot_native_resolution,RX_VK_FOLLOW_MESH,TOTK_*,RX_VK_OOT_*,RX_VK_DESC_SLOTGEN/NO_DESC_REUSE/DESC_REUSE_DGENorRX_VK_NO_NAN_GUARD, and that includes scripts, workflows, builders, docs, the readme and tests. Nothing calls the removedbuild.pyflags either. The Eden changes are only switch plumbing. With nothing set, the translator does what it did before:FOLLOW_MESHwas off by default,GuardFragmentOutputsmoved over byte for byte, and both NaN guards are still on by default.MkwVkHost/MkwVkRendererare untouched (only comments invk_api.h), so no API bump is needed. No new option ids. The edited tests aren't weakened: the needle changes follow the rename,HOS_HEADLESS=0andRX_VK_REGISTER_AT_ONCE=0now expect off, and everyENV_ON_Haddition hasPathimported first. No Windows macro clashes inhookshot_env.h, and every file that callsenv_onincludes it.Blocking
c09e0ac): #2020 Movement speed, #1971 Mesh shaders row, #2000, #2046 and others touchvk_menu.cpp,vk_draw.cpp,vk_shader.cpp,vk_api.h,hos_main.cand 7 of the edited tests. Only the title check ran. The head'svk_api.hstill lacksHOS_OPT_CHEAT_SPEEDbecause #2020 isn't in the base yet. After the rebase, the newtest_preset_exemptwill flag main's Mesh shaders row:apply_presetdoesn't setmesh_mode, and the row isn't marked exempt. That's the right call, it just needs thetrue.debug-robust-buffers.pnganddebug-astc-rgba8.pngas relative paths, so GitHub serves broken images. They need to be uploaded into the description.Should fix (inline)
hookshot_env.txt, and the log then says every line was "left out".RX_VK_DESC_REUSE=1means the row's Off indesc_reuse_level.test_menu_env_onstill checks the env throughmenu_env_on, where 1 means on, and the real code never takes that path.HOS_NO_HANDOFF,RX_VK_NO_F16,RX_VK_NO_DMABUF,RX_VK_PROF_ALL, half ofRX_VK_LOW_SPEC).test_env_ononly catches the!= NULLform.RX_VK_ASTC_RGBA8=1inhookshot_env.txt. For them, the new row can't turn the workaround off.What a player with an existing ini /
hookshot_env.txtsees after updating. No saved choice flips, so nooptions_versionbump or migration is needed:0,false,off,noor empty is now off, where it was on before. A leftoverRX_VK_NO_NAN_GUARD=1orRX_VK_DESC_SLOTGEN=1line now does nothing.hookshot_env.txt.RX_VK_PACE,HOS_DYNRESand the other menu-row switches no longer write themselves into the ini. Values saved by earlier runs stay.robust_buffers), so the saved value carries over. ASTC as RGBA8 is a new row, Off by default.gpu/vk/eden,compatorvk_shader.cpp. The stamp's new prefixes change nothing when they aren't set.Nits
saved_value: if a preset or the upscaler's snap sets an overridden row (resolution,realtime,pace) to the same value the environment forced,save()writes the player's old value instead of the preset's.from_file[64][96]: past 64 names, or for a name of 96 characters or more, a later line no longer replaces an earlier one. On Windows the file is read twice, so the second read also logs "left out" for those names.--no-pollsmentions remain in comments atnx2/oot_patches.py:315andtests/test_text_speed.py:24.The two maintainer questions at the end (the WebGPU fallback, the A/B switch policy) are NotRexed's call, so I've only noted them here.
On Windows this breaks the menu's Restart.
hos_relaunch.cstarts the new process withCreateProcessW(..., NULL /* env */, ...), so it inherits this process's environment, and_putenvhas already put every line from the file there. In the new processfrom_filestarts out empty, so each of the file's names is "set in the environment" and gets left out. If the player editshookshot_env.txtand then picks Restart, the edit is ignored, and the log lists every line as left out. Linux is fine, because it re-execs with/proc/self/environ, the startup environment.One fix: save the environment block before
load_hookshot_env(GetEnvironmentStringsW) and give that toCreateProcessWwithCREATE_UNICODE_ENVIRONMENT, plusHOS_RESTART_OF. Another: pass the file's names to the child, e.g. aHOS_ENV_FROM_FILElist that pre-fillsfrom_file.Players who followed the old instructions still have
RX_VK_ASTC_RGBA8=1inhookshot_env.txt. That line goes over the row, so turning the row off does nothing for them, and the row shows Off while the workaround is on. Could this say "turn the row off (and remove anyRX_VK_ASTC_RGBA8line fromhookshot_env.txt)"? Even better, the row could show as fixed while the variable is set, the wayrow_fixeddoes for other env-held rows.@ -0,0 +1,127 @@"""One rule for on/off switches: env_on (gpu/vk/compat/hookshot_env.h) in C and C++, kit.env_on in Python.This only matches
getenv("X") != NULLand== NULL. The forms the rewrite skipped still read set-means-on, so=0turns them on:host/nn_os_sync.c:446getenv("HOS_NO_HANDOFF") ? 0 : 1gpu/vk/vk_shader.cpp:572!getenv("RX_VK_NO_F16")(also:1559andvk_draw.cpp:6747; it's a translation switch)gpu/vk/vk_memory.cpp:276getenv("RX_VK_NO_DMABUF") ? nullptr : ...gpu/vk/vk_internal.h:358getenv("RX_VK_PROF_ALL") || ...RX_VK_LOW_SPEC:vk_menu.cppreadsatoi != 0, butvk_memory.cpp:1410treats any value as set, so=0is half on.Converting these and widening the pattern (a bare
getenv("X")followed by),?,&&,||, or preceded by!) would make "every check that only asked whether a switch was set now uses it" true, and keep it true.@ -38,3 +39,4 @@#include <string>#include "hookshot_env.h"using DWORD = unsigned long;constexpr int MAX_PATH = 260;This now checks behaviour the real code doesn't have.
desc_reuse_level()readsRX_VK_DESC_REUSEitself, asclamp(atoi, 0, 2), and only callsmenu_env_onwhen the variable is unset. So the env cases here ("1"meaning reuse on,"0"meaning the row's Off) go through a path the game never takes. In the game,RX_VK_DESC_REUSE=1gives level 1, which is the row's Off (no slotgen), and=0turns reuse off completely. That's also a trap for anyone used toRX_VK_DESC_SLOTGEN=1meaning on. Could the test cutdesc_reuse_leveltoo and check 0/1/2 plus the unset case? Making the env values match the row (0/1) with a separate value for "never" would also avoid the surprise.Two more dead ones in the same area, in case you want them in this pass:
RX_VK_DUMP_ATandRX_VK_DUMP_TEXare named ingpu/vk/VULKAN.md(lines 72-73 onf915af9) and in the comment atgpu/vk/vk_texture.h:211, but nothing in the source reads either one any more.nullifyshot, thanks for the careful read.
Here is where each point ended up:
Before merge
preset_exemptset (and the restart flag);test_preset_exemptpasses on it.fix(restart): Windows' Restart reads hookshot_env.txt again, the way you suggested.mainkeepsGetEnvironmentStringsW()beforeload_hookshot_env()(hos_relaunch_keep_env).relaunch()passes that block withCREATE_UNICODE_ENVIRONMENT.HOS_RESTART_OFreplaces any older value and is placed in the block's sorted order (hos_relaunch_env_blockinhost/hos_relaunch.h).test_menu_restartchecks the block-building on its own and checks thatmainandrelaunch()wire it up. If saving the block failed, the restart falls back to inheriting the current environment, as before.Minor
SDL_VIDEODRIVER/SDL_VIDEO_DRIVER: back togetenv. You're right, they hold a driver name.RX_VK_NO_DESC_REUSE→RX_VK_DESC_REUSE=never,RX_VK_DESC_SLOTGEN→RX_VK_DESC_REUSE(same 0/1),RX_VK_NO_NAN_GUARD→RX_VK_NAN_GUARD=0. The rest (RX_VK_OOT*,HOS_FIX_RES,HOS_SCENE_NATIVE,RX_VK_FOLLOW_MESH,RX_VK_DESC_REUSE_DGEN,TOTK_MINIMAL_LAYOUT) are logged as doing nothing.from_filelimits: raised to 256 names of up to 127 characters, with a comment saying what happens past that.Suggestion (splitting out the env_on rule): I kept it in this PR. The merges and CI fixes have already been done on top of it. Splitting it now would mean re-resolving the same files twice. If a maintainer would still rather have it separate, I can split it.
jarynclouatre:
Thanks, both removed.
gpu/vk/VULKAN.mdnow shows the currentRX_VK_DUMP=<present>form and no longer namesRX_VK_DUMP_TEX. Thevk_texture.hcomment now describestexture_read_texelsitself (docs: drop the dead RX_VK_DUMP_AT and RX_VK_DUMP_TEX, ...).Thanks, hckrman101. I checked the follow-ups and everything from my review is handled:
HOS_RESTART_OFput in at its sorted place, is exactly what I had in mind, and the fallback to inheriting is a nice touch.from_filelimits all look good.Two small things are left:
A new one-line conflict with main in
host/hos_main.c. #926 (the control bridge) addedhos_control_start(HOOKSHOT_VERSION);right where this PR addsremoved_switch_notes();, just after the version line. Keeping both resolves it. #926's new variables (HOS_CONTROL,HOS_CONTROL_MEM) hold a path and a value rather than on/off, sotest_env_onshouldn't flag them after the merge. Main's other new commit (#2251) doesn't touch this PR's files.The PR description still has the old
RX_VK_DESC_REUSEvalues. It saysRX_VK_DESC_REUSE=0/1/2 (never, the global check, by slot). Since641f516, the code anddocs/development.mduse the row's values instead:0is the row's Off (the global check)1is On (by slot)neverturns reuse offSo anyone following the description and setting
=0to turn reuse off would get the global check. The docs are right; only the description needs the new values.I only read the code this time and haven't run the tests on a merge with main. CI's full pass on
13bb15ccovers everything except main's two newest commits.Quick correction: you'd already merged main (
b62dcc0) a couple of minutes before my comment went up, and it keeps both lines, so ignore point 1. Point 2, theRX_VK_DESC_REUSEvalues in the description, still applies.The failed
appimagecheck is the runner, not the PR: it couldn't resolvearchive.ubuntu.com, so apt failed before anything was built. Re-running the job should clear it.Thanks for checking again. The description now has the row values:
RX_VK_DESC_REUSE=0is the row's Off (the global check),1is On (by slot, the default), andneverturns reuse off. Same asdocs/development.md.The merge with main (
b62dcc0) keeps both lines inhos_main.c, as you said. It also needed one test change:save()now takes a lock since #926, sotest_menu_env_overrides.py's harness includes<mutex>. The game-free suite passes on the merge, and a full build of it is running.github-sync referenced this pull request2026-11-12 06:22:54 +00:00