Repository navigation
DM_UPSCALER=metalfx takes agl's agl_ndsr_vr.pck networks too, and a variant with no curve and no power is drawn as one colour space: Ocarina of Time's upscaler is MetalFX's - #1459
Conversation
…ariant with no curve and no power is drawn as one colour space: Ocarina of Time's upscaler is MetalFX's Ocarina of Time (Switch 2) upscales 1536x864 to 2048x1152 with agl_ndsr_vr.pck's network (f8965bffbdf51d78 and others). game.py listed only agl_ndsr.pck's shaders, so the MetalFX option left it running; listed, its variants were refused, as their code holds no sRGB curve (R11G11B10F in and out). A variant with no curve constant and no MUFU.EX2 / MUFU.LG2 (which every curve takes, wherever its constants come from) neither encodes nor decodes, and is drawn as the linear shape, which converts nothing either. With MetalFX in its place, the dotted horizontal lines the network's output showed in fog and light shafts are gone. Tests: t_upscaler_mfx (Bananza's and Splatoon Raiders' profiles, game and metalfx, both encoding modes): no curve and no power -> one colour space; a power with no curve constant -> the shader runs; a MUFU that is no power does not count. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Port PR seedds#1459 and PR seedds#1461 onto origin/main 0cefa86. Keep the game upscaler and ordinary window placement as defaults. Select a requested screen before layer setup so backing-scale and local HDR capability reads use that display. Front-ends: DM_SCREEN accepts a display-name substring. The existing Game upscaler choice now recognizes agl_ndsr_vr and agl_ndsr_vr_light networks. Both options remain opt-in.
…MetalFX option draws its agl_ndsr_vr.pck upscale (main's dead-code fix removed the dotted lines at their source) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Tested this PR on top of main 0c7e88b (chain 844bf1a5ea8f) with The Legend of Zelda: Ocarina of Time (0400486024DEC000, v131072), Mac app, Mac Studio M5 Ultra, macOS 27.2. With The log classifies every variant as linear and runs MetalFX in HDR mode:
|
…ted colour: MetalFX gets its input squared into linear colour, and the picture is no longer washed out Ocarina of Time's agl_ndsr_vr and agl_ndsr_vr_light networks have no sRGB curve but square their output, keeping its sign (FMUL / HMUL2 of a register by itself with |x| on one side). Drawn as one colour space, the result stayed root-encoded: about the square root of the game's picture. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks @dinadur, reproduced here (M5 Pro) and fixed in d715366. Cause: these networks have no sRGB curve, but they aren't in one colour space either. A small pass before them square-roots the scene colour (gamma 2, into RGB9E5F), and the network writes its result squared with its sign kept, Fix: the host now detects that square in the shader's code, an FMUL or HMUL2 of a register by itself with The log now says |
|
This branch's game.py regex covers the _vr packs but its test change stops at agl_ndsr.pck's rows; test_game_profile.py still pins DM_GAME_UPSCALER_KEYS at 2 keys, so nothing would catch a VR-pack row dropping out again. One row fixes that, and it happens to be the pack Ocarina of Time's own upscaler key lives in: after the agl_common.sharcb row in the MAP fixture, and the expectation becomes Defined outside MAP the fixture's escape could bite: horizontal tab and newline as above, and the file treats MAP as one string split on 'cs_other.bin' elsewhere, so a new key in a pixel row or a source outside the three packs would break the split. Without the regex line this row turns the fixture green only while main's UPSCALER_SOURCE still holds, which is why it rides on this branch rather than standing alone (PR #1559 has it as a standalone; if this PR takes it I will close that). |
…ture, so the VR packs' upscaler keys stay covered (Ocarina of Time's fa3033d05c0a41d6) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks @bryanjeal, taken as you wrote it: the |
…ull requests brought in early (seedds#1459, seedds#1543)
|
From Ocarina of Time on our tree, where MetalFX's spatial scaler replaced the agl_ndsr_vr chain:
|
|
Tested on Ocarina of Time (0400486024DEC000, v131072) on a 16 GB M2 MacBook Air, macOS 27, applied on top of a current main-based host (7f50222 plus a few host PRs). Host only: no shader rebuild needed, chain unchanged.
Details and the comparison table: #1911. |
|
Thanks @FifteenPen and @dpadr. @FifteenPen: the game's network stays the default. @dpadr: thank you for the measurements and for #1911, which describes the cause this branch fixes. |
…tworks too, and a variant with no curve and no power is drawn as one colour space: Ocarina of Time's upscaler is MetalFX's Upstream pull requests applied in this commit (their authors' work, brought onto this tree with a three-way merge; the description is in each PR): - seedds#1459 by PromethOps (open): DM_UPSCALER=metalfx takes agl's agl_ndsr_vr.pck networks too, and a variant with no curve and no power is drawn as one colour space: Ocarina of Time's upscaler is MetalFX's
…nds once to half), seedds#1909 (fragment uniform reads bound to the binding length), seedds#1901 (dispatch_overlap on for Ocarina), seedds#1459 (MetalFX takes agl_ndsr_vr, no-curve variants linear), seedds#1903 (render scale stubs for Ocarina; replaces the seedds#1497 ceiling we carried) Hand-resolved: the mesh draw keeps the task isolation of seedds#1842 and the copy paths our nvn_tex_level_range / DM_SHARPEN; seedds#1497's stub, test and BINDING entry go; the build-keyed rule names the render scale function (main+0x31d3200). Chain e906c7467690. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014eD437mxrMnW2UwLZhpwc7 Upstream pull requests applied in this commit (their authors' work, brought onto this tree with a three-way merge; the description is in each PR): - seedds#1459 by PromethOps (open): DM_UPSCALER=metalfx takes agl's agl_ndsr_vr.pck networks too, and a variant with no curve and no power is drawn as one colour space: Ocarina of Time's upscaler is MetalFX's - seedds#1497 by givethesourceplox (open): Add a render-scale ceiling for Ocarina v131072 - seedds#1842 by ycarogabriel-lgtm (open): Ocarina of Time: opt-in task isolation (DM_NVN_ISOLATE_TASK), the Hi-Z task a5288 in command buffers of its own, a workaround for its GPU hangs on an M1 - seedds#1897 by Know-It-All-Brother (closed): HMMA with an f16 accumulator rounds once per 8 products, as Ampere does (chain change) - seedds#1901 by FifteenPen (open): The game's compute dispatches with no game barrier between them run side by side (profile key dispatch_overlap, on for Ocarina of Time): Kokiri Forest GPU p50 15.63 → 14.76 ms - seedds#1902 by fxd0h (open): HFMA2 rounds once to half, as Ampere does (chain change) - seedds#1903 by FifteenPen (open): Ocarina of Time takes the launcher's Render scale: the 3D views at that fraction of the game's own size, the dynamic resolution held at its top level (Kokiri Forest docked at 0.75: GPU p50 15.77 → 14.31 ms, 60 fps held) - seedds#1909 by oz-rinkliff (open): Bound translated fragment uniform reads to the NVN binding length
seedds#1901 seedds#1459 seedds#1928 seedds#1942 seedds#1940 seedds#1952 seedds#1611 seedds#2065 seedds#2083 seedds#2008 seedds#2079 seedds#2022 seedds#2075 seedds#2077 seedds#2020 seedds#2021 onto main 04811a6 Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014eD437mxrMnW2UwLZhpwc7 Upstream pull requests applied in this commit (their authors' work, brought onto this tree with a three-way merge; the description is in each PR): - seedds#1459 by PromethOps (open): DM_UPSCALER=metalfx takes agl's agl_ndsr_vr.pck networks too, and a variant with no curve and no power is drawn as one colour space: Ocarina of Time's upscaler is MetalFX's - seedds#1611 by Esteban-V (open): An argument block whose only change is a uniform buffer is patched instead of encoded again - seedds#1774 by uncraftablexd (closed): Compute threads that exit before a barrier keep arriving at it, and every shader loop has a cap (GPU hang defences), chain change - seedds#1824 by cocoman93 (open): Clamp texel fetches past a sampled 2D texture's edge: no hard edge in Ocarina of Time's mist - seedds#1901 by FifteenPen (open): The game's compute dispatches with no game barrier between them run side by side (profile key dispatch_overlap, on for Ocarina of Time): Kokiri Forest GPU p50 15.63 → 14.76 ms - seedds#1928 by FeReuss (open): Ocarina of Time: enc_thread on, the replay encodes on a thread of its own - seedds#1929 by FeReuss (open): Unused border corrections are compiled out of pipelines that bind no sampler with a twin (function constant DMSH_BORDER_FC) - seedds#1930 by FeReuss (open): A float add to storage memory with no result read is one native atomic add instead of a compare-and-swap loop - seedds#1940 by uncraftablexd (open): A prewarm list's lines after its #@after_first_frame line are built after the first frame, in the background, instead of in the prepare step (issue seedds#1747) - seedds#1942 by uncraftablexd (open): Frame step: late frames with the GPU idle do not step up, and a longer hold the GPU does not explain is probed - seedds#1952 by AdyaGMD (open): Compute moves ahead of scene passes past occlusion queries and conditional rendering; clears wait across dispatches - seedds#2008 by bquilty25 (open): nvn: reactive memory watchdog, 16-way view cache, and texture upload batching - seedds#2020 by padsiwono (open): Ocarina of Time v131072: Output Native draws the full output size instead of the game's 80 % frame (`DM_OUTPUT`) - seedds#2021 by padsiwono (open): Ocarina of Time v131072 renders at the launcher's Resolution (`DM_RENDER_SIZE`), docked - seedds#2022 by sleepyeyedjoe (closed): Ocarina of Time: large models no longer go black for one frame twice, 4–5 frames apart, when the game streams new textures into them (a texture ID a shader has read keeps its read mark when it gets another texture) - seedds#2030 by humanperzeus (open): A NaN colour at alpha 0 is returned as 0, as NVIDIA's blender takes a zero factor: Ocarina of Time's white clouds over the ferns are gone - seedds#2035 by Know-It-All-Brother (open): The shader build runs as worker processes, and no shader waits for a batch (Ocarina of Time's cold Mac map: 3,002 s to 1,298 s) - seedds#2065 by Raymon82777 (closed): A vertex library with layer entry points of its own gets bases for its main0 pairs: Ocarina of Time's 230 ms camera-turn hitch in Hyrule Field goes to 39 ms - seedds#2075 by sleepyeyedjoe (closed): Ocarina of Time: a patch of scenery no longer draws dark for one frame when the game gives it a sharper texture (a pool texture the walk does not make holds a stand-in of its own colours until its first read) - seedds#2077 by roandegraaf (closed): Ocarina of Time: fix the "plaid" terrain / missing texture tiles (GPU-drawn textures now reach the storage the game copies) - seedds#2079 by uncraftablexd (open): Render pipelines that share a vertex function are taken from the archive or compiled one at a time: the AGX driver crashes in createVertexProgramVariant's completion block - seedds#2083 by FifteenPen (closed): Ocarina of Time's prewarm list gets 41 more task / mesh pipelines from later play

What and why
The Legend of Zelda: Ocarina of Time (Switch 2,
0400486024DEC000v131072) upscales 1536x864 to 2048x1152 with agl's NDSR network fromagl_ndsr_vr.pck:f8965bffbdf51d78,fa3033d05c0a41d6and the other variants. It has two siblings,agl_ndsr.pckandagl_ndsr_vr_light.pck.DM_UPSCALER=metalfx(the launcher's "Game's upscaler: MetalFX") is meant to draw that network with MetalFX's spatial scaler instead. On this game it did nothing, for two reasons:UPSCALER_SOURCEindm/games/game.pymatched only/agl_ndsr.pck#, so the profile named none of the shaders the game runs. It now also matchesagl_ndsr_vr.pckandagl_ndsr_vr_light.pck.A variant whose code has no curve constant and no
MUFU.EX2/MUFU.LG2(up_mfx_has_pow) is now drawn as the linear shape. Every curve takes a power, whichever buffer its constants come from, so the power check covers curves whose constants are not in the code. Such a variant converts nothing, so its input and output are in one colour space, whichever it is. The linear shape converts nothing either, so the colour passes as it is. The washed-out picture of An upscaler's colour read from its code came from a decode the shader does and the swap did not; there is none here. Code with a power but no curve constant still runs the game's shader.With the change the option works on this game: the log reads
upscaler f8965bffbdf51d78_b: input and output in one colour space …, thenfirst dispatch of fa3033d05c0a41d6_b drawn by MetalFX, 1536x864 … → 2048x1152.An earlier version of this description presented MetalFX as the cure for dotted horizontal lines the network's output showed in fog and light shafts. Main's dead-code removal fix, which covers two NDSR variants, removed them at their source: on main the game's own upscaler draws the same scene clean. This PR only makes the player's MetalFX choice work on these packs.
Checked
0400486024DEC000, update v131072, SDK 22.2.8), on main 75c1a8c with this PR (and A GPU-only pool's render targets share one placement heap: Ocarina of Time's 3 GB of render targets fit in 0.7 GB #1453, Shared textures no live object resolves to are retired when GPU memory runs short: Ocarina of Time no longer freezes after the talk with Saria #1455). Kokiri Forest in fog and light shafts, a fixed scene,DM_UPSCALER=metalfxagainst the game's upscaler, compared on screenshots and log lines. The player confirmed the picture with both of their MetalFX launchers.t_upscaler_mfxwith Donkey Kong Bananza's (040074A01BF12000) and Splatoon Raiders' (0400380020056000) profiles,DM_UPSCALERgame and metalfx, both encoding modes: 15 and 94 checks. One expectation changed: no curve and no power is now one colour space, not "the shader runs". New checks:test_docs.py,docs_symptoms.py. The failing checks (host unit tests, tool tests, sanitizers, clang-tidy) fail the same way on main 75c1a8c; the build check passes.scripts/regress.py check --games. Bananza's and Splatoon Raiders' variants have curve constants, so their classification is unchanged.Docs
docs/reference/rendering.mdentries (the upscaler variants, and the no-curve shape), andpython3 dm/tools/docs_symptoms.pywas run (the symptom index)