Choose FSR 4.1 or FSR 3.1 from one Insert menu row #1097

Closed
N3oTraX wants to merge 15 commits from fsr3/menu-row into main
N3oTraX commented 2026-11-09 11:07:50 +00:00 (Migrated from github.com)

Part 3 of 3 of the split of #871, and the last of it.

Depends on #1096. Only the last commit is new here: 3 files, +58/-22. GitHub shows the rest until #1096 and its dependencies land.

What changed

  • The AMD FSR 4.1 row becomes FSR upscaler: Off, Auto, FSR 4.1, FSR 3.1, changed at once while playing. It shows the engine in use, and why a forced choice cannot run.
  • The readme and a short docs/upscaling.md describe the row and the two engines.

How it was tested

In game, on the #871 tree (6095c4d) RX 7900 XTX, RADV Mesa 26.2.6, Linux: the row switched between FSR 4.1.1 INT8 and FSR 3.1 live several times at 5120x2160, no crash or device lost in the log. The row's code is unchanged from that tree
On this branch hookshot_vk.so builds with 0 warnings. tests/run_all.py fsr upscale menu: 8 passed
Full suite 129 passed, 7 skipped, 1 failed: test_program_answer_domains, which fails the same way on main (8b2e1d3)

Not tested

  • This exact tree has not run in game yet.
  • Mouse clicks on this row (#946), and reading an old fsr4= in play.
  • Image quality and fps were not measured.
  • RDNA2 and RDNA4, and Windows.

🤖 Generated with Claude Code

Part 3 of 3 of the split of #871, and the last of it. > **Depends on #1096. Only the last commit is new here: 3 files, +58/-22.** GitHub shows the rest until #1096 and its dependencies land. ## What changed - The `AMD FSR 4.1` row becomes **`FSR upscaler`: Off, Auto, FSR 4.1, FSR 3.1**, changed at once while playing. It shows the engine in use, and why a forced choice cannot run. - The readme and a short `docs/upscaling.md` describe the row and the two engines. ## How it was tested | | | |---|---| | In game, on the #871 tree (`6095c4d`) | RX 7900 XTX, RADV Mesa 26.2.6, Linux: the row switched between FSR 4.1.1 INT8 and FSR 3.1 live several times at `5120x2160`, no crash or device lost in the log. The row's code is unchanged from that tree | | On this branch | `hookshot_vk.so` builds with 0 warnings. `tests/run_all.py fsr upscale menu`: 8 passed | | Full suite | 129 passed, 7 skipped, 1 failed: `test_program_answer_domains`, which fails the same way on `main` (`8b2e1d3`) | ## Not tested - **This exact tree has not run in game yet.** - Mouse clicks on this row (#946), and reading an old `fsr4=` in play. - Image quality and fps were not measured. - RDNA2 and RDNA4, and Windows. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
hckrman101 commented 2026-11-09 18:39:52 +00:00 (Migrated from github.com)

Hi! This PR has merge conflicts with main now (a lot has landed today). Could you merge main in or rebase and resolve them? Happy to give it a proper review once it's up to date.

Hi! This PR has merge conflicts with `main` now (a lot has landed today). Could you merge `main` in or rebase and resolve them? Happy to give it a proper review once it's up to date.
hckrman101 (Migrated from github.com) reviewed 2026-11-09 23:24:53 +00:00
hckrman101 (Migrated from github.com) left a comment

Looked at the last commit only (menu row, upscale_engine.h resolution, ini/env handling). The row logic reads right to me: engine_for and row_text agree with what fsr_engine() in vk_draw.cpp resolves, fsr4_failed() is only true after a successful start so a missing library does not silently switch a forced FSR 4.1 to FSR 3.1, and an unavailable engine shows its reason (FSR 4.1 (no AMD FSR DLLs), FSR 3.1 (no push descriptors)) while the game's own upscale runs.

The real problem is the stack underneath, not this commit. It conflicts with #1008 (still open, updated today), which does the same job differently:

  • #1008 renames opts.dlss to opts.upscaler and makes it the single Upscaler row: 0 game's own, 1 DLSS, 2 DLAA, 3 FSR 4, 4 FSR 4 Native AA, still saved as dlss= (ini_key maps it to "dlss" so old files load). This PR adds a second, different opts.upscaler (0 Off, 1 Auto, 2 FSR 4.1, 3 FSR 3.1) beside opts.dlss, saved as upscaler=. After a rebase onto #1008 the name opts.upscaler would still compile everywhere while meaning two different things, and ini_key's "upscaler" special case would hit #1008's row. That is the dangerous kind of conflict, so please check every opts.upscaler use by hand.
  • So after #1008 lands the FSR choice should become values of #1008's one row (e.g. extend its enum/upscaler_rows.h with Auto/FSR 4.1/FSR 3.1) rather than a second row. Keep the existing dlss= values 0-4 meaning what #1008 says, so saved files stay valid; add FSR 3.1 (and Auto) as new values above 4 and clamp in the row's hi. DLSS and FSR then stop being independent, so dlss_on in EngineState and the "(DLSS is on)" text go away.
  • The old-ini fallbacks (fsr4= and RX_FSR4) are dead code against #1008: main never wrote fsr4=, and #1008 saves FSR 4 as dlss=3/4. Drop them, or map RX_UPSCALER=off|auto|fsr4|fsr3 onto the merged row.
  • #1008 also carries its own vk_fsr4.cpp/vk_fsr4.h and third_party/fidelityfx; this stack has a second copy (gpu/vk/vk_fsr4.*, third_party/fidelityfx-sdk). Use #1008's FSR 4 side and keep only the FSR 3.1 backend (vk_fsr3.*, shaders) and upscale_engine.h from here.

Smaller things, nits:

  • tx_upscaler runs on the menu thread and calls fsr3::available(), whose first call builds the supported() static (Vulkan queries) and reads g.failed / g_reason that the replay thread writes. The static init is safe, but g.failed and the reason pointers are plain reads of data the replay thread writes: make them atomic or copy them.
  • The readme says FSR 3.1 takes over only for a forced FSR 4.1; Auto also falls to FSR 3.1 after a failure (via fsr4_usable going false). Fine behaviour, the docs just under-say it.

The PR is mergeable: false right now, and there are no CI checks on the branch. Not an approval until it is rebuilt on #1008's row model.

Looked at the last commit only (menu row, `upscale_engine.h` resolution, ini/env handling). The row logic reads right to me: `engine_for` and `row_text` agree with what `fsr_engine()` in vk_draw.cpp resolves, `fsr4_failed()` is only true after a successful start so a missing library does not silently switch a forced FSR 4.1 to FSR 3.1, and an unavailable engine shows its reason (`FSR 4.1 (no AMD FSR DLLs)`, `FSR 3.1 (no push descriptors)`) while the game's own upscale runs. The real problem is the stack underneath, not this commit. It conflicts with #1008 (still open, updated today), which does the same job differently: - #1008 renames `opts.dlss` to `opts.upscaler` and makes it the single Upscaler row: 0 game's own, 1 DLSS, 2 DLAA, 3 FSR 4, 4 FSR 4 Native AA, still saved as `dlss=` (`ini_key` maps it to "dlss" so old files load). This PR adds a second, different `opts.upscaler` (0 Off, 1 Auto, 2 FSR 4.1, 3 FSR 3.1) beside `opts.dlss`, saved as `upscaler=`. After a rebase onto #1008 the name `opts.upscaler` would still compile everywhere while meaning two different things, and `ini_key`'s `"upscaler"` special case would hit #1008's row. That is the dangerous kind of conflict, so please check every `opts.upscaler` use by hand. - So after #1008 lands the FSR choice should become values of #1008's one row (e.g. extend its enum/`upscaler_rows.h` with Auto/FSR 4.1/FSR 3.1) rather than a second row. Keep the existing `dlss=` values 0-4 meaning what #1008 says, so saved files stay valid; add FSR 3.1 (and Auto) as new values above 4 and clamp in the row's `hi`. DLSS and FSR then stop being independent, so `dlss_on` in `EngineState` and the "(DLSS is on)" text go away. - The old-ini fallbacks (`fsr4=` and `RX_FSR4`) are dead code against #1008: main never wrote `fsr4=`, and #1008 saves FSR 4 as `dlss=3/4`. Drop them, or map `RX_UPSCALER=off|auto|fsr4|fsr3` onto the merged row. - #1008 also carries its own vk_fsr4.cpp/vk_fsr4.h and third_party/fidelityfx; this stack has a second copy (`gpu/vk/vk_fsr4.*`, `third_party/fidelityfx-sdk`). Use #1008's FSR 4 side and keep only the FSR 3.1 backend (`vk_fsr3.*`, shaders) and `upscale_engine.h` from here. Smaller things, nits: - `tx_upscaler` runs on the menu thread and calls `fsr3::available()`, whose first call builds the `supported()` static (Vulkan queries) and reads `g.failed` / `g_reason` that the replay thread writes. The static init is safe, but `g.failed` and the reason pointers are plain reads of data the replay thread writes: make them atomic or copy them. - The readme says FSR 3.1 takes over only for a forced FSR 4.1; Auto also falls to FSR 3.1 after a failure (via `fsr4_usable` going false). Fine behaviour, the docs just under-say it. The PR is mergeable: false right now, and there are no CI checks on the branch. Not an approval until it is rebuilt on #1008's row model.
NotRexed commented 2026-11-10 02:07:47 +00:00 (Migrated from github.com)

Superseded by #1386, which adds FSR 3.1 as a value of the existing Upscaler row. This branch depends on #1096 and #1008 and conflicts with main. Closing; thanks!

Superseded by #1386, which adds FSR 3.1 as a value of the existing Upscaler row. This branch depends on #1096 and #1008 and conflicts with main. Closing; thanks!
Commenting is not possible because the repository is archived.
No description provided.