Repository navigation
Conversation
…raw shader was encoded no longer reads 0 An argument block holds the pool table that was current when it was encoded. A pool made after that, later in the submission or on another thread while it is encoded, is not in it, and a raw read of that pool gets 0, the failure that hung agl's task shaders. On the author's stack, loading Ocarina of Time's outdoor save, 5,729 of 154,107 table words in argument buffers held an older table than the current one by frame 5,100, and 2,582 held the current one behind the pools. As seedds#1407 does in its stack, the words are noted as they are encoded (gmem_slot_note) and rewritten at each commit, whole or segment (gmem_commit_patch), before the GPU can read them. A new table is built when the pools changed, not refilled in place, as earlier segments may be reading the old one; the replaced one goes through the deferred release as before. The write log of these blocks lists pages, not table entries, so it needs nothing here. The memory report prints the words, those that held an older table and those that held the current one behind the pools. Whether this is what is left of the hang in seedds#1326, minutes after a clean table growth, is open: nothing here reproduced it. t_gmem_words, 13 checks: an unchanged table leaves the words alone; a pool made after two words were noted is in the table they are pointed at, and a new table was built; an older table and one that lags the pools are rewritten and counted; a commit with no words changes nothing. With the rewrite removed, 2 checks fail. t_pool_chunks 75 checks pass; test_docs, test_gfx_tests_makefile, test_env_switches, docs_symptoms.py --check; lint_c.py tidy on nvn_mtl.m and t_gmem_words.m: 0 file/check pairs above the baseline.
1 task done
3 tasks done
table_has walked DMSH_GMEM_MAP_ENTRIES entries. A table that grows with its pools (seedds#1360) has more, and a pool past entry 4,095 would not have been found. It walks the buffer's length now, which is the same 4,096 entries on main. Pointed out by deanpektas27 on seedds#1360. Checked: check_t_gmem_words, 13 checks, 0 failed.
gnosticgeek
pushed a commit
to gnosticgeek/nxforge
that referenced
this pull request
Nov 6, 2026
…rina of Time, with the reasons Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016qteK29T18U8p1c9LsVY8g
…ollows its table at the commit Main's b1d7c70 made the raw write log a bitmap of the table's entries and read it against the table captured when the log was taken (gml_take). The commit-time repointing of a block's table word (gmem_commit_patch) then made the shader write bits of the newer table while gml_read decoded them against the older one. NvGmlLog keeps a log with its table, the slot note carries the log, the commit patch updates it, and encode_args takes the table for both slots once (raw_map), as a pool coming in between the two slots would otherwise give them different tables. t_gmem_words follows: the slot signature, its pools are addressed (main lists only those), and a new check that the log's table moves with the word. Checked: check_t_gmem_words (16 checks, 0 failed), check_t_pool_chunks, test_docs.py, docs_symptoms.py --check, with GAME=01007EF00011E000.
seedds
added a commit
that referenced
this pull request
Nov 6, 2026
…etween a raw shader's encode and its command buffer's commit is no longer missing from the table the GPU reads, where its loads read 0 (PR #1427) An argument block held the address of the raw pool table that was current when it was encoded (gmem_map_gpu). A pool made after that, on another thread while the submission was encoded, was not in that table, though the GPU reads the block only after the commit, as NVN's GPU reads memory when it runs. Raw reads of that pool read 0: the failure that hung agl's task shaders in Ocarina of Time. The table words are noted as they are encoded (gmem_slot_note) and, at each commit of the command buffer, whole or segment (mtl_sub_commit, sub_cut), pointed at a table of the pools as they are then (gmem_commit_patch). A new table is built when the pools changed, not refilled in place, as earlier segments may be reading the old one. A block's write log follows its table (NvGmlLog), so gml_read decodes its bits against the table the shader searched. The memory report counts the words and those that were out of date (raw pool table words at commit). The idea of rewriting the words at commit is from #1407 (@uncraftablexd). On the author's stack, loading Ocarina of Time's outdoor save, 5,729 of 154,107 words held an older table by frame 5,100 and 2,582 held the current one behind the pools. Whether this window is behind issue #1326's page faults is open: an address the table misses is skipped, not faulted, and the pools near the M1 Max faults were made 8-41 s before them. Checked: t_gmem_words 16 checks, 0 failed; t_pool_chunks 102, 0 failed; test_docs, test_gfx_tests_makefile, docs_symptoms --check. Donkey Kong Bananza (raw stores and the write log), hosts at 6d928fd with and without this (the build's libraries are chain cfcc3a82c78b), fresh save into the mining tunnel, 210 s each on an M6: no GPU error on either, the same 4 VP9 red lines, frame p50 16.66 ms on both, 23 long-frame lines each; the patch rewrote 1 of 6,035 words. Co-authored-by: Pedro Nascimento <91118+lunks@users.noreply.github.com>
Owner
|
Landed on main as 339d9f2 with your code unchanged, credited with Co-authored-by, and #1407 named for the idea. Thank you. Checks: t_gmem_words 16 checks and t_pool_chunks 102, 0 failed. Donkey Kong Bananza (raw stores and the write log) A/B on an M6, fresh save into the mining tunnel, 210 s each: no GPU error, the same red lines and frame times with and without it; it rewrote 1 of 6,035 words there. #1326 stays open: whether this window is behind its page faults is open (a missed address is skipped, not faulted, and the pools near the M1 Max faults were 8-41 s old). mbanusic's M1 Max run with it will tell. |
Aeonitis
pushed a commit
to Aeonitis/nxnative
that referenced
this pull request
Nov 6, 2026
…er and shader chain, the branch's host services, movie clock, packing and Ocarina of Time additions Upstream reached about 60 fps in Kokiri Forest with its own versions of most of the branch's merged PRs, so where both changed the same code upstream's is kept: - The shader chain is upstream's (translator, lock, dmsh tools, Ryujinx sources), plus the branch's bracket-depth flattening (dmsh_depth.py, test_dmsh_depth.py); chain c732699d4fdb. Not carried: the LDSM subgroup fence (seedds#1376, needs a translator rebuild; upstream's HMMA/LDSM rework reports clean movies) and the shared raw-memory lookups (seedds#1405, superseded by upstream's last-entry lookups). - The renderer (dm/gfx/nvn, dm/gfx/msl) and its tests are upstream's. Not carried: seedds#1390-seedds#1394, seedds#1404, seedds#1408, seedds#1409, seedds#1417, seedds#1418, seedds#1420, seedds#1427, seedds#1320, seedds#1331, seedds#1332, seedds#1368, seedds#1285 renderer parts, pool_skip_retired, and the branch's warning fixes and prewarm progress there. They stay on oot-integration. - Ocarina of Time's profile is upstream's, with the branch's 12 movie compute rows in pso_manifest.tsv, PLAN.md and PR-AUDIT.md. - shader_split.py is upstream's plus the BAHS record check (test_split_bahs_records.py). - Host: upstream's EventFd, PlayReport send, audio lock and vibration answers; the branch's service sessions (hle_sf, hle_prepo), sync waits, AV1 movie clock and parallel decode, diag_abort frame fix and focus control are kept. - Scripts: shader.noindex, tmp.noindex, notes outside the shader key, bench and regress changes. Checked: the Mac host builds (GAME=0400486024DEC000); host unit tests pass; the Python tool tests pass on Python 3.13 except test_dmsh_pool_arrays, test_nro_pack, test_nsp_dump and test_nsp_incremental, which fail on upstream main as well. Not run: the full shader build on this chain, gameplay.
Aeonitis
pushed a commit
to Aeonitis/nxnative
that referenced
this pull request
Nov 7, 2026
…ixes (chain 844bf1a5ea8f, exactly upstream's), raw pool table words at commit (seedds#1427), incremental pool tables (seedds#1489), ocarina input stream (seedds#1527), damaged .zs check (seedds#1530) Conflicts: chain tools and shader_split.py taken from upstream (dmsh_depth.py dropped: upstream compiles the 259-bracket shaders its own way); the build script keeps shader.noindex and takes upstream's progress watch; docs keep both packing entries.
cfryerdev
pushed a commit
to cfryerdev/nxnative
that referenced
this pull request
Nov 7, 2026
…a, gmem commit repoint on the test stack seedds#1589 (carrying seedds#1391 + seedds#1482) the GPU memory guard reads the residency set's size and stops before macOS runs out of RAM; hand-merged with seedds#1590's ghost-active alias tables. seedds#1599 soft textures (gated, default off). seedds#1662's tip commit: the ocarina plays into the Mac's microphone (DM_MIC=1). seedds#1427 raw pool table words follow the pools at commit, as a candidate for seedds#1326's page faults (its window is skipped, not faulted: kept for the record). Full-map shader library (42,848), clearing the no-stamp and c1_full red lines. In-game: the GPU page fault at scene changes (seedds#1326) remains on this stack - one session lost the picture at frame 55,940 with the device revoked; the fault predates seedds#1585, which was excluded after the M2 Pro report but is not its cause. Front-ends: host change only, chain 2027aa29b1b7.
3 tasks done
Know-It-All-Brother
pushed a commit
to Know-It-All-Brother/nxnative
that referenced
this pull request
Nov 9, 2026
…etween a raw shader's encode and its command buffer's commit is no longer missing from the table the GPU reads, where its loads read 0 (PR seedds#1427) An argument block held the address of the raw pool table that was current when it was encoded (gmem_map_gpu). A pool made after that, on another thread while the submission was encoded, was not in that table, though the GPU reads the block only after the commit, as NVN's GPU reads memory when it runs. Raw reads of that pool read 0: the failure that hung agl's task shaders in Ocarina of Time. The table words are noted as they are encoded (gmem_slot_note) and, at each commit of the command buffer, whole or segment (mtl_sub_commit, sub_cut), pointed at a table of the pools as they are then (gmem_commit_patch). A new table is built when the pools changed, not refilled in place, as earlier segments may be reading the old one. A block's write log follows its table (NvGmlLog), so gml_read decodes its bits against the table the shader searched. The memory report counts the words and those that were out of date (raw pool table words at commit). The idea of rewriting the words at commit is from seedds#1407 (@uncraftablexd). On the author's stack, loading Ocarina of Time's outdoor save, 5,729 of 154,107 words held an older table by frame 5,100 and 2,582 held the current one behind the pools. Whether this window is behind issue seedds#1326's page faults is open: an address the table misses is skipped, not faulted, and the pools near the M1 Max faults were made 8-41 s before them. Checked: t_gmem_words 16 checks, 0 failed; t_pool_chunks 102, 0 failed; test_docs, test_gfx_tests_makefile, docs_symptoms --check. Donkey Kong Bananza (raw stores and the write log), hosts at 9fe44cc with and without this (the build's libraries are chain cfcc3a82c78b), fresh save into the mining tunnel, 210 s each on an M6: no GPU error on either, the same 4 VP9 red lines, frame p50 16.66 ms on both, 23 long-frame lines each; the patch rewrote 1 of 6,035 words. Co-authored-by: Pedro Nascimento <91118+lunks@users.noreply.github.com>
2 of 3 tasks
UserDerezzed
pushed a commit
to UserDerezzed/nxnative
that referenced
this pull request
Nov 12, 2026
…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
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
An argument block holds the address of the raw pool table that was current when the block was encoded (
gmem_map_gpu). A memory pool made after that, later in the same submission or on another thread while it is encoded, is not in that table, and the GPU reads the block after the commit. A raw read of that pool then gets 0, the failure that hung agl's task shaders in Ocarina of Time (loop (0 - 1) >> 5 times; the table in #1360 fixes the pools that did not fit it, this is about the ones that were made too late for the block's table).How often it happens (one boot, not a benchmark): on the author's stack, loading Ocarina of Time's outdoor save (profile in #1299), 5,729 of 154,107 table words in argument buffers held an older table than the current one by frame 5,100, and 2,582 held the current one while it lagged the pools. A save load makes more than 4,000 pools in a burst.
Change: the idea is @uncraftablexd's in #1407 (rewrite the words at commit). The words are noted as they are encoded (
gmem_slot_note) and, at each commit of the command buffer, whole or segment (mtl_sub_commit,sub_cut), pointed at a table of the pools as they are then (gmem_commit_patch), before the GPU can read them. A new table is built when the pools changed; it is not refilled in place, as earlier segments may be reading the old one, and the replaced one goes through the deferred release as before. The write log of these blocks lists pages, not table entries, so it needs nothing here. The memory report prints the words, those that held an older table than the current one, and those that held the current one behind the pools (raw pool table words at commit).Whether this is what is left of the hang in #1326 (@dacONJA's, minutes after a clean table growth, 4,098 ranges, no overflow line) is not known: nothing here reproduced it. The counts say the window exists in Ocarina of Time; they do not say a hang came through it.
Related: #1360 (the table's size; merges with this one except for one line of
dm/gfx/tests/Makefile, pergit merge-tree), #1407 (the same rewrite in its stack, with an in-place refill of a table first bound in the same submission, which this does not do).Reference entry: Raw pool table words that predate the pools. The symptom index is regenerated.
Checked
make -C dm/gfx/tests GAME=010015100B514000 ...):check_t_gmem_words(new, 13 checks, 0 failed): an unchanged table leaves the words alone; a pool made after two words were noted is in the table they are pointed at and a new table was built; an older table and one that lags the pools are rewritten and counted; a commit with no words changes nothing. With the rewrite removed, 2 checks fail.check_t_pool_chunks75 checks, 0 failed.test_docs.py,test_gfx_tests_makefile.pyandtest_env_switches.pypass;docs_symptoms.py --checkcurrent;lint_c.py tidyonnvn_mtl.mandt_gmem_words.m: 0 file/check pairs above the baseline.make -C dm/gfx/tests run, the host tests,regress.py, any game on main. The change only rewrites words in argument blocks that hold a table address, and only when it differs from the current one, so a game with raw global memory shaders is the only one that can see a difference.Docs
docs/reference/shaders.mdandpython3 dm/tools/docs_symptoms.pywas run