# The Legend of Zelda: Ocarina of Time (`0400486024DEC000`)

A Switch 2 game: update v131072, SDK 22.2.8 (`Ounce`). Nintendo EPD's engine (sead, agl, gsys, Havok, CRIWARE; project `Owl`, with Tears of the Kingdom's file layout) on NVN2. Modules `main`, `subsdk0` (NintendoSDK_movie) and `sdk`, no rewriter patches. Status: plays on the Mac through the title, the opening, a new file's first scene, Link's house and Kokiri Forest, with saves, at about 59 fps with the picture close to console video. Mac only so far.

## What it needs

| Setting | Where | Why |
|---|---|---|
| `mem_reserve 0x320000000`, `mem_alias 0x100000000`, `mem_stack 0x10000000`, `app_pool 0x240000000` | [`game.tsv`](game.tsv) | the game asks `SetHeapSize` for 0x18ce00000; the rest as Donkey Kong Bananza, the Switch 2's 9 GB |
| `mem_map_limit on` | [`game.tsv`](game.tsv) | a map past the application pool fails with ResultLimitReached, as on Horizon. The SDK's allocator keeps freed pages mapped until a map fails, then gives them back ([PR 1444](https://github.com/seedds/nxnative/pull/1444) reports a black screen leaving the Deku Tree without it; not reached here) |
| `sys_resource 0x3000000` | `game.tsv` | 48 MB, as the NPDM declares |
| `render_cond on` | `game.tsv` | agl clears a copy of the prepass depth again under a render condition the console skips. Run unconditionally, the opaque pass's `EQUAL` test fails everywhere ([PR 1299](https://github.com/seedds/nxnative/pull/1299)'s finding) |
| `gpu_timestamps segment` | `game.tsv` | the game's dynamic resolution decides from GPU timestamps, and with one time per submission it never lowers its resolution ([why](../../../docs/reference/frame-rate.md#dynamic-resolution-that-never-moves-and-draw-passes-that-wait-for-each-other)) |
| Dynamic-resolution stub | [`patches.py`](patches.py) (frame step rule, `others`) | full resolution unless the launcher's Dynamic resolution is on ([Dynamic resolution](#dynamic-resolution)) |
| `draw_barriers game` | `game.tsv` | about 180 full barriers a frame NVN does not ask for: GPU 25 → 18 ms at full resolution |
| `tex_flush_upload on`, `tex_dirty_upload on` | `game.tsv` | as Tears of the Kingdom: the CPU writes the terrain tiles' height (R32F), blend and hole (RGBA8) maps into textures after creating them. Without the keys those textures stay zero: flat blue holes in the ground around the path with grass floating in them, and grey stone where the console shows dirt |
| `shader_groups`, `shader_note` | `game.tsv` | shaders grouped as `/Shader/`, `/Effect/`, `/Lib/`, `/UI/` |
| `pad_layout full` | `game.tsv` | a 3D field and both sticks |

## Files

One [NUP container](../../../docs/development.md#the-packing-script-in-detail) of 25.6 GB: `scripts/pack_nup.py` unpacks it to `extract/v131072/`. The RomFS keeps most files as zstd with dictionaries from `Pack/ZsDic.pack.zs`. The movies are AV1.

## Shaders

- About 42,850 in [`shader_map.tsv`](shader_map.tsv), including 500 mesh and 20 task shaders in the BNSH programs ([Task and mesh shaders in BNSH](../../../docs/reference/shaders.md#task-and-mesh-shaders-in-bnsh-and-indirect-mesh-draws)), and the movie library's in an NDVE pack ([`nn::ndve`](../../../docs/reference/shaders.md#nnndves-movie-enhancement-file)).
- The runs here used a partial Mac library of the keys the playtests asked for, listed in [`shader_seen.tsv`](shader_seen.tsv) (7,276; building them took about 10 minutes when most came from the previous chain's libraries).
- Current: [`RED.F32.FTZ.RN`](../../../docs/reference/shaders.md#float-atomics-in-storage-memory) translates. The build's `Attribute offset 0x5C is not valid` (about 2,300 shaders) is a vertex shader's write to an output the translator drops, probably a shading rate, as `nvnCommandBufferBindShadingRateImage` and its family are no-ops: everything shades at full rate, which is right to look at and costs GPU time. Not verified against the hardware.

## Frame rate

Measured on an M6 Mac with 16 GB, headless, on one walk with camera turns (`walk.sh` in the work folder).

- Current: the title and menu, a movie behind them, are a locked 60 fps (p50 16.67 ms, GPU span 15.6 ms).
- Game speed: the game steps its time by a frame ratio, its base rate (60, or 30) / its int frame rate, whatever the frame took (`main+0x6e6cc4` on v131072), so frames longer than a vsync played in slow motion (seen by the user on a slower Mac; [issue 1375](https://github.com/seedds/nxnative/issues/1375)'s M1 Max ran the title at about 28 fps). With `fps_target 60` the ratio is the host's frame step × base / 60 ([A fixed frame step plays in slow motion on a slow Mac](../../../docs/reference/frame-rate.md#a-fixed-frame-step-plays-in-slow-motion-on-a-slow-mac)), a stub placed by its function's fingerprint ([`patches.py`](patches.py)). Mac runs on the M6 (2026-11-08, a test host on the libraries of chain `3ee493b2c3a4`): the user's play sessions held 60 fps with 2- and 3-vsync holds while areas loaded, game time 1.000 of real time by the host's count. That count is the stub's own; no run on a Mac slow enough to show the slow motion before and after.
- Current: walking the village at the game's top internal resolution, 1536x864: a locked 60 fps, mean 16.67 ms over each settled window. Per 2,700 frames: 0-8 frames over 25 ms and 0-2 over 33 ms. Frame p95 17.8-18.9 ms with no window, as the game's own loop moves around its fence wait; in a window p95 17.8 ms, 3 over 25 ms and 5-16 over 18 ms per 600. GPU span p50 16.5 ms, summed GPU 15.8 ms, CPU 6 ms, about 101 passes a frame. The heavy stretch where the village opens (about 1,560 draws) holds 16.65-16.8 ms by lowering its resolution, then returns to full. The main pass used to sit at 763x429 at the same GPU time: [marked shaders tested depth late](../../../docs/reference/frame-rate.md#a-hosts-own-store-in-a-fragment-shader-moves-its-depth-test).
- Before [pool shaders stopped counting as depth readers](../../../docs/reference/rendering.md#pool-shaders-taken-as-depth-readers): passes 118, 104, 219, 224 in a four-frame cycle, frame times 15, 15, 18, 18.5 ms, mean 16.9 ms. Half the frames rendered the reflection probe's faces with one draw a pass.
- The host's GPU figure adds up command buffers, which overlap, so it reads above the real span: 17.5 ms was never a frame's real time. The real span is `@gpu_end_ms − @gpu_beg_ms` in `DM_NVN_TSV`, or the `first start to last end` of `DM_NVN_GPUPROF`.
- The roughly 1 ms the [wind fix](../../../docs/reference/shaders.md#dead-code-removal-dropped-a-coordinate-of-a-multi-output-instruction) seemed to add: 0.66 ms of it is the upscaler, 416 → 1076 µs, because its variants then read what they had lost. It is doing its real work.
- Attachment traffic was not the cost it looked: 254 MB load and 277 MB store remain, and the cheapest passes move 20 MB in about 30 µs. The pass count was the cost.
- Resolved: 25-40 ms frames while the GPU sat idle with the next command buffer committed, 51-75 per 2,700 in a bad run: [the GPU idles with the next command buffer already committed](../../../docs/reference/frame-rate.md#the-gpu-idles-with-the-next-command-buffer-already-committed). What holds Metal's submission queue in the kernel is still unknown.
- Resolved: Kakariko Village at 30-70 ms a frame with 1,502 `background render pipeline creation failed … MDB_MAP_FULL` lines after a compacting prewarm of 40,000 rows put 8,693 bases into one archive period: [Metal's archiver store filled by one flush period](../../../docs/reference/rendering.md#metals-archiver-store-filled-by-one-flush-period).
- The title movie's network took 14.8 ms of compute a frame here (median from frame 3,000), so the title held 60 fps with almost nothing to spare, and slower GPUs fell below it: [issue 1375](https://github.com/seedds/nxnative/issues/1375), 35 ms on an M1 Max. Since [HMMA chains keep their matrices in the SIMD-group](../../../docs/reference/shaders.md#hmma-chains-keep-their-matrices-in-the-simd-group), 11.4 ms, and the GPU span 11.9 ms instead of 15.6 (26.7 → 18.9 ms of compute on an M4 with 8 GPU cores). Not measured on an M1 Max since.
- In a run that takes shots, each shot costs its frame 60–100 ms, and `DM_NVN_GPUPROF` and pass dumps slow the frames they cover.
- Open: frames of 100–650 ms when an area first loads (640 first uploads, 321 MB, in one frame of 294 ms; another 640 ms of submit with 68 MB).
- `DM_NVN_TBDR=1` was tried and does not help: p95 19 ms on the same walk, against 17.8.
- The first long run on a new chain is slower (p50 60–114 ms), while `MTLCompilerService` compiles pipelines; the next run is not.
- [`pso_manifest.tsv`](pso_manifest.tsv) seeds the [prepare step](../../../docs/development.md#the-prepare-step) of a first start: 9,625 rows (8,376 shaders, 1,112 render and 137 compute pipelines) recorded on an M3 Pro Mac (macOS 27.2) with no lists present, over boot, the title and its movie, a new game and the opening, Link's house, Kokiri Forest and a save load ([PR 1493](https://github.com/seedds/nxnative/pull/1493)), and five compute pipelines Saria's greeting builds (Deku Scrub, Business Scrub, Deku Baba), found in [PR 1488](https://github.com/seedds/nxnative/pull/1488). With the list empty, a first start with a cold Metal shader cache showed a black picture with the title music for minutes: one title frame built 11 pipelines and loaded 12 shader libraries in 252.6 s on that Mac ([issue 1477](https://github.com/seedds/nxnative/issues/1477)). Before compute pipelines were in the offline archive, a true first start with the list prepared for 134.7 s on an M4 MacBook Air and then had no frame over 0.25 s to a save load. Open: the first start has not been measured with the archive's compute pipelines, nor on iOS, where this game has no bundled archive (no `pso_mtl4`) and the list is all a first start has; the render bases the `R` rows need are not in the offline archive. A longer list from hours of iPad play (PR 1488, 9,789 rows) prepared 16 s longer on that MacBook and avoided only 7 render builds that made no frame over 100 ms.
- With a window, the first start on a new chain runs the pipeline prebuild first: 33,190 shader pairs, 691 s on this Mac. A run with no window skips it.
- The opening movie runs at the movie's own 24 fps pace during the story section and cannot be skipped: about 8 minutes on a new file.

## Dynamic resolution

- The controller (v131072; found by fingerprint, so the addresses are only for reading): the parameters are `game__gfx__DynamicResolutionParam` (`LoadThreshold`, `ReduceCounterMax`, `IncreaseCounterMax`, and a list of levels, each a `ResolutionReduceScale` and a `Priority`). Once a frame the update (`main+0x805aa0`) reads the frame's GPU time, subtracts what its cost model predicts at the current size and keeps the trend of that residual. The level function (`main+0x8065e0`) adds the residual to the model's cost at each level and returns the best level under the threshold: 0, the full 1536x864, when the current size fits. The update moves down after `ReduceCounterMax` frames that ask for it and back up after `IncreaseCounterMax`. Scripted `GPULoad` hints from event data (`main+0x31c3de0`) and `OneshotSetDynamicResolutionLoadThreshold` adjust it in cutscenes.
- Resolved on the host: after a loading screen it sat at its floor, 683x384, for minutes while the frame held 60 fps with GPU time to spare. A stale frame-start timestamp and event waits that idled the GPU made its timer read more than the frame took: [Dynamic resolution at its floor while the GPU has time to spare](../../../docs/reference/frame-rate.md#dynamic-resolution-at-its-floor-while-the-gpu-has-time-to-spare).
- Current: the launcher's **Dynamic resolution** (`DM_DYNAMIC_RESOLUTION`, off by default) holds full resolution. A stub of the frame step rule in [`patches.py`](patches.py), placed by the level function's fingerprint, makes that function return level 0 while state page `+0x40` is 0, so the update climbs to full size and stays there; 1 runs the game's own choice. The rewriter declares the `DYNAMIC_RESOLUTION` capability when it places the stub.
- Measured on the M4 Pro (20-core GPU, 2026-11-08, `kokiri-deck`, one run each): at full resolution (the main passes 1536x864 in pass dumps at 75, 100 and 125 s) 48.1 fps, frame p50 16.74 / p95 33.41 ms, GPU p50 15.0 / p95 16.9 ms: the GPU needs about one vsync a frame, so the frame step holds 2 vsyncs much of the time. With the game's own dynamic resolution and the host fixes above: 60 fps, GPU p50 12.6 ms, at a lower resolution. A second dynamic-resolution run wandered off the route into Saria's dialogue and is not counted.

## Memory

- Current: on the walk, run from an external drive with a 3.5 GB pipeline archive: resident 10.9-11.4 GB, wired about 9.4 GB, on a 16 GB Mac. `vmmap` and `footprint`: 6.4 GB of guest memory and 3.8 GB of Metal textures and targets, 1 GB of IOAccelerator memory. [Reading the archive into memory](../../../docs/reference/memory.md#a-pipeline-archive-on-an-external-drive-is-read-into-memory) used to add 3.5 GB (footprint 15.0, peak 16.7). `mem_map_limit on`: a map past the application pool fails as on Horizon, and the SDK's allocator then gives back the pages it keeps. Other apps' memory adds to the swap: other games running beside it can push the Mac over.
- This game took the Mac down before the fixes (kernel panic in `IOGPUGroupMemory` at 14.7 GB wired): [raw pool table](../../../docs/reference/memory.md#memory-pools-nothing-gave-an-address-to-stay-out-of-the-raw-pool-table), [textures made only when read](../../../docs/reference/memory.md#shaders-report-which-textures-they-read-through-a-pool), [out-of-memory exit](../../../docs/reference/memory.md#repeated-gpu-out-of-memory-failures-end-the-game).
- Why so much: the game's own memory is about the console's 9 GB application pool, and on the Mac its textures also exist as Metal textures, as Metal cannot sample the guest's block-linear storage.
- Open: render targets that move in the game's pool and change size with its dynamic resolution (1580 → 1579 → 1578 …) get a new Metal texture each time, about 2 GB added to the residency set per 300 frames. It costs about 0.5 ms a frame once settled, so recycling them is a smaller win than the walk, but [a report of a GPU driver panic](https://github.com/seedds/nxnative/pull/1299) lines up with this churn.

## Saves

The game autosaves into `slot_00` and `slot_01`, with `option.sav` and `account.sav`. The Load screen lists them and reloading works. A save's thumbnail is a 543x306 JPEG in `caption.sav`, made from a copy of a texture to a buffer. A manual save (Menu, System, Save) on the current build has the picture (slot 02, mean colour 138 / 123 / 86). The autosaves in the work folder's saves, made on older chains, hold a black one. Open: an autosave made on the current build has not been looked at.

## Driving it on the Mac

Run headless, `DM_CTL` at a control file. The work folder has `boot.sh <secs> <log>` (with a guard that kills the host past 12.5 GB wired or 16 GB of swap; do not run without it), `ctl.sh`, `seq.sh`, `snap.sh`, `keys.sh <logs>` (adds and builds the keys the logs ask for), `white.py` (share of near-white pixels in a shot) and `run/save_ref` (autosaves in Kokiri Forest).

From an empty save: at about 45 s `A` (title), `A` (New Game), then the movie. From `save_ref`: at about 58 s `A~0.2`, 5 s later `A~0.2` (Load), 30 s later three `A~0.1` 3 s apart, then 12 s to the bridge outside Link's house. There `LUp~3.5`, `A~0.2` (Climb Down) and `LDown~4` three or four times reach the village floor.

## Open

- Root cause confirmed on M4 Pro (2026-11-08): [ignored event waits](../../../docs/reference/nvn-objects.md#gpu-event-waits-order-work-across-queues) let lighting consumers run before their producers. The game issues about 25 waits and 19 signals per frame. All 297 complete traced frames submit queue 5's ambient-cache consumer `9e6b00b050e30801` before queue 1's SH producer `21d9f83e6027c565`, despite the explicit dependency. Queue 1 also waits for the CPU frame-ready event after the CPU clears the lighting buffer. At frame 3872 the consumer ran at 0.686 ms, the clear at 0.966–0.968 ms, and the producer at 1.282 ms; its release followed at 4.467 ms. Exposure writer `1bba09ec4bc8ff67` has another event dependency. The native SDK's flush/invalidate functions are no-ops for these coherent pools.
- The pale outline around Link is produced before fog, bloom and upscaling, by task `efaa4fa6a80ba719`, mesh `066f5daf12e43c71`, fragment `5ad65c0eefd09c7f`. An offline replay matches both 768x432 RGBA16F targets byte for byte. Removing shared-buffer bytes 48–111 makes direct SH lighting agree with the cached ambient lookup (affected-pixel mean RGB error 0.100/0.136/0.218 falls to 0.0034/0.0020/0.0008): the cache lacked the SH contribution available to the later direct draw. Honoring the event dependency removes the outline, confirmed by the player and later captures.
- A repeating patchy pale layer remained after event ordering was fixed, including with optional attachment discard disabled. [Conditional rendering state lost across queue continuations](../../../docs/reference/rendering.md#conditional-rendering-survives-queue-continuations) caused repeated clears: disabled draws and pending timestamp counter values must survive physical Metal submission boundaries. Fixing both removes the layer in 2,000 asynchronous frames covering a stationary view, loading, camera rotation and movement to the village floor. The loading peak is the normal black-to-scene fade; the camera peak is a foreground branch crossing the view. These bounded samples do not establish every later area is unaffected. Synchronous screenshots wait for the GPU and can hide the original race, so validation uses asynchronous present copies. The rebased delivery subset passes the focused queue, descriptor, continuation, completion, residency and mesh-first-use checks. The current-main shader rebuild and five-game regression are still running at the visual-fix push.
- Diagnostic caveat: earlier shader probes used fragment buffer 30, which conflicts with alpha-test state, then buffer 28 with added atomics that can move depth testing late. Visual conclusions from those instrumented runs are inconclusive. The event trace, offline producer comparison and combined validation above use the original uninstrumented fragment libraries. The scene flash predates those probes.
- Regression reach is uncertain because every NVN submission now passes through logical queue scheduling. The five selected checks are Ocarina (the original dependency), Three Houses (multiple queues), Octopath Traveler 0 (command-buffer fences and Unreal RHI), Octopath Traveler II (an available boot route), and Okami HD (an older NVN path). The run is in progress; its unfinished rebuild is not a passing result. The focused tests pass with Metal validation: event/receipt 80, descriptor lifetime 38, continuation 38, native mesh first use 42 and storage-writer state 34 checks per encoding mode; capture 91, suspend 22, NVN 245, alias residency 28, completion ordering 36 in each of three configurations, and counter-overlap 42 per mode. The older CPU-post report/GPU-byte ordering limitation remains open as described in the rendering reference.

- Current on M4 Pro (20-core GPU, 2026-11-08, the `kokiri-deck` route in [`bench.tsv`](bench.tsv), the partial shader set): GPU p50 12.6 / p95 13.6 ms, 51.8 fps, frame p50 16.69 ms (60 fps most of the time; two runs). Before, the main pass sat at the game's floor, 683x384, and the frame step held 30 fps at 16.3 / 18.6 ms (a hold of one vsync needs a cost under 1.1 vsyncs, a probe back to it 0.85). The time was geometry: per frame about 9 ms in the vertex and mesh stages, 5 ms compute, 4 ms fragment (Metal System Trace); the foliage task/mesh pass 4.6 ms of vertex-stage time against 0.2 ms of fragment. Two causes, both general: the mesh shaders read their 128-bit raw loads a word at a time ([128-bit raw global loads read one word at a time](../../../docs/reference/shaders.md#128-bit-raw-global-loads-read-one-word-at-a-time), about 3.1 ms), and occlusion conditions were never read ([Occlusion conditions read once landed](../../../docs/reference/rendering.md#occlusion-conditions-read-once-landed), 0.6 ms). Ruled out by A/B: the mesh shaders' threadgroup memory (folding it 50-77% smaller did not help), its zero fill, the pool table reads, their primitive output (0.3 ms) and missing `c1_full.tsv` / `cb_extent.tsv`. Open: compute is still about 5 ms of the frame (the NDSR upscaler `d99fbeeb53d38847` writing 2048x1152, a fixed cost at any internal resolution, and a culling group), not looked into.

- Resolved: the build left 9 shaders out. Six foliage compute shaders used `ATOMG.CAS` ([Global memory: descriptors, ATOMG.CAS, INC / DEC](../../../docs/reference/shaders.md#global-memory-descriptors-atomgcas-inc--dec)); `1f78730053feb036` and `e172bd7ec218ab8e` nest 259 brackets ([Bracket nesting past the front end's 256](../../../docs/reference/shaders.md#bracket-nesting-past-the-front-ends-256)); `68bbe98b3bfd9876` (`Ampere instruction 481 at 0x0`) and five more map rows were no shaders at all ([A control section's words read as a BAHS entry](../../../docs/reference/shaders.md#a-control-sections-words-read-as-a-bahs-entry)), now gone from the map. None of the eight real ones was used on the walk to Kokiri Forest.
- Open: [the movie network](https://github.com/seedds/nxnative/issues/1375) took 35 ms a frame on an M1 Max, so movies and the title ran at about 28 fps there; on this M6 it takes 11.4 ms since [HMMA chains keep their matrices in the SIMD-group](../../../docs/reference/shaders.md#hmma-chains-keep-their-matrices-in-the-simd-group) (from 14.8), not measured on an M1 Max since.
- Current: against a frame of console video of Navi's close-up the picture matches: hair and sign within 1–2 % in red and green. The causes, each general: [float atomics](../../../docs/reference/shaders.md#float-atomics-in-storage-memory) (too bright, yellow skin, a pale veil: the exposure read back from buffers that stayed 0), the terrain's CPU-written maps (holes, wrong materials; the profile keys above), [the gather offsets](../../../docs/reference/shaders.md#texturegatheroffsets-and-a-loop-over-its-offsets) (the dotted rows in blurred areas, born in the NDSR upscaler, three pictures from one input), and [image atomics on RGBA8](../../../docs/reference/shaders.md#image-atomics-on-a-32-bit-colour-texture) (the anti-aliasing's blend weights).
- Current: the grass no longer flickers. Its blades shifted at 10 Hz because the wind's pressure solve read one neighbour at an undefined row ([dead-code removal](../../../docs/reference/shaders.md#dead-code-removal-dropped-a-coordinate-of-a-multi-output-instruction)), so the velocity field (512x512 RGBA16F, a two-buffer ring) held strong stripes up to ±11 with a 6-frame cycle. In the moss on the bridge, the mean difference between adjacent frames fell from 5.97 to 0.70 of 255, and it now grows smoothly with the lag.
- Resolved in the log, to be eye-checked at the spots it showed: flat blue holes in the ground with grass and rocks floating over them (Kokiri Forest, the village floor, the Deku Tree) after an hour of play: [textures made for GPU use kept from their CPU rewrites](../../../docs/reference/nvn-objects.md#textures-made-for-gpu-use-kept-from-their-cpu-rewrites). The terrain tiles' height, blend and hole maps are rewritten from the CPU as tile slots are reused, and the dirty-page poll dropped every uncompressed one; with the fix, about 250 of them upload in the first 160 s of the Kokiri Forest autosave and a walk onto the village floor (M4 Pro), and the normal tiles the GPU draws stay, or become again, the GPU's.
- Open, small differences from that same console frame: Navi's core has a harder edge and a narrower glow here (the bloom texture peaks at 0.44; the ball's HDR is about 0.9 with a tiny spot at 45); shadows are less blue, and the far grass about 1.4 times brighter. One frame of compressed video is weak evidence for either. The falling leaves look dark near the camera, not compared.
- A red `texture type mismatch` on `9b310b3349825e9a` (a UI merge shader): a 3D texture left bound in a slot its active branch does not sample. Harmless so far.
- `nn::codec AV1: busy (result 3603), a packet refused with 12 pictures waiting` (4 lines a run): the decoder's queue is full and the movie library retries, as it is written to ([a refusal is no fault](../../../docs/reference/movies.md#the-submission-ready-event-counted-as-packets)); movies play. It was a red line until then.
- The `pipeline archive` red line is [issue 342](https://github.com/seedds/nxnative/issues/342), a limit of this system build. `c1_full.tsv is stale` holds on partial libraries, which no full build has stamped.
- The "Navi" name label in the Great Deku Tree scene was missing on an earlier chain and has not been checked since. Not played yet: the Deku Tree dungeon, combat, later areas. Sound opens with no red line; movies and speech were not listened to. Physics issues reported in PR 1299 were not seen on this route (walking, the ladder, the camera).
- Resolved: dotted horizontal rows across the picture in play, in fog and light (GitHub issue 1537): the agl_ndsr_vr networks' HMMA calls outside a chain overwrote an accumulator a chain held ([An HMMA outside a chain overwrote the chain's accumulator](../../../docs/reference/shaders.md#an-hmma-outside-a-chain-overwrote-the-chains-accumulator)), since chain 23a1ea1db092; found by bisecting chains on the Kokiri Forest autosave (0f510fd5's chain clean, bd9f422d's not). Under the game's upscaler they had also grown into white blotches: [LDSM reads rows other lanes stored](../../../docs/reference/shaders.md#ldsm-reads-rows-other-lanes-stored).
- No iOS shader build or iPhone run has been done. Its memory use makes an iPhone unlikely as it stands.

## Found on this game

- [One Pro Controller read as two players](../../../docs/reference/services.md#one-pro-controller-read-as-two-players): resolved, no music in Kokiri Forest gameplay and its cutscenes; the controller applet opened over and over and the game kept its music suspended while it had focus.
- [A fixed frame step plays in slow motion on a slow Mac](../../../docs/reference/frame-rate.md#a-fixed-frame-step-plays-in-slow-motion-on-a-slow-mac): the frame-ratio division.
- [Frame-step stubs placed by their function](../../../docs/reference/rewriter.md#frame-step-stubs-placed-by-their-function)

- [Position invariance across shaders](../../../docs/reference/shaders.md#position-invariance-across-shaders): white shapes on plants and bushes for single frames in Kokiri Forest, from the foliage's mesh pre-pass and mesh colour pass rounding the position apart.
- [GPU event waits order work across queues](../../../docs/reference/nvn-objects.md#gpu-event-waits-order-work-across-queues): the lighting producer-to-consumer dependency is proven in native SDK code and 297 live traced frames; the halo disappears when it is honored.
- [128-bit raw global loads read one word at a time](../../../docs/reference/shaders.md#128-bit-raw-global-loads-read-one-word-at-a-time): the foliage mesh shaders read 464 of their 506 raw words as pieces of 116 `LDG.128`s, one lookup and one load each; GPU p50 16.3 → 12.6 ms with the occlusion fix below.
- [Occlusion conditions read once landed](../../../docs/reference/rendering.md#occlusion-conditions-read-once-landed): 213 conditions on its occlusion queries in a dumped frame, all landed at replay and 42% false over the route, were drawn anyway; GPU p50 17.06 → 16.44 ms on an M4 Pro.
- [Conditional rendering survives queue continuations](../../../docs/reference/rendering.md#conditional-rendering-survives-queue-continuations): event/fence splits lost disabled draws and pending counter values, causing the remaining patchy scene flashes.
- [Native mesh draws omitted while their pipeline compiles](../../../docs/reference/shaders.md#native-mesh-draws-omitted-while-their-pipeline-compiles): compile the first demanded native mesh pipeline before its draw; the prior background path omitted geometry and depth while loading.

- [An old NUP cache stamp makes the build unpack again](../../../docs/reference/packing.md#an-old-nup-cache-stamp-makes-the-build-unpack-again): after a packer update the v131072 image is checked against the NUP in 21.6 s and kept, instead of unpacked again.
- [Uncompressed storage beside storage the GPU writes](../../../docs/reference/nvn-objects.md#uncompressed-storage-beside-storage-the-gpu-writes): resolved, the ground opening in holes after walking out of a cave and back (the terrain's height and blend maps came out as zeros once the first normal map had been drawn into their pool); a reload had hidden it.
- [A damaged file in a NUP or a dump has no hash to fail](../../../docs/reference/packing.md#a-damaged-file-in-a-nup-or-a-dump-has-no-hash-to-fail): a contributor's NUP held three `.zs` textures beginning with zeros, and the background loader reloaded the fairy fountain model for ever (412% CPU); this repository's copy has none.
- [A control section's words read as a BAHS entry](../../../docs/reference/shaders.md#a-control-sections-words-read-as-a-bahs-entry): six map rows that were no shaders, one of them failing the build; `tera_common` gave its variation pairs once its row was gone.
- [Freeing a memory pool during a texture ID walk](../../../docs/reference/nvn-objects.md#freeing-a-memory-pool-during-a-texture-id-walk): the `-[NvPkg buffer]: unrecognized selector` crash after a save or a scene change.
- [HMMA chains keep their matrices in the SIMD-group](../../../docs/reference/shaders.md#hmma-chains-keep-their-matrices-in-the-simd-group): the NDVE movie networks behind the title and the opening, 14.8 → 11.4 ms of compute a frame on this M6.
- [Raw global memory lookups that start from their last entry](../../../docs/reference/shaders.md#raw-global-memory-lookups-that-start-from-their-last-entry): the foliage, vertex and compute shaders read structures word by word through loaded addresses; about 2 ms less GPU a frame at the spawn point.
- [The GPU idles with the next command buffer already committed](../../../docs/reference/frame-rate.md#the-gpu-idles-with-the-next-command-buffer-already-committed): the 25-40 ms frames.
- [The 30 Hz display link in fullscreen on a fixed-rate screen](../../../docs/reference/frame-rate.md#the-30-hz-display-link-in-fullscreen-on-a-fixed-rate-screen): 66.7 ms frames at a 30 fps cap in fullscreen on a MacBook Air M4, with the frame-delta change that applies the cap.
- [Pool tables and readback buffers made anew each frame](../../../docs/reference/memory.md#pool-tables-and-readback-buffers-made-anew-each-frame): about 1,500 residency changes per 300 frames.
- [Pool tables patched instead of built whole](../../../docs/reference/nvn-objects.md#pool-tables-patched-instead-of-built-whole): the game registers something between most of its draws, its streamed textures map and unmap virtual pool runs dozens of times a second, finalized descriptors stay registered and textures take over each other's storage; each of these walked the 33,025-entry texture table again, about 53 s of a seven-minute walk.
- [Pool shaders taken as depth readers](../../../docs/reference/rendering.md#pool-shaders-taken-as-depth-readers): about 80 extra passes a frame, and half the frames over budget.
- [A pipeline archive on an external drive is read into memory](../../../docs/reference/memory.md#a-pipeline-archive-on-an-external-drive-is-read-into-memory): 3.5 GB of swapped memory, now mapped.
- [A texture in a sparse pool came out CPU-written at its first use](../../../docs/reference/memory.md#a-texture-in-a-sparse-pool-came-out-cpu-written-at-its-first-use): found by the unit test, on this profile's `tex_dirty_upload`.
- [Textures made for GPU use kept from their CPU rewrites](../../../docs/reference/nvn-objects.md#textures-made-for-gpu-use-kept-from-their-cpu-rewrites): the terrain tiles' height, blend and hole maps rewritten as tile slots are reused; flat blue holes in the ground after an hour of play.
- [`EventFd` needs no network](../../../docs/reference/services.md#eventfd-needs-no-network)
- [No virtual audio input devices (SDK 22)](../../../docs/reference/audio.md#no-virtual-audio-input-devices-sdk-22)
- [`nn::ndve`'s movie enhancement file](../../../docs/reference/shaders.md#nnndves-movie-enhancement-file)
- [Task and mesh shaders in BNSH, and indirect mesh draws](../../../docs/reference/shaders.md#task-and-mesh-shaders-in-bnsh-and-indirect-mesh-draws)
- [Indirect task / mesh draws on the encode thread](../../../docs/reference/rendering.md#indirect-task--mesh-draws-on-the-encode-thread): the iOS app aborted when a save loaded.
- [F2IP](../../../docs/reference/shaders.md#f2ip)
- [A pixel shader's depth after a partly written target](../../../docs/reference/shaders.md#a-pixel-shaders-depth-after-a-partly-written-target): 46 depth-writing pixel shaders read their depth from the wrong register, agl_common's depth pass among them.
- [An HMMA outside a chain overwrote the chain's accumulator](../../../docs/reference/shaders.md#an-hmma-outside-a-chain-overwrote-the-chains-accumulator): dotted rows across fog and light in play.
- [LDSM reads rows other lanes stored](../../../docs/reference/shaders.md#ldsm-reads-rows-other-lanes-stored): white blotches over Kokiri Forest through agl's upscaler on an M4 Pro.
- [A shader that writes a whole frame through raw global memory](../../../docs/reference/frame-rate.md#a-shader-that-writes-a-whole-frame-through-raw-global-memory)
- [Stage memory byte stores through a compare-and-swap loop](../../../docs/reference/shaders.md#stage-memory-byte-stores-through-a-compare-and-swap-loop): 515 shaders, the foliage mesh shaders among them; pull request #1503 measured the foliage pass at 8.3-8.6 ms on an M3 Pro with the loop, while on an M6 the loop, the store and AND / OR measure the same.
- [Memory pools nothing gave an address to stay out of the raw pool table](../../../docs/reference/memory.md#memory-pools-nothing-gave-an-address-to-stay-out-of-the-raw-pool-table)
- [Shaders report which textures they read through a pool](../../../docs/reference/memory.md#shaders-report-which-textures-they-read-through-a-pool)
- [Repeated GPU out-of-memory failures end the game](../../../docs/reference/memory.md#repeated-gpu-out-of-memory-failures-end-the-game)
- [Pools that hold shader code made resident to key the shaders](../../../docs/reference/memory.md#pools-that-hold-shader-code-made-resident-to-key-the-shaders): first reported here (222 pools, 334 MB on a build with other changes); on main the raw pool table makes those pools resident anyway (4,276 resident pools before the fix, 4,277 after, on the village walk).
- [A GPU whose access macOS revoked stops the game](../../../docs/reference/rendering.md#a-gpu-whose-access-macos-revoked-stops-the-game): after a GPU hang or page faults (issue #1326), nothing was drawn for about 70 s before the game aborted, and in full screen WindowServer's watchdog killed it.
- [A texture ID with no texture kept its cached view](../../../docs/reference/rendering.md#a-texture-id-with-no-texture-kept-its-cached-view): the page faults at f3,677 and f4,851 with the render-target reclaim on.
- [Compute pipelines compiled at first use](../../../docs/reference/shaders.md#compute-pipelines-compiled-at-first-use): the offline archive holds a compute pipeline for each of the 4,125 compute shaders (480 MB, 204 s on an `applegpu_g18g` Mac). From `save_ref` to the village with an empty prewarm list, all 103 compute pipelines came from it and none were built. PR #1522 measured what that saves with the Metal cache cold: 195 s of pipelines on the submit thread before, 155 s of it in the title movie's twelve kernels.
- [Compute pipelines outside the bundled archive built at every start](../../../docs/reference/shaders.md#compute-pipelines-outside-the-bundled-archive-built-at-every-start): without the bundle, the first start's flushes wrote 88 compute pipelines into the device's archive, and the second start took 88 from it.
- [Metal's archiver store filled by one flush period](../../../docs/reference/rendering.md#metals-archiver-store-filled-by-one-flush-period): a compacting prewarm of 40,000 rows filled the archiver's store, Kakariko drawn without 1,502 pipelines (PR #1735).
- [Texture IDs of one storage share one packaged texture](../../../docs/reference/nvn-objects.md#texture-ids-of-one-storage-share-one-packaged-texture)
- [A texture shared by its packaged texture's serials left the residency set with one of them](../../../docs/reference/nvn-objects.md#a-texture-shared-by-its-packaged-textures-serials-left-the-residency-set-with-one-of-them): GPU page faults 15-45 minutes into play (issue #1326), on 260x260 terrain tiles made GPU textures at the GPU's first write.
- [Finalizing a copy of a texture object](../../../docs/reference/nvn-objects.md#finalizing-a-copy-of-a-texture-object)
- [Dynamic resolution that never moves, and draw passes that wait for each other](../../../docs/reference/frame-rate.md#dynamic-resolution-that-never-moves-and-draw-passes-that-wait-for-each-other)
- [Dynamic resolution at its floor while the GPU has time to spare](../../../docs/reference/frame-rate.md#dynamic-resolution-at-its-floor-while-the-gpu-has-time-to-spare): a stale frame-start timestamp, and event waits that idled the GPU
- [A full table of running GPU writes ends passes for nothing](../../../docs/reference/frame-rate.md#a-full-table-of-running-gpu-writes-ends-passes-for-nothing)
- [Float atomics in storage memory](../../../docs/reference/shaders.md#float-atomics-in-storage-memory)
- [textureGatherOffsets and a loop over its offsets](../../../docs/reference/shaders.md#texturegatheroffsets-and-a-loop-over-its-offsets)
- [Image atomics on a 32-bit colour texture](../../../docs/reference/shaders.md#image-atomics-on-a-32-bit-colour-texture)
- [A host's own store in a fragment shader moves its depth test](../../../docs/reference/frame-rate.md#a-hosts-own-store-in-a-fragment-shader-moves-its-depth-test)
- [Dead-code removal dropped a coordinate of a multi-output instruction](../../../docs/reference/shaders.md#dead-code-removal-dropped-a-coordinate-of-a-multi-output-instruction)
- [Mesh stage memory reserves the primitive index bytes for every primitive block](../../../docs/reference/shaders.md#mesh-stage-memory-reserves-the-primitive-index-bytes-for-every-primitive-block): the white blotches over Kokiri Forest's foliage and ground (light tiles drawn with corrupt triangles).
- [Mesh attributes: every vertex block before the primitive blocks](../../../docs/reference/shaders.md#mesh-attributes-every-vertex-block-before-the-primitive-blocks): the Poe Sisters and Phantom Ganon paintings' per-primitive colours (pull request #1590), and the point size of the 5 point mesh shaders.
- [The alias flush on every encoder's end barrier](../../../docs/reference/frame-rate.md#the-alias-flush-on-every-encoders-end-barrier): the main submission's 8 command allocators at 36-80 MB each and 6-15 ms a frame in scenes of about 150 passes before main's Ocarina fixes; on main at 2eb71820, CPU-visible Metal memory 392 → 298 MB and no measurable frame-time change (M3 Pro, 18 GB).
- [Live resolution variants share physical image storage](../../../docs/reference/rendering.md#live-resolution-variants-share-physical-image-storage): the dynamic-resolution depth buffer (`COMPRESSIBLE` alone) kept 15-16 live sizes at one offset, 14.5 MB each, as separate Metal textures (GPU allocation 7,710 → 7,520 MB in Kokiri Forest before main's Ocarina fixes; the 17 sizes still form on main at 2eb71820, where all Depth32Float textures take 225 MB with them shared).
- [Pixel shader inputs the mesh shader does not write](../../../docs/reference/shaders.md#pixel-shader-inputs-the-mesh-shader-does-not-write): the foliage point meshes' pipelines (pixel shaders reading generic attribute 5 that no mesh output writes).
- [Mesh outputs as wide as their pixel shaders read](../../../docs/reference/shaders.md#mesh-outputs-as-wide-as-their-pixel-shaders-read): the foliage mesh `626fbf48041cb82b`, padded to 35,840 bytes of mesh output, past Metal's 32 KB.
