Repository navigation
feat(host): a widescreen picture up to 5120x2160's pixels, native for 21:9 at the 4K output - #2120
Merged
Merged
Conversation
… 21:9 at the 4K output On a 5120x2160 (21:9) monitor the 3840x2160 output with Ultrawide on made a 4416x1864 picture, which the window copy then stretched to the screen: the monitor never got a native frame, and the Output resolution row showed 4416x1864. The cap behind it, 3840x2160's pixels, came from issue 1031, where a 32:9 screen's 7680x2160 picture ran its render targets' pool out. A 21:9 screen's native picture needs a third more pixels than 4K, not twice as many, and the pool already grows with the picture. What changed: - host/hos_wide_size.h: a picture wider or narrower than 16:9 takes at most 5120x2160's pixels (was 3840x2160's). At the 4K output a 21:9 screen gets its native 5120x2160, and the Output resolution row says "5120x2160 (native)". A 32:9 screen at the 4K output is still capped, now at 6256x1760 (was 5400x1520), its shape kept. - No pool change: host/nn_applet.c already scales the render-target pool with the picture's pixels, to 915 MB at 5120x2160. - HOS_WIDE_MAX_PX=<pixels> sets another cap without a rebuild (8294400 is the old 3840x2160's), in case a GPU needs the smaller picture. Listed in docs/development.md; the readme's Output resolution notes give the new cap. - Tests: test_widescreen_shapes.py (21:9 and 32:9 at 2160, and the override), test_output_resolution.py (21:9 at the 4K output: "5120x2160 (native)"), test_rt_pool_minimum.py (5120x2160: 915 MB). Tested: - In game on Windows 11, RTX 5090 (driver 621.14), 5120x2160 (21:9) monitor, 4K output, picture at the monitor's shape: picture 5120x2160, pool 915 MB, DLAA at 5120x2160. Kokiri Forest and Castle Town, where issue 1031's pool ran out, load. About 57 fps at native DLAA (GPU about 12 ms a frame). - The three tests above pass with llvm-mingw. - tests/run_all.py on Windows: 326 passed, 26 skipped, 4 failed. The 4 touch none of these files and fail the same on feat/aspect-monitor-default, which lacks this change: test_recorder_sync (its exit case), test_precompile_compute_guard (no windows.h for the MSVC target on this PC), nx2/test_nup_read_name (no zstandard module here), test_make_game_ngx (the Linux builder test's stub has no switching()). Not tested: - A 32:9 screen at the 4K output in game (its picture grows to 6256x1760, its pool to about 915 MB too), and GPUs with less memory than the 5090 at these sizes. - Linux. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in NotRexed#2052 (48:9 surround), NotRexed#2041 and the rest of main. NotRexed#2052's code is kept as merged (output limits, hos_wide_clamp up to 48:9, the 24-row alignment at 48:9); the cap and HOS_WIDE_MAX_PX sit on top. With the 5120x2160-pixel cap, 48:9 comes out as: - the 7680x1440 output: full size (it has exactly 5120x2160's pixels) instead of 6528x1224. Its pool stays 900 MB, set by the output's own size as before; the 5120x2880 output already plays in that pool with more pixels. - 48:9 at the 4K output (11520x2160 wanted): kept to 7680x1440, exactly 48:9, pool 915 MB, the same pixels and pool as 21:9's 5120x2160. Tests follow: test_widescreen_shapes.py takes the full-size 7680x1440 and a 48:9-at-2160 case, and keeps NotRexed#2052's 6528x1224 cases (the 24-row alignment and the four-decimal 5.3333) under HOS_WIDE_MAX_PX=8294400, the old cap; test_output_resolution.py's 7680x1440 output is full size (its scene special case is no longer needed); test_rt_pool_minimum.py has 48:9 at the 4K output (915 MB). The readme's 7680x1440 sentence and the cap follow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Joey-Magnus
approved these changes
Nov 11, 2026
Joey-Magnus
left a comment
Contributor
There was a problem hiding this comment.
This looks right to me. I checked the render-target pool for each new size against hos_rt_pool_size (host/nn_applet.c:180):
- 21:9 at the 4K output (5120x2160) gets 305 × 11.06 / 3.69 ≈ 915 MB. The output itself isn't above 4K's pixels, so the 900 MB cap doesn't apply.
- 32:9 at the 4K output (6256x1760) gets about 911 MB, scaled with the picture as #1031 needed.
- The 7680x1440 output now renders a full 7680x1440 picture. That output is above 4K's pixels, so the pool stays capped at 900 MB, and as you say, the 5120x2880 output already plays in 900 MB with more pixels (14.7M against 11.06M).
The test changes move expectations to the new sizes and keep #2052's 24-row and 5.3333 cases under HOS_WIDE_MAX_PX=8294400 instead of dropping them, which is what I'd want. Stripping HOS_WIDE_MAX_PX from the fixture's environment keeps a developer's own setting from leaking in. The new switch is documented in docs/development.md, the readme sentence is updated, and the host and menu agree because both call the same hos_wide_max_px() (the menu already reads HOS_OUTPUT_RES the same way). It merges cleanly with current main, and CI is green.
A few small things, none blocking:
- minor
host/hos_wide_size.h:35-39:HOS_WIDE_MAX_PXhas a floor but no ceiling. The documented use is lowering the cap, but a value above the default at the 4K output brings back exactly #1031. 7680x2160 asks for a 1373 MB pool, and the description of #1031 says a pool that size failed the game's reservation at boot. Clamping it (v > 5120.0 * 2160.0 ? 5120.0 * 2160.0 : v), or saying in the development.md row that it's for lowering only, would stop someone "raising" it into a crash. - question: The default now gives 21:9 players at the 4K output 34% more pixels than before (5120x2160 against 4416x1864), and in-game testing so far is on a 5090. On an 8 GB card at that output, is there a VRAM risk worth a line in the readme pointing at
HOS_WIDE_MAX_PX=8294400? As it stands, the only way back is an undocumented-for-players environment variable. Not a blocker; just asking whether you looked at memory use on a smaller card. - minor: As you note, this and #2119 touch the same readme paragraph. Whichever lands second needs the one-line merge.
hckrman101
added a commit
that referenced
this pull request
Nov 11, 2026
…ape by default (#2119) A player on an ultrawide, 16:10 or 4:3 screen starts with the game's 16:9 picture until they find the Graphics tab's **Ultrawide** row, change it and restart. The name also hides that the same row shapes the picture on screens narrower than 16:9. PC games usually follow the monitor's shape from the first start, with 16:9 as a choice. **What changed** - The **Ultrawide** row is now **Aspect ratio**, and **Monitor's shape** is its default (`gpu/vk/vk_menu.h`; `host/hos_main.c` reads an options file with no `ultrawide=` line as Monitor's shape). 16:9 stays a choice. On a 16:9 screen nothing changes. - The saved key stays `ultrawide=` (`ini_key`), so a saved `ultrawide=0` still means 16:9. - **Older options files on a screen narrower than 16:9.** The game saves every row, so a file from before this PR holds `ultrawide=0`, the old default, whether chosen or not. On a screen narrower than 16:9 (16:10 such as the Steam Deck's 1280x800, or 4:3), where 16:9 only adds bars above and below, that file's 16:9 moves to Monitor's shape; an ultrawide keeps its 16:9 (often a real choice there). The rule is one function, `hos_aspect_on` in `host/hos_wide_size.h`: `host/hos_main.c` starts the game with it, and the menu's row follows what the host started with (`host->aspect_ratio()`, in `menu_init` before `restart_init`), so the two agree on Linux too, where the menu has no screen size of its own. `save()` writes `options_version=6`, so a 16:9 chosen after the update stays. - The other value reads **16:9** again instead of #2078's "Off (16:9)". #2078 added "Off" because "Ultrawide: 16:9" read as if ultrawide were already on; under the name Aspect ratio the value is a shape, and "Aspect ratio: Off (16:9)" would not read well. Happy to keep "Off (16:9)" if you prefer it. - `recomplauncher.json`: the same label and help, and its default is `1`, so the launcher does not write 16:9 over the new default. - New help text for the row, and for **Ultrawide menus**, whose text named the old row. The readme's settings table and Output resolution notes, `menu_restart.h` and the comments that named the row follow (#2052's wording kept, with the new name). - Tests: `test_menu_restart.py` and `test_menu_restart.cpp` use the new name; `test_audio_output_menu.py` and `test_stick_dead_zone.py` give their option stubs the `ultrawide` field that `ini_key` now reads. New `test_aspect_default.py`: `hos_aspect_on` over 16:10, 4:3, 5:4, 16:9, 1366x768, 21:9, 32:9, portrait and no screen size, plus the host and menu source checks. **Tested** - In game on Windows 11, RTX 5090 (driver 621.14), 5120x2160 (21:9) monitor, in one build with the widescreen cap change from #2120: the picture takes the monitor's shape, and Kokiri Forest and Castle Town load. That run was before the merge with current main (#2052, #2041, #2078). This PR only moves a default and renames a row; the code that sizes the picture is unchanged. - `tests/run_all.py` on Windows (llvm-mingw) after merging main at 06c30bd (with #2197): 392 passed, 31 skipped, 1 failed: `test_vram_budget_row`, which fails the same way on main's own sources on this PC (clang stops on the unused `kVramMinimumOnly`). - A build of this branch compiled (`hos_main.c`, `vk_menu.cpp`) before that merge; the merge itself only adds the version 6 move next to #2197's. The move for older files was not run in game: this PC has a 21:9 screen, where an older 16:9 stays. The tests this PR touches pass, and so do the others that build `ini_key` or the row: `test_framegen_preset`, `test_menu_env_on`, `test_recomplauncher_json`, `test_rumble_menu`, `test_upscaler_rows`, `test_vsync_row`, `test_output_resolution`, `test_widescreen_shapes`. **Not tested** - 16:10, 4:3, 32:9 and 48:9 screens in game (`test_widescreen_shapes.py` covers their sizes). - Linux and the Steam Deck: SDL gives the screen's size there too, so a Steam Deck (16:10) now starts with a 16:10 picture instead of 16:9. - If #1864's translations name the row, they would need the new name. **Screenshots** From a headless run of this branch (head 2a74ec4) on Windows 11, RTX 5090, with a 5120x2160 (21:9) monitor and no options file, so a first start (`HOS_HEADLESS=1`, `RX_VK_SHOTS` at 2560x1080; the save loaded with `HOS_INPUT_SCRIPT` presses). The log: `widescreen: picture 3416x1440, scene 2560x1080, camera ratio 2.3722`.   _The menu shot is the middle 16:9 of the frame: behind it the title movie stays 16:9 with black sides. Its build had one extra line so the list scrolls headless (`ease_step = 1.0f` in `menu_record_image`), not part of this PR._ The widescreen cap PR (#2120) edited the same readme paragraph; it has merged, and the paragraph is merged with it here. **`options_version`:** #2197 (merged) took 5 for the Esc default, so this writes 6 and moves an older file's 16:9 from files before 6 (`version < 6` in `hos_aspect_on` and `menu_init`). #2110 also writes 5 today; whichever of the two lands later takes the next number. #2197's `test_menu_keys.py` compiles `menu_init`'s options read, which now also reads `host->aspect_ratio`, so its `host` stub gains that member. Its check of older files expected every version below the one `save()` writes to move Insert or F1 to Insert, F1 or Esc, which would move a version 5 file's chosen Insert or F1 again; it now reads the move's version from `menu_init` and checks that files from it up to `save()`'s version keep their choice. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: hckrman101 <239247847+hckrman101@users.noreply.github.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.
On a 5120x2160 (21:9) monitor, the 3840x2160 output with Ultrawide on made a 4416x1864 picture, which the window copy then stretched to the screen: the monitor never got a native frame, and the Output resolution row showed 4416x1864. The cap behind it, 3840x2160's pixels, came from issue 1031, where a 32:9 screen's 7680x2160 picture ran its render targets' pool out. A 21:9 screen's native picture needs a third more pixels than 4K, not twice as many, and the pool already grows with the picture.
What changed
host/hos_wide_size.h: a picture wider or narrower than 16:9 takes at most 5120x2160's pixels (was 3840x2160's). At the 4K output a 21:9 screen gets its native 5120x2160, and the Output resolution row says "5120x2160 (native)". A 32:9 screen at the 4K output is still capped, now at 6256x1760 (was 5400x1520), its shape kept.host/nn_applet.calready scales the render-target pool with the picture's pixels, to 915 MB at 5120x2160 (test_rt_pool_minimum.pynow checks that case).HOS_WIDE_MAX_PX=<pixels>sets another cap without a rebuild (8294400 is the old 3840x2160's), in case a GPU needs the smaller picture. Listed indocs/development.md; the readme gives the new cap.Relation to #2052
Merged with current main; #2052's code is kept as merged (the output limits,
hos_wide_clampup to 48:9, the 24-row alignment at 48:9). With the new cap:test_widescreen_shapes.pykeeps feat(video): support 48:9 triple-monitor picture geometry #2052's 6528x1224 cases (the 24-row alignment and the four-decimal5.3333) underHOS_WIDE_MAX_PX=8294400, the old cap, and adds the full-size 7680x1440 and 48:9 at 2160.test_output_resolution.py's 7680x1440 output is full size;test_rt_pool_minimum.pyadds 48:9 at the 4K output.Tested
tests/run_all.pyon Windows (llvm-mingw) after the merge: 339 passed, 30 skipped, 4 failed. The 4 also fail on untouched main on this PC:test_recorder_sync(its exit case),test_precompile_compute_guard,test_bake_portability, andnx2/test_nup_read_name(no zstandard here).test_widescreen_shapes.py,test_output_resolution.py,test_rt_pool_minimum.pyandgpu/vk/tests/present_rect_test.cpppass.Not tested
This and the Aspect ratio PR (#2119) edit the same readme paragraph, so whichever merges second needs a one-line merge.
🤖 Generated with Claude Code