Skip to content

fix(vk): keep ultrawide loading fades full width - #2851

Draft
mooki000 wants to merge 3 commits into
NotRexed:mainfrom
mooki000:fix/wide-loading-fade
Draft

mooki000 wants to merge 3 commits into
NotRexed:mainfrom
mooki000:fix/wide-loading-fade

Conversation

@mooki000

Copy link
Copy Markdown
Contributor

What this is for: centred ultrawide menus currently leave the scene visible in the side strips during a loading fade. This keeps the fade full-width, but it also moves the loading icon into the side treatment, so this is a draft proposal, not a complete visual fix. What is measured: real windowless game captures on Linux/RTX 4090 at the reporter's 4432×1856 game-picture size, plus compiled regression checks. Not measured: a physical ultrawide display, Windows gameplay, other GPU vendors or performance.

Refs #2220. Credit to @EjianYT for identifying bit 3 and testing the 0xa → 0x2 correction.

Problem

  • nx2/oot_wide.py has one keep bit per UI canvas. Bit 3 belongs to the loading fade, not the map.
  • wide_sides() in gpu/vk/vk_framegen.cpp removed bits 1 and 3 in either centred mode. The HUD patch therefore squeezed the entire loading canvas into the middle 16:9.
  • Keeping bit 3 fixes the uncovered sides. However, the icon shares that canvas: it becomes wider and moves towards the full picture's right edge. The existing blurred-side pass then blurs it. This is visible in the comparison below, not just a theoretical risk.

What changed

  • Keep only the pause/system background's bit 1 out of the full-width mask in centred modes. Full width still uses 0xf; centred modes now use 0xd instead of 0x5.
  • Correct the canvas descriptions in vk_framegen.cpp and oot_wide.py.
  • Add test_wide_loading_fade.py, compiling the real renderer policy and generated HUD patch with authored state, in the existing wide-shape fixture style.
  • Document the icon trade-off and add six rows to docs/tested-configurations.md, including the unsuccessful input routes. No new shader, runtime switch, host interface, pane hook or generated game code is included.

The pause/map centring, wheel background, event fades and inactive 16:9 projection are deliberately unchanged.

How it was tested

Environment: Arch Linux, kernel 7.2.15-1-omarchy; Intel Core i9-13900K; NVIDIA RTX 4090, driver 615.78.08. Base 51da0464, mask-only change 7dc0773b, 2026-11-12. The same host executable was used before and after. Its base build includes dormant readback diagnostics (c372e16e, not enabled); the changed renderer was built from this branch. No Xbox UI mod or overlay was used.

Rebase: final head d2e37d47 is on e2057b2b. The one end-of-task rebase was conflict-free. The fade regression was rerun with GCC and Clang and passes; its generated unit is byte-identical to the Windows-syntax-checked unit. Upstream added AMD Anti-Lag frame-generation tagging, not a change to the fade policy. The game build/captures and full-suite result below are from before that rebase; the rebased game was not rebuilt or run.

The reporter's log distinguishes 3840×2160 output setting, 4432×1856 game picture, 3328×1392 scene, and a 3440×1440 swapchain. The reproduction uses the first three, with HOS_ASPECT=2.3889 and HOS_WIDE_MAX_PX=8294400; it does not pretend that a windowless run has the reporter's swapchain. Both 21:9 captures are 2216×928, preserving the game picture's shape.

Game-free checks

  • GCC 16.2.1 and Clang 23.1.3: the new test compiles and fails on the pre-fix sources with 12 FAIL lines each: four keep-mask checks and eight loading-projection components. With the change:
    PASS: loading/event fades and wheel stay full width; pause/HUD centring, sides and 16:9 unchanged
    
  • Existing wide-shape, save-picture and independent-scaler tests pass with both compiler families.
  • An initial test-only chained volatile assignment was rejected by both C++20 compilers. It was split into separate stores before collecting the runtime negative control; no warning was suppressed.
  • Full Linux suite, pinned Python 3.12.16:
    476 passed, 0 failed, 20 skipped in 164 s (linux, 8 at once)
    
  • The final generated C++ fixture passes Windows-target syntax compilation with its own -std=c++20 -O2 -Wall -Wextra -Werror flags. The local preflight had an incorrect C/libc++ include order; its captured source was compiled with that order corrected. This is not Windows execution.
  • Renderer builds and links. A separate full-file -Wall -Wextra check reports 11 missing-initializer warnings at unchanged Vulkan structure initializers, none at the mask change. No fixture core dumps were produced.

Game captures

All captures used the real scale pass (RX_VK_SHOT_FX=1). The bridge's named raw screenshots bypass that pass and were not used to judge the blur. These were ordinary runs on a busy PC, not exclusive timing runs; no fps, latency or performance claim is made.

Run Picture Place and result Driver faults
Before, centred blurred sides 4432×1856 Load into Hyrule Field: only the middle fades, with bright side strips. Pause and actual Map centred. 0
Before, 16:9 3840×2160 Loading fade fills the frame; sharp icon; pause checked. The attempted Map capture was the first-use tapestry, so it is not counted as a Map result. 0
Mask only, centred blurred sides 4432×1856 Hyrule Field fade fills the width; pause/Map remain centred. Transition to Kokiri Forest completed. Loading icon becomes a dim blur at the side. 0
Before, corrected 16:9 route 3840×2160 Loading fade, sharp icon, pause and actual Map checked; transition to Kokiri Forest completed. 0
Mask only, 16:9 3840×2160 Same fade, icon proportions/position, pause and Map; transition completed. 0
Mask only, black bars then Full width 4432×1856 Both fades cover the width. Black bars hide the loading icon; Full width shows it sharply but stretched. Black-bar pause/Map remain centred. Both requested transitions completed. 0

Retained input failures: one initial capture helper used a relative count with an absolute-frame wait; the first 16:9 route dismissed the tapestry but did not leave its menu; the extended mode check used an unrecognized setting key. Each stopped on its error, and no unreached step is counted as evidence. None was a game crash or device loss.

Six panels at the reporter's picture size: the loading fade before (only the middle fades) and with the mask change (the whole picture), the pause menu and the Map unchanged

six inspected panels: before/mask-only loading fade, pause and Map. Same save, picture size and settings; the loading frames compare coverage, not identical fade opacity or frame numbers.

The loading icon, 2x crops: sharp inside the middle 16:9 before; a dim blur at the outer edge with the mask change

identical bottom-right crops, enlarged 2×: the original sharp icon inside the central 16:9 versus the mask-only icon blurred near the outer edge. This is why the proposal remains a draft.

16:9 before and after: the fade, the sharp icon, the pause menu and the Map are unchanged

six inspected panels at the same 3840×2160 picture size: before/after loading fade and sharp icon, pause and actual Map. Captures are 1920×1080.

The icon in each mode: before; mask change with blurred sides (a dim blur); with black bars (hidden); Full width (sharp but stretched)

equal 2× crops showing the original centred icon, the mask-only blurred icon, the hidden black-bars icon and the sharp-but-stretched Full-width reference. A separate raw image immediately before the black-bars capture still shows the icon: the side pass, not a missing draw, removes it.

All six runs reported zero fatal/crash/device-loss/kernel-driver-fault lines. The first 16:9 run recorded one virtual-core escape at startup; the other five recorded none. The last three capture routes passed their checks and quit normally. Full width's unchanged mask is covered by the compiled before/after checks; its runtime image is a reference from the changed binary, not a separate pre-fix Full-width run.

Not tested / not shown

  • Windows gameplay, AMD/Intel/Steam Deck, physical ultrawide presentation, HDR and frame-generated output. (The new test itself ran on Windows: both windows-2022 source-check parts passed on a run on my fork at this head before the pull request was opened.)
  • A complete fade-pane-only fix that preserves the icon's original position and shape has not been implemented or demonstrated.

Why not simply keep the icon centred too?

The existing HUD hook changes one projection for the whole canvas, not an individual pane. Clearing bit 3 centres both the icon and fade; keeping it widens both. The side pass receives only margins and its mode, not a pane identity or loading opacity.

A complete solution needs a new game-side hook that widens only the fade pane, or a new loading-state/opacity hand-off to the side-fill path and its shader. Exempting the outer pixels alone would still leave a stretched, displaced icon. This proposal does not add an unproved pane patch or a dark-pixel heuristic.

Risks

The loading icon regression is real in both centred modes: it is a dim blur with blurred sides and completely hidden by black bars. Full width shows it sharply but stretched; 16:9 keeps its original position and proportions. The mask-only change should not be merged as if it preserves the loading indicator.

Overlaps

The pre-rebase open-PR comparison found 57 PRs touching one of the initial four changed files. The shared-code PRs #1488, #1979, #2015, #2017, #2172, #2261, #2262, #2531, #2658 and #2665 merged cleanly in that comparison; no conflict hunk was reported. No competing loading-fade repair was found. The final branch gate passes against e2057b2b.

Questions for the maintainers and reporter

  1. Do you prefer the full-width fade with this icon trade-off, or the current behaviour until the fade pane can be handled separately?
  2. @EjianYT, does your real-window build of the mask correction also blur or hide the icon in the centred modes, or does it differ from these captures without the UI mod?

Assisted-by: GPT-6 Astra
Co-Authored-By: GPT-6 Astra noreply@openai.com

mooki000 and others added 2 commits November 12, 2026 10:21
Keep the loading-fade canvas in the full-width mask in both centred menu modes. The pause background still centres, and Full width and 16:9 projections stay unchanged. Credit EjianYT for identifying the loading-fade bit in issue NotRexed#2220.

Compile the real mask policy and HUD patch in a game-free regression fixture. Document the shared loading-icon layout trade-off.

Assisted-by: GPT-6 Astra

Co-Authored-By: GPT-6 Astra <noreply@openai.com>
Keep the mask-only proposal a draft: real scale-pass captures show that centred blurred sides blur the loading icon and black bars hide it. Record the six runs, including unsuccessful input helpers and the unchanged 16:9 controls.

Assisted-by: GPT-6 Astra

Co-Authored-By: GPT-6 Astra <noreply@openai.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants