Repository navigation
A run that ends during its prewarm writes the pipelines it compiled, so Ocarina of Time's next run takes them from the archive instead of compiling them again - #2625
Open
computerguy526 wants to merge 1 commit into
Conversation
…it compiled, so Ocarina of Time's next run takes them from the archive instead of compiling them again Since seedds#1879 the timer's flushes wait for the prewarm's end, so a period is written only when it is full (2,000) or at exit. Ocarina of Time's prewarm (31,663 lines after the first frame, on 5 workers) outlives a play session, and the graceful exit gave the archive what was left of 1.5 s (a write takes 1.8-4 s per 900 bases), or nothing when a draw was still compiling its pipeline. Every warm-up run ended with 400-500 bases not written; the next run compiled 57-167 bases again and area loads stalled over 20 s. - nvn_mtl.m: during a prewarm that is not compacting, the timer's flush hands the period over once it is DM_PSO_ARCH_WARM_FLUSH_MS old (default 60 s, 0 = off), then 120 s, 240 s, ... up to 16 min; while captures wait the timer looks again every 10 s - hle_lifecycle.c: the graceful exit (SIGTERM) starts the archive's write before the drain (dm_gfx_quit_begin) and gives it DM_EXIT_ARCH_MS (8 s, 3 s on iOS) beyond the 1.5 s; when graphics do not suspend in 1.5 s (a draw under way) the fallback still waits for the write within the deadline, and one claim flag lets only one of the two paths write, run the exit's continuation and end the process; a hard deadline ends the process at 1.5 s + budget + 0.5 s - nvn_mtl.m pso4_init: a start removes a <file>.mtl4a.tmp a stopped write left (the hard deadline can end the process inside a write) - t_pso_archive / test_pso_archive.py: in fresh processes, a timer flush in the prewarm then _exit SIGTERM in the prewarm with and without a draw holding the graphics layer, and a torn write beside a good file; the timer-flush and held-draw cases write no file without the change, and the torn write's .tmp stays - docs/reference/rendering.md: new entry; symptom index; docs/development.md; env_switches.tsv rows Co-authored-by: uncraftablexd <352372032+uncraftablexd@users.noreply.github.com>
gnosticgeek
pushed a commit
to gnosticgeek/nxforge
that referenced
this pull request
Nov 14, 2026
…rly (patches 0022-0024) Ocarina movies at a 30 fps cap, prewarm pipelines kept at quit, Mario Kart World 1.8.0 build row. seedds#2625's test Makefile line rebased onto the pinned engine (no t_wline there). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016qteK4T7SLBnbRPXQUVaNR
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.
Replaces our earlier #2221.
Symptom
Every Ocarina of Time run compiled the same few dozen to few hundred bases again, although the run before had compiled them. Area loads stalled on them: a draw waits in
pso_get→arch_capture→MTLCompiler. Each run ended with one of these:The second has no archive line at all.
Cause
ARCH_PERIOD_MAX, 2,000) or at exit.SIGTERM) gave the archive what was left of 1.5 s. A write takes 1.8–4 s per 900 bases.dm_gfx_suspendwaited on that draw, and the 1.5 s fallback ended the process before any write. A harness that stops a run for "no new frame" sendsSIGTERMat exactly that moment.What changes
nvn_mtl.m: during a prewarm that is not compacting, the timer's flush hands the period over once it isDM_PSO_ARCH_WARM_FLUSH_MSold.0turns the flush off.hle_lifecycle.c, the graceful exit:dm_gfx_quit_begin), before the drain.DM_EXIT_ARCH_MSbeyond the 1.5 s: 8 s on the Mac, 3 s on iOS, where the app is ended about 5 s after its termination callback.then) and ends the process..tmpand renamed after their index, so a write the deadline cuts short leaves the files already there valid.nvn_mtl.mpso4_init: a start removes a<file>.mtl4a.tmpthat a stopped write left. Main kept these leftovers, and the hard deadline can now end the process inside a write.docs/development.md, and rows indocs/env_switches.tsvforDM_PSO_ARCH_WARM_FLUSH_MS,DM_EXIT_ARCH_MSand the test-onlyDM_TEST_STUCK_DRAW.Tests
make -C dm/gfx/tests GAME=0400486024DEC000 check_t_pso_archiverunst_pso_archiveandtest_pso_archive.py. The new cases each use fresh processes.nvn_mtl.m,hle_nvn.c,dm.h,hle_lifecycle.c)DM_PSO_ARCH_WARM_FLUSH_MS=300, then_exitSIGTERMin a prewarm while a draw holds the graphics layer (dm_gfx_enterwith no leave)SIGTERMin a prewarm, no draw held.tmpand an index without its file, beside a file that is not an archive.tmpstaysTotals:
t_pso_archivein process, 355 checks, 0 failed;test_pso_archive.py, 11 tests OK with the change and 3 of 11 failing without it.test_docsandtest_env_switchespass.Local CI
t_pso_archive,test_pso_archive.py,test_docsandtest_env_switches.ci_local.sh --full, this commit merged intomainf31d607: every stage passes, including the host tests, ASan, TSan and the iOS build, except one tool test. lint-c's findings and the CPU-only gfx test failures are only in files this change does not touch, and are the same onmain.test_bench'stest_cli_relative_paths, which this change does not touch (bench.pyand the test are the same as onmain). It is flaky here: it failed in 1 of 10 runs of the branch alone.In game
Ocarina of Time v131072, M4 Pro, macOS 26.6, 2026-11-10, on our fork's host with this change (
oot_r13af_host), not on main. These are warm-up runs on the walkcam route, each ended bySIGTERM, each starting from the archive the one before left. Logs are inZelda_OoT/0400486024dec000-work/runs/<run>/.r13w2101343_*,r13w3101353..101417_*(same chain, without the change)r13w4101505_{fog,hyrule-field,kakariko,kokiri-house,zora-domain}00152-713.mtl4a,00153-1677,00155-447,00157-358,00159-52r13w2101343_hyrule-field:425 pipelines not written yet … (968 ms);r13w2101343_kakariko:graceful exit not done in 1.5 secondsand no write; about 500 pipelines unwritten per runWhat the next run takes from the archive was checked separately on 2026-11-10 (runs
kmA1/kmA2, which have since been deleted; the numbers are from our notes):kmA2found all 54 of the baseskmA1had written and later asked for.So what a run writes, the next run uses. The before runs compiled 57–167 bases at each area load, and area loads at Hyrule Field, Zora's Domain and Kakariko stalled for more than 20 s.
Not measured with the change: the area-load compile counts and stall times. Later verify runs still compiled 33–167 bases per area load. The keymatch runs show those are mostly content the earlier passes never reached, not lost writes. I don't claim a stall number for the change.
Not covered yet:
r13w4101505_fog, the first of the series) still ended with 1,378 pipelines unwritten after 9.3 s: its second period had not reached the 120 s flush when the run ended, and compute-heavy periods take tens of seconds to write.Regression
regress.py impact HEAD~1..HEADpicks The Legend of Zelda: Breath of the Wild, Pokémon Scarlet and The Legend of Zelda: Tears of the Kingdom. All three use the pipeline archive, and BotW and TotK also use the prepare step. Hades is not affected, and 163 profiles have no usage manifest. None of the three games was run for this PR (I don't have them).dm/host/dm.handdm/host/hle_lifecycle.chave no row inimpact_map.tsv. They change the graceful exit for every game: aSIGTERMexit with unwritten captures can now take up to 10 s instead of 1.5 s (2.0 s withDM_EXIT_ARCH_MS=0). Anoe::ExecuteProgramhand-off goes through the same exit, so it waits the same way.PSO_ARCH_COMPACT) that many files closer.DM_PSO_ARCH_WARM_FLUSH_MS=0turns the prewarm flush off.DM_EXIT_ARCH_MS=0gives the main exit path the old 1.3 s, but the timings are not quite the old ones: a fallback at 1.5 s hands the archive over without waiting (dm_gfx_quit(0)), and the hard deadline is at 2.0 s.Co-authored with UncraftableXD.