fix(vk): DLSS at handheld Ultra Performance, and NGX paths on Linux #1364
No reviewers
Labels
No labels
accessibility
autorelease: pending
autorelease: tagged
bug
dependencies
documentation
duplicate
enhancement
github_actions
good first issue
help wanted
invalid
question
testing wanted
wontfix
No milestone
No assignees
1 participant
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Hookshot!1364
Loading…
Reference in a new issue
No description provided.
Delete branch "dlss-handheld-paths"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Two fixes for NVIDIA DLSS (#841), both found by the validation report on #841. Thanks for the careful testing.
Handheld + Ultra Performance ran the game's own upscale
The handheld profile's output is 1536x864, so Ultra Performance draws the scene at a third of that: 512x288.
dlss_note_scene_drawonly took scenes of at least 640x360, so that scene never gave DLSS its camera. The game's own upscale ran while the menu said DLSS.dlss_skin_check(actor motion) and theRX_VK_DLSS_TRACEdiagnostic had the same fixed floor.The floor now follows the gameplay upscale's output, as last seen. A scene is taken when the output is 1 to 3 times its size on each axis, from DLAA to Ultra Performance. This is the same rule
dlss_upscalealready checks before it draws (ow < rw || ow > rw * 3). It is indlss_checks.hnow and used in all three places. Before the first upscale the output is not known, so nothing is taken. That first frame runs the game's upscale, as it already did.The 640x360 floor was a cheap filter against other passes that look like the scene: B10G11R11 colour plus depth plus a camera, such as the pause screen's model views or reflections. These checks still turn them away:
For docked 2048x1152 the new floor is 683x384, a little stricter than before.
Linux: NGX paths with non-ASCII characters
The Linux
wide()widened each byte of the UTF-8 path on its own, soCaféreached NGX asCafé. It now decodes UTF-8 itself, without the process locale. Bytes that are not UTF-8 become U+FFFD, one per bad sequence, as Unicode recommends. I chose U+FFFD over keeping the raw byte: a raw byte such as 0xE9 would become U+00E9, which NGX writes back as the bytes foré, a different and possibly real path. A path with U+FFFD names nothing, so it can only fail.Decoding alone is not enough. NGX's Linux library (
libnvsdk_ngx.a,WStrToUTF8Str) turns every wide path back into bytes withnewlocale(LC_ALL, "C")andwcsrtombs. In the C locale that fails on any character past ASCII, and the path comes out empty. I checked this by calling that function directly. So:/proc/self/fd/<n>: the folder is opened, kept open, and NGX gets an ASCII name for it. Nothing is written to disk. NGX's data folder (the game folder'sngx) works this way, and NGX finds the runtime through it.libnvidia-ngx.so) then loads the runtime by its real path (realpath), and that fails the same way. So on Linux the DLSS runtime itself must be in a folder whose real path is ASCII. When it is only in other folders, the log and the menu now say so and name the fix. Before, they said "DLSS needs an NVIDIA RTX GPU". The fix is to putlibnvidia-ngx-dlss.so.*in$XDG_DATA_HOME/hookshot/ngxor in another ASCII folder named byRX_VK_DLSS_DIR. The readme says this too.Windows is unchanged. Its paths are wide end to end (
GetModuleFileNameW,_wgetenv,fs::path::native()).How it was tested
tests/test_dlss_checks.py(new) compiles and runstests/test_dlss_checks.cppwith-Wall -Wextra -Werror(g++ and clang++):wide()widens byte by byte only for ASCII paths.tests/run_all.py: 176 passed, 5 skipped. One check,nx2/test_nup_verify.py, timed out once under load (a 5 s subprocess limit) and passed when run again. It is unrelated.hookshot_vk.dllcross-built with llvm-mingw and the NGX SDK (as thevulkan-dlssjob does): compiles and links.NVIDIA DLSS draws OoT's upscale: 512x288 -> 1536x864,feature 1 made ... 512x288 ... -> 1536x864, mode 3, statusDLSS: 600 frames drawn ... actor motion 48924 draws in 600 frames1366x768 -> 2048x1152,600 frames drawnHookshot-dlss-utf8-Café-ゼルダnot available on this GPU (0xbad00004): DLSS needs an NVIDIA RTX GPUon an RTX 3090. 0xbad00004 is NGX's FeatureNotFound... is only in folders whose path is not all ASCII (...) ... put it in $XDG_DATA_HOME/hookshot/ngx, or RX_VK_DLSS_DIR=<an ASCII folder>, and the menu says the sameRX_VK_DLSS_DIRNGX started,NVIDIA DLSS draws OoT's upscale: 1366x768 -> 2048x1152,528 frames drawnin the first status lineWith
RX_VK_DLSS_LOG=1, NGX's own lines show both steps. Through the alias it finds the runtime (Loading most recent 'libnvidia-ngx-dlss.so' snippet from '/proc/self/fd/135'... Found 1 snippets). Then the driver cannot load it from the real path (failed to load signed snippet - Unable to open fd).Not tested: Windows end to end (no change there), and the U+FFFD fallback in a real run. That fallback only applies when a non-ASCII folder cannot be opened, and NGX would not find anything there anyway.