Skip to content

The host reports the task / mesh draws it dropped while their pipeline was still being built - #1720

Open
crypt0dj wants to merge 1 commit into
seedds:mainfrom
crypt0dj:mtk-dropped-draws-report
Open

crypt0dj wants to merge 1 commit into
seedds:mainfrom
crypt0dj:mtk-dropped-draws-report

Conversation

@crypt0dj

@crypt0dj crypt0dj commented Nov 7, 2026

Copy link
Copy Markdown

What and why

mesh_tasks_draw leaves a draw out when mtk_pso returns nil, which it does until the background build of that pipeline finishes (dm/gfx/nvn/nvn_geometry.inc, "its draws are left out until it is ready"). The sibling geometry-mesh path counts and reports the same thing through mtl_geomesh_stats, but g_mtk_wait was only incremented, never read: nothing in the log said a frame was missing geometry, or how much of it. A whole-repo grep finds it at its declaration and its increment and nowhere else.

This adds mtl_mtk_stats and reports it beside the geometry mesh line, marked [RED] in the intervals that dropped a draw.

What it measured, on an M1 Max, Ocarina of Time 0400486024DEC000 v131072, chain 3ee52af3ca18:

frame 1200: 24432 draws, 222 dropped   [RED]
frame 1500: 21354 draws,   4 dropped   [RED]
frame 2700: 21493 draws,   2 dropped   [RED]
frame 3000 onwards:        0 dropped

That run built 62 task / mesh pipelines, each taking 57 ms to 5,356 ms. The window matches when this game's foliage shows white shapes after a load and when it stops: a depth pre-pass and a colour pass are separate pipelines and become ready at different times, so a pre-pass that is ready writes depth for geometry whose colour draw was dropped.

That those white pixels are these draws is not shown. DM_NVN_SKIP_MESH=1 cannot decide it — dropping both passes removes the depth write too, so the frame is simply short of foliage either way. Showing it needs the near-white share of shots taken inside the window (white.py in this game's work folder, which was not available on the test machine). The game note keeps it open.

Related, found on the way and not addressed here: mesh pipelines never look in the pipeline archive. nvn_geometry.inc:434 and :585 build straight on the device, while the other path tries g_arch4 / g_arch4p first, so these pipelines are rebuilt on every run and the window exists every time.

Game note: dm/games/0400486024DEC000/README.md, under Open. No reference entry: the mechanism is reported, not yet explained.

Checked

  • Tests: dm/tools/tests/test_docs.py (11), dm/tools/tests/test_nsp_chain.py (17), and the host builds (make -C dm/host GAME=0400486024DEC000)
  • Games run, with title ID and version: Ocarina of Time 0400486024DEC000 v131072, about 15 minutes on the Mac over a 5,100-frame run, reading the new log line against the task / mesh pipeline build times in the same log
  • Devices and OS: MacBook Pro M1 Max, macOS 27.0.1 (26A434), applegpu_g13s
  • No scripts/regress.py check --games report. This adds a log line and an accessor and changes no behaviour or code path. regress.py list on this machine shows three games, all baselines: none, green: never recorded, so a run would first have to build baseline and candidate shader trees — hours per game. Flagging it rather than omitting it; say the word if it should be run anyway.
  • Measurements before and after: not applicable, nothing here affects speed, memory or power

Docs

  • The finding is in its game note; python3 dm/tools/docs_symptoms.py was run (no change: no reference entry was added)
  • A chain tool changed: not applicable, the chain is untouched
  • No game files, keys or data extracted from a game in the change or the attachments

🤖 Generated with Claude Code

…e was still being built: Ocarina of Time drops 222 over the first 1,200 frames after a load, where its foliage shows white

mesh_tasks_draw leaves a draw out when mtk_pso returns nil, which it does until the background build of that
pipeline finishes (nvn_geometry.inc, "its draws are left out until it is ready"). The sibling path counted and
reported the same thing through mtl_geomesh_stats, but g_mtk_wait was only incremented, never read: nothing in
the log said a frame was missing geometry, or how much. It is now reported beside the geometry mesh line, marked
[RED] in the intervals that dropped a draw.

Measured on an M1 Max, Ocarina of Time 0400486024DEC000 v131072, chain 3ee52af3ca18: 222 draws dropped over the
first 1,200 frames, 4 by frame 1,500, 2 at a new area near frame 2,700, and 0 for the rest of a 5,100-frame run,
while that run's 62 task / mesh pipelines took 57 ms to 5,356 ms each to build. The window matches when the
foliage shows white after a load and when it stops; a depth pre-pass and a colour pass are separate pipelines and
become ready at different times, so a pre-pass that is ready writes depth for geometry whose colour draw was
dropped. That those pixels are these draws is not shown yet and the game note keeps it open.

Checked: the host builds, test_docs.py, test_nsp_chain.py. No regress.py check --games run: this adds a log line
and an accessor and changes no behaviour, and the harness has no baseline on this machine (regress.py list: three
games, none recorded), so building one would have cost hours of shader builds for a change with no code path.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@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
@crypt0dj

crypt0dj commented Nov 7, 2026

Copy link
Copy Markdown
Author

Correction and credit: the paragraph above about mesh pipelines bypassing the pipeline archive reads as a finding of this PR. It is not. #1583 already documents it, and its mesh_archive probe goes further than this PR does:

A mesh pipeline built through MTL4Compiler is stored in a Metal 4 archive and found again (0.18 ms, against a 36 ms build). The host builds mesh pipelines with newRenderPipelineStateWithMeshDescriptor, which bypasses the archive.

That settles the question this PR left open, that the fix is possible at all: MTL4Compiler does archive a mesh pipeline, so the bypass is the host's and not a Metal limit.

Two more things a reviewer may want beside this:

This PR still only reports the drops. Nothing here changes behaviour, and the fix is left for the work on the archive path.

Know-It-All-Brother added a commit to Know-It-All-Brother/nxnative that referenced this pull request Nov 9, 2026
…build-before-first-use a draw is dropped only when its pipeline fails, which is what g_mtk_wait now counts
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