Repository navigation
DM_CTL poolstat and texstat, and what fills Ocarina of Time's GPU working set (iPad out of memory at 8,259 of 8,192 MB) - #1436
aksmith-git wants to merge 2 commits into
Conversation
…lls Ocarina of Time's GPU working set (iPad out of memory at 8,259 of 8,192 MB) # Conflicts: # dm/gfx/nvn/nvn_mtl.m # dm/host/hle_hid.c
…fills Ocarina of Time's GPU working set (iPad out of memory at 8,259 of 8,192 MB) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016qteK29T18U8p1c9LsVY8g
) replaces the pull request heads Upstream landed Ocarina of Time in main (chain adec7d81d970: "holds 60 fps in Kokiri Forest, 4 GB less") and closed the pull requests it folded in, with reworded and partly different code. Mixing a pull request head with its landed version hunk by hunk silently broke things (two GlobalToStorage tables, a duplicate AF2ip, two mtk_pso definitions), so the rule here is one version per feature: - Pull requests upstream closed (seedds#1299, seedds#1300, seedds#1312, seedds#1343, seedds#1345, seedds#1353, seedds#1354, seedds#1359, seedds#1360, seedds#1373, seedds#1428, seedds#1430, seedds#1434): their hunks are taken out of our side before the three-way merge, so upstream's landed version stands alone. Gone with them: bindless pool table patching (reg_bump), the ghost table's per-submission hold, the growing raw pool table and its write-log sizing, seedds#1428's pool_buf spares (upstream's pool_table_take is the same idea), the ixc-based indirect mesh draw (upstream uses mdx), and their tests (t_pool_table, t_mesh_indirect, t_gmem_raw, finalized_bindless_pool, test_bnsh_nvn2, test_ndve). - Open pull requests that upstream's landing supersedes: seedds#1394 (upstream's mtl_pool_addressed) and seedds#1393 pool_skip_retired (upstream's budgeted pool walk; the profile does not use it) are dropped with their tests and docs. seedds#1368's mesh pipeline prewarm is dropped too: upstream kept the background build in nvn_geometry.inc, and the prewarm's mtk_build / mtk_claim / g_warm_mps went with it. - Kept, as upstream does not have them: NXForge's own features (GPU watchdog, present filters and anti-aliasing, aniso floor, quick settings, pipeline archive compaction, upload breakdown, memory report lines) and the still open pull requests seedds#1304, seedds#1305, seedds#1308, seedds#1320, seedds#1331, seedds#1332, seedds#1355, seedds#1356, seedds#1369, seedds#1376, seedds#1377, seedds#1379, seedds#1382, seedds#1390, seedds#1391, seedds#1392, seedds#1414, seedds#1420, seedds#1436, seedds#1439, seedds#1446, seedds#1453. - Combined where both sides changed the same lines: GW_N 1 << 16 with seedds#1320's wide-write intervals (GW_PAGES = SBW_WPAGES, 128 slots), the CPU upload log with upstream's linear upload route, arch_open_end before the compaction limit, cbn_prog in geo_gs_one (seedds#1382). - Translator: upstream's sources and binaries, plus seedds#1414's InstEmitAmpereMem diff and the LDSM SubgroupBarrier in InstEmitAmpereTensor.cs. The binaries and dmsh_chain.lock are upstream's until the Mac rebuilds them (dotnet publish, tool_lock --update-lock, dmsh_chain --header); dmsh_chain.h is regenerated for now. - RED_ONCE keys: upstream took 153 and 154, so the present anti-aliasing lines move to 156 and 157 and seedds#1420's packaged-entry line to 158 (array 159). - Host: hle_net.c and t_net_eventfd.c are upstream's (its eventfd poll waits out the whole timeout, which our 5d7920c fixed another way). - Kept ours: dm/tools/romfs_image.py and its test, so the 26 GB RomFS image is not packed again. dm/tools tests on Linux: same failures as on 875449e (Linux-only quirks), plus test_nlg4 and test_dmsh_pool_arrays, which fail on upstream main too. Not yet built on the Mac. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016qteK29T18U8p1c9LsVY8g
…n Kokiri Forest, about 4 GB less memory) beside this tree's own work Kept from this tree: the growing raw pool table with two-word hints (plus upstream's read-before-OR on its write log), seedds#1439's held count, seedds#1436's diagnostics, seedds#1447's texture release, seedds#1435, the idle evictions, the GPU watchdog, range-tracked GPU writes, the packaged-texture cache (g_pkg_alias), the synchronous task / mesh pipeline build with prewarm, this tree's F2IP. Taken from upstream: the pool tables (only what shaders read is made, within a budget; pool draws count as depth readers only when one was seen reading, replacing seedds#1430's rule; table reuse), sub_cut's busy rule, the indirect task / mesh draw through mdx, the empty mesh fragment, the larger GPU-write table (65,536 slots), linear textures by rows, the atomic alias on any 32-bit format, its eventfds (with this tree's select and fcntl on them), its prepo Send and audio update lock, its shader split and Ocarina profile and tables. Duplicates both sides added were removed (SDK 22 answers, F2IP, test stubs); RED_ONCE 153 split; t_pool_table (the replaced pool table code) removed; tests adapted to the taken rules. Translator rebuilt; chain 695a9393d125. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
01cce66 to
f05638c
Compare
|
Same device class here: iPad Pro 11-inch (M5), 12 GB, iPadOS 27.2, same game (v131072), NX2Apple 1.2.3 engine pin It runs at about 54 fps (frame p50 18.5 ms, p95 29 ms over the last windows), but memory climbs the whole time (host
At 20:00 of play (frame 41,806) the host log just stops, with no If it helps, I can run any of the Drafted with Claude; reviewed by me. |
|
Thanks, that matches what pushed us to the guest-file path. On an iPad Pro 13-inch (M5) with the same game (v131072) and guest memory in files ( |
…sured on Ocarina of Time (iPad GPU out of memory at 8,259 of 8,192 MB) poolstat logs the resident memory pools and the texture storage inside them, with the largest pools. texstat logs the host textures by kind: those made from guest memory by frames since their last use (NvPkg gets a last-use frame), and render targets by shape, with how many distinct guest storage addresses, over what span, and how many live serials name them. Each host texture is counted once. docs/reference/memory.md records the Ocarina of Time measurements they gave (12.1-12.5 GB on an M4 Pro Mac in handheld mode against the iPad's 8 GB: 5.9 GB of pools the raw table keeps resident, 2.6 GB of it texture storage also held as Metal textures; 2.36 GB of guest-memory textures all used every second; 2.4 GB of render targets with transient ones duplicated at shifting offsets) and three experiments that did not help.
…lls them and the host tests link without nvn_mtl.m
01d35db to
c9d83f1
Compare
|
Rebased on main eed7c42 (the conflicts were the note's entry list and the DM_CTL row of env_switches.tsv). Builds with the Ocarina of Time profile; t_hid 169 checks, 0 failed; docs_symptoms --check current; test_docs OK. test_env_switches fails on main itself (DM_NVN_CUT_FIRST, DM_NVN_RT_RECLAIM, DM_NVN_VC_WAYS, DM_NVN_BC_ALIAS), nothing from this change. |
…set) Upstream pull requests applied in this commit (their authors' work, brought onto this tree with a three-way merge; the description is in each PR): - seedds#1436 by aksmith-git (open): DM_CTL poolstat and texstat, and what fills Ocarina of Time's GPU working set (iPad out of memory at 8,259 of 8,192 MB)
What and why
Ocarina of Time (Switch 2,
0400486024DEC000, profile in #1299) runs on an iPad (iPad17,3, M5, 12 GB) at about 22 ms a frame until the first area load after a save, then runs out of GPU memory:GPU out of memory: the residency set holds 9124 objects, 8259 MBagainst Metal's 8,192 MB working set, withkIOGPUCommandBufferCallbackErrorOutOfMemory, pink or broken frames and 120-300 ms of GPU a frame. Handheld mode fails later, 27 MB over. #1369 hit the same wall on an iPhone. This PR does not fix it: it adds two diagnostics and records what fills the working set, so the next attempt starts from numbers.DM_CTLpoolstat: the resident memory pools, the texture storage inside them, the largest pools.DM_CTLtexstat: host textures by kind; those made from guest memory by frames since their last use (NvPkggets a last-use frame); render targets by shape with distinct guest storage addresses, their span, and live serials. Each host texture is counted once.docs/reference/memory.md: the measurements and three experiments that did not help (symptom index regenerated), with a line in Ocarina of Time's note;docs/env_switches.tsvlists the two lines underDM_CTL.Measurements (M4 Pro, handheld, 7 minutes from a save; guest memory in files)
These were taken before main's raw pool table and pool read bitmap changes, which address the pool row below (the 2,432 MB pool now stays out of the table). The doc entry says so and links them; the render-target row is still open. The iPad has not been measured on a host with both changes.
The raw table is needed: 783 of the 8,319 shaders a play used do raw loads.
Not kept (details in the doc entry): leaving texture-only pool memory out of the raw table (one GPU hang before the first frame), a large pool through its chunks only (no saving), reclaiming taken-over shared textures by alias-lookup idleness (active targets looked idle).
Checked
make -C dm/host GAME=0400486024DEC000 dmhostbuilds;check_t_pso_pending,check_t_pool_chunks,check_t_cpu_tex,docs_symptoms.py,test_docs.py,test_env_switches.pypass.lint_c.py tidynot run here (this machine's LLVM does not start). The earlier clang-tidy failure was main'st_int_float_view.m, not this change.