fix(vk): FSR 3.1 frees its images once the chain lets it go, not at its next upscale #556

Open
zeldaootr wants to merge 3 commits from zeldaootr/Longshot:fsr3-release-frees-its-images into main
Contributor

Type: fix · Risk: low · Tested on: Linux x86-64 (game-free); Steam Deck OLED, SteamOS 3.9.5, RADV (a tester's run) · Needs: none

Why

A player who tried AMD FSR 3.1 and went back to the game's own upscaler kept FSR 3.1's images in video memory for the rest of the session: about 40-60 MB on the Steam Deck, about 320 MB at 4K. The tracker has no issue for it (searched).

How to reproduce

Seen on: Steam Deck OLED, RADV VANGOGH, Mesa 26.2.0-devel git-5c65d4fc31, SteamOS 3.9.5 (a tester's run, main 7ff5256e); first found by reading gpu/vk/vk_fsr3.cpp, and the game-free test reproduces it
Settings and switches: defaults (on the Deck: output 1280x720, Render resolution 50%, the game's own upscaler, frame generation off, VRAM budget 2.2 GB)
Steps: in Kokiri Forest, set the Upscaler to AMD FSR 3.1, wait 10 s, set it back to the game's own; wait for the not used for 120 frames line and 5 s more, then read the next vk: VRAM: line
Expected: FSR 3.1's images are freed: the renderer holds less besides the textures than before FSR 3.1 was tried
Actual: on main what the renderer holds besides the textures ends within 29 MB of where it began (-29 and +29 MB in two runs): FSR 3.1's images wait for its next upscale, which never comes

What changed

FSR 3.1's release now asks the chain to free its images a few frames on, once the GPU is past them, instead of leaving the ones still in flight for an upscale that never comes. The memory comes back when the Upscaler row leaves FSR 3.1.

  • vk: release() in gpu/vk/vk_fsr3.cpp retires its images until the GPU is past them, but freed only those already complete; the rest waited for FSR 3.1's next upscale or prepare. It now asks the chain to free them a few frames on (temporal_later), as TemporalEngine::release expects.
  • tests: tests/test_fsr3_release_frees.py compiles the real Image, State, destroy_now, drop_image, free_dead, all_images and release with the timeline and temporal_later stood in for: release while the GPU is behind, then the GPU past it, and every image and view must be destroyed exactly once, none early.

Measurements

Verdict: pass, it helps. On a tester's Steam Deck OLED, after leaving FSR 3.1 the renderer held about 74 MB less besides textures than on main (median 1,091.5 against 1,165.5 MB); within each run it fell by 115 and 102 MB with this PR and stayed within 29 MB on main. The texture cache, at its budget there, took up part of the space: used minus free, textures included, came out the same in both builds. Switching back to FSR 3.1 makes its images again and the picture is right. The game-free test: not all images freed on main, 22 of 22 here.

Hardware: Steam Deck OLED, AMD Custom APU 0932 (RADV VANGOGH), 16 GB, Mesa 26.2.0-devel git-5c65d4fc31, SteamOS 3.9.5 (build 20261023.100), kernel 7.2.7-valve2, Game Mode, docked, stock clocks (dukenheimer's run, test request T-UH7H); game-free: Linux x86-64 server, no GPU or game
Scene: Kokiri Forest after Continue, standing; main's own defaults on that Deck (Quality preset Auto, output 1280x720, Render resolution 50%, so FSR 3.1 upscaled 640x360 to 1280x720; frame generation off; VRAM budget 2.2 GB)
Method: the vk: VRAM: lines (logged every 600 frames) of longshot_log.txt: the last one before FSR 3.1 was set (after 25 s standing), and the next one after the not used for 120 frames line plus 5 s; "besides textures" is used, minus the free space in its blocks, minus the textures. Upscaler set through the menu's own setter (control bridge): FSR 3.1 for 10 s, back to the game's own, later FSR 3.1 again for 12 s and a picture. Four runs, interleaved (this PR, main, main, this PR), one test folder with warm caches and the binaries swapped; the median of each build's two runs. Game-free: python3 -I -B tests/test_fsr3_release_frees.py --cxx g++ --headers (the Vulkan headers' include) at 93f9d02b and at 6732e8b3 (rebased onto main aa95d35f), with g++ 13.3 and with clang 23.1.5; before that, at b5ec0f79 and 69fd56bd on main 53f96d78, and before the first rebase at 97223942 and acd34022, twice each, alternating
How to reproduce: build main 7ff5256e, and main with this PR's renderer from acd34022 (the PR changes only gpu/vk/vk_fsr3.cpp and a test), both x86-64-v3 with the release play profile and LLVM 23.1.5; then the steps under How to reproduce, reading the vk: VRAM: lines

Before: main @ 7ff5256e After: this PR @ acd34022 (main with this PR's renderer)
besides textures after leaving FSR 3.1, MB (run 1 / run 2; median) 1,154 / 1,177; 1,165.5 1,107 / 1,076; 1,091.5
change within the run, before FSR 3.1 to after it, MB -29 / +29 -115 / -102
used, after, MB 4,181 / 4,309 4,117 / 4,117
used minus free (textures included), after, MB 3,585 to 3,607 in all four runs 3,585 to 3,607 in all four runs
FSR 3.1 again: images made again, the picture right yes / yes yes / yes
before FSR 3.1: used / free in blocks / textures   ->   the next line after leaving it (+5 s)   (besides textures)
run 1, this PR: 4,149 / 442 / 2,485 -> 4,117 / 510 / 2,500   (1,222 -> 1,107, -115)
run 2, main:    4,149 / 496 / 2,470 -> 4,181 / 575 / 2,452   (1,183 -> 1,154, -29)
run 3, main:    4,149 / 544 / 2,457 -> 4,309 / 708 / 2,424   (1,148 -> 1,177, +29)
run 4, this PR: 4,149 / 467 / 2,504 -> 4,117 / 532 / 2,509   (1,178 -> 1,076, -102)
vk: AMD FSR 3.1: not used for 120 frames (...): what it made and its images let go; the next upscale with it makes them again   (8 to 9 s after leaving FSR 3.1, all four runs, main too)
vk: fsr3: 640x360 -> 1280x720   (FSR 3.1 again, all four runs)

The textures, which fill up to their 2,560 MB budget there, held 48 to 85 MB more in this PR's runs, so the total did not fall. The expected 40-60 MB was for the Deck's 1280x800; this run was docked at 1280x720 and measured 47 to 101 MB less besides textures than main. The tester's report with the pictures: #556 (comment)

Before: main @ aa95d35f (with the test, 93f9d02b) After: this PR @ 6732e8b3
FSR 3.1 images freed after release, without FSR 3.1 drawing again (g++ and clang the same) not all (image 1 not freed) 22 of 22
93f9d02b: image 1 not freed / FAIL: every image FSR 3.1 made is freed once the chain let it go and the GPU is past it (exit 1, g++ and clang)
6732e8b3: FSR 3.1's 22 images freed after release without FSR 3.1 drawing again (exit 0, g++ and clang)

Flags and settings

None.

Testing

Tested: Linux x86-64, game-free. The new test fails on the test-only commit 93f9d02b and passes at 6732e8b3, this branch rebased onto main aa95d35f, with g++ 13.3 and with clang 23.1.5 (before, it did the same at b5ec0f79 and 69fd56bd on main 53f96d78, and at 97223942 and acd34022, twice each, alternating) (python3 -I -B tests/test_fsr3_release_frees.py --cxx g++ --headers with the Vulkan headers' include). This PR's own tests and the checks its fix commit edits ran at both commits, and once more on land/integration 27553c83 (main 7ff5256e with this PR and twelve other fixes merged), where the thirteen fixes' tests and edited checks pass, 16 of 16; the full python3 -I -B tests/run_all.py ran on that branch too (see the checklist).

In the game: dukenheimer ran test request T-UH7H on a Steam Deck OLED (RADV VANGOGH, Mesa 26.2.0-devel, SteamOS 3.9.5, Game Mode, docked) and reported a pass on 2026-11-15 at 03:06 UTC (#556 (comment)). The builds were main 7ff5256e and main with this PR's renderer built from its head then, acd34022 (6732e8b3 after the rebases, the same change by git patch-id; not the combined build), four runs interleaved. FSR 3.1 itself ran on the Deck: the Upscaler was set to AMD FSR 3.1 through the menu's own setter, upscaling 640x360 to 1280x720, for 10 s, then back to the game's own; FSR 3.1 let its images go (the not used for 120 frames line, 8 to 9 s after), the next vk: VRAM: line showed the drop above, and FSR 3.1 set again made its images again with the picture right in all four runs (nothing missing or garbled in the pictures). No crash, device lost or device fault; the kernel's amdgpu lines were only the display's Losing delta precision while programming shaper LUT notices.

The branch has been rebased since the tester's run, onto main aa95d35f, with its commits re-authored under the forge's noreply address; each commit's change is identical to before by git patch-id, so the commits named above are the ones tested and the result stands for this head (80f66c9b).

Not tested: FSR 3.1 on Windows, and on another GPU maker. The Deck's own 1280x800 (the run's output was 1280x720), and 4K, where about 320 MB is expected back. More than one switch away from FSR 3.1 in a session. Frame generation, whose images this PR does not touch (see Risks).

Must be tested: None

Risks

What could break: The free runs through the chain's temporal_later, after the GPU is past the images, so an image freed early would show as a validation error or a device lost right after a switch away from FSR 3.1 (none in the tester's four runs). About 39-58 MB come back at the Deck's 1280x800 and about 320 MB at 4K, once per switch away from FSR 3.1; where the texture cache is at its budget, as on the tester's Deck, the textures take the space up. Found with it and not fixed here: frame generation's images are never released, and FSR 3.1 remakes about 43 MB at each resolution step.

Turning it off: revert the commit

Compatibility: Nothing changes

Checklist

Everyone

  • One topic.
  • The title is a Conventional Commit (type(scope): description) of the status line's type.
  • Why gives the reason plainly and links the issues that fit (the tracker searched).
  • Measurements has a verdict, or one line saying why there is nothing to measure.
  • Testing names what was tested, what wasn't, and what must still be tested, where and how.
  • Rebased on current main. Onto main aa95d35f with no conflict, the commits re-authored under the forge's noreply address: each of the three commits' changes (the test, the fix, the docs/tested/ file) is identical to before by git patch-id. Since 53f96d78, main changed nothing in this PR's files.
  • python -I -B tests/run_all.py passes (any failure that also fails on main is named). Run on this branch at 157d688b on main 53f96d78, before this rebase (80f66c9b now, the same patches by git patch-id; the Vulkan and SPIR-V headers from the CPM cache, 8 at once, on a loaded Linux x86-64 server): 531 passed, 15 failed, 48 skipped. The 15 are the ones that fail on main 53f96d78 in the same run: test_appimage_player_build, test_bake_portability, test_cpm_discovery, test_crash_dialog, test_env_on, test_lift_cache, test_lift_cleanup_error, test_make_game_cache, test_pipeline_tour, test_readback_late, test_vk_pgo, test_vram_budget_row, test_walk_key, nx2/test_mesh_first_types.py and nx2/test_texture_init_barrier.py. Main's run also timed out test_fpx_sticky (it passes alone there). After the rebase onto main aa95d35f, at 80f66c9b: 10 checks, this PR's test and those that read its changed files, with g++ 13.3 and with clang 23.1.5: all 10 pass.
  • No game files, dumps, build output or generated files.
  • third_party/ untouched (a new folder with a PROVENANCE.md instead).
  • The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled.

When it applies

  • AI assistance recorded with Assisted-by: / Co-Authored-By: trailers.
  • Numbers from the same PC, scene and settings, at least 2 interleaved runs each, the median reported. The tester's four Steam Deck runs (this PR, main, main, this PR); the game-free test twice each, alternating.
  • A file in docs/tested/ for each new measured run (format in docs/tested-configurations.md). docs/tested/2026-11-15-fsr3-release-dukenheimer-t-uh7h.md, the tester's run; scripts/tested_configurations.py and tests/test_tested_configurations.py pass with it.
  • A game-free test added for the fix, failing on main and passing here.
  • Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. Built on Linux for both, in the combined branch 27553c83: RX_VK_ONLY=1 RX_RELEASE=1 RX_TARGET=windows with llvm-mingw 20261104 linked longshot_vk.dll (sha256 25117493...), and the same without RX_TARGET linked longshot_vk.so; the changed file has no new warning under -Wall -Wextra on either platform against main. The tester's renderer linked for Linux (x86-64-v3, LLVM 23.1.5). After the rebase onto main aa95d35f, gpu/vk/vk_fsr3.cpp at 80f66c9b checked whole (-fsyntax-only -Wall -Wextra, clang 23.1.5 for Linux and llvm-mingw 20261104 for Windows): the same warnings as main aa95d35f's, none new.
**Type:** fix · **Risk:** low · **Tested on:** Linux x86-64 (game-free); Steam Deck OLED, SteamOS 3.9.5, RADV (a tester's run) · **Needs:** none ## Why A player who tried AMD FSR 3.1 and went back to the game's own upscaler kept FSR 3.1's images in video memory for the rest of the session: about 40-60 MB on the Steam Deck, about 320 MB at 4K. The tracker has no issue for it (searched). ## How to reproduce **Seen on:** Steam Deck OLED, RADV VANGOGH, Mesa 26.2.0-devel git-5c65d4fc31, SteamOS 3.9.5 (a tester's run, main 7ff5256e); first found by reading `gpu/vk/vk_fsr3.cpp`, and the game-free test reproduces it **Settings and switches:** defaults (on the Deck: output 1280x720, Render resolution 50%, the game's own upscaler, frame generation off, VRAM budget 2.2 GB) **Steps:** in Kokiri Forest, set the Upscaler to AMD FSR 3.1, wait 10 s, set it back to the game's own; wait for the `not used for 120 frames` line and 5 s more, then read the next `vk: VRAM:` line **Expected:** FSR 3.1's images are freed: the renderer holds less besides the textures than before FSR 3.1 was tried **Actual:** on main what the renderer holds besides the textures ends within 29 MB of where it began (-29 and +29 MB in two runs): FSR 3.1's images wait for its next upscale, which never comes ## What changed FSR 3.1's release now asks the chain to free its images a few frames on, once the GPU is past them, instead of leaving the ones still in flight for an upscale that never comes. The memory comes back when the Upscaler row leaves FSR 3.1. - vk: `release()` in `gpu/vk/vk_fsr3.cpp` retires its images until the GPU is past them, but freed only those already complete; the rest waited for FSR 3.1's next upscale or prepare. It now asks the chain to free them a few frames on (`temporal_later`), as `TemporalEngine::release` expects. - tests: `tests/test_fsr3_release_frees.py` compiles the real `Image`, `State`, `destroy_now`, `drop_image`, `free_dead`, `all_images` and `release` with the timeline and `temporal_later` stood in for: release while the GPU is behind, then the GPU past it, and every image and view must be destroyed exactly once, none early. ## Measurements **Verdict:** pass, it helps. On a tester's Steam Deck OLED, after leaving FSR 3.1 the renderer held about 74 MB less besides textures than on main (median 1,091.5 against 1,165.5 MB); within each run it fell by 115 and 102 MB with this PR and stayed within 29 MB on main. The texture cache, at its budget there, took up part of the space: used minus free, textures included, came out the same in both builds. Switching back to FSR 3.1 makes its images again and the picture is right. The game-free test: not all images freed on main, 22 of 22 here. Hardware: Steam Deck OLED, AMD Custom APU 0932 (RADV VANGOGH), 16 GB, Mesa 26.2.0-devel git-5c65d4fc31, SteamOS 3.9.5 (build 20261023.100), kernel 7.2.7-valve2, Game Mode, docked, stock clocks (dukenheimer's run, test request T-UH7H); game-free: Linux x86-64 server, no GPU or game Scene: Kokiri Forest after Continue, standing; main's own defaults on that Deck (Quality preset Auto, output 1280x720, Render resolution 50%, so FSR 3.1 upscaled 640x360 to 1280x720; frame generation off; VRAM budget 2.2 GB) Method: the `vk: VRAM:` lines (logged every 600 frames) of `longshot_log.txt`: the last one before FSR 3.1 was set (after 25 s standing), and the next one after the `not used for 120 frames` line plus 5 s; "besides textures" is used, minus the free space in its blocks, minus the textures. Upscaler set through the menu's own setter (control bridge): FSR 3.1 for 10 s, back to the game's own, later FSR 3.1 again for 12 s and a picture. Four runs, interleaved (this PR, main, main, this PR), one test folder with warm caches and the binaries swapped; the median of each build's two runs. Game-free: `python3 -I -B tests/test_fsr3_release_frees.py --cxx g++ --headers` (the Vulkan headers' `include`) at 93f9d02b and at 6732e8b3 (rebased onto main aa95d35f), with g++ 13.3 and with clang 23.1.5; before that, at b5ec0f79 and 69fd56bd on main 53f96d78, and before the first rebase at 97223942 and acd34022, twice each, alternating How to reproduce: build main 7ff5256e, and main with this PR's renderer from acd34022 (the PR changes only `gpu/vk/vk_fsr3.cpp` and a test), both x86-64-v3 with the release play profile and LLVM 23.1.5; then the steps under How to reproduce, reading the `vk: VRAM:` lines | | Before: main @ 7ff5256e | After: this PR @ acd34022 (main with this PR's renderer) | |---|---|---| | besides textures after leaving FSR 3.1, MB (run 1 / run 2; median) | 1,154 / 1,177; 1,165.5 | 1,107 / 1,076; 1,091.5 | | change within the run, before FSR 3.1 to after it, MB | -29 / +29 | -115 / -102 | | used, after, MB | 4,181 / 4,309 | 4,117 / 4,117 | | used minus free (textures included), after, MB | 3,585 to 3,607 in all four runs | 3,585 to 3,607 in all four runs | | FSR 3.1 again: images made again, the picture right | yes / yes | yes / yes | ``` before FSR 3.1: used / free in blocks / textures -> the next line after leaving it (+5 s) (besides textures) run 1, this PR: 4,149 / 442 / 2,485 -> 4,117 / 510 / 2,500 (1,222 -> 1,107, -115) run 2, main: 4,149 / 496 / 2,470 -> 4,181 / 575 / 2,452 (1,183 -> 1,154, -29) run 3, main: 4,149 / 544 / 2,457 -> 4,309 / 708 / 2,424 (1,148 -> 1,177, +29) run 4, this PR: 4,149 / 467 / 2,504 -> 4,117 / 532 / 2,509 (1,178 -> 1,076, -102) vk: AMD FSR 3.1: not used for 120 frames (...): what it made and its images let go; the next upscale with it makes them again (8 to 9 s after leaving FSR 3.1, all four runs, main too) vk: fsr3: 640x360 -> 1280x720 (FSR 3.1 again, all four runs) ``` The textures, which fill up to their 2,560 MB budget there, held 48 to 85 MB more in this PR's runs, so the total did not fall. The expected 40-60 MB was for the Deck's 1280x800; this run was docked at 1280x720 and measured 47 to 101 MB less besides textures than main. The tester's report with the pictures: https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/556#issuecomment-22263 | | Before: main @ aa95d35f (with the test, 93f9d02b) | After: this PR @ 6732e8b3 | |---|---|---| | FSR 3.1 images freed after release, without FSR 3.1 drawing again (g++ and clang the same) | not all (image 1 not freed) | 22 of 22 | ``` 93f9d02b: image 1 not freed / FAIL: every image FSR 3.1 made is freed once the chain let it go and the GPU is past it (exit 1, g++ and clang) 6732e8b3: FSR 3.1's 22 images freed after release without FSR 3.1 drawing again (exit 0, g++ and clang) ``` ### Flags and settings None. ## Testing **Tested:** Linux x86-64, game-free. The new test fails on the test-only commit 93f9d02b and passes at 6732e8b3, this branch rebased onto main aa95d35f, with g++ 13.3 and with clang 23.1.5 (before, it did the same at b5ec0f79 and 69fd56bd on main 53f96d78, and at 97223942 and acd34022, twice each, alternating) (`python3 -I -B tests/test_fsr3_release_frees.py --cxx g++ --headers` with the Vulkan headers' `include`). This PR's own tests and the checks its fix commit edits ran at both commits, and once more on `land/integration` 27553c83 (main 7ff5256e with this PR and twelve other fixes merged), where the thirteen fixes' tests and edited checks pass, 16 of 16; the full `python3 -I -B tests/run_all.py` ran on that branch too (see the checklist). In the game: dukenheimer ran test request T-UH7H on a Steam Deck OLED (RADV VANGOGH, Mesa 26.2.0-devel, SteamOS 3.9.5, Game Mode, docked) and reported a pass on 2026-11-15 at 03:06 UTC (https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/556#issuecomment-22263). The builds were main 7ff5256e and main with this PR's renderer built from its head then, acd34022 (6732e8b3 after the rebases, the same change by `git patch-id`; not the combined build), four runs interleaved. FSR 3.1 itself ran on the Deck: the Upscaler was set to AMD FSR 3.1 through the menu's own setter, upscaling 640x360 to 1280x720, for 10 s, then back to the game's own; FSR 3.1 let its images go (the `not used for 120 frames` line, 8 to 9 s after), the next `vk: VRAM:` line showed the drop above, and FSR 3.1 set again made its images again with the picture right in all four runs (nothing missing or garbled in the pictures). No crash, device lost or device fault; the kernel's amdgpu lines were only the display's `Losing delta precision while programming shaper LUT` notices. The branch has been rebased since the tester's run, onto main aa95d35f, with its commits re-authored under the forge's noreply address; each commit's change is identical to before by `git patch-id`, so the commits named above are the ones tested and the result stands for this head (80f66c9b). **Not tested:** FSR 3.1 on Windows, and on another GPU maker. The Deck's own 1280x800 (the run's output was 1280x720), and 4K, where about 320 MB is expected back. More than one switch away from FSR 3.1 in a session. Frame generation, whose images this PR does not touch (see Risks). **Must be tested:** None ## Risks **What could break:** The free runs through the chain's `temporal_later`, after the GPU is past the images, so an image freed early would show as a validation error or a device lost right after a switch away from FSR 3.1 (none in the tester's four runs). About 39-58 MB come back at the Deck's 1280x800 and about 320 MB at 4K, once per switch away from FSR 3.1; where the texture cache is at its budget, as on the tester's Deck, the textures take the space up. Found with it and not fixed here: frame generation's images are never released, and FSR 3.1 remakes about 43 MB at each resolution step. **Turning it off:** revert the commit **Compatibility:** Nothing changes ## Checklist ### Everyone - [x] One topic. - [x] The title is a Conventional Commit (`type(scope): description`) of the status line's type. - [x] Why gives the reason plainly and links the issues that fit (the tracker searched). - [x] Measurements has a verdict, or one line saying why there is nothing to measure. - [x] Testing names what was tested, what wasn't, and what must still be tested, where and how. - [x] Rebased on current `main`. Onto main aa95d35f with no conflict, the commits re-authored under the forge's noreply address: each of the three commits' changes (the test, the fix, the `docs/tested/` file) is identical to before by `git patch-id`. Since 53f96d78, main changed nothing in this PR's files. - [x] `python -I -B tests/run_all.py` passes (any failure that also fails on `main` is named). Run on this branch at 157d688b on main 53f96d78, before this rebase (80f66c9b now, the same patches by `git patch-id`; the Vulkan and SPIR-V headers from the CPM cache, 8 at once, on a loaded Linux x86-64 server): 531 passed, 15 failed, 48 skipped. The 15 are the ones that fail on main 53f96d78 in the same run: `test_appimage_player_build`, `test_bake_portability`, `test_cpm_discovery`, `test_crash_dialog`, `test_env_on`, `test_lift_cache`, `test_lift_cleanup_error`, `test_make_game_cache`, `test_pipeline_tour`, `test_readback_late`, `test_vk_pgo`, `test_vram_budget_row`, `test_walk_key`, `nx2/test_mesh_first_types.py` and `nx2/test_texture_init_barrier.py`. Main's run also timed out `test_fpx_sticky` (it passes alone there). After the rebase onto main aa95d35f, at 80f66c9b: 10 checks, this PR's test and those that read its changed files, with g++ 13.3 and with clang 23.1.5: all 10 pass. - [x] No game files, dumps, build output or generated files. - [x] `third_party/` untouched (a new folder with a `PROVENANCE.md` instead). - [x] The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled. ### When it applies - [x] AI assistance recorded with `Assisted-by:` / `Co-Authored-By:` trailers. - [x] Numbers from the same PC, scene and settings, at least 2 interleaved runs each, the median reported. The tester's four Steam Deck runs (this PR, main, main, this PR); the game-free test twice each, alternating. - [x] A file in `docs/tested/` for each new measured run (format in `docs/tested-configurations.md`). `docs/tested/2026-11-15-fsr3-release-dukenheimer-t-uh7h.md`, the tester's run; `scripts/tested_configurations.py` and `tests/test_tested_configurations.py` pass with it. - [x] A game-free test added for the fix, failing on `main` and passing here. - [x] Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. Built on Linux for both, in the combined branch 27553c83: `RX_VK_ONLY=1 RX_RELEASE=1 RX_TARGET=windows` with llvm-mingw 20261104 linked `longshot_vk.dll` (sha256 25117493...), and the same without `RX_TARGET` linked `longshot_vk.so`; the changed file has no new warning under `-Wall -Wextra` on either platform against `main`. The tester's renderer linked for Linux (x86-64-v3, LLVM 23.1.5). After the rebase onto main aa95d35f, `gpu/vk/vk_fsr3.cpp` at 80f66c9b checked whole (`-fsyntax-only -Wall -Wextra`, clang 23.1.5 for Linux and llvm-mingw 20261104 for Windows): the same warnings as main aa95d35f's, none new.
Assisted-by: Claude
fix(vk): FSR 3.1 frees its images once the chain lets it go, not at its next upscale
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 5s
beanstalk/approval Test farm not requested
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
acd34022f2
Assisted-by: Claude
Author
Contributor

Filled in: the full game-free suite on the combined branch, the Windows and Linux builds, and the test request T-UH7H. Still work in progress until a Steam Deck run is in.

Filled in: the full game-free suite on the combined branch, the Windows and Linux builds, and the test request T-UH7H. Still work in progress until a Steam Deck run is in.
Contributor

Test request T-UH7H: pass

Built main 7ff5256e, and main with this PR's renderer from its head acd34022 (the PR changes only gpu/vk/vk_fsr3.cpp and a test).
Output 1280x720, render 640x360 (main's own defaults on this Deck), so FSR 3.1 upscaled 640x360 -> 1280x720.

Result

The vk: VRAM: lines (MB). "Besides textures" is from the same line: used, minus the free space in its blocks, minus the textures.

run build before FSR 3.1: used / free in blocks / textures the next line after leaving it (+5 s) besides textures: before -> after
1 main + #556 4,149 / 442 / 2,485 4,117 / 510 / 2,500 1,222 -> 1,107 (-115)
2 main 4,149 / 496 / 2,470 4,181 / 575 / 2,452 1,183 -> 1,154 (-29)
3 main 4,149 / 544 / 2,457 4,309 / 708 / 2,424 1,148 -> 1,177 (+29)
4 main + #556 4,149 / 467 / 2,504 4,117 / 532 / 2,509 1,178 -> 1,076 (-102)
  • Lower with this PR. After leaving FSR 3.1 the renderer held 1,107 and 1,076 MB besides textures with this PR, against 1,154
    and 1,177 MB on main. That is 47 to 101 MB less, 74 on average; the request expected about 40-60 MB at 1280x800.
    • Within each run, what it held besides textures fell by 115 and 102 MB with this PR. Main's runs ended within 29 MB of where
      they began.
    • "Used" on that line was 4,117 MB in both runs with this PR, against 4,181 and 4,309 MB on main.
    • Used minus free, textures included, came out the same in both builds (3,585 to 3,607 MB). The textures, which fill up to their
      2,560 MB budget here, held 48 to 85 MB more in this PR's runs.
  • The release line: vk: AMD FSR 3.1: not used for 120 frames (...): what it made and its images let go; the next upscale with it makes them again, 8 to 9 s after leaving FSR 3.1 (about 15 fps) in all four runs. Main logs the same line.
  • FSR 3.1 again: the picture is right in all four runs, this PR's included: its images were made again
    (vk: fsr3: 640x360 -> 1280x720), and nothing is missing or garbled (pictures attached: before, with FSR 3.1, and FSR 3.1 again).
  • Faults: none (no crash, device lost or device fault). The kernel's amdgpu lines were only the display's "Losing delta
    precision while programming shaper LUT" notices, 6 a start.

Setup

  • Steam Deck OLED: AMD Custom APU 0932 (RADV VANGOGH), 16 GB; Mesa 26.2.0-devel git-5c65d4fc31; SteamOS 3.9.5 (build 20261023.100),
    kernel 7.2.7-valve2. Game Mode, docked, stock clocks.
  • Builds: main 7ff5256e; main + this PR, its renderer built from the PR's head. Both for x86-64-v3 with the release play profile
    and LLVM 23.1.5. One test folder (warm caches) with the binaries swapped.
  • Settings: main's own defaults on this Deck, the options file its first start wrote. Quality preset Auto (this PC), output
    1280x720, Render resolution 50%, the game's own upscaler, frame generation off, VRAM budget 2.2 GB.
  • Steps, through the control bridge:
    1. Continue into Kokiri Forest, then 25 s standing. The vk: VRAM: line before is the last one logged by then.
    2. Upscaler set to AMD FSR 3.1 through the menu's own setter. 10 s, then back to the game's own.
    3. The not used for 120 frames line, then 5 s more, then the next vk: VRAM: line (logged every 600 frames).
    4. FSR 3.1 again, 12 s, and a picture.
  • Order: main + #556, main, main, main + #556.

t-uh7h-fsr31-crops.png

t-uh7h-sheet.png

Test request T-UH7H: pass Built main 7ff5256e, and main with this PR's renderer from its head acd34022 (the PR changes only `gpu/vk/vk_fsr3.cpp` and a test). Output 1280x720, render 640x360 (main's own defaults on this Deck), so FSR 3.1 upscaled 640x360 -> 1280x720. **Result** The `vk: VRAM:` lines (MB). "Besides textures" is from the same line: used, minus the free space in its blocks, minus the textures. | run | build | before FSR 3.1: used / free in blocks / textures | the next line after leaving it (+5 s) | besides textures: before -> after | |---|---|---|---|---| | 1 | main + #556 | 4,149 / 442 / 2,485 | 4,117 / 510 / 2,500 | 1,222 -> **1,107** (-115) | | 2 | main | 4,149 / 496 / 2,470 | 4,181 / 575 / 2,452 | 1,183 -> **1,154** (-29) | | 3 | main | 4,149 / 544 / 2,457 | 4,309 / 708 / 2,424 | 1,148 -> **1,177** (+29) | | 4 | main + #556 | 4,149 / 467 / 2,504 | 4,117 / 532 / 2,509 | 1,178 -> **1,076** (-102) | - **Lower with this PR.** After leaving FSR 3.1 the renderer held 1,107 and 1,076 MB besides textures with this PR, against 1,154 and 1,177 MB on main. That is 47 to 101 MB less, 74 on average; the request expected about 40-60 MB at 1280x800. - Within each run, what it held besides textures fell by 115 and 102 MB with this PR. Main's runs ended within 29 MB of where they began. - "Used" on that line was 4,117 MB in both runs with this PR, against 4,181 and 4,309 MB on main. - Used minus free, textures included, came out the same in both builds (3,585 to 3,607 MB). The textures, which fill up to their 2,560 MB budget here, held 48 to 85 MB more in this PR's runs. - **The release line:** `vk: AMD FSR 3.1: not used for 120 frames (...): what it made and its images let go; the next upscale with it makes them again`, 8 to 9 s after leaving FSR 3.1 (about 15 fps) in all four runs. Main logs the same line. - **FSR 3.1 again:** the picture is right in all four runs, this PR's included: its images were made again (`vk: fsr3: 640x360 -> 1280x720`), and nothing is missing or garbled (pictures attached: before, with FSR 3.1, and FSR 3.1 again). - **Faults:** none (no crash, device lost or device fault). The kernel's amdgpu lines were only the display's "Losing delta precision while programming shaper LUT" notices, 6 a start. **Setup** - Steam Deck OLED: AMD Custom APU 0932 (RADV VANGOGH), 16 GB; Mesa 26.2.0-devel git-5c65d4fc31; SteamOS 3.9.5 (build 20261023.100), kernel 7.2.7-valve2. Game Mode, docked, stock clocks. - **Builds:** main 7ff5256e; main + this PR, its renderer built from the PR's head. Both for x86-64-v3 with the release play profile and LLVM 23.1.5. One test folder (warm caches) with the binaries swapped. - **Settings:** main's own defaults on this Deck, the options file its first start wrote. Quality preset Auto (this PC), output 1280x720, Render resolution 50%, the game's own upscaler, frame generation off, VRAM budget 2.2 GB. - **Steps, through the control bridge:** 1. Continue into Kokiri Forest, then 25 s standing. The `vk: VRAM:` line before is the last one logged by then. 2. Upscaler set to AMD FSR 3.1 through the menu's own setter. 10 s, then back to the game's own. 3. The `not used for 120 frames` line, then 5 s more, then the next `vk: VRAM:` line (logged every 600 frames). 4. FSR 3.1 again, 12 s, and a picture. - **Order:** main + #556, main, main, main + #556. ![t-uh7h-fsr31-crops.png](https://git.magicbean.dev/attachments/f0c46ccd-61c8-41fe-8bb8-7ab62792d50c) ![t-uh7h-sheet.png](https://git.magicbean.dev/attachments/a3adf963-b628-4393-a4c8-c43d9bb18e49)
zeldaootr force-pushed fsr3-release-frees-its-images from acd34022f2
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 5s
beanstalk/approval Test farm not requested
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
to 157d688bb1
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 15s
Website / Website on Cloudflare (pull_request_target) Has been skipped
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Guide screenshots / Guide images and local UI source review (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
Website / Website on Cloudflare (pull_request) Has been cancelled
2026-11-15 05:35:26 +00:00
Compare
Author
Contributor

Thank you, dukenheimer, for T-UH7H on the Steam Deck (#556 (comment)), with FSR 3.1 switched on and off in the game.

Rebased onto main 53f96d78 with no conflict: the test and fix commits are the same as before (git range-diff: 97223942 is now b5ec0f79, acd34022 is now 69fd56bd), and the run is added as docs/tested/2026-11-15-fsr3-release-dukenheimer-t-uh7h.md in a third commit, 157d688b. The description now ticks the rebase and docs/tested/ boxes.

Tests run again after the rebase: tests/test_fsr3_release_frees.py fails at b5ec0f79 (image 1 not freed) and passes at the tip (22 images freed), with g++ 13.3 and with clang 23.1.5. The full python3 -I -B tests/run_all.py on this branch: 531 passed, 15 failed, 48 skipped, the same 15 that fail on main 53f96d78 in the same run (named in the checklist). gpu/vk/vk_fsr3.cpp checked whole for Linux and Windows: the same warnings as main's, none new.

Why the Deck result still holds: main changed nothing in the lines this PR changes. Since the tested base 7ff5256e, main changed gpu/vk/vk_fsr3.cpp in one commit, b80a68f1 (PsychoV35 compatibility by default): a chain_hdr callback on the chain's engine, true only with HDR output and the PsychoV35 tone mapper, and a colour-format pair check at the start of fsr3_upscale. release(), free_dead, drop_image and the images this PR frees are untouched, and the tester's run had no HDR output, so neither change was on its path.

Thank you, dukenheimer, for T-UH7H on the Steam Deck (https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/556#issuecomment-22263), with FSR 3.1 switched on and off in the game. Rebased onto main 53f96d78 with no conflict: the test and fix commits are the same as before (`git range-diff`: 97223942 is now b5ec0f79, acd34022 is now 69fd56bd), and the run is added as `docs/tested/2026-11-15-fsr3-release-dukenheimer-t-uh7h.md` in a third commit, 157d688b. The description now ticks the rebase and `docs/tested/` boxes. Tests run again after the rebase: `tests/test_fsr3_release_frees.py` fails at b5ec0f79 (image 1 not freed) and passes at the tip (22 images freed), with g++ 13.3 and with clang 23.1.5. The full `python3 -I -B tests/run_all.py` on this branch: 531 passed, 15 failed, 48 skipped, the same 15 that fail on main 53f96d78 in the same run (named in the checklist). `gpu/vk/vk_fsr3.cpp` checked whole for Linux and Windows: the same warnings as main's, none new. Why the Deck result still holds: main changed nothing in the lines this PR changes. Since the tested base 7ff5256e, main changed `gpu/vk/vk_fsr3.cpp` in one commit, b80a68f1 (PsychoV35 compatibility by default): a `chain_hdr` callback on the chain's engine, true only with HDR output and the PsychoV35 tone mapper, and a colour-format pair check at the start of `fsr3_upscale`. `release()`, `free_dead`, `drop_image` and the images this PR frees are untouched, and the tester's run had no HDR output, so neither change was on its path.
zeldaootr changed title from WIP: fix(vk): FSR 3.1 frees its images once the chain lets it go, not at its next upscale to fix(vk): FSR 3.1 frees its images once the chain lets it go, not at its next upscale 2026-11-15 05:35:27 +00:00
zeldaootr force-pushed fsr3-release-frees-its-images from 157d688bb1
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 15s
Website / Website on Cloudflare (pull_request_target) Has been skipped
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Guide screenshots / Guide images and local UI source review (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
Website / Website on Cloudflare (pull_request) Has been cancelled
to 80f66c9b19
Some checks are pending
CI / Conventional Commit title (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Blocked by required conditions
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Blocked by required conditions
CI / Workflow lint (actionlint) (pull_request) Blocked by required conditions
Guide screenshots / Guide images and local UI source review (pull_request) Blocked by required conditions
Third-party parts / As their notes say (pull_request) Blocked by required conditions
Third-party parts / The same as upstream (pull_request) Blocked by required conditions
Website / Website on Cloudflare (pull_request) Blocked by required conditions
PR description / Description follows the template (pull_request_target) Successful in 4s
2026-11-15 17:11:38 +00:00
Compare
Author
Contributor

Rebased onto main aa95d35f (head 80f66c9b); the commits are re-authored with the forge's noreply address: no code change, the same patches by git patch-id.
Tests re-run on the new base, g++ 13.3 and clang 23.1.5: test_fsr3_release_frees fails at the test-only commit 93f9d02b (image 1 not freed) and passes at 6732e8b3; the 10 checks that are this PR's or read its files all pass. The Deck run (T-UH7H) stands; the description names the new commits.

Rebased onto `main` aa95d35f (head 80f66c9b); the commits are re-authored with the forge's noreply address: no code change, the same patches by `git patch-id`. Tests re-run on the new base, g++ 13.3 and clang 23.1.5: `test_fsr3_release_frees` fails at the test-only commit 93f9d02b (image 1 not freed) and passes at 6732e8b3; the 10 checks that are this PR's or read its files all pass. The Deck run (T-UH7H) stands; the description names the new commits.
Some checks are pending
CI / Conventional Commit title (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Blocked by required conditions
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Blocked by required conditions
CI / Workflow lint (actionlint) (pull_request) Blocked by required conditions
Guide screenshots / Guide images and local UI source review (pull_request) Blocked by required conditions
Third-party parts / As their notes say (pull_request) Blocked by required conditions
Third-party parts / The same as upstream (pull_request) Blocked by required conditions
Website / Website on Cloudflare (pull_request) Blocked by required conditions
PR description / Description follows the template (pull_request_target) Successful in 4s
This pull request doesn't have enough approvals yet. 0 of 1 approvals granted.
Some workflows are waiting to be reviewed.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u 'fsr3-release-frees-its-images:zeldaootr-fsr3-release-frees-its-images'
git switch 'zeldaootr-fsr3-release-frees-its-images'
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
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/Longshot!556
No description provided.