Skip to content

A texture ID with no texture drops its cached view: nil == nil kept a released texture on the pool tables' fast path (GPU page faults) - #1607

Closed
nafields wants to merge 1 commit into
seedds:mainfrom
nafields:tex-nil-view
Closed

nafields wants to merge 1 commit into
seedds:mainfrom
nafields:tex-nil-view

Conversation

@nafields

@nafields nafields commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

What and why

Symptom. With DM_NVN_RT_RECLAIM=1 (#1588), Ocarina of Time's command buffers failed with a GPU page fault at f3,677 and f4,851 in every run. The faults are in compute shader 9e6b00b050e30801, which samples through the texture pool.

Cause. tex_by_id's slow path (nvn_mtl.m) keeps an ID's cached view when cur == v || v.parentTexture == cur, with cur = treg_tex(rp).

With the reclaim on, this happened about 60 times in a 5,000-frame run. It's main's code, not the reclaim's: main reaches the same nil whenever an ID's texture goes and isn't made again.

Change. The cached view is kept only when cur is non-nil. An ID with no texture drops its view, and its slot takes the typed zero texture an empty slot of that type gets.

Reference entry: A texture ID with no texture kept its cached view. The Ocarina note has a line for it.

Checked

  • Game: Ocarina of Time (0400486024DEC000, v131072), M2 Pro 16 GB, reclaim on:

    Run Faults Pace
    Before, to f7,731 f787, f3,677, f4,851 7,731 frames in 202.75 s
    Fix, to f5,241, every texture the reclaim's trim released marked f786 only; none handed back —
    Fix, clean, to f7,750 f786 only 7,750 frames in 202.5 s
    • The fault at f786 has another cause and happens with the reclaim off too.
    • Reclaim counts were alike: 45,045 reclaimed and 30,833 dead-ID reads, against 45,895 and 30,525.
    • The picture wasn't compared: a dead ID now reads the typed zero texture instead of the released one.
  • How it was found:

  • Tests: make -C dm/host GAME=0400486024DEC000; make -C dm/host/tests GAME=0400486024DEC000 -j run; check_t_alias_takeover (28, 0 failed); check_t_image_alias (329, 0 failed); test_docs.py; docs_symptoms.py.

  • Not run: scripts/regress.py check, since only Ocarina of Time is available here. Without the reclaim the path is rare, but this change reaches every game whose texture IDs outlive their textures.

Docs

  • The finding is in docs/reference/rendering.md and the game note, and python3 dm/tools/docs_symptoms.py was run
  • No chain tool changed
  • No game files, keys or data extracted from a game in the change or the attachments

@github-actions github-actions Bot added nvn NVN on Metal and its tests (dm/gfx/nvn, dm/gfx/tests) docs Documentation game: 0400486024DEC000 A game labels Nov 7, 2026
cheemu21 pushed a commit to cheemu21/kid-with-sword-remake that referenced this pull request Nov 7, 2026
… released texture on the pool tables' fast path, and the GPU page-faulted on it (PR seedds#1607)

(cherry picked from commit 4a678a3)
cfryerdev pushed a commit to cfryerdev/nxnative that referenced this pull request Nov 7, 2026
…il cached view, on the test stack

seedds#1604 uncompressed textures are taken from their storage unless the GPU
wrote that storage, by address range, not their pool: the terrain no
longer opens holes after walking a distance (streamed tiles came out
zero once any texture in their pool had been a render target; the
260x260 tera_tile special case goes with it). Hand-merged with the
stack's own ownership code: serial GPU writes (seedds#1558) and the BC
render-target shadows (seedds#1590) stay; the image bind records the range
through mtl_tex_gpu_written beside them; mtl_pool_gpu_written is gone
with its last caller.

seedds#1607 a texture ID with no texture drops its cached view: nil == nil
kept a released texture valid on the pool tables' fast path, and the
fast paths gave the shaders its resource ID after the host had released
it (GPU page faults). The nil guard keeps the alias-view parent match.

Tested in game on an M3 Max: a walk between areas holds the ground
whole, no page faults, no regression of the earlier fixes (upscaler
lines, load-time holes, stutters).

Front-ends: host change only, chain unchanged (2027aa29b1b7).
… released texture on the pool tables' fast path, and the GPU page-faulted on it

Symptom: with DM_NVN_RT_RECLAIM=1 (PR 1588), Ocarina of Time's command buffers failed with a GPU page fault at f3,677 and f4,851 in every run, in compute shader 9e6b00b050e30801, which samples through the texture pool.
Cause: tex_by_id's slow path keeps an ID's cached view when cur == v || v.parentTexture == cur, where cur = treg_tex(rp). treg_tex is nil when the ID has no texture now: a texture gone and not made again, one that could not be made, or a reclaimed render target's dead read. A cached view that is the base texture has no parent either, so nil == nil kept it and stamped it valid. tex_fast_rid then gave the pool tables its resource ID after the host had released it and dropped its residency. With the reclaim it happened about 60 times in a 5,000-frame run.
Fix: the cached view is kept only when cur is non-nil. An ID with no texture drops its view, and its slot takes the typed zero texture an empty slot of that type gets. This holds without the reclaim too, whenever an ID's texture goes.
Checked: Ocarina of Time on an M2 Pro 16 GB with the reclaim on, to f5,241 and f7,750. The f3,677 and f4,851 faults are gone, and marking every texture the reclaim's trim released found none handed back. Pace was the same (7,750 frames in 202.5 s against 7,731 in 202.75 s). A fault at f786 has another cause and remains without the reclaim. The picture was not compared. Host build, host tests, t_alias_takeover (28), t_image_alias (329) and test_docs pass. regress.py check was not run (only Ocarina of Time is available here).
john62036203-ops added a commit to john62036203-ops/NXNativeWindows that referenced this pull request Nov 7, 2026
…rom cheemu21/kid-with-sword-remake 5bb8653)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013SzykpcKm2eZPvPjGPKx1C
seedds added a commit that referenced this pull request Nov 7, 2026
… released texture on the pool tables' fast path (GPU page faults) (PR #1607)

tex_by_id kept an ID's cached view when cur == v || v.parentTexture == cur. When the ID has no texture now, treg_tex returns nil, and a cached view that is the base texture has no parent either, so nil == nil kept it and stamped it valid; tex_fast_rid then gave the pool tables a released texture's resource ID. The view is kept only when cur is non-nil. Ocarina of Time with PR #1588's reclaim: the faults at f3,677 and f4,851 are gone. An A/B walk on main reached the path zero times, with the same red lines and pace.

Co-authored-by: nafields <2613057+nafields@users.noreply.github.com>
@seedds

seedds commented Nov 7, 2026

Copy link
Copy Markdown
Owner

Landed unchanged as 0e4480d, with you as co-author. Thanks: the nil == nil diagnosis was exact.

Checked on main with Ocarina of Time (v131072): an A/B walk from a save through the village reached the path zero times, with the same red lines and pace as before. So on main the fix matters only when a texture ID outlives its texture, as you said. The faults it removes are the ones you showed with #1588's reclaim. The host tests pass.

@seedds seedds closed this Nov 7, 2026
Know-It-All-Brother pushed a commit to Know-It-All-Brother/nxnative that referenced this pull request Nov 9, 2026
… released texture on the pool tables' fast path (GPU page faults) (PR seedds#1607)

tex_by_id kept an ID's cached view when cur == v || v.parentTexture == cur. When the ID has no texture now, treg_tex returns nil, and a cached view that is the base texture has no parent either, so nil == nil kept it and stamped it valid; tex_fast_rid then gave the pool tables a released texture's resource ID. The view is kept only when cur is non-nil. Ocarina of Time with PR seedds#1588's reclaim: the faults at f3,677 and f4,851 are gone. An A/B walk on main reached the path zero times, with the same red lines and pace.

Co-authored-by: nafields <2613057+nafields@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation game: 0400486024DEC000 A game nvn NVN on Metal and its tests (dm/gfx/nvn, dm/gfx/tests)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants