feat(linux): AMD FSR 4 on Linux: the build compiles the Vulkan back end with it, for the player's own FSR 4 library #24

Merged
HumanBean merged 1 commit from HumanBean/LongshotLauncher:feat/linux-fsr4 into main 2026-11-13 10:25:07 +00:00
Owner

On Linux the launcher shows AMD FSR 4 as "Windows only for now", but the game has had a Linux FSR 4 path for a while (a Vulkan FSR 4 library the player puts beside the game, such as fsr4-vk's amd_fidelityfx_upscaler_vk.so). Builds just never compiled it in. With MagicBeanDev/Longshot#174, a Linux build with --fsr compiles its own Vulkan back end with FSR 4. This PR offers the switch on Linux to match.

What changed

  • Core/MakeGameCommand.cs: on Linux, FSR 4 passes --fsr alone. Nothing of AMD's is fetched (AMD publishes no Linux runtime), there's no LONGSHOT_FFX_SDK, and LONGSHOT_VK_PREBUILT is dropped as it already is for DLSS, so the back end is compiled with FSR 4. The new FsrBuilds() is true on Windows, and on Linux only when the version's tools carry third_party/fidelityfx (Longshot PR 174).
  • Core/LauncherSettings.cs: a new FsrLinuxNotice records that the Linux notice was read. It is kept apart from FsrLicense, so a launcher home shared with Windows never takes it for AMD's licence. Checked() keeps FSR on with either one.
  • App/ViewModels/SettingsStepViewModel.cs, App/Views/SettingsStepView.axaml, App/Views/LicenceView.axaml: the AMD FSR 4 row shows on Linux, replacing the "Windows only for now" row. Turning it on shows "AMD FSR 4 on Linux" instead of AMD's licence. That screen says nothing is downloaded, the renderer is compiled with FSR 4 (a few minutes longer), and the player supplies amd_fidelityfx_upscaler_vk.so, whose source and terms are theirs to check. Its button is "Turn on".
    • When this version's tools can't build FSR 4 on Linux (FsrBuildable, from FsrBuilds with the job's tools), the switch is greyed out and the row says "This version can't build it on Linux yet."
    • Otherwise the row reads "Needs your own Vulkan FSR 4 library." / "Put amd_fidelityfx_upscaler_vk.so beside the game."
    • The Windows licence text is unchanged.
  • App/ViewModels/BuildStepViewModel.cs: the build gets the acknowledgement for its platform. The build list and the failure report record FSR 4 as it was really built ("asked, not built" when the tools couldn't). The log says so when that happens.
  • tests/launcher_core/Program.cs:
    • Linux with FSR 4 gives --fsr alone, with no prebuilt back end and no AMD runtime folder.
    • Linux with DLSS and FSR 4 gives both, with one back end compiled.
    • Tools without the headers give no --fsr, now with an explicit stub rather than the real disk.
    • Without the acknowledgement, the build uses the prebuilt back end.
    • FsrBuilds is always true on Windows.
    • Settings: the Linux notice keeps FSR on without AMD's licence, and neither one means off.

Testing

  • python -I tests/test_launcher_core.py --dotnet ~/.dotnet/dotnet --longshot <Longshot checkout>: 582 checks passed on this head. python -I tests/test_release.py: OK. dotnet build App/LongshotLauncher.csproj -c Release --no-incremental -warnaserror: succeeded (Linux, .NET 10).
  • Not tested: the screen itself (no screenshot yet: the settings step needs real game files to reach), and a real Linux build with FSR 4 from the launcher. That needs a Longshot AppImage with PR 174 and an AMD RX 9000 with a Vulkan FSR 4 library to see it in the game (test request T-MARB on PR 174).

Left for a follow-up

MakeGameCommand.ForCheck (the files step's check) always sets LONGSHOT_VK_PREBUILT. On a Linux CPU without AVX2 it therefore rejects the game files, even though a DLSS or FSR 4 build would compile its own back end. That was already true for DLSS before this PR, and fixing it means carrying the build's choices into the files step.

Screenshots

To add: the settings step on Linux with the AMD FSR 4 row, and the "AMD FSR 4 on Linux" screen.

🤖 Generated with Claude Code

On Linux the launcher shows AMD FSR 4 as "Windows only for now", but the game has had a Linux FSR 4 path for a while (a Vulkan FSR 4 library the player puts beside the game, such as fsr4-vk's `amd_fidelityfx_upscaler_vk.so`). Builds just never compiled it in. With https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/174, a Linux build with `--fsr` compiles its own Vulkan back end with FSR 4. This PR offers the switch on Linux to match. ## What changed - **`Core/MakeGameCommand.cs`**: on Linux, FSR 4 passes `--fsr` alone. Nothing of AMD's is fetched (AMD publishes no Linux runtime), there's no `LONGSHOT_FFX_SDK`, and `LONGSHOT_VK_PREBUILT` is dropped as it already is for DLSS, so the back end is compiled with FSR 4. The new `FsrBuilds()` is true on Windows, and on Linux only when the version's tools carry `third_party/fidelityfx` (Longshot PR 174). - **`Core/LauncherSettings.cs`**: a new `FsrLinuxNotice` records that the Linux notice was read. It is kept apart from `FsrLicense`, so a launcher home shared with Windows never takes it for AMD's licence. `Checked()` keeps FSR on with either one. - **`App/ViewModels/SettingsStepViewModel.cs`, `App/Views/SettingsStepView.axaml`, `App/Views/LicenceView.axaml`**: the AMD FSR 4 row shows on Linux, replacing the "Windows only for now" row. Turning it on shows "AMD FSR 4 on Linux" instead of AMD's licence. That screen says nothing is downloaded, the renderer is compiled with FSR 4 (a few minutes longer), and the player supplies `amd_fidelityfx_upscaler_vk.so`, whose source and terms are theirs to check. Its button is "Turn on". - When this version's tools can't build FSR 4 on Linux (`FsrBuildable`, from `FsrBuilds` with the job's tools), the switch is greyed out and the row says "This version can't build it on Linux yet." - Otherwise the row reads "Needs your own Vulkan FSR 4 library." / "Put amd_fidelityfx_upscaler_vk.so beside the game." - The Windows licence text is unchanged. - **`App/ViewModels/BuildStepViewModel.cs`**: the build gets the acknowledgement for its platform. The build list and the failure report record FSR 4 as it was really built ("asked, not built" when the tools couldn't). The log says so when that happens. - **`tests/launcher_core/Program.cs`**: - Linux with FSR 4 gives `--fsr` alone, with no prebuilt back end and no AMD runtime folder. - Linux with DLSS and FSR 4 gives both, with one back end compiled. - Tools without the headers give no `--fsr`, now with an explicit stub rather than the real disk. - Without the acknowledgement, the build uses the prebuilt back end. - `FsrBuilds` is always true on Windows. - Settings: the Linux notice keeps FSR on without AMD's licence, and neither one means off. ## Testing - `python -I tests/test_launcher_core.py --dotnet ~/.dotnet/dotnet --longshot <Longshot checkout>`: 582 checks passed on this head. `python -I tests/test_release.py`: OK. `dotnet build App/LongshotLauncher.csproj -c Release --no-incremental -warnaserror`: succeeded (Linux, .NET 10). - **Not tested:** the screen itself (no screenshot yet: the settings step needs real game files to reach), and a real Linux build with FSR 4 from the launcher. That needs a Longshot AppImage with PR 174 and an AMD RX 9000 with a Vulkan FSR 4 library to see it in the game (test request T-MARB on PR 174). ## Left for a follow-up `MakeGameCommand.ForCheck` (the files step's check) always sets `LONGSHOT_VK_PREBUILT`. On a Linux CPU without AVX2 it therefore rejects the game files, even though a DLSS or FSR 4 build would compile its own back end. That was already true for DLSS before this PR, and fixing it means carrying the build's choices into the files step. ## Screenshots To add: the settings step on Linux with the AMD FSR 4 row, and the "AMD FSR 4 on Linux" screen. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
HumanBean left a comment

Code review only (diff and surrounding code read; no build or tests run). The Linux FSR 4 change looks right: --fsr alone, no LONGSHOT_FFX_SDK, LONGSHOT_VK_PREBUILT dropped as for DLSS, gated on third_party/fidelityfx where Longshot PR 174's appimage.sh puts it (usr/share/longshot, which is ToolsRoot). entry.Fsr now records what was actually built, and fsr is set in Run() before Complete() can run. The launcher never runs --update itself (an Update or Rebuild passes the game files and --out), so make_game's .longshot_fsr mark can't turn FSR back on behind the launcher's LONGSHOT_VK_PREBUILT. With FSR off the mark is removed, and build.py's prebuilt_renderer() ignores the variable under LONGSHOT_FSR anyway.

Findings, most severe first:

  1. High: the head commit carries an unrelated feature. Core/SystemRequirements.cs, tests/launcher_core/RequirementsChecks.cs, the requirements card in FilesStepView.axaml/WizardViewModel.cs and a README section (5 of the 11 files, about 180 lines) are a system-requirements check that the description doesn't mention. It's a separate topic: take it out of this PR and give it its own.
  2. Medium: the switch is offered on Linux for every version, but only tools with Longshot PR 174 build it. Today that means none. With an older AppImage the player turns it on, is told to put the .so beside the game, and gets a build without FSR 4. The only sign is one log line under Show details.
  3. Low: FsrLicense now also means "acknowledged the Linux notice", so it no longer always means AMD's licence was accepted (see inline).
  4. Low: the files step's --check still runs with the prebuilt back end's AVX2 check, which an FSR or DLSS build skips (already true for DLSS).
  5. Description: "579 checks passed" is 575 plus the 4 new FSR checks, so it wasn't run on this head (RequirementsChecks adds 12 more). The What changed list leaves out finding 1.
Code review only (diff and surrounding code read; no build or tests run). The Linux FSR 4 change looks right: `--fsr` alone, no `LONGSHOT_FFX_SDK`, `LONGSHOT_VK_PREBUILT` dropped as for DLSS, gated on `third_party/fidelityfx` where Longshot PR 174's `appimage.sh` puts it (`usr/share/longshot`, which is `ToolsRoot`). `entry.Fsr` now records what was actually built, and `fsr` is set in `Run()` before `Complete()` can run. The launcher never runs `--update` itself (an Update or Rebuild passes the game files and `--out`), so make_game's `.longshot_fsr` mark can't turn FSR back on behind the launcher's `LONGSHOT_VK_PREBUILT`. With FSR off the mark is removed, and `build.py`'s `prebuilt_renderer()` ignores the variable under `LONGSHOT_FSR` anyway. Findings, most severe first: 1. **High: the head commit carries an unrelated feature.** `Core/SystemRequirements.cs`, `tests/launcher_core/RequirementsChecks.cs`, the requirements card in `FilesStepView.axaml`/`WizardViewModel.cs` and a README section (5 of the 11 files, about 180 lines) are a system-requirements check that the description doesn't mention. It's a separate topic: take it out of this PR and give it its own. 2. **Medium:** the switch is offered on Linux for every version, but only tools with Longshot PR 174 build it. Today that means none. With an older AppImage the player turns it on, is told to put the .so beside the game, and gets a build without FSR 4. The only sign is one log line under Show details. 3. **Low:** `FsrLicense` now also means "acknowledged the Linux notice", so it no longer always means AMD's licence was accepted (see inline). 4. **Low:** the files step's `--check` still runs with the prebuilt back end's AVX2 check, which an FSR or DLSS build skips (already true for DLSS). 5. **Description:** "579 checks passed" is 575 plus the 4 new FSR checks, so it wasn't run on this head (RequirementsChecks adds 12 more). The *What changed* list leaves out finding 1.
@ -135,1 +136,4 @@
command = MakeGameCommand.For(job.Tools!, request, job.Service.Platform, job.Service.Home, LauncherService.LauncherPath);
fsr = command.Arguments.Contains("--fsr");
if (s.Fsr && s.FsrLicense && !fsr)
lock (log) log.Add("AMD FSR 4: this version's tools carry no AMD FSR API headers for Linux, so it is built without FSR 4.");
Author
Owner

Nit: the settings: line at 76 still says ", FSR 4" for this build, and so does the bug report's "FSR 4 on" (Report). This line corrects it two lines later, but writing the effective state (fsr) in Report would make a pasted report unambiguous. Also, this message can only fire on Linux today. Nothing ties it there, so if FsrBuilds ever turns false on Windows it would still say "for Linux".

**Nit:** the `settings:` line at 76 still says ", FSR 4" for this build, and so does the bug report's "FSR 4 on" (`Report`). This line corrects it two lines later, but writing the effective state (`fsr`) in `Report` would make a pasted report unambiguous. Also, this message can only fire on Linux today. Nothing ties it there, so if `FsrBuilds` ever turns false on Windows it would still say "for Linux".
@ -126,3 +125,4 @@
if (value == s.Fsr) return;
if (value && !s.FsrLicense)
{
Main.Modal = new LicenceViewModel(Main, false, Linux, () => { s.FsrLicense = true; s.Fsr = true; Save(); RaiseUpscalers(); },
Author
Owner

Low: on Linux, "Turn on" sets s.FsrLicense = true, although the comment at line 141 says there is no licence to accept there. LauncherSettings documents a licence flag as "true only once its license was accepted", and on Windows that flag is what passes --accept-amd-license and shows "Licence accepted earlier.". A home shared across a dual boot (LONGSHOT_LAUNCHER_HOME, or a portable launcher's home) would carry a Linux acknowledgement into a Windows build that downloads AMD's runtime without the player ever seeing AMD's licence. A separate flag for the Linux notice (and windows ? r.FsrLicense : r.FsrNotice in MakeGameCommand.For, with Checked() following) would keep the two apart.

**Low:** on Linux, "Turn on" sets `s.FsrLicense = true`, although the comment at line 141 says there is no licence to accept there. `LauncherSettings` documents a licence flag as "true only once its license was accepted", and on Windows that flag is what passes `--accept-amd-license` and shows "Licence accepted earlier.". A home shared across a dual boot (`LONGSHOT_LAUNCHER_HOME`, or a portable launcher's home) would carry a Linux acknowledgement into a Windows build that downloads AMD's runtime without the player ever seeing AMD's licence. A separate flag for the Linux notice (and `windows ? r.FsrLicense : r.FsrNotice` in `MakeGameCommand.For`, with `Checked()` following) would keep the two apart.
@ -141,2 +141,3 @@
// (Linux: nothing of AMD's is downloaded, so there is no licence to accept; the player's own library goes beside the game)
public bool FsrAccepted => s.Fsr && Windows;
public string FsrLine => Linux ? "" : s.Fsr ? "" : s.FsrLicense ? "Licence accepted earlier." : "Shows AMD's licence first.";
public string FsrLine => Linux ? (s.Fsr ? "Put amd_fidelityfx_upscaler_vk.so beside the game." : "Needs your own Vulkan FSR 4 library.")
Author
Owner

Medium: on Linux this row is offered whatever the version's tools are. Only an AppImage with Longshot PR 174 carries third_party/fidelityfx, and no release has it yet. With an older one, MakeGameCommand.For quietly leaves out --fsr: the player turns it on, reads "Put amd_fidelityfx_upscaler_vk.so beside the game.", and gets a build without FSR 4. The only sign is the log line under Show details. Job.Tools is known by step 2 (Start already needs it), so MakeGameCommand.FsrBuilds(Job.Tools, Job.Service.Platform) could drive this line, e.g. "This version's tools can't build FSR 4 on Linux yet", or disable the switch for such tools.

**Medium:** on Linux this row is offered whatever the version's tools are. Only an AppImage with Longshot PR 174 carries `third_party/fidelityfx`, and no release has it yet. With an older one, `MakeGameCommand.For` quietly leaves out `--fsr`: the player turns it on, reads "Put amd_fidelityfx_upscaler_vk.so beside the game.", and gets a build without FSR 4. The only sign is the log line under Show details. `Job.Tools` is known by step 2 (`Start` already needs it), so `MakeGameCommand.FsrBuilds(Job.Tools, Job.Service.Platform)` could drive this line, e.g. "This version's tools can't build FSR 4 on Linux yet", or disable the switch for such tools.
Author
Owner

Low (already true for DLSS): ForCheck (line 113, below this hunk; anchored here, on FsrBuilds) builds its environment from a request with no FSR, so LONGSHOT_VK_PREBUILT is always set for --check. make_game's check() runs check_cpu(), which returns early only without LONGSHOT_VK_PREBUILT or with LONGSHOT_FSR=1. On a Linux CPU without AVX2, the files step therefore rejects the game files, even though an FSR 4 (or DLSS) build compiles its own back end and Longshot PR 174 makes check_cpu let it through. That's rare (an RX 9000 with a pre-AVX2 CPU), but worth knowing. A fix would pass the upscaler choice into ForCheck.

**Low (already true for DLSS):** `ForCheck` (line 113, below this hunk; anchored here, on `FsrBuilds`) builds its environment from a request with no FSR, so `LONGSHOT_VK_PREBUILT` is always set for `--check`. make_game's `check()` runs `check_cpu()`, which returns early only without `LONGSHOT_VK_PREBUILT` or with `LONGSHOT_FSR=1`. On a Linux CPU without AVX2, the files step therefore rejects the game files, even though an FSR 4 (or DLSS) build compiles its own back end and Longshot PR 174 makes `check_cpu` let it through. That's rare (an RX 9000 with a pre-AVX2 CPU), but worth knowing. A fix would pass the upscaler choice into `ForCheck`.
@ -0,0 +1,116 @@
using System.Runtime.InteropServices;
Author
Owner

High: this file, tests/launcher_core/RequirementsChecks.cs, the requirements card in App/Views/FilesStepView.axaml and App/ViewModels/WizardViewModel.cs, and the README's new last paragraph aren't part of FSR 4 on Linux, and the description doesn't mention them. Please drop them from this PR (one topic) and open them separately if they're wanted.

**High:** this file, `tests/launcher_core/RequirementsChecks.cs`, the requirements card in `App/Views/FilesStepView.axaml` and `App/ViewModels/WizardViewModel.cs`, and the README's new last paragraph aren't part of FSR 4 on Linux, and the description doesn't mention them. Please drop them from this PR (one topic) and open them separately if they're wanted.
@ -772,3 +773,3 @@
"-I", lin.MakeGame, "--romfs", "/d/romfs", "--exefs", "/d/exefs", "--out", "/g", "--language", "fr", "--work", "/w",
"--jobs", "6", "--no-prepare-shaders", "--fetch-ngx-sdk", "--accept-nvidia-license",
}), "Linux arguments (no FSR): " + string.Join(" ", l.Arguments));
}), "Linux arguments (tools without AMD's FSR API headers: no FSR): " + string.Join(" ", l.Arguments));
Author
Owner

Nit: this check now claims "tools without AMD's FSR API headers", but l is built with no directoryExists stub, so it holds only because Directory.Exists finds nothing under the scratch home. Passing _ => false would make the claim explicit, like lf/lfu below do. There's also no Linux case with DLSS and FSR together (argument order, one own back end).

**Nit:** this check now claims "tools without AMD's FSR API headers", but `l` is built with no `directoryExists` stub, so it holds only because `Directory.Exists` finds nothing under the scratch home. Passing `_ => false` would make the claim explicit, like `lf`/`lfu` below do. There's also no Linux case with DLSS and FSR together (argument order, one own back end).
HumanBean force-pushed feat/linux-fsr4 from 5f2c02c96b
All checks were successful
CI / Compile and test (pull_request) Has been skipped
CI / Conventional Commit title (pull_request) Successful in 2s
to a7780720c3
All checks were successful
CI / Compile and test (pull_request) Has been skipped
CI / Conventional Commit title (pull_request) Successful in 2s
2026-11-13 10:24:37 +00:00
Compare
HumanBean changed title from WIP: feat(linux): AMD FSR 4 on Linux: the build compiles the Vulkan back end with it, for the player's own FSR 4 library to feat(linux): AMD FSR 4 on Linux: the build compiles the Vulkan back end with it, for the player's own FSR 4 library 2026-11-13 10:25:04 +00:00
HumanBean deleted branch feat/linux-fsr4 2026-11-13 10:25:07 +00:00
Author
Owner

Self-review fixes (a7780720):

  • The branch now holds only this change. The first push had also picked up another session's system-requirements work from the same checkout (that work is on its own branch, feat/system-requirements).
  • On Linux the switch is greyed out with "This version can't build it on Linux yet." when the tools lack AMD's FSR API headers, instead of turning on and silently building without FSR 4.
  • The Linux notice is its own setting, FsrLinuxNotice, and no longer sets FsrLicense.
  • The failure report says FSR 4 as it was built.
  • Tests: an explicit stub for the no-headers case, Linux DLSS + FSR 4 together, and the settings round trip with the notice.
  • 582 checks passed on this head; builds with -warnaserror.
  • Not fixed here: ForCheck's AVX2 rejection (already true for DLSS), noted in the description as a follow-up.
Self-review fixes (a7780720): - The branch now holds only this change. The first push had also picked up another session's system-requirements work from the same checkout (that work is on its own branch, feat/system-requirements). - On Linux the switch is greyed out with "This version can't build it on Linux yet." when the tools lack AMD's FSR API headers, instead of turning on and silently building without FSR 4. - The Linux notice is its own setting, FsrLinuxNotice, and no longer sets FsrLicense. - The failure report says FSR 4 as it was built. - Tests: an explicit stub for the no-headers case, Linux DLSS + FSR 4 together, and the settings round trip with the notice. - 582 checks passed on this head; builds with -warnaserror. - Not fixed here: ForCheck's AVX2 rejection (already true for DLSS), noted in the description as a follow-up.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
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/LongshotLauncher!24
No description provided.