Repository navigation
Conversation
|
Tried this on The Legend of Zelda: Ocarina of Time ( Setup
1x (
1.5x, about 4 minutes, same area
So for this engine (sead/agl on NVN2), the rules that keep the PR safe also keep the scene at 1x: compute passes that write their targets as images, and alias families. That fits the PR's "not checked: 2x on other engines". Not checked: 2x; other areas; where in the frame the first mixed pass sits. 🤖 Generated with Claude Code |
… a multiple of the game's size, a Render resolution setting and a Mac menu PR seedds#405's upscaling commits as of 2026-11-05, one commit so the branch applies on main (its GPU hang watchdog and Hyrule Warriors cheats are left out: they are not part of this change): - 7607594 nvn: resolution upscaling (DM_UPSCALE 1/1.5/2) with a Mac Render Resolution menu - e48f788 Upscaling: per-texture fetch scale, demotion of mixed passes, scaled snapshots, clears and queries - 0d08950 Upscaling: IMAGE-flagged render targets scale; a texture a shader writes as an image is demoted first - 4bc8123 Upscaling: an unused depth stays out of the mixed-pass vote; short 2D arrays scale - b2be78b Upscaling: a game's own FSR upscaler is resolved by the host above 1x (DM_UPSCALE_GAME) - 10e6c31 Upscaling: images bound by a handle in a uniform buffer (IMGU) demote, rank and are not the upscaler's shape Applied onto main at bd979ce, where these changed under it: - tex_upgrade's rename loop is tex_rename_all, shared with ups_demote; it now carries main's per-name counts (g_by_serial_held / g_ghost_held, entry_holds), so a demotion keeps them too. - copy_t2t resolves the destination after bc_alias_copy (a631295): the upscaling block follows that lookup, and bc_alias_copy demotes a scaled source before it reads it at the game's regions. - copy_t2t_draw: main draws Depth16 copies at every factor; the integer kinds stay for g_ups > 1. - present: main's picture shape (2202d61), then the scaled crop. - copy_t2b takes main's size argument; the image slot keeps main's atomic reinterpretation. - The demotion's red line takes RED_ONCE 158 (113 is main's 2048-layer line). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Co-Authored-By: seedds <seedds@gmail.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…w, made again on the replacement Main's twin views (92f223a) let a serial hold an sRGB or linear view of a texture another serial holds as its base. ups_demote renamed the base's names to the game-size replacement and then, since the serial itself named the view and not the base, put the bare replacement under it: the serial lost its view's format (an sRGB target read and written as linear from then on), and the replacement was made in the serial's own format (tex_desc), so the base's other names got the twin's format. tex_held_view finds the view a serial holds (tex_upgrade's test, now shared), tex_replace renames every name and makes the view again on the replacement (tex_upgrade's code, now shared), and ups_demote makes the replacement in the base's format. tex_upgrade does as before through the same two functions. Checked: t_upgrade_alias (13), t_srgb_alias (8), t_image_alias (332), t_pfv, t_ups, t_ups_resolve and t_clear_ds pass; the host builds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s size until a pass draws into it ups_pick decided at a texture's first resolution, often its descriptor's, before any use, and two classes of render target were left at the game's size for good: - a colour texture with neither COMPRESSIBLE nor DISPLAY was taken for data copied in, but Super Mario Bros. Wonder's scene colour has neither flag: left at 1x beside the scaled depth, the mixed-pass rule demoted the scene back to 1920x1080 (12 demotions); - a COMPRESSIBLE texture whose storage in a CPU-visible pool holds bytes may be data the game wrote (SD GUNDAM G GENERATION CROSS RAYS sets COMPRESSIBLE on every texture), which a scaled texture would lose, as it is not filled from its storage. Without a rule for it such data came out blank; with a rule that keeps it at 1x, Pikmin 4's Unreal targets, whose pools hold what earlier resources left there, all stayed at 1x and the scene's depth was demoted (9 demotions, the scene at 1920x1080). Both are now held (g_ups_held): made at the game's size with their data, and the first pass that draws into one, which shows it is a render target, promotes it (ups_promote, the reverse of ups_demote, before the pass's vote): a scaled texture under every name with its content drawn up, an sRGB / linear view of it made again (tex_replace). A texture that is only ever read stays as it was. nvn_ups.h: nvn_ups_screen_ok (the size part) and nvn_ups_classify (scale, leave or hold), checked in t_ups. ups_pick logs why a screen-like render target stays at the game's size (first 40 cases). Measured on the branch these rules come from (Mac, 2x): Pikmin 4's scene at 3840x2160 with 1 demotion (a 640x360 buffer a shader writes as an image) instead of 9; Super Mario Bros. Wonder's at 3840x2160 with none instead of 12. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the held textures' rule - rendering.md: A render target taken for data at a render resolution above 1x (the symptom, why ups_pick cannot decide at a texture's first resolution, the hold and the promotion); the symptom index regenerated. - Pikmin 4 (1.1.1): 1x / 1.5x / 2x on an M5 with the host's 60 fps (1.5x holds 60, 2x about 52-55), what is scaled and held, and the "HQ Graphics" RomFS mod: it keeps bUseFixedFrameRate, so the host's fixed-rate writer steps it at 60; the mod's 60 FPS variants are no longer needed. - Super Mario Bros. Wonder: its measurements at 1x / 1.5x / 2x from the branch these rules come from. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…oved The menu only wrote the saved choice launcher.DM_UPSCALE for the next launch (textures keep the size they were made at), which the settings window's Render resolution row already does before the game starts. In the running game it looked like a control that did nothing. The factor stays a launcher setting and DM_UPSCALE; dm_gfx_upscale, which only the menu read, goes with it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…5.9 ms in the base camp) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…y without a texture ends at its start, and t_ups_resolve initializes each texture in the caller's object copy_b2t allowed c->tex to be NULL (zskip_del's guard) and then read it: the pass dump's "no host texture" line named its serial after tex_mtl(NULL) gave nil, and the analyzer followed that path once this branch's tex_mtl changes moved its budget (clang-analyzer-core.NullDereference, nvn_mtl.m 11 against main's 9). A copy without a texture now ends before anything reads it. t_ups_resolve's texture() returned a tex_t that mtl_tex_init had recorded by address in g_tex_live (clang-analyzer-core.StackAddressEscape): the test relied on the return value being built in the caller's variable, and mtl_tex_release tells a texture's own object from a copy by that address. It now initializes the caller's object, as a game's texture is. Checked: lint_c.py tidy (LLVM 23.1.4, Xcode 27.2) over all 261 sources of this branch and of main 1794a35 gives the same findings per file and check (22 pairs above the baseline and 12 below it on both: main's own); t_ups, t_ups_resolve (2x and 1x), t_upgrade_alias, t_srgb_alias, t_image_alias, t_clear_ds, t_copy_alias pass; the host builds. CI's clang-tidy job failed before checking anything: its LLVM download returned 504, as main's did. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ch 2 renders at its own resolution unless DM_UPSCALE_SWITCH2=1, and the Mac settings window offers Render resolution only for Switch 1 games Switch 2 games draw their 3D at a dynamic resolution and enlarge it with an upscaler of their own toward a 1440p or 4K output, and the factor does not carry through those paths: - Ocarina of Time at 1.5x (a contributor's run in PR seedds#1716's review): agl writes scene targets in compute and keeps targets in image alias families, so 24 demotions and 7 family members brought the 1536x864 scene back to the game's size, GPU p50 as at 1x. - NVN2's DLSS (dlss_eval) and agl's NDSR drawn by MetalFX (up_mfx_encode) take their rectangles in the game's pixels on textures that may be scaled; neither has been run above 1x. - Hyrule Warriors: Age of Imprisonment's chain stays scaled at 2x, but its dynamic resolution settles near 1007x566 of 1600x900 and the frame is GPU-bound. ups_init reads the sdk's console (dm_sdk_ounce) and logs why the factor stays 1; settings.py's console:switch condition reads the same spec string from sdk.patched.bin. t_ups_resolve runs as a Switch 2 game with and without DM_UPSCALE_SWITCH2; docs/reference/rendering.md, Render resolution on Switch 2 games, lists what extending it would take (open). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gssci
force-pushed
the
render-resolution
branch
from
November 8, 2026 21:26
d65ac1c to
a4c01bb
Compare
One conflict: Ocarina of Time's "Found on this game" list, where main added the native mesh pipelines' entry and this branch the render resolution one at the top; both are kept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two conflicts: - nvn_feedback.inc: main's vertex stream check (bind_vbufs returns a stream in no memory pool, the draw skipped with a red line) is kept, and the upscaling line that starts the vertex entries at render_scale[1] follows vconv_bind as before. - RED_ONCE: main now uses keys 158, 159 and 160, so the demotion's and promotion's lines take 161 and 162, and g_red_once holds 163. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Three conflicts, each two additions kept side by side: Super Mario Bros. Wonder's "Found on this game" list (the held textures' line and main's Joy-Con npads line), the settings page's Mac sections (Render resolution and the upscaler, then main's Switch 2 controllers, in settings.tsv's order), and test_launcher_settings' Mac-only rows (DM_UPSCALE, DM_UPSCALE_GAME and main's DM_SW2). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in main's fix to dm/tools/unity_bucket.py (7479adf), which cleared the Python lint ratchet's three findings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The samples-passed counter is now main's running total in submission order (VIS_ZERO / VIS_FOLD / VIS_REPORT); each slot's count is still divided by its pass's resolution upscaling factor squared (nvn_ups_samples) before it is added to the total. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both sides kept in nvn_mtl.m: the support buffer carries the resolution upscaling factors (ups_support) and main's new uniform-size bank (NVN_RB_CBSIZE) follows it; ups_bypass_encode is declared beside main's ndve_engine_dispatch, which dispatch() tries first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both sides kept in dispatch(): the resolution upscaling bypass of the game's upscaler, then main's threadgroup-memory spill setup. Main's spill messages took RED_ONCE keys 161 and 162, so the two resolution upscaling texture-creation failures move to 163 and 164 (g_red_once[165]). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main's new RED_ONCE key 163 met the resolution upscaling texture-creation failures, which move to 164 and 165 (g_red_once[166]). 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 and why
Switch 1 NVN games render their 3D at 1.5× or 2× their own resolution on the Mac (
DM_UPSCALE, the Render resolution setting of the Mac settings window; default 1×, where none of this runs). Switch 2 games keep their own resolution (below). This is #405 by @Amost- applied to today'smain, with two fixes found while playing Pikmin 4, Super Mario Bros. Wonder and Metroid Dread with it. It supersedes #405 (credited as the author of its commit) and leaves out #405's two unrelated commits (the GPU hang watchdog and Hyrule Warriors' cheats).Commits:
render_scalefor texel fetches and size queries, demotion of passes and copies that mix scaled and unscaled textures, IMAGE-flagged targets scaled with written images demoted, an unused depth kept out of the vote, short 2D arrays, the game's own FSR upscaler resolved by the host (DM_UPSCALE_GAME), IMGU bindings. Applied ontomainat bd979ce; the commit message lists what changed under it:tex_rename_allcarries main's per-name counts (g_by_serial_held/g_ghost_held),copy_t2t's upscaling block follows the destination lookup that a631295 moved afterbc_alias_copy(which demotes a scaled source first), Depth16 copies at every factor as on main, main's picture shape (2202d61) before the scaled crop, and the demotion's red line on a freeRED_ONCEkey (113 is main's 2048-layer line).ups_demoterenamed the base and then put the bare replacement under the serial, which lost its view's format, and made the replacement in the serial's format, which the base's other names then got.tex_held_viewandtex_replace(whattex_upgradedid inline) now servetex_upgrade,ups_demoteand the promotion below.ups_pickdecides at a texture's first resolution, often before any use. A colour texture with neitherCOMPRESSIBLEnorDISPLAYwas taken for data (Wonder's scene colour has neither flag: 12 demotions, the scene at 1920x1080), and aCOMPRESSIBLEtexture whose CPU-visible storage holds bytes may be data the game wrote (SD GUNDAM G GENERATION CROSS RAYS setsCOMPRESSIBLEon every texture), which a scaled texture would lose. Both are now held and promoted by the first pass that draws into them (ups_promote, the reverse ofups_demote); a texture that is only ever read keeps its data.nvn_ups_classify(scale, leave, hold) innvn_ups.h, checked byt_ups. Reference entry: A render target taken for data at a render resolution above 1x.t_ups_resolveinitializes each texture in the caller's object (a texture's address escaped the stack).dm_sdk_ounce,spec: Ounce) renders at its own resolution unlessDM_UPSCALE_SWITCH2=1is set too;ups_initlogs why. The Mac settings window shows Render resolution and Upscaler at 1.5× / 2× only for Switch 1 games (console:switch, a new condition insettings.tsvthatsettings.pyreads fromsdk.patched.bin). Reference entry: Render resolution on Switch 2 games.Switch 2 games (the review on Ocarina of Time)
The review found that on Ocarina of Time (
0400486024DEC000) 1.5× leaves the 3D at 1536x864: 24 demotions (12 mixed passes, 12 written images) and 7 image alias family members, GPU time as at 1×. That is how Switch 2 games are made, not a single bug. They draw their 3D at a dynamic resolution and enlarge it with an upscaler of their own toward a 1440p or 4K output, and the factor does not carry through those paths:dlss_eval) and agl's NDSR drawn by MetalFX (up_mfx_encode) take their rectangles in the game's pixels on textures that may be scaled; neither was run above 1×. The host resolves only FSR 1's EASU, so NDSR runs its own taps.Each of those needs work and runs on the games that have them, so this PR limits the feature to Switch 1 games, where it was measured, and keeps the Switch 2 paths reachable behind
DM_UPSCALE_SWITCH2=1for whoever takes them on. The reference entry lists what extending it would take, marked open. Thet_ups_resolvefailure the review saw with #1590's code (stores into an sRGB image through the linear view) does not happen onmainand belongs with #1590.Compared with the other resolution PRs: #491 (
DM_RESCALE) scales the same class of targets in 96 lines but has no demotion of mixed passes and copies, no scaled CPU readback and no setting; #525, #354, #1497 and #1323 are per-game render scales through the games' own code. This one works for any Switch 1 NVN game from the host.Checked
Rebased onto
mainat 7f50222: the branch is linear again (the two merge commits are gone), and its tree before commit 8 is the one CI ran at d65ac1c8.Tests:
make -C dm/gfx/tests GAME=0100B7C00933A000check_t_ups(with the new classify checks),check_t_ups_resolve(2×: 20, 1×: 13; as a Switch 2 game: 14 atDM_UPSCALE=2, 21 withDM_UPSCALE_SWITCH2=1),check_t_upgrade_alias(13),check_t_srgb_alias(8),check_t_image_alias(332),check_t_clear_ds(59),t_pfv, 0 failures;test_launcher_settings(withtest_render_resolution_only_for_switch_1_games),test_settings,test_docspass;make -C dm/hostbuilds;dm/ios/tools/compile_check.py: 261 files, 0 failed;lint_python.py --against 7f502220(ruff 0.17.2, pyright 1.1.414): one new finding,dm/tools/ue_cvar.py:65, which ismain's (its own lint run fails on that line), none from this change.test_env_switchesfails onmaintoo (DM_NVN_CUT_FIRST,DM_NVN_RT_RECLAIMandDM_NVN_VC_WAYSquoted in the docs but read nowhere); this change's four switches have their rows.clang-tidy (
lint_c.py tidy, LLVM 23.1.4): the same 23 file/check pairs above the baseline as a run ofmainat 7f50222 on the same Mac, so none from this change. CI's run ofmainfails on three of them, all innvn_mtl.mcode this PR does not touch (the same 10 findings at the same lines).Games run (Mac, 1.1.1 = v262144 of Pikmin 4
0100B7C00933A000): boot, title, a Day 2 save into the base camp's dialogue at 1x, 1.5x and 2x, about 90 s each, with the community "HQ Graphics" RomFS mod and main's 60 fps. At 2x the scene is 3840x2160, one 640x360 buffer is demoted (written as an image), four CPU-written textures stay held, no red line at any factor:Without the mod, 2x holds 60 fps on the same route: GPU p50 14.6–15.9 ms (p95 at most 17.1), 0–3 of 300 frames held, 4,049 MiB, two small buffers demoted (written as images).
Super Mario Bros. Wonder (1.2.1) and Metroid Dread (2.1.0) at 2x were played with the same rules on the branch they come from, before main's last 107 commits (Wonder's numbers are in its note); not rerun at 2x on this base.
Devices and OS: MacBook Pro M5, 24 GB, macOS 27.2. The iPhone was not run (the row is Mac-only;
DM_UPSCALEis read there too).scripts/regress.py: not run. Only two local games have a Mac build and a route here (Pikmin 4 and Wonder), and at 1x every upscaling path is gated off (g_ups > 1); what runs at 1x is the shared texture-upgrade renaming (tex_held_view/tex_replace, covered byt_upgrade_alias,t_srgb_aliasandt_image_alias) and the settings row. Pikmin 4 at 1x played as above with no red line.Not checked: a Switch 2 game run with the new rule (the rule is checked by
t_ups_resolve's Switch 2 runs and the settings test), DLSS and NDSR above 1× (DM_UPSCALE_SWITCH2=1),make -C dm/gfx/tests runand the host unit tests as a whole, a scaled multisample resolve (none of these games), 2x on other engines than Unreal, Mario's and Dread's, long sessions, and outdoor missions with many Pikmin.Docs
docs/reference/<subsystem>.mdentry, andpython3 dm/tools/docs_symptoms.pywas run (the symptom index)🤖 Generated with Claude Code