Skip to content

[DRAFT] nvn: opt-in native-size window copy (experimental) - #1140

Closed
oliverames wants to merge 9 commits into
seedds:mainfrom
oliverames:experimental-native-size-window-copy
Closed

oliverames wants to merge 9 commits into
seedds:mainfrom
oliverames:experimental-native-size-window-copy

Conversation

@oliverames

@oliverames oliverames commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

This is an experimental, off-by-default window-copy path. For an explicitly allowlisted pure-copy shader, it redirects the final window pass into a host target sized to the drawable's letterboxed viewport, preserves the game's shader and sRGB target view, then presents that target 1:1. It removes one resample; the present draw remains.

DM_NVN_WINDOW_COPY=[verify:]<fragment key>[:<vertex key>][,...] enables it. verify: checks and logs the gates without redirecting. The change includes the coverage proof for a two-triangle quad, associated t_cover cases, and ownership through queued-present completion or drop. Each window texture gains a host target; the original full-size window texture remains allocated.

Late original-window access is a fail-stop diagnostic. The redirected picture isn't copied back, so a later read can see stale contents and contaminate game state. A [RED] stop invalidates the run; it isn't a repaired fallback. Unusual cross-submission paths haven't been formally proved, and resize/finalization still need runtime coverage.

Scope and dependencies

Based on upstream main 1b94fab298fb1014314e776d33a701b5f68c6c3a, with only five changed files. Extracted from a local source snapshot based on c7ba23df. All retained hunks matched current main exactly except one context adjustment beside mtl_tex_release: current main's was_live optimization is preserved. No unrelated source or upstream changes were imported.

This doesn't include the drawable capture in #1136, half/byte attribute decoding in #1137, the upscaler size-transition logger, profiler counter-order fix, or DKB game note. The feature has no source dependency on #1137, but DKB's half-float/unsigned-byte quad requires #1137 to pass the proof. That dependency is separate and isn't included here. Neither existing PR was changed.

Evidence and remaining validation

The parent reported the following on an earlier local source version, before the newest late-access checks:

  • At least 70 seconds of physical iPhone 17 Pro Max gameplay, with all three 2880x1620 window textures redirected to 2346x1320, the actual drawable size. The game's fragment shader and sRGB view were retained.
  • A 2346x1320 drawable capture and no [RED] errors. Measured gameplay windows held 33.34 ms display intervals; a later route had 20 fps dips, so this isn't a claim of sustained performance across routes.
  • t_cover: 31 checks passed, including 16 new quad-proof checks. These aren't GPU or lifetime tests.

The latest late-access checks have since run in a combined local build on Newt, a physical iPhone 17 Pro Max running iOS 27.2. The installed executable SHA-256 was 37de3a284c1e27176d3d274fd7384ae9d99d6d6aef1659cbd7f24380866551fa, with shader chain 215a6d278114. This build also includes MetalFX, border-shader optimization and mesh batching, so these results do not isolate this PR's performance effect.

Two docked routes each drove 70 seconds of movement and attacks, with fresh host logs, constructor memory traces and actual-drawable PNGs. Both retained the logged 1676x943 to 2304x1296 gameplay scaler sizes and produced 2346x1320 captures with intact terrain and character detail. No window-copy fail-stop was reported. At thermal state 0, all six complete 300-frame windows had p99 33.34 ms intervals and zero drops. A repeat at thermal state 1 had three 50 ms windows, two 33.34 ms windows and one dropped frame. Sustained 30 fps remains unresolved.

A separate 70-second handheld route exercised the refusal path: the cropped scissor failed the whole-window proof, zero passes were redirected, and the ordinary crop presentation remained intact. Local evidence is recorded under logs/dkb-sharpness-2026-11-03/ in border-summary.json, border-handheld-summary.json, border-restored-summary.json, and the corresponding logs, memory traces and PNGs.

This draft was extracted and checked for file/diff scope, including the published file bytes. No build or device run was performed for this exact head, and there is no published-head regression report, GPU/lifetime test, resize/finalization runtime coverage or cross-game validation. The repository's required build, lint and selected-game regression checks remain outstanding. This isn't ready to merge.

CI prerequisite update: this head includes the reviewed shared lint repair from #1164. The updated renderer and window-copy fixture have zero file/check pairs above or below the LLVM 23.1.4 baseline. The production offscreen presentation fixture passes 32 checks with Metal API validation; 11 documentation tests, the environment-switch table and whitespace checks also pass. The three documented C-registry analyzer exceptions remain narrow and unchanged. Once #1164 lands, its prerequisite changes drop from this PR's diff. Fresh hosted CI, physical-screen/display-link behavior and exact-head gameplay remain pending; prior phone fixtures and combined DKB runs retain their recorded source identities.

@github-actions github-actions Bot added nvn NVN on Metal and its tests (dm/gfx/nvn, dm/gfx/tests) docs Documentation labels Nov 3, 2026
@oliverames

Copy link
Copy Markdown
Contributor Author

@seedds, an update on Switch 2 games running on iPhone: I've continued testing Donkey Kong Bananza on a physical iPhone 17 Pro Max (A19 Pro, iOS 27.2).

The combined local build retains a 1676×943 gameplay scene, MetalFX output at 2304×1296, and a 2346×1320 actual drawable. A 350-second movement/attack run had 33 complete reporting windows: 26 at 33.34 ms on-screen p99 and seven at 50 ms, with four dropped frames and one discarded frame reported. Thermal state stayed 0. The slow windows have nearby game-requested interval changes; this does not establish their cause. Fur shimmer remains unresolved.

A separate 70-second comparison changed only DM_PRESENT_LATENCY to 2. All six complete windows had 33.34 ms p99 and no drops/discards at thermal state 1. That's a bounded result, not a sustained-performance claim or a proposed default change.

I also ran the existing t_clear_ds fixture against the combined renderer in a separate signed iPhone app: all 11 cases and 59 checks passed on A19 Pro with Metal API Validation explicitly enabled. This includes the full-depth/masked-stencil cases from your landed depth-clear fix. The wrapper includes the fixture unchanged and records source hashes and GPU readback results. This is physical iPhone coverage of the shared clear paths; other titles and devices still need their own validation.

These runs are from the combined local build, not this PR's exact head. This PR stays draft pending presentation lifetime/resize/finalization coverage and resolution of the upstream draw-wrapper conflict. Commit 099e3cd fixes the environment-table ordering failure; the targeted test passes locally. I'm reconciling the remaining work into focused PRs and will reuse existing contributions where the work overlaps, rather than duplicate the border proposals.

@oliverames

Copy link
Copy Markdown
Contributor Author

The upstream conflict is resolved in c432195, preserving mesh-task dispatch and window-copy tracking. Commit 3d436cf adds 17 focused checks for window-copy target retirement, texture-object reuse, crop mapping, discarded-present cleanup and late-access/second-draw fail-stop guards.

These checks passed on the physical iPhone 17 Pro Max (A19 Pro, iOS 27.2) with Metal API Validation Enabled. The unchanged fixture was compiled in a Debug/O1 iOS app and called on a background thread. Run ID: f5647fc0-a71b-4549-9ab2-d2223f28badd; fixture SHA-256: 3fd04c2336e58147ce5b8e98b7fadf1bc3c0ef8c0d7624469dc203a366df7025. The fixture deliberately triggers three RED fail-stop messages; all corresponding checks pass. The Mac invocation is make -C dm/gfx/tests GAME=040074A01BF12000 check_t_window_copy. The reusable iPhone runner is still being prepared for a separate contribution.

The fixture seeds window-copy entries and calls production ownership paths. It does not prove wc_try target creation/resizing, GPU-inflight presentation or redirected pixel output. Those remain open, and this PR stays draft.

The longer DKB latency2 experiment also failed to establish steady pacing: a 350-second route had nine slow reporting windows at thermal state 0. Scene 1676×943, MetalFX 2304×1296 and drawable 2346×1320 remained intact. I restored default latency1 and completed another 70-second gameplay check with fresh log and memory data; it also had dips at thermal state 1. Neither setting is a sustained stability fix. These gameplay results still describe the combined local build, not this PR head.

@oliverames

Copy link
Copy Markdown
Contributor Author

@seedds The physical iPhone regression coverage for this Switch 2 games on iPhone work now includes production wc_try target creation, reuse and resize. Commit 1531dd7 passes 27 checks with 0 failures on Newt (iPhone 17 Pro Max, A19 Pro, iOS 27.2), with Metal API Validation Enabled in the device log. The same fixture passes on the Mac.

The new case creates a 4×4 target for a synthetic 8×8 window, takes a present reference, queues an offscreen GPU clear/readback behind a shared-event gate, then resizes to 2×2. It checks that the old target remains registered, verifies all 16 returned pixels after releasing the gate, and verifies retirement after releasing the present reference. Run ID: 8cda7ca7-7c56-433a-a117-fb398c3f0b89; fixture SHA-256: 8ce421b6088bd40900945b9b0c5d517231228ed3c1a3da0e16664525da3ceb92.

Limits remain explicit: shader reflection and draw state are synthetic; the clear uses a direct Metal encoder, and release is manual after command completion. This does not test the production redirected copy draw, actual presentation, or its completion callback. No renderer or DKB settings changed, and no exact-PR-head gameplay or pacing/fur improvement is claimed. Keeping this PR draft. The generic iPhone runner is in #1153; this fixture uses the local runner's window_copy selection.

@oliverames

Copy link
Copy Markdown
Contributor Author

@seedds: the regression now exercises the production redirected textured draw, including attachment selection and viewport scaling, then verifies all 16 pixels against a literal asymmetric color pattern. The fixture passed 31 checks with zero failures on both the Mac and the physical iPhone 17 Pro Max (Apple A19 Pro, iOS 27.2), with Metal API Validation Enabled in the device log. The three RED messages are deliberately triggered by the existing negative guard cases.

This extends the Switch 2 games running on iPhone work prompted by Donkey Kong Bananza. The test may protect other titles using the same window-copy path. It does not establish game-shader equivalence, actual drawable presentation, or the production present completion callback; the PR remains draft.

Reproduce the Mac check with make -C dm/gfx/tests GAME=040074A01BF12000 check_t_window_copy. The physical run used the local iPhone fixture wrapper (the standalone clear_ds runner is proposed in #1153), Debug configuration, default iOS 26 deployment target, and the unchanged fixture. Run ID: 243d1f8c-2a08-4f17-9756-0d5e4584b829; fixture SHA-256: 78972ac40e7a4b53ab85c5f1456b1de69d4308157a87ebeb8c2f81e2dcc3a68d. No renderer change or DKB performance improvement is claimed by this test commit.

@oliverames

Copy link
Copy Markdown
Contributor Author

Added the production present-completion regression in 957061c. From dm/gfx/tests, make GAME=040074A01BF12000 check_t_window_copy passes 32 checks with no failures on Apple M2 Pro with Metal API validation enabled. Parent review and a separate rerun confirmed the result.

The test redirects the asymmetric textured draw, enqueues the window, invokes the production display-link callback with an offscreen drawable, and gates GPU execution while resizing. Completion releases the retired target without a manual release, and readback preserves all 16 expected drawable pixels. The three RED messages are expected negative-guard cases; no Metal validation errors appeared.

This remains draft. The earlier 31-check fixture passed on iPhone 17 Pro Max, but this new completion case has only run on Mac. Visible screen output and real display-link scheduling remain unverified by this fixture. No renderer behavior changed in this commit.

@oliverames

Copy link
Copy Markdown
Contributor Author

Fixed the fixture-specific findings in c4f44f2. Shader-compilation failure now releases the registered window and restores the present-list count; vertex-allocation failure goes through the existing registry cleanup. The buffering call is now checked setvbuf.

The cleanup alone removed the pr ownership warning. Three remaining diagnostics arise immediately after serial_put stores a CFBridgingRetain reference in its C hash table. That table releases references on deletion; the fixture's lifecycle checks cover target retirement. I added three line-scoped RetainCount exceptions with the owning and releasing paths stated, following the existing t_image_attachment_store.m precedent. No baseline growth or blanket analyzer disable was added. The targeted LLVM 23.1.4 analyzer now reports no fixture warnings. Inherited renderer findings remain separate and are addressed by #1164; this does not establish a green full CI run.

The updated executable behavior passed 32 checks with Metal API validation on M2 Pro. No allocation-failure injection or new iPhone run was performed. The prepared build-04 predates this cleanup and must be rebuilt before exact-head phone verification. This PR remains draft; physical presentation and sustained gameplay gaps are unchanged.

@github-actions github-actions Bot added host The Horizon host: SVCs, services, threads, memory (dm/host) tools Tools and scripts (dm/tools, scripts) labels Nov 4, 2026
@oliverames

Copy link
Copy Markdown
Contributor Author

@seedds, update on the experimental Switch 2 games running on iPhone window-copy PR: current head 312d6a8 includes the shared lint prerequisite from #1164. The production offscreen draw/present/completion regression passes 32 checks with Metal validation on M2 Pro, and targeted renderer/fixture analysis passes the ratchet. A signed iPhone fixture is prepared from this exact head but has not run; older Newt evidence covers the preceding 31-check fixture. This stays draft: actual physical presentation, display-link scheduling and sustained DKB gameplay on iPhone 17 Pro Max remain gaps, and the late-access path is still explicitly fail-stop rather than a safe fallback.

@oliverames

Copy link
Copy Markdown
Contributor Author

@seedds Physical iPhone update for the Switch 2 games running on iPhone work: the window-copy fixture built from current head 312d6a8efa215d16551c488d7607724af729a923 completed on Newt, iPhone 17 Pro Max / Apple A19 Pro GPU / iOS 27.2: 32 checks, 0 failures, with the device log explicitly reporting Metal API Validation Enabled. Run ID 78f3cb8b-3ade-48da-85a7-7de4654e30cc matches the signed build receipt. The three RED diagnostics are expected negative-guard cases.

The fixture exercises production target creation/reuse/resize, redirected textured draw and viewport scaling, asymmetric 16-pixel readback, gated offscreen present, and completion-driven retention/release. Reproducer: the window_copy fixture in #1153's iPhone runner with this checkout and your own team/bundle/device arguments.

The callback is manually invoked. This does not verify actual display-link scheduling or physical-screen output, and it is not a DKB pacing or sustained warm-gameplay result. The reusable presentation coverage may help other titles, but the feature remains experimental/draft. Our installed-artifact provenance is the recorded build/install/run-ID chain, not an independent hash read back from the phone executable.

@oliverames

Copy link
Copy Markdown
Contributor Author

@seedds Reconciled this Switch 2 / iPhone experiment with current upstream and the repaired #1164 prerequisite at head f62a2bc. The focused Mac Metal-validation fixture still passes 32 checks; 11 documentation tests and whitespace checks pass. New hosted CI is pending. The physical iPhone 17 Pro Max 32-check run reported above belongs to the preceding head 312d6a8e, not this merge. The new head remains draft pending its own device/gameplay verification; no pacing improvement is claimed.

@oliverames

Copy link
Copy Markdown
Contributor Author

Head a06e88c fixes the one clang-tidy finding this branch caused. Merged with main, this PR's changes to nvn_mtl.m (included by the test) made the analyzer report clang-analyzer-core.UndefinedBinaryOperatorResult at t_image_usage.m:66, where main has none: with a nil texture, read_level copies zero bytes and pixels stayed uninitialized. The fix is uint16_t pixels[64] = {0};. With it, clang-tidy 23.1.4 reports 0 findings for that file in the merged tree (it reports 1 without it), and no baseline entry was added.

clang-tidy run 41840587830 on a06e88c now fails only on four pairs from files this PR does not touch, which also fail on main: run 41819072419 at 0b8e0dc (dm/gfx/vk/hle_vk.m NullDereference, dm/host/hle_jit.c suspicious-realloc-usage, dm/host/hle_oe.c StdCLibraryFunctions, dm/host/web_apple.m NullablePassedToNonnull). No commit to dm/host or dm/gfx has landed on main since.

@oliverames
oliverames force-pushed the experimental-native-size-window-copy branch from a06e88c to c3a677d Compare November 5, 2026 14:47
@oliverames oliverames mentioned this pull request Nov 5, 2026
1 of 3 tasks
@oliverames
oliverames marked this pull request as ready for review November 5, 2026 15:17
@oliverames

Copy link
Copy Markdown
Contributor Author

Closing this experimental prototype PR; native-size window copies require per-game heuristics and will not be pursued.

@oliverames oliverames closed this Nov 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation host The Horizon host: SVCs, services, threads, memory (dm/host) nvn NVN on Metal and its tests (dm/gfx/nvn, dm/gfx/tests) tools Tools and scripts (dm/tools, scripts)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant