Repository navigation
fix(gfx): the empty-grid guard dropped every indirect compute dispatch (Ocarina of Time's grass, #2152) - #2190
Open
peachtaozhutou wants to merge 1 commit into
Conversation
…he empty-grid guard dropped every one of them The guard took the direct dispatches' zero grids before the dispatch's own indirect branch: Metal 4 rejects zero dimensions and BotW's ordinary loading path submits them. But nvnCommandBufferDispatchComputeIndirect records only the caller and the argument-buffer address (hle_nvn.c): its x/y/z are zero at record time by design, and their real values live in the 12 bytes the buffer holds. The guard therefore silently dropped every indirect compute dispatch before its arguments were ever read. Ocarina of Time generates its grass through indirect compute dispatches and lost its vegetation on the shared layer (ly05010419#2152: good at b0d2f35, bad at f9f7aa8, the window this guard came in with). With the guard restricted to direct dispatches the grass is back, verified on a MacBook Pro M4 Pro (macOS 27.2.1), same save and settings. An indirect dispatch whose argument buffer holds zeros still runs and does nothing, as it did on Ocarina of Time's own graphics layer before the merge.
This was referenced Nov 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
The shared layer's
dispatch()skips an empty grid before anything else:The guard is right for direct dispatches (Metal 4 rejects zero dimensions, and BotW's ordinary loading path submits them). But an indirect dispatch is recorded by
nvnCommandBufferDispatchComputeIndirect(hle_nvn.c) with only its caller and the argument-buffer address —x/y/zare zero at record time by design; the real grid lives in the 12 bytes the buffer holds. The guard therefore returned beforedp->indirectwas ever looked at, and every indirect compute dispatch was silently dropped — the exact class of failure hle_nvn.c's own comment warns about ("entries that would silently drop GPU work (indirect draws/dispatch …) were removed").The regression
This is #2152: Ocarina of Time's grass is generated through indirect compute dispatches, so Hyrule Field and Lon Lon Ranch lost their vegetation on the shared layer. The reported bisect (good
b0d2f353, badf9f7aa8d) is exactly the window this guard came in with. Ocarina of Time's own graphics layer had no such guard, and its indirect dispatches read their arguments and ran. Trees, characters and everything drawn through ordinary draws were unaffected, which is why the fields broke alone. The v28 mesh-output fix (#2166) did not touch this path and did not restore the grass.The fix
One condition:
if (!dp->indirect && (!dp->x || !dp->y || !dp->z)) return;. Direct zero grids keep being skipped; an indirect dispatch whose argument buffer holds zeros still runs and does nothing, as before.Verification
MacBook Pro (Mac16,8) M4 Pro 24 GB, macOS 27.2.1, Ocarina of Time v131072, same save and settings,
update_runtime.pyrebuild:Separately, this checkout also carries a local workaround for the pinned
.sha256format change of PR #2166 (#2184) — it is not part of this PR, which is the singlenvn_mtl.mhunk only.