WIP: fix(vk): the Anisotropic filtering row leaves images of one level alone, so no bright lines along edges #910

Draft
bvtterbrot wants to merge 1 commit from bvtterbrot/Longshot:fix/aniso-one-level into main
First-time contributor

Type: fix · Risk: low · Tested on: Windows 11, AMD Radeon RX 7900 XTX, driver 26.10.1 (in Slingshot, a fork with the same sampler code; game-free checks here) · Needs: Windows or Linux, an AMD card, Lon Lon Ranch or Hyrule Field on main with this change

Why

With Anisotropic filtering above "Game's" (the default is 16x), thin dashed bright lines run along edges: mountain
ridges against the sky, roofs, shelves, and across the ground at Lon Lon Ranch. Players work around it by setting the
row to "Game's", which also takes the ground's sharpness away. Fixes #834, fixes #293, see #308 (its first point).

How to reproduce

Seen on: Windows 11, AMD Radeon RX 7900 XTX, driver 26.10.1 (in Slingshot; reported here on an RX 9070 XT, an RX 7800 XT on CachyOS and an RX 6750 XT: #834, #308)
Settings and switches: Anisotropic filtering 16x (any value above "Game's")
Steps: Stand in Lon Lon Ranch's field, or in Hyrule Field facing the mountains, and look along the ridges and roof edges.
Expected: Clean edges, as with the row at "Game's".
Actual: Dashed bright lines along the edges, one or two pixels wide.

What changed

The row's anisotropy is no longer added to a sampler when the image bound with it has a single level. The game's own
anisotropy stays, and mipmapped textures keep the row's value, so the ground's sharpness is unchanged.

The cause: the row's value went to every sampler with mip filtering, also where the game reads back a picture it drew
itself. OoT composites its half-size fog and particle layer (program 1a7482c0ec9991ea) through such a sampler. Where
a 2x2 block of pixels crosses an object's edge, its texture coordinates lie far apart, and the anisotropic filter
takes texels along that whole span: from the sky behind a ridge into the ridge.

  • renderer: sampler_make() and sampler_for() in gpu/vk/vk_draw.cpp take one_level; with it the row's value is
    left out of the sampler and of its cache key. sampler_for()'s thread table has a second index for it.
    build_descriptors() passes tex && tex->levels <= 1.
  • tests: tests/sampler_admission_test.cpp and tests/test_sampler_admission.py take the new argument and add the
    case anisotropy-one-level.
  • docs: the README's note on the row; docs/worklist.md moves the row to Fixed.

Measurements

Verdict: Not measured in Longshot yet. In Slingshot, with the same change to the same code, the lines went: 180
bright edge pixels on one ridge before, 0 to 3 after, and the ground's detail at 16x was kept.

Hardware: Windows 11, AMD Radeon RX 7900 XTX, driver 26.10.1
Scene: Lon Lon Ranch, day; a fixed camera from a save, headless, Anisotropic filtering 16x
Method: a frame saved before and after (RX_VK_SHOTS), bright pixels counted along one ridge by a script; RX_VK_ANISO=0 as the control (lines gone, ground blurred)
How to reproduce: the steps above, with the row at 16x and at "Game's"

Flags and settings

None new. The Anisotropic filtering row and RX_VK_ANISO no longer reach samplers bound with an image of one level.

Testing

Tested: The game-free checks on Windows 11: tests/test_sampler_admission.py passes with the new case. The whole
run (python -I -B tests/run_all.py --jobs 8, with the Vulkan headers): 561 passed, 20 failed, 42 skipped; the same
20 fail on main @ f637b42 on this PC (test_appimage_player_build, test_auto_handheld, test_cpp_preflight,
test_crash_dialog, test_crt_options, test_env_on, test_fpx_sticky, test_lift_cleanup_error, test_linux_preflight,
test_make_game_cache, test_make_game_prepare, test_missing_nup, test_oot_state_tap, test_options_budget_once,
test_readback_late, test_spawn_emit, test_tested_configurations, test_vk_occlusion_queries, test_vk_pgo,
test_walk_key). In the game: in Slingshot only (see Measurements), where it has been played since.

Not tested: Longshot built with this change, in the game. NVIDIA and Intel cards. Linux.

Must be tested:

  • Windows or Linux, an AMD card (amd, radv): Lon Lon Ranch's field and Hyrule Field facing the mountains with Anisotropic filtering at 16x, expecting no dashed bright lines along ridges and roofs and the ground as sharp as before (by hand: the same spot on main and on this branch, a screenshot each).
  • Windows or Linux, an NVIDIA or Intel card: the same spots at 16x, expecting no change from main (by hand: a screenshot each).

Risks

What could break: A single-level texture that is not a picture the game drew (a small texture without mipmaps)
no longer gets the row's anisotropy; it keeps the game's. With one level there is nothing sharper to pick, so the
difference should not show.

Turning it off: Revert the commit; "Game's" on the row behaves as before.

Compatibility: Nothing changes for saves, longshot_options.ini, the shader and pipeline caches or the vk ABI.

Issues

Fixes #834
Fixes #293
See #308

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. (measured in Slingshot, not yet in Longshot)
  • Testing names what was tested, what wasn't, and what must still be tested, where and how.
  • Rebased on current main.
  • python -I -B tests/run_all.py passes (any failure that also fails on main is named).
  • 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.
  • Screenshots of the same spot, captioned like the Measurements columns, for a change that shows on screen. (to come with the run in Longshot)
  • A game-free test added for the fix, failing on main and passing here.
  • A check under tests/ that reads changed source updated in this PR, not weakened.
  • Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. (the changed functions compile in the sampler check on Windows; the game was not built with it yet)
  • Docs updated.

🤖 Generated with Claude Code

**Type:** fix · **Risk:** low · **Tested on:** Windows 11, AMD Radeon RX 7900 XTX, driver 26.10.1 (in Slingshot, a fork with the same sampler code; game-free checks here) · **Needs:** Windows or Linux, an AMD card, Lon Lon Ranch or Hyrule Field on `main` with this change ## Why With Anisotropic filtering above "Game's" (the default is 16x), thin dashed bright lines run along edges: mountain ridges against the sky, roofs, shelves, and across the ground at Lon Lon Ranch. Players work around it by setting the row to "Game's", which also takes the ground's sharpness away. Fixes #834, fixes #293, see #308 (its first point). ## How to reproduce **Seen on:** Windows 11, AMD Radeon RX 7900 XTX, driver 26.10.1 (in Slingshot; reported here on an RX 9070 XT, an RX 7800 XT on CachyOS and an RX 6750 XT: #834, #308) **Settings and switches:** Anisotropic filtering 16x (any value above "Game's") **Steps:** Stand in Lon Lon Ranch's field, or in Hyrule Field facing the mountains, and look along the ridges and roof edges. **Expected:** Clean edges, as with the row at "Game's". **Actual:** Dashed bright lines along the edges, one or two pixels wide. ## What changed The row's anisotropy is no longer added to a sampler when the image bound with it has a single level. The game's own anisotropy stays, and mipmapped textures keep the row's value, so the ground's sharpness is unchanged. The cause: the row's value went to every sampler with mip filtering, also where the game reads back a picture it drew itself. OoT composites its half-size fog and particle layer (program `1a7482c0ec9991ea`) through such a sampler. Where a 2x2 block of pixels crosses an object's edge, its texture coordinates lie far apart, and the anisotropic filter takes texels along that whole span: from the sky behind a ridge into the ridge. - renderer: `sampler_make()` and `sampler_for()` in `gpu/vk/vk_draw.cpp` take `one_level`; with it the row's value is left out of the sampler and of its cache key. `sampler_for()`'s thread table has a second index for it. `build_descriptors()` passes `tex && tex->levels <= 1`. - tests: `tests/sampler_admission_test.cpp` and `tests/test_sampler_admission.py` take the new argument and add the case `anisotropy-one-level`. - docs: the README's note on the row; `docs/worklist.md` moves the row to Fixed. ## Measurements **Verdict:** Not measured in Longshot yet. In Slingshot, with the same change to the same code, the lines went: 180 bright edge pixels on one ridge before, 0 to 3 after, and the ground's detail at 16x was kept. Hardware: Windows 11, AMD Radeon RX 7900 XTX, driver 26.10.1 Scene: Lon Lon Ranch, day; a fixed camera from a save, headless, Anisotropic filtering 16x Method: a frame saved before and after (`RX_VK_SHOTS`), bright pixels counted along one ridge by a script; `RX_VK_ANISO=0` as the control (lines gone, ground blurred) How to reproduce: the steps above, with the row at 16x and at "Game's" ### Flags and settings None new. The Anisotropic filtering row and `RX_VK_ANISO` no longer reach samplers bound with an image of one level. ## Testing **Tested:** The game-free checks on Windows 11: `tests/test_sampler_admission.py` passes with the new case. The whole run (`python -I -B tests/run_all.py --jobs 8`, with the Vulkan headers): 561 passed, 20 failed, 42 skipped; the same 20 fail on `main` @ f637b42 on this PC (test_appimage_player_build, test_auto_handheld, test_cpp_preflight, test_crash_dialog, test_crt_options, test_env_on, test_fpx_sticky, test_lift_cleanup_error, test_linux_preflight, test_make_game_cache, test_make_game_prepare, test_missing_nup, test_oot_state_tap, test_options_budget_once, test_readback_late, test_spawn_emit, test_tested_configurations, test_vk_occlusion_queries, test_vk_pgo, test_walk_key). In the game: in Slingshot only (see Measurements), where it has been played since. **Not tested:** Longshot built with this change, in the game. NVIDIA and Intel cards. Linux. **Must be tested:** - Windows or Linux, an AMD card (amd, radv): Lon Lon Ranch's field and Hyrule Field facing the mountains with Anisotropic filtering at 16x, expecting no dashed bright lines along ridges and roofs and the ground as sharp as before (by hand: the same spot on `main` and on this branch, a screenshot each). - Windows or Linux, an NVIDIA or Intel card: the same spots at 16x, expecting no change from `main` (by hand: a screenshot each). ## Risks **What could break:** A single-level texture that is not a picture the game drew (a small texture without mipmaps) no longer gets the row's anisotropy; it keeps the game's. With one level there is nothing sharper to pick, so the difference should not show. **Turning it off:** Revert the commit; "Game's" on the row behaves as before. **Compatibility:** Nothing changes for saves, `longshot_options.ini`, the shader and pipeline caches or the vk ABI. ## Issues Fixes #834 Fixes #293 See #308 ## 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). - [ ] Measurements has a verdict, or one line saying why there is nothing to measure. (measured in Slingshot, not yet in Longshot) - [x] Testing names what was tested, what wasn't, and what must still be tested, where and how. - [x] Rebased on current `main`. - [x] `python -I -B tests/run_all.py` passes (any failure that also fails on `main` is named). - [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. - [ ] Screenshots of the same spot, captioned like the Measurements columns, for a change that shows on screen. (to come with the run in Longshot) - [x] A game-free test added for the fix, failing on `main` and passing here. - [x] A check under `tests/` that reads changed source updated in this PR, not weakened. - [ ] Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. (the changed functions compile in the sampler check on Windows; the game was not built with it yet) - [x] Docs updated. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(vk): the Anisotropic filtering row leaves images of one level alone, so no bright lines along edges
Some checks failed
Website / Website on Cloudflare (pull_request_target) Has been skipped
PR description / Description follows the template (pull_request_target) Has been cancelled
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
b8959c5a40
The row's anisotropy (16x by default) went to every sampler with mip filtering, also where the game reads back a
picture it drew itself. OoT composites its half-size fog and particle layer (program 1a7482c0ec9991ea) through such a
sampler; where a 2x2 block of pixels crosses an object's edge its texture coordinates lie far apart, and the
anisotropic filter took texels along that whole span: dashed bright lines along mountain ridges, roofs and shelves
(#834, #293, #308's first point).

sampler_make and sampler_for take whether the bound image has one level; then only the game's own anisotropy applies,
and the row's value is not part of the sampler's key. Mipmapped textures keep the row's value.

Ported from Slingshot, where it was reproduced headless on an RX 7900 XTX at Lon Lon Ranch: 180 bright edge pixels on
one ridge before, 0 to 3 after, with the ground's detail at 16x kept. Not yet played in Longshot.

Co-Authored-By: Claude Fable 5.2 <[email protected]>
bvtterbrot force-pushed fix/aniso-one-level from b8959c5a40
Some checks failed
Website / Website on Cloudflare (pull_request_target) Has been skipped
PR description / Description follows the template (pull_request_target) Has been cancelled
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
to 29ed5fb9b2
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
PR description / Description follows the template (pull_request_target) Successful in 3s
Website / Website on Cloudflare (pull_request_target) Has been skipped
2026-11-15 20:15:38 +00:00
Compare
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
PR description / Description follows the template (pull_request_target) Successful in 3s
Website / Website on Cloudflare (pull_request_target) Has been skipped
This pull request is marked as a work in progress.
Some workflows are waiting to be reviewed.
This branch is out-of-date with the base branch
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u 'fix/aniso-one-level:bvtterbrot-fix/aniso-one-level'
git switch 'bvtterbrot-fix/aniso-one-level'
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/Longshot!910
No description provided.