Repository navigation
A game's own upscaler drawn by MetalFX, the player's choice in the launcher: Donkey Kong Bananza's NDSR network 3.5-5 ms → about 1 ms a frame on an M1 - #1086
Closed
AdyaGMD wants to merge 1 commit into
Conversation
…uncher: Donkey Kong Bananza's NDSR network 3.5-5 ms → about 1 ms a frame on an M1 Donkey Kong Bananza upscales its frame with agl's NDSR network, one compute dispatch between the render-resolution passes and the output-resolution ones. On an M1 in handheld mode (960x540 → 1920x1080) it takes 3.5-5 ms of the heavy areas' frame: its HMMA products are emulated and its shared-memory matrix loads move their row addresses between lanes with shuffles. MetalFX's spatial scaler does the same job in about 1 ms. The profile key metalfx_upscaler names a game's upscaler shaders (Bananza: the 24 NDSR compute variants). For such a game the launcher shows Game's upscaler (DM_UPSCALER: Game's own, the default, or MetalFX). With MetalFX, dispatch gives those shaders' dispatches to up_mfx_encode: MetalFX's Metal 4 spatial scaler in HDR mode from the input rectangle to the output rectangle (the push constants c[24]: origin and inclusive last texel of each), through RGBA16F scaler textures when the game's formats or rectangles need it (Bananza's R11G11B10F), straight otherwise. MetalFX is encoded through rec_cb_block, so on the encoding thread it gets the real command buffer. An output not larger than the input, an indirect dispatch, an output texture that is not a render target, or a size MetalFX refuses runs the game's shader. The rectangle decoding, HDR mode and the encoding-thread handling follow the NDSR replacement in the iPhone port's PR seedds#1073. Co-authored-by: givethesourceplox <272928635+givethesourceplox@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 tasks done
seedds
added a commit
that referenced
this pull request
Nov 3, 2026
…uncher: Donkey Kong Bananza's NDSR network 3.5-5 ms → about 1 ms a frame on an M1 (#1086) The launcher's new Game's upscaler row (DM_UPSCALER=game|metalfx) is shown for games whose shader map holds agl's NDSR network: game.py takes the compute shaders found in agl_ndsr.pck (Bananza's 24, Splatoon Raiders' 20) into DM_GAME_UPSCALER_KEYS, with no profile key. With MetalFX, up_mfx_encode replaces such a dispatch with MetalFX's Metal 4 spatial scaler in HDR mode between the rectangles of its push constants, through RGBA16F where the game's formats or rectangles need it; anything else keeps the game's shader. MetalFX encodes on the real command buffer through rec_cb_block (nvn_rec.h), on the encoding thread when it runs. NVN2's DLSS (dlss_eval) now goes the same way: on the encoding thread it stopped the host at its first evaluation (DmRecCB has no stand-in for -useResidencySet:); check_t_dlss_mfx covers it with the thread off and on. Co-authored-by: Adya <114347520+AdyaGMD@users.noreply.github.com> Co-authored-by: givethesourceplox <272928635+givethesourceplox@users.noreply.github.com>
Owner
|
Landed in 85468b6, with you and givethesourceplox as co-authors. Thank you for this. The MetalFX path, the RGBA16F conversion, the fallbacks and
Not checked: the iPhone, and Raiders with MetalFX. |
2 of 3 tasks
3 tasks done
seedds
added a commit
that referenced
this pull request
Nov 3, 2026
…e's first upscaler key (DM_GAME_UPSCALER_KEYS), not Donkey Kong Bananza's 7629d857a0a93833, and a profile without upscalers swaps none; make run failed it for every other game (#1086)
Know-It-All-Brother
pushed a commit
to Know-It-All-Brother/nxnative
that referenced
this pull request
Nov 9, 2026
…uncher: Donkey Kong Bananza's NDSR network 3.5-5 ms → about 1 ms a frame on an M1 (seedds#1086) The launcher's new Game's upscaler row (DM_UPSCALER=game|metalfx) is shown for games whose shader map holds agl's NDSR network: game.py takes the compute shaders found in agl_ndsr.pck (Bananza's 24, Splatoon Raiders' 20) into DM_GAME_UPSCALER_KEYS, with no profile key. With MetalFX, up_mfx_encode replaces such a dispatch with MetalFX's Metal 4 spatial scaler in HDR mode between the rectangles of its push constants, through RGBA16F where the game's formats or rectangles need it; anything else keeps the game's shader. MetalFX encodes on the real command buffer through rec_cb_block (nvn_rec.h), on the encoding thread when it runs. NVN2's DLSS (dlss_eval) now goes the same way: on the encoding thread it stopped the host at its first evaluation (DmRecCB has no stand-in for -useResidencySet:); check_t_dlss_mfx covers it with the thread off and on. Co-authored-by: Adya <114347520+AdyaGMD@users.noreply.github.com> Co-authored-by: givethesourceplox <272928635+givethesourceplox@users.noreply.github.com>
Know-It-All-Brother
pushed a commit
to Know-It-All-Brother/nxnative
that referenced
this pull request
Nov 9, 2026
…ing them: lint-c's ratchet passes again (seven nullability findings from seedds#1086, seedds#1084 and seedds#1073, whose own runs were cancelled)
Know-It-All-Brother
pushed a commit
to Know-It-All-Brother/nxnative
that referenced
this pull request
Nov 9, 2026
…e's first upscaler key (DM_GAME_UPSCALER_KEYS), not Donkey Kong Bananza's 7629d857a0a93833, and a profile without upscalers swaps none; make run failed it for every other game (seedds#1086)
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 and why
Donkey Kong Bananza upscales its frame with agl's NDSR network (
agl_ndsr.pck): one compute dispatch between the render-resolution passes and the output-resolution ones, which then draw the HUD over it. On an M1 in handheld mode (960x540 → 1920x1080) it is the largest single item of a heavy frame, 3.5–5 ms (DM_NVN_GPUPROF), because its HMMA products are emulated and its shared-memory matrix loads move their row addresses between lanes with shuffles (41 % of its time). MetalFX's spatial scaler does the same job, same sizes, in about 1 ms.A new launcher option: Game's upscaler. The menu before the game starts gets a Game's upscaler row with Game's own (the default) and MetalFX. It appears only for games whose profile names their upscaler shaders (the new profile key
metalfx_upscaler; today only Bananza, its 24 NDSR compute variants), so other games' menus do not change. It is a choice and not a default because the picture is then Apple's scaler rather than the game's trained network. It is not the same as the existing Upscaling row: that one scales the finished picture, HUD included, to the screen; this one replaces the game's own step inside the frame. Both can be on.docs/settings.mdexplains it for players; the variable isDM_UPSCALER=game|metalfx.How it works (
up_mfx_encodeinnvn_mtl.m). A dispatch of a named shader is replaced by MetalFX's Metal 4 spatial scaler in HDR mode, from the input rectangle to the output rectangle the shader would use (its push constantsc[24]: origin and inclusive last texel of each). Bananza's colour is R11G11B10F, which MetalFX does not take, so the input rectangle is drawn into an RGBA16F scaler texture and the result drawn into the output rectangle (copy_t2t_draw); RGBA16F textures with whole rectangles go straight through. MetalFX is encoded throughrec_cb_block(new innvn_rec.h), so on the encoding thread (iOS's default) it gets the real command buffer. The game's shader still runs for an output not larger than the input, an indirect dispatch, an output texture that is not a render target, or a size MetalFX refuses.Credit: the rectangle decoding, HDR mode and the encoding-thread handling follow @givethesourceplox's NDSR replacement in #1073 (credited as co-author). This PR differs from that one in being a player setting in the launcher, covering every NDSR variant and size ratio, and encoding on the Metal 4 queue instead of a Metal 3 queue synchronized by events.
Checked
Tests:
make -C dm/gfx/tests GAME=040074A01BF12000 check_t_upscaler_mfx: a named shader's 960x540 → 1920x1080 dispatch is drawn by MetalFX; a cropped R11G11B10F input with a highlight above 1.0 into an offset output rectangle, every pixel inside and outside checked; an output no larger than the input and an unnamed shader keep the shader; nothing changes without the switch; also on the encoding thread.dm/tools/tests/test_game_profile.py(the key's values) andtest_settings.py(the row shows for Bananza with "Game's own" as default, not for NieR:Automata);test_docs.py.Games run, with title ID and version: Donkey Kong Bananza
040074A01BF12000v458752, handheld, the same heavy area, on a build with this change, the border-colour change (Pixel shaders without the border-colour correction in their main library: it spilled registers in every pixel where it never ran #1032) and mesh draw runs (a separate PR):No visual difference noticed between the two in play.
The launcher's new row (shown only for Bananza):
The same heavy area with the frame-rate counter, the game's own upscaler (NDSR):
With MetalFX:
Devices and OS: MacBook Pro (13-inch, M1, 8-core GPU), macOS 26.6.2, Xcode 27.2.
scripts/regress.py: not run. The shader chain does not change; the host change only acts for a game withmetalfx_upscalerandDM_UPSCALER=metalfx.Not checked: the iPhone. One open note (in the reference entry): a standalone MetalFX test on the M1 intermittently produced invalid pixels at small sizes, and one handheld run showed one wrong HDR pixel; not seen in play since.
Known Metal-side quirk: MetalFX's Metal 4 scaler stops under Metal validation (
MTL_DEBUG_LAYER=1) on a barrier-stage setting it does not expose (_outputTextureBarrierStages not set), so that test runs without validation; Donkey Kong Bananza on iPhone: border corrections out of the main pixel libraries, NDSR replacements, pacing and fence fixes #1073 reports the same.Docs
docs/reference/rendering.mdentry ("A game's own upscaler drawn by MetalFX"), the game note anddocs/settings.md;python3 dm/tools/docs_symptoms.pywas run🤖 Generated with Claude Code