Repository navigation
Conversation
…Ocarina of Time's slow spot on an M1, GPU 38.5 -> 35.6 ms a frame The deferred pass merge (defer_try), so far only with tbdr_on(), now also runs with DM_NVN_PASS_DEFER=1|ab (off by default). OoT draws its light volumes one per pass into one RGBA8 buffer, each after the shadow depth pass of that light; the merge moves all eleven into one pass after the shadow passes (126 -> 115 passes a frame). Extra rules when TBDR is off: the deferred draw must not read bindless resources (DM_NVN_PASS_DEFER_BINDLESS=1 allows it) or write shader memory, no draw between may write shader memory, the scan stops after 6000 ops, and the pass that replays deferred draws does not hoist dispatches (cs_hoist_try). A summary every 300 frames counts the accepted groups and the rejections by reason. Measured (0400486024DEC000, Kokiri Forest looking down at the map, M1 8-core GPU, fullscreen, with seedds#2413's mesh compute on throughout): DM_NVN_PASS_DEFER=ab, DM_AB=600, one run, phases 1-4: on GPU p50 36.08 / 35.57 ms, frame p50 38.60 / 38.02; off 38.61 / 38.54, frame 41.10 / 41.05. Attachment loads 300 -> 200 MB a frame. 11 groups a frame accepted (3300 per 300 frames). The lighting looked right. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e (M1, M2) Where it was measured: the GPU lacks MTLGPUFamilyApple9 on macOS (the M1 and M2), -2.9 ms a frame at Ocarina of Time's slow spot. =0 turns it off; off elsewhere (the iPhone and the M3 on are not measured). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
UserDerezzed
pushed a commit
to UserDerezzed/nxnative
that referenced
this pull request
Nov 13, 2026
…fter memory writes, not on every barrier: Ocarina of Time -1.3 ms a frame on an M1 resource_vis() put MTL4VisibilityOptionResourceAlias on every barrier while an image heap was alive, about 230 barriers a frame. Ocarina of Time keeps one from its first frame (its dynamic-resolution targets are a resolution family, one storage shared by several sizes), and a counter-free Metal System Trace of its Kokiri Forest slow spot on an M1 showed the GPU's stages never overlapping: vertex work started under a running fragment phase in 0.9 % of kicks, compute under fragment in 0 %, and the GPU was idle a quarter of each frame. The relaxed draw-pass barriers allowed the overlap; the alias flush on each of them took it away. A family changes the size it draws at between frames, not inside one, so the flush is needed at a submission's start and after a write that another view of the memory might read. Now, with DM_NVN_VIS_HEAPFRAME (on by default; =0 flushes on every barrier again, ab for the DM_AB phases), an image heap's alias flush is on the first barrier of each submission (g_alias_heap_pend, set by mtl_sub_begin) and on the first barrier after an encoder that may have written memory (g_alias_pend: any compute or copy encoder, a draw pass with shader writes, g_pass_swrite). Large chunked pools without an image heap keep the flush on every barrier, as before. Measured (0400486024DEC000, Kokiri Forest, MacBook M1 8-core GPU, fullscreen, with the light-pass merge and mesh compute of seedds#2441 / seedds#2413 on, in a tree with other local changes): DM_NVN_VIS_HEAPFRAME=ab:1/3 in 300-frame phases, frame p50 36.61 / 36.25 / 37.20 / 37.27 ms with it (mean 36.83) against 38.12 / 38.16 / 38.15 without (38.14): -1.3 ms, lower in every phase. Its GPU p50 (the sum of command-buffer durations) rises to 37.7-39.7 ms, as command buffers now overlap. With it a Metal System Trace shows vertex under fragment in 32.8 % of kicks and the GPU idle 21 % of the time. Screenshots look right (the fog of seedds#2487 included). Dropping the flush altogether (a diagnostic) gave -1.5 to -1.8 ms; this keeps most of that. Not run: this branch's host in game, any test suite, the iPhone, M3 and later, other games. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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
The deferred pass merge (
defer_try) has only run with TBDR fusion (tbdr_on()). WithDM_NVN_PASS_DEFERit also runs without it: on by default on a Mac whose GPU lacksMTLGPUFamilyApple9(the M1 and M2, where it was measured),=0turns it off, off elsewhere.Ocarina of Time draws its light volumes one per render pass into one RGBA8 buffer, each right after the shadow depth pass of that light. The merge moves all eleven light draws into one pass after the shadow passes: 126 → 115 passes a frame.
Extra rules when TBDR is off:
DM_NVN_PASS_DEFER_BINDLESS=1allows it) or write shader memory.cs_hoist_try).The existing rules still apply: a dispatch, uniform update or copy ends the deferral, and nothing in between may touch what the deferred draw reads or writes.
Every 300 frames a log line counts the accepted groups and the rejections by reason.
Performance
Ocarina of Time (0400486024DEC000), Kokiri Forest looking down at the map, MacBook with an M1 (8-core GPU), fullscreen. Mesh compute from #2413 was on throughout.
DM_NVN_PASS_DEFER=abwithDM_AB=600, one run, phases 1–4:About −2.9 ms a frame. 11 groups were accepted every frame. The lighting looked right.
Switches (in
docs/env_switches.tsv)DM_NVN_PASS_DEFER=0|1|ab: the feature (default on for M1 / M2 Macs).DM_NVN_PASS_DEFER_BINDLESS=1: allow bindless reads in the deferred draw (diagnostic).Not run
🤖 Generated with Claude Code