Skip to content

fix(vk): render BC targets through raw views, and stop leaving out OoT's noise volume pass - #1338

Merged
hckrman101 merged 3 commits into
NotRexed:mainfrom
Nitnek:fix/bc-raw-render-targets
Nov 10, 2026
Merged

hckrman101 merged 3 commits into
NotRexed:mainfrom
Nitnek:fix/bc-raw-render-targets

Conversation

@Nitnek

@Nitnek Nitnek commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

What this fixes

Trees lose their needles or leaves at mid distance, full again from far and near (#1151, part of #994).

OoT renders the slices of two 64³ BC4 noise volumes while an area loads (program 53509044401d78d2, 128 draws). Each slice is an RGBA16UI target with one texel per BC block. The foliage's two LODs crossfade with a dither read from that noise. In a spruce's fragment stages, the near LOD (68e4ed4beeba2155) fades out over a view depth of 34→65, and the far LOD (2ee91258acc43828) fades in over 32→60. Each fragment keeps the needle when alpha + fade + noise >= 0.5.

The volumes were always zero, so the crossfade became a hard cut on each side, and trees went bare in between:

  • 53509044401d78d2 is on RX_VK_SKIP_PROG's default list, because it lost the device on about half the first starts (7 of 14 in the comment there);
  • with it re-enabled, the replay still wrote nothing:
    • BC images had no colour attachment usage, so the raw views failed: view of texture 0x1133ccb000 (vk 139) as vk 95 type 1 ... not made, for every slice;
    • targets() sized the pass in texels (64×64) over a view that is 16×16 blocks.

Change

  • gpu/vk/vk_texture.cpp: BC images take COLOR_ATTACHMENT usage when the raw format supports it. 3D ones take it too, for their per-slice views.
  • gpu/vk/vk_draw.cpp:
    • targets() sizes raw views of BC targets in blocks;
    • the default skip list is empty. RX_VK_SKIP_PROG still takes keys.
  • tests/test_bc_raw_targets.py checks all three. It fails on main and passes here.

How it was tested

RTX 3070 8 GB, Windows 11.

  • The visible fix: the spruce near Lon Lon Ranch that went bare at mid distance keeps its needles.
  • How it was found:
    • bisected with RX_VK_SKIP_FILE to the two LOD programs;
    • fade ranges read from their c5 per draw;
    • F9 dump with RX_VK_DUMP_SAMPLED: the noise volume (#171, 0x1133ccb000) was all zero before. With the change, the pass writes it (RX_VK_WATCH_TEX: written, render area 16x16) and the needles stay.
  • The noise pass on load:
    • 12 starts with it running: 8 with a diagnostic build and 4 with this exact change, loading 6 different saves;
    • the noise was written every time;
    • 0 device lost. Before, the pass's own comment counts 7 losses in 14 first starts.
  • Test suite: tests/run_all.py (llvm-mingw) fails only on four tests that fail the same way on main: nup_read_name, nup_paths, fps_overlay_order, precompile_compute_guard.

Not tested: AMD and Intel, Linux. The usage is added only where the driver reports it for the raw format, as the storage usage next to it is.

No game data included.

🤖 Generated with Claude Code

…T's noise volume pass

OoT renders the slices of two 64^3 BC4 noise volumes while an area loads (program 53509044401d78d2, 128 draws), each
slice as an RGBA16UI target with one texel per BC block. Two things went wrong in the replay:

- BC images were made without colour attachment usage, so the raw attachment views were not made;
- targets() sized the pass in texels (64 x 64) over a view that is 16 x 16 blocks, a render area past the attachment.

The pass lost the device on about half the first starts, so it was put on RX_VK_SKIP_PROG's default list. Left out, the
volumes stayed zero. The foliage's two LODs crossfade with a dither read from that noise; with zero noise the crossfade
becomes a hard cut on each side, and trees go bare at mid distance, full again near and far (issue 1151, part of 994).

BC images now take COLOR_ATTACHMENT usage when the raw format supports it (3D ones too, for their per-slice views), raw
views of BC targets are sized in blocks, and the default skip list is empty (RX_VK_SKIP_PROG still takes keys).
tests/test_bc_raw_targets.py checks the three.

Assisted-by: Claude Code (Claude Opus 5.5)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Nitnek

Nitnek commented Nov 9, 2026

Copy link
Copy Markdown
Contributor Author

Note for reviewers: #1332 (@BiasedMonkey, opened just before this one) makes the same BC views and block-sized render area, found from the AMD side. It is enabled on RADV only, and it keeps 53509044401d78d2 on the default skip list. What this PR adds is the skip-list change, NVIDIA, and the link to #1151. Details in #1332 (comment). I'm fine with whichever of the two lands, as long as the noise pass runs.

…zed clears, noise pass only where its views are made

- A BC image the driver refuses is made again without COLOR_ATTACHMENT first, then without STORAGE. The usage query
  includes the 3D image's 2D_ARRAY_COMPATIBLE / 2D_VIEW_COMPATIBLE flags.
- clear_tex(): a clear through a raw view of a BC image is sized in blocks, with its rect converted and clamped.
- 53509044401d78d2 stays left out by default, but only while its targets have no view (the views could not be made).
  RX_VK_SKIP_PROG=- runs it anyway.
- tests/test_bc_raw_targets.py covers all three.

Assisted-by: Claude Code (Claude Opus 5.5)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Nitnek

Nitnek commented Nov 9, 2026

Copy link
Copy Markdown
Contributor Author

@hckrman101 thanks for the review. All three points are addressed in 5daa99c:

  1. Fallback:
  2. Skip list: 53509044401d78d2 stays left out by default, but only while its targets have no view, i.e. where the raw views could not be made. Where the driver takes the usage, the pass runs. RX_VK_SKIP_PROG=- still runs it anyway.
  3. clear_tex(): a clear through a raw view of a BC image is sized in blocks, with the rect converted to blocks and clamped.

tests/test_bc_raw_targets.py covers all three.

Re-tested on the RTX 3070 with the final build:

  • 5 starts, no env, the noise pass written every time, 0 device lost;
  • the volume read back as 23..247 (mean 135), where it was all 0 before;
  • the full run_all.py locally: only the four Windows-local failures that main has too.

I also posted NVIDIA results for #1332 there. I'm still fine with whichever of the two lands.

…x reads it for raw BC views)

Assisted-by: Claude Code (Claude Opus 5.5)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@blushOFF

Copy link
Copy Markdown
Contributor

Test results on another machine, merged on today's main (bbdc3704 + this PR), RTX 3070 8 GB, Windows 11, NVIDIA driver 610.88 as Vulkan reports it.

First starts with the noise pass on (the PR's default, empty skip list):

  • 6 starts, the first 2 with the program cache deleted: all 6 reached the game, 0 device lost, 0 not made in the log.
  • 53509044401d78d2 shows up in play in the first cold start's log.
  • The 83 failed programs on a cold-cache start are not from this PR: an earlier cold-cache start on a build without it had the same 83 (53 594 programs then, 53 595 here).

Kakariko entrance, scripted camera, 4 runs (with / without, then again), the "without" runs with RX_VK_SKIP_PROG=53509044401d78d2:

  • all 4 in game, 0 device lost;
  • no difference I can see in the trees there. I can't tell whether that view puts any spruce in the 34→65 range, so it says nothing about the crossfade either way.

A teleport tour of 26 areas on the same build (Kokiri Forest to Ganon's Castle, skipping 4 my teleport script doesn't handle): all in game, 0 device lost, 0 not made.

I didn't test the Lon Lon spruce or AMD/Intel.

@NotRexed

Copy link
Copy Markdown
Owner

This landed in the v2.0.12 branch (merged there for testing; it reaches main with that release), so closing. Thanks!

@NotRexed NotRexed closed this Nov 10, 2026
@NotRexed NotRexed mentioned this pull request Nov 10, 2026
3 tasks done
@NotRexed

Copy link
Copy Markdown
Owner

Reopened: closing this was a mistake on my side. It was tested in the v2.0.12 branch, and it will be merged into main here, so it shows as merged. Sorry for the noise.

@NotRexed NotRexed reopened this Nov 10, 2026
@hckrman101
hckrman101 merged commit 9d6936a into NotRexed:main Nov 10, 2026
19 checks passed
Joey-Magnus pushed a commit to Joey-Magnus/Hookshot that referenced this pull request Nov 10, 2026
…otRexed#1338): row removed

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Joey-Magnus pushed a commit to Joey-Magnus/Hookshot that referenced this pull request Nov 10, 2026
…otRexed#1338): row removed

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lbmeng added a commit to lbmeng/Hookshot that referenced this pull request Nov 11, 2026
The opening cutscene crashes on a GTX 1080 with driver 581.80
when the noise pass renders to a raw color view of a BC4 volume.
A standalone Vulkan probe reproduces device loss by clearing
the attachment without running any game shaders.

Load each compressed slice into an uncompressed attachment with
one texel per block, then copy the result back after rendering.
Use the same path for texture clears and preserve mip and slice
addressing, including partial blocks at the edges.

On the GTX 1080, the standalone probe read back all 16,384 blocks
correctly. Hookshot now recorded all 128 noise draws and reached
the Great Deku Tree and Navi dialogue without device loss. The full
Windows test suite had the same seven failures as the baseline.

Refs: NotRexed#996
Refs: NotRexed#1001
Refs: NotRexed#1338
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.

3 participants