Skip to content

feat(builder): an up-to-date game without a ticked DLSS or FSR 4 offers Update, not Play - #2591

Open
roblesleo wants to merge 2 commits into
NotRexed:mainfrom
roblesleo:feat/builder-update-adds-upscalers
Open

roblesleo wants to merge 2 commits into
NotRexed:mainfrom
roblesleo:feat/builder-update-adds-upscalers

Conversation

@roblesleo

@roblesleo roblesleo commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

A game is built with NVIDIA DLSS or AMD FSR 4 or without it, so ticking one after the game was built changed nothing: the Builder still said "Your game is up to date" and showed Play, and the game kept starting without it until the next release's update.

Now, when the game is up to date but lacks a ticked upscaler, the page says "Update to add NVIDIA DLSS" (or AMD FSR 4, or both), and Update builds the folder again from the game files it keeps, with the ticks. It updates to the game's own version, so nothing is downloaded when the builder is that release (also when GitHub does not answer).

UpscalerParts.Missing decides it from what make_game.py leaves in the folder:

  • NVIDIA DLSS: NVIDIA's runtime in the ngx folder (place_ngx_runtime, only for a build with NVIDIA's SDK).
  • AMD FSR 4: the .hookshot_fsr mark, and, with AMD's license accepted (feat: make_game.py --fetch-fsr-runtime fetches AMD's FSR 4 runtime #1866), AMD's upscaler DLL beside the exe or in the folder, where gpu/vk/vk_fsr4.cpp looks. Without the license the DLLs are the player's to put there, so a folder built with FSR 4 is not sent back to Update for them.

Both ticks refresh the page.

Tests: tests/test_builder_upscaler_parts.py runs UpscalerParts.Missing on authored placeholder folders (.NET 8, Windows, like test_builder_dlss_update) and checks that RefreshMode asks it for an up-to-date game and that both ticks refresh. Ran locally on Windows with test_builder_dlss_update, test_ffx_sdk, test_builder_status, test_builder_python and dotnet build of the Builder, all passing.

…rs Update, not Play

A game is built with NVIDIA DLSS or AMD FSR 4 or without it, so ticking one after the game was built changed nothing:
the Builder still said "Your game is up to date" and Play, and the game kept starting without it until the next
release's update. Now, when the game is up to date but lacks a ticked upscaler, the page says "Update to add NVIDIA DLSS"
(or AMD FSR 4, or both) and Update builds the folder again from the game files it keeps, with the ticks. The
version is the game's own, so nothing is downloaded when the builder is that release (also when GitHub does not answer).

UpscalerParts.Missing decides it from what make_game.py leaves in the folder: NVIDIA's runtime in the ngx folder
(place_ngx_runtime, only for a build with NVIDIA's SDK), the .hookshot_fsr mark, and, with AMD's license accepted,
AMD's upscaler DLL beside the exe or in the folder (where gpu/vk/vk_fsr4.cpp looks). Without the license the DLLs are
the player's to put there, so a folder built with FSR 4 is not sent back to Update for them. Both ticks refresh the page.

tests/test_builder_upscaler_parts.py runs UpscalerParts.Missing on authored placeholder folders (.NET 8, Windows, like
test_builder_dlss_update) and checks that RefreshMode asks it for an up-to-date game and that both ticks refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@roblesleo roblesleo changed the title feat(builder): an up-to-date game without a ticked DLSS or FSR 4 offe… feat(builder): an up-to-date game without a ticked DLSS or FSR 4 offers Update, not Play Nov 12, 2026
roblesleo added a commit to roblesleo/Hookshot that referenced this pull request Nov 12, 2026
… the Builder Update PR into full

The fork's commits again over current main: the FSR 4 model row, Montar-Hookshot and the fork's HookshotBuilder.exe,
the Builder's 12 languages. Upstream's own languages, FSR 4 runtime fetch and AMD license replace the fork's earlier
versions of them; UpscalerParts (NotRexed#2591) replaces Fork.Missing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@SimonKimDev SimonKimDev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A legacy FSR tick (saved before #1866: Fsr=true, FsrLicense=false) on an up-to-date folder without .hookshot_fsr gets "Update to add AMD FSR 4" forever:

  • UpscalerParts.Missing flags the missing mark whatever fsrLicense is.
  • Update goes to UpdateBuild, where fsr = (saved.Fsr && saved.FsrLicense) || (mark && AMD DLL && license file) is false, so Run adds no --fsr.
  • make_game.py's fsr_wanted is then false (no --fsr, no mark), the folder is rebuilt without FSR and the mark is never written.

So each Update is a full rebuild that changes nothing, and Play isn't offered until the box is unticked. (ApplySettings sets the tick without the Click handler, so this state survives loading.)

Either UpdateBuild should pass --fsr for the saved tick without the license, as StartBuild does (keeping --fetch-fsr-runtime gated on the license), or Missing shouldn't require the mark when fsrLicense is false.

…out AMD's license too

Review of NotRexed#2591: a tick saved before AMD's license was asked (Fsr, no FsrLicense) on an up-to-date folder without
make_game.py's .hookshot_fsr mark was offered "Update to add AMD FSR 4" for good. UpscalerParts.Missing reports the
missing mark whatever the license; UpdateBuild passed --fsr never (only make_game.py's mark kept a folder's FSR 4), so
the folder was built again without FSR 4, the mark was not written, and the next look offered Update again: a full
rebuild each time that changed nothing, and no Play until the box was unticked.

UpdateBuild now passes --fsr for the saved tick, as StartBuild does for the page's; fetching AMD's runtime stays gated
on the accepted license. The folder is built with FSR 4, the mark is written, and Play is offered.

tests/builder_dlss_update_test.cs checks the arguments: --fsr with the saved tick, with the license or without it, and
none for a folder that only has the mark (make_game.py keeps it there).

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
@roblesleo

Copy link
Copy Markdown
Contributor Author

Thanks, you're right: that state looped. Fixed in aa03b86.

UpdateBuild now passes --fsr for the saved tick whether AMD's license was accepted or not, as StartBuild does for the page's tick; fetching AMD's runtime stays gated on the license. So a legacy tick (Fsr=true, FsrLicense=false) builds the folder with FSR 4 once, make_game.py writes .hookshot_fsr, and Play is offered afterwards.

I took your first option rather than relaxing UpscalerParts.Missing, so a ticked FSR 4 still means the folder is built with it.

tests/builder_dlss_update_test.cs now checks the arguments: --fsr with the saved tick (with and without the license), and none for a folder that only has the mark, where make_game.py keeps FSR 4 on its own.

@Joey-Magnus Joey-Magnus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I merged this into current main, which already has #2528's dlssLicense record. It merges cleanly, and it also applies cleanly with #2553 and #2565 on top. tests/test_ffx_sdk.py and test_builder_status.py pass. The .NET fixtures need the SDK, so for those I'm relying on the Windows jobs, which are green.

SimonKimDev's loop is fixed. MainWindow.xaml.cs:1468 now passes --fsr for the saved tick whether or not AMD's license was accepted, so a legacy Fsr=true, FsrLicense=false folder gets built once with the mark, and Play comes back after that. The fetch is still gated on the license. UpscalerParts.Missing (called at :189) only asks for AMD's DLLs when the license was accepted, so a player who brings their own DLLs isn't sent back to Update. The DLSS side follows saved.Dlss in UpdateBuild, so it can't loop the same way.

The one red job is tests/test_release_scripts.py (test_nightly_two_runs_at_once_end_at_the_newer_commit). It's flaky and unrelated to the Builder.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants