Repository navigation
Ocarina of Time: diagnostics, off by default: TEXDUMP over a range of frames with depth targets, DM_NVN_A5288_C3 for the task hang - #1843
Conversation
…Time's shadow lag Ocarina of Time's actor shadows trail the camera when it turns. Each actor's shadow is a 76x76 depth-only pass, followed by a pass that projects it into a screen-space mask, and the game makes these textures anew every frame. So DM_NVN_TEXRAW (which takes a serial known beforehand) cannot reach them, and DM_NVN_TEXDUMP saved only colour targets of a single frame. Deciding whether the mask projects a shadow map from the same frame needs the maps of several consecutive frames while the camera turns. DM_NVN_TEXDUMP=first-last:path now dumps every frame of the range, with _F<frame> in each file name. DM_NVN_TEXDUMP_DEPTH=1 (or =WxH, to keep only that size) also saves the depth attachments of those frames: the raw depth and an 8-bit PGM stretched over the depths below 1. Both are off unless set; the single-frame, size= and layers= forms behave as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…VN_MESH_GRID_LOG On Apple silicon (M1, 16 GB here; seedds#1326, seedds#1605) Ocarina of Time's GPU hangs fall in passes where its Hi-Z task a5288d0a6c4971fd launches mesh 3439aaa071d868ae. Reading the hung pass offline (seedds#1605) found no raw global loads in its task, mesh or vertex shaders. The task's only loop scans a Hi-Z rectangle per object, clamped to c3[193].xy - 1: the occlusion tile grid's width and height, ints at byte 3088 of Maxwell constant buffer 3 (NVN uniform binding 0), with the tiles as floats of the same block from byte 3120 (seedds#1326). Garbage there (float bits read as ints) would make the scan run for seconds, or read past the block. Telling the suspects apart needs those values per draw: the game rewriting the block while the GPU reads it, a stale binding, or a write the host loses. DM_NVN_A5288_C3=1 keeps, for every a5288 draw, c3[193].xy, the block's address and size, whether an inline update of the block is deferred in the pass, and the fence of its command buffer. It logs a change of value, address or size (and once every 900 frames), and logs in red a W x H whose tiles do not fit the block, with the values read as floats too. At each submission's completion it reads the values again and counts the draws where they changed since encode, that is, a block rewritten while the GPU could read it. On kIOGPUCommandBufferCallbackErrorHang it lists the hung command buffer's draws against the values of the 64 command buffers before it. DM_NVN_MESH_GRID_LOG=1 logs direct task / mesh draws of more than 1,024 workgroups. seedds#1708 confirms 1,024 as the mesh grid limit on M1 / M2. Indirect counts are written by the GPU and are not seen here. Both are off by default and cost one getenv when off. docs/env_switches.tsv lists them, with DM_NVN_TEXDUMP_DEPTH from the previous commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
A note on the red |
…d has not been run The three switches were used or are meant for this game's open problems (shadow lag, the Hi-Z task hang of seedds#1326), and a reader of the game's note had no way to find them. The note says which was used (the TEXDUMP range and depth dump, on an M1 over 9 frames) and which has only been built (DM_NVN_A5288_C3, DM_NVN_MESH_GRID_LOG), so that no result is implied for the second kind, and that the dump changes timing. It also keeps the profile directory touched, from which the pr-areas workflow takes the "game: 0400486024DEC000" label, as on the game's other pull requests. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
main moved (270b6fd, 09dcb62 and others) and mtk_encode conflicted: 09dcb62 makes a mesh shader with no task launch through an object function in blocks of 1024, and an indirect or direct draw now passes its {count, first} record to the shader (ind_rec, DMSH_MESH_DRAW_SLOT). Resolution: mtk_encode is main's, unchanged. DM_NVN_MESH_GRID_LOG is removed from this PR (code, docs/env_switches.tsv row and the game note). It logged direct task / mesh draws of more than 1,024 workgroups to find the mesh grid limit of seedds#1708; main now launches such a draw in blocks of 1024 (the workgroups are no longer the mesh grid), so the log would only report draws that no longer exceed the limit, and its text for a mesh with no task ("a mesh grid past 1,024") is no longer true. The other diagnostics of the PR (TEXDUMP range and depth, DM_NVN_A5288_C3) do not touch this function and stay, off by default. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… made The clang-tidy ratchet failed on this PR with one more clang-analyzer-nullability.NullablePassedToNonnull in nvn_mtl.m than the baseline (16 against 15): td_dump_depth, added here, passed the result of newBufferWithLength: (nullable) as the toBuffer: of a blit copy and then read buf.contents. The finding was ours, not main's (main's lint-c is green since its baseline refresh). A failed allocation now logs a [texdump] line and skips that texture, so the diagnostic cannot blit into or read from a nil buffer. Behaviour with the switch off, or with a buffer made, is unchanged. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
Update on the red The failure on head bf62ae0 is a different one and it is from this PR: Pushed 0ae9505: a failed allocation now logs a |
|
The This PR changes only |
|
The It is not from this diff ( |
main 9983d65 (seedds#1906) fixed the iOS link that main's Bluetooth commit a342d64 had broken ("framework 'IOBluetooth' not found"), which was failing this PR's "Unsigned iOS app" job although the diff does not touch it. Merging it gives the job a tree that links, and re-runs every job of the PR on the current main, the Sanitizers one among them (its failure was an audio test under TSan, which this diff does not touch, and I cannot re-run a single job without admin rights). No conflicts, no change to this PR's own files. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
The This PR does not touch |
|
The |
main moved (0d84a3f) and nvn_mtl.m conflicted where 26062f9 made the uniform-buffer slot of a binding come from cbuf_slot(): the zero-bank fallback, the deferred-update shadow and the bound-size padding moved out of encode_args_'s binding loop. Resolution: the loop is main's. The one line this PR keeps in it, the DM_NVN_A5288_C3 note of binding 0 of the task stage (a5c_note), now runs after cbuf_slot, only when the diagnostic is on, the binding is bound and mapped (mtl_gpu_addr), and with the same arguments as before (shader key, address, bound size, whether an inline update is deferred over the block). Task draws still always take the full encode (mtk_encode sets g_args_dirty[3]), so the reuse and patch paths added by adaff73 do not skip it. Nothing else in this PR changes; it stays off by default. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
What and why
Three switches we used, or will use, while chasing Ocarina of Time (0400486024DEC000) problems on an M1, 16 GB. All are off by default and cost one
getenvwhen off.TEXDUMP over a range, with depth targets.
DM_NVN_TEXDUMP=<first>-<last>:<path>dumps every frame of the range. Each file name gets_F<frame>before its extension, because a serial that lives across frames would otherwise be overwritten.DM_NVN_TEXDUMP_DEPTH=1(or=WxH) also saves the depth attachments of the dumped frames: the raw depth with a text header, and an 8-bit PGM stretched over the depths below 1.DM_NVN_TEXRAW, which takes a known serial, cannot reach them, and TEXDUMP saved only one frame's colour targets.size=andlayers=forms behave as before.DM_NVN_TEXDUMP_MINW. The two do not overlap in code, but they touch the same function.DM_NVN_A5288_C3=1.a5288d0a6c4971fd, bounded byc3[193].xy. Those are the occlusion tile grid's width and height, at byte 3088 of Maxwell constant buffer 3 (NVN uniform binding 0). The tiles are floats of the same block from byte 3120.kIOGPUCommandBufferCallbackErrorHang, lists the hung command buffer's draws against the 64 command buffers before it.DM_NVN_MESH_GRID_LOGwas dropped from this PR after merging main: 09dcb62 launches a mesh shader with no task in blocks of 1024, so a log of draws past the 1,024 mesh grid no longer applies.Evidence
DM_NVN_A5288_C3builds and is documented, but has not been run in a game yet. The first run is planned withDM_NVN_ISOLATE_TASK=0against=1on the M1. No result is claimed here.Risks and caveats
DM_NVN_A5288_C3reads guest memory on the completion handler thread, for a5288 draws only.Checked
MTL_DEBUG_LAYER=1:t_pso_archive135 checks, 0 failed;t_clear_tex51 checks, 0 failed.test_env_switches: the new rows are accepted. The test still fails onDM_NVN_BC_ALIASandDM_YIELD_CLOCK, which also fail on main 7f50222.🤖 Generated with Claude Code