Skip to content

vk: BC3 levels that halve evenly on AMD (the terrain grid in Hyrule Field) - #705

Merged
NotRexed merged 3 commits into
NotRexed:mainfrom
madebyjordan:amd/uneven-bc-levels
Nov 8, 2026
Merged

NotRexed merged 3 commits into
NotRexed:mainfrom
madebyjordan:amd/uneven-bc-levels

Conversation

@madebyjordan

@madebyjordan madebyjordan commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

What this fixes

On AMD, the terrain in Hyrule Field draws a grid of dark lines along its seams, worse in the distance.

AMD's drivers sample a BC level wrong when its block grid isn't level 0's halved. For example, 1365 texels are 342 blocks, but level 2 (341 texels) is 86 blocks, not 342 >> 2 = 85. The big ASTC textures kept as BC3 include Ocarina's terrain material arrays (1365 x 1365 x 90), which hit this. Lichii #448 found the same on an RX 6600 XT.

Change

On AMD, an ASTC texture that would be kept as BC3 with uneven block levels is now:

  • encoded at the nearest size whose blocks halve evenly down to its 16-texel levels (1365 -> 1536, 683 -> 768; 768 and 1536 stay), through a second scratch and a filtered blit;
  • given only the levels that halve evenly (the ones dropped are under 16 texels).

The game samples with normalized coordinates, so a resized level covers the same area. Copies into part of a resized texture, out of one, or into a level it left out are skipped and logged. When resizing would grow it by more than a quarter, or past the scratch, it stays RGBA8.

  • RX_VK_UNEVEN_BC=1: BC3 as before; =0: this on other cards too.
  • RX_VK_UNEVEN_RGBA8=1: RGBA8 instead of resizing.
  • gpu/vk/bc_levels.h holds the size maths; tests/test_bc_levels.py checks it (tests/run_all.py picks it up).

Tested

RX 6700 XT, Adrenalin 32.0.21045.16010, Windows 11:

  • Hyrule Field: the grid is gone, with no visible quality loss up close or in the distance.

  • Keeping these textures RGBA8 also removed the grid but used about 3 GB more VRAM. This path made 466 textures BC3 (256 resized, 210 with fewer levels, none RGBA8), about 2.1 GB less than RGBA8; the texture budget averaged 4.7 GB instead of 3.9 GB.

  • v2.0.2 with this change: a 20-minute run through Hyrule Field, the grid stayed gone. The log shows 846 textures taking this path (512 resized, 334 with fewer levels, none RGBA8), no copies skipped, and the texture budget held at its full 6 GB.

🤖 Generated with Claude Code

…ield)

AMD's drivers sample a BC level wrong when its block grid is not level 0's
halved. 1365 texels are 342 blocks, but level 2 (341 texels) is 86 blocks,
not 85. The big ASTC textures kept as BC3 include Ocarina's terrain material
arrays (1365 x 1365 x 90): on an RX 6700 XT they drew a grid of dark lines
along the terrain's seams, worse in the distance. Lichii NotRexed#448 found the same
on an RX 6600 XT.

On AMD such a texture is now encoded at the nearest size whose blocks halve
evenly down to its 16-texel levels (1365 -> 1536, 683 -> 768; 768 and 1536
stay), through a second scratch and a filtered blit, and keeps only the levels
that halve evenly. The game samples with normalized coordinates, so a resized
level covers the same area. Copies into part of a resized texture, out of one,
or into a level it left out are skipped and logged. When resizing would grow
it by more than a quarter, or past the scratch, it stays RGBA8.

Tested in Hyrule Field (RX 6700 XT, Adrenalin 32.0.21045.16010): the grid is
gone with no visible loss. Keeping them RGBA8 instead also removed it but
used about 3 GB more VRAM; this path made 466 textures BC3 (256 resized,
210 with fewer levels, none RGBA8), about 2.1 GB less than RGBA8, and the
texture budget averaged 4.7 GB instead of 3.9 GB.

RX_VK_UNEVEN_BC=1: BC3 as before; =0: this on other cards too.
RX_VK_UNEVEN_RGBA8=1: RGBA8 instead of resizing. tests/test_bc_levels.py
checks the sizes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@madebyjordan
madebyjordan marked this pull request as ready for review November 8, 2026 18:15
madebyjordan and others added 2 commits November 8, 2026 18:16
The workflow now runs every test through tests/run_all.py, which finds
tests/test_bc_levels.py by itself: took upstream's workflow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolves the conflict with NotRexed#585 (BC3 scratch made on demand, given back
when idle): the second scratch for resized textures now follows the same
lifecycle, made with the first when a resized upload needs it and given
back with it after RX_VK_BC_IDLE_S seconds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@NotRexed
NotRexed merged commit f2223df into NotRexed:main Nov 8, 2026
@NotRexed NotRexed mentioned this pull request Nov 8, 2026
3 tasks done
NotRexed pushed a commit that referenced this pull request Nov 9, 2026
… it fails or stalls

Players had no sound at all while every other program played ("no sound in 2.0.5", "Yo I dont have ANY SOUND"):
the output only ever opened WAVE_MAPPER, and a helper on Discord got one player's sound back by opening device 0.
Now HOS_AUDIO_DEVICE=<n> is tried first, then the default, then each device in turn; a device that takes no block
for 1.5 s is closed and the next candidate opened (at most 6 times a run). The log names the device and, 10 s in,
how many blocks it took and the loudest sample, so a log tells a silent game from a deaf device.

tests: the output fixture stubs the device count/name and the clock and gains a "stall" case;
test_mem_trim accepts bc_scratch_layout's second argument (#705 added it; CI failed on every PR since).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
NotRexed pushed a commit that referenced this pull request Nov 9, 2026
… time and rainbow ground on AMD

Issue 823's RX 6700 XT logs: v2.0.4 played at 10-13 ms of GPU time a frame, v2.0.5 at 70-100 ms, the only AMD
render change between them being #705 (the 1365 x 1365 x 90 terrain material arrays re-encoded at 1536 x 1536
with 8 of their 11 levels). AMD players also posted rainbow/iridescent ground and characters on v2.0.5.
RX_VK_UNEVEN_BC=0 turns it on (any card) for testing; by default BC3 is made as in v2.0.4 (the thin grid on
Hyrule Field's terrain seams comes back on AMD until the resize is fixed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rakefire-impala pushed a commit to rakefire-impala/Hookshot-w-Mesh-Shader-Fallback that referenced this pull request Nov 9, 2026
…s 7x GPU time and rainbow ground on AMD

Issue 823's RX 6700 XT logs: v2.0.4 played at 10-13 ms of GPU time a frame, v2.0.5 at 70-100 ms, the only AMD
render change between them being NotRexed#705 (the 1365 x 1365 x 90 terrain material arrays re-encoded at 1536 x 1536
with 8 of their 11 levels). AMD players also posted rainbow/iridescent ground and characters on v2.0.5.
RX_VK_UNEVEN_BC=0 turns it on (any card) for testing; by default BC3 is made as in v2.0.4 (the thin grid on
Hyrule Field's terrain seams comes back on AMD until the resize is fixed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit dc2f4dc)
sanchodecuba11-del added a commit to sanchodecuba11-del/Lichii that referenced this pull request Nov 10, 2026
…tead of keeping RGBA8

AMD drivers sample a BC level wrong when its 4x4 block grid is not level 0's halved (dark
lines on distant terrain, zortos293#448), so zortos293#679 keeps such ASTC textures as RGBA8, 4 to 8 times
larger than BC. In Ocarina of Time's Kokiri Forest that is 2,848 MiB, 1,705 MiB of it in two
1365x1365x90 terrain arrays, and a card that reports 6,500 MiB stays above the texture
cache's critical threshold.

Those textures now get a BC copy whose levels are all even: the same size without its tail
when the first uneven level is 32 texels or smaller (1536x1536 keeps 8 of 11 levels), else
the nearest larger size whose blocks halve evenly down to its last level of 16 texels or
more (1365 -> 1536, 683 -> 768), the size rule of NotRexed/Hookshot#705. The BC encoder resamples
the decoded level when the sizes differ. Copies into or out of a resized image are skipped
and logged. Shapes with no even shape keep the RGBA8 path.

Kokiri Forest cave, RX 9070 XT limited to 6,500 MiB, same MSVC build folder: 30.7 -> 37.3
fps on the route, 32.1 -> 42.2 fps on the camera turn, peak card memory 6,858 -> 5,210 MiB.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
kyc pushed a commit to kyc/Lichii that referenced this pull request Nov 10, 2026
…tead of keeping RGBA8

AMD drivers sample a BC level wrong when its 4x4 block grid is not level 0's halved (dark
lines on distant terrain, zortos293#448), so zortos293#679 keeps such ASTC textures as RGBA8, 4 to 8 times
larger than BC. In Ocarina of Time's Kokiri Forest that is 2,848 MiB, 1,705 MiB of it in two
1365x1365x90 terrain arrays, and a card that reports 6,500 MiB stays above the texture
cache's critical threshold.

Those textures now get a BC copy whose levels are all even: the same size without its tail
when the first uneven level is 32 texels or smaller (1536x1536 keeps 8 of 11 levels), else
the nearest larger size whose blocks halve evenly down to its last level of 16 texels or
more (1365 -> 1536, 683 -> 768), the size rule of NotRexed/Hookshot#705. The BC encoder resamples
the decoded level when the sizes differ. Copies into or out of a resized image are skipped
and logged. Shapes with no even shape keep the RGBA8 path.

Kokiri Forest cave, RX 9070 XT limited to 6,500 MiB, same MSVC build folder: 30.7 -> 37.3
fps on the route, 32.1 -> 42.2 fps on the camera turn, peak card memory 6,858 -> 5,210 MiB.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
@madebyjordan
madebyjordan deleted the amd/uneven-bc-levels branch November 10, 2026 21:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants