Repository navigation
Conversation
…ommit, as sub_cut and mtl_sub_commit do: blocks encoded before an indirect-count multi-draw's count wait no longer reach the GPU with a pool table that lacks pools made since they were encoded (the window 339d9f2, PR seedds#1427, closed for whole and segment commits), nor have their words rewritten after the GPU ran them. mdi_wait ends the render pass and commits the main command buffer in the middle of a submission (endCommandBuffer, rec_commit) so it can wait for the GPU and read on the CPU what the GPU wrote: a multi-draw's count, a geometry draw's indirect record, an indirect dispatch's grid (tg_spill), or memory for DM_NVN_UBP_CHECK. It did not call gmem_commit_patch(), so the table words of that command buffer's argument blocks (gmem_slot_note) stayed as they were encoded: a pool made between their encode and this commit was missing from the table the GPU searched there, and a raw read of it got 0. The words also stayed in the noted list, so the next commit (a segment or the end of the submission) rewrote them after the GPU had already run those blocks, and moved their write logs (NvGmlLog) to a table their bits were not taken against. gmem_commit_patch() now runs after up_flush() and before res_commit() / endCommandBuffer, where sub_cut has it. It clears the noted list, so the next commit patches only the blocks encoded after the wait. t_gmem_words gets the case: a word that holds the table from before a pool was made, then mdi_wait(), points at a table that holds that pool, and no word is left noted after it. The reference entry (Raw pool table words that predate the pools) and the comment above NvGmlLog name the count wait's commit. Found by reading the code, not seen in a game. Checked: t_gmem_words 18 checks, 2 failed (the two new ones) with only the new case and 18, 0 failed with the nvn_mtl.m change (5 runs); make -C dm/gfx/tests GAME=0400486024DEC000 run, 135 of 136 tests pass (among them t_large_mdi, t_geometry and t_tg_spill, which also reach mdi_wait), and the other, t_feedback's "with nothing running: a commit", which does not reach mdi_wait, fails now and then on unmodified main too (3 of 6 runs on main, 4 of 6 here); test_docs; the Mac host builds (make -C dm/host GAME=0400486024DEC000 dmhost). Not run: a game that reaches mdi_wait (Ocarina of Time logs no indirect-count multi-draw wait), regress.py, lint_c.py (no clang-tidy here), iOS
Aznracer
pushed a commit
to Aznracer/Mighty-Green-Kokiri-Kid
that referenced
this pull request
Nov 11, 2026
…ommit (PR seedds#2330) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGrCTWig49u9S8ZCH37TUc
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.
What and why
mdi_wait(dm/gfx/nvn/nvn_mtl.m:13371) ends the render pass and commits the main command buffer in the middle of a submission, then waits for the GPU so the replay can read on the CPU what the GPU wrote: an indirect-count multi-draw's count, a geometry draw's indirect record, an indirect dispatch's grid when its threadgroup memory spills (tg_spill), or memory forDM_NVN_UBP_CHECK. The other two commits ofg_cb,mtl_sub_commit(2390) andsub_cut(15004), callgmem_commit_patch()before they end the command buffer.mdi_waitdoesn't (13374 goes straight fromup_flush()tores_commit()).So the window that 339d9f2 (PR #1427) closed for whole and segment commits is still open at this one:
NvGmlLog) to the newer table, sogml_readdecodes bits the shader set against the old table against the new one.The fix is the same call in the same place as
sub_cut:gmem_commit_patch()afterup_flush()and beforeres_commit()/endCommandBuffer. It clears the noted list, so the next commit only patches blocks encoded after the wait. In the host that's the one call and its comment, plus the comment aboveNvGmlLog, which now lists the count wait's commit too.I found this by reading the code, not in a game. Ocarina of Time, the game I play, never reaches
mdi_wait(no "indirect-count multi-draw" line in its logs), so this is for games that do. Going by docs/reference/rendering.md, those are geometry draws that can't be masked on the GPU (Donkey Kong Bananza as a level opens) and draws that need a CPU count (quads, fans, 8-bit indices).Overlaps:
mdi_wait: it addsif (g_tf_enc) tf_pass_end();at the top and right afterup_flush(); res_commit();. Itsmdi_waithunk no longer applies on top of this change. In a merge only its second line conflicts. To resolve it, keepup_flush();,gmem_commit_patch();andres_commit();from here, then itstf_pass_end(), the order it already uses insub_cut.gmem_segment_commit(), which callsgmem_commit_patch(), runs inmdi_waitbetweenup_flush()andres_commit().gmem_commit_patchandt_gmem_words. It changestable_hasto take the pool pointer and dropsa, so whichever of the two goes in second needs the new check written astable_has(w8, mem + 48 * MB). Under itsmtl_gva_onmode,gmem_commit_patchis also where the pools are made resident before a commit, so with both in, the count wait's commit does that too.Checked
t_gmem_wordswith the new case (a word that holds the table from before a pool was made, thenmdi_wait(), must point at a table that holds that pool, and no word may be left noted after it): with only the test change, 18 checks, 2 failed (the two new ones). With the fix, 18 checks, 0 failed, 5 runs in a row.make -C dm/gfx/tests GAME=0400486024DEC000 run: 135 of 136 tests pass. Among them aret_large_mdi,t_geometryandt_tg_spill, which also go throughmdi_wait. They don't use the raw pool table, so they only show that nothing else broke. The other one,t_feedback, fails its check "with nothing running: a commit" now and then, on an unmodified export of main too (3 of 6 runs on main, 4 of 6 with this change). It doesn't reachmdi_wait.python3 -m unittest dm/tools/tests/test_docs.py: 6 tests, OK. I ranpython3 dm/tools/docs_symptoms.py, and the symptom index doesn't change (only the entry's Fix and Check lines did).make -C dm/host GAME=0400486024DEC000 dmhost.mdi_wait. The same change has been in my own fork's builds since November 8. That's where I play Ocarina, so it never runs there either.regress.py: not run. Only Ocarina of Time is built here, and it doesn't reach this path, so a report from it couldn't show anything. The change only does something when a submission reachesmdi_waitwith words noted since the last commit.lint_c.py(no clang-tidy on this machine), iOS.Docs
docs/reference/<subsystem>.mdentry, andpython3 dm/tools/docs_symptoms.pywas run (the symptom index): the Fix and Check lines of "Raw pool table words that predate the pools" in docs/reference/shaders.md now name the count wait's commitdmsh_chain.py --headerwas run anddm/gfx/nvn/dmsh_chain.his part of the change (no chain tool changed)