NVIDIA DLSS, DLAA and Reflex (NGX + Vulkan, Linux and Windows, opt-in) #841
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!841
Loading…
Reference in a new issue
No description provided.
Delete branch "dlss"
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?
NVIDIA DLSS for Hookshot: Super Resolution, DLAA and Reflex, through NVIDIA's NGX library and Vulkan directly (no Streamline), on Linux and Windows. Opt-in at build time and off by default: a normal build, CI's release builds and the Builder without its NVIDIA DLSS tick are unchanged and fetch nothing.
No Streamline: everything uses NVIDIA's NGX library from the DLSS SDK directly, plus Vulkan's own
VK_NV_low_latency2for Reflex, so it works on native Linux as well as Windows.NVIDIA's files. Nothing of NVIDIA's is committed, bundled or uploaded. Only someone who opts in fetches them, for their own build:
scripts/ngx_sdk.pydownloads them from NVIDIA's own repository (NVIDIA/DLSS on GitHub) at one pinned commit, checks every file against a SHA-256 in the script, and refuses to download until NVIDIA's license is accepted (--accept-nvidia-license, or the Builder's tick, which shows the license first). The only automated fetch is thevulkan-dlssCI workflow, which downloads the headers and the .lib to check that the Windows link still works: it runs by hand (workflow_dispatch), and on a push or pull request only when a file DLSS's build depends on changes (paths:filters in its own workflow file, so the other jobs are untouched). It accepts NVIDIA's license for that CI run only, and uploads and caches nothing.What's in it
DLSS Super Resolution
ngx/. DLSS then replaces OoT's gameplay upscale network (fd029a31) every frame, preset K. Input and output sizes follow the game's: with #849 the output is 2048x1152, 2560x1440 or 3840x2160 and the Resolution row scales the 3D against it; the feature is made again when the output size changes or the render size leaves its mode's range. Colours and brightness match the native path.RX_VK_DLSS_DEBUG=motionshows them.Camera jitter
nx2/oot_jitter.pypatches the function that fills each view's uniform buffers (three loads of the view's projection) to add a Halton sub-pixel offset to P[0][2]/P[1][2] in registers, only while DLSS draws. Nothing in the game's memory changes: the GPU gets the jittered projection, and the CPU (shadow cascade fitting, culling) keeps the real camera. The host asks the renderer for the scene size and the sequence's length throughrx_option(HOS_OPT_DLSS_JITTER_W,_H,_PHASES). The renderer reads the offset back from P[0][2]/P[1][2], passes it to DLSS and removes it from the motion vectors. Verified in game: the offsets go through the sequence as expected, with no faults.The sequence is 8 × (output / render)² frames long, 8 (DLAA) to 64, as NVIDIA's guide recommends. The sites are only lifted into a build with NVIDIA's SDK (make_game.py sets
OOT_DLSS_JITTER=1for the lift, part of its cache key).dlss_jitter_clip(indlss_math.h, tested) picks the projections that get it: perspective, at 16:9 or the window's ratio; orthographic and 1:1 projections (the shadow maps, the per-character projector) never do.Shadows (reported by a tester): the first version put the jitter into sead's projection itself, so the shadow cascades, fitted to the view frustum, followed it and their origin moved by about 0.17 shadow texels a frame with a still camera at DLAA 3840x2160 (up to 0.4), against 0.003 with the jitter off. With the jitter only in the uniform buffers, it is back to the jitter-off level; picture detail is unchanged and fps is the same (38.5–39.4 at DLAA 3840x2160, jitter on or off).
DLAA
DLAA is the NVIDIA DLAA choice of the Upscaler row (
RX_VK_DLSS=2; see Settings). DLAA runs DLSS at a scale of 1 on the scene as drawn. At full scale the game doesn't run its 4/3 upscale but the same network as a same-size pass (9dc98871eb7fc101); DLSS replaces that pass too, which also covers the Resolution row's top step with DLSS on. The 3D is held at full scale whatever the Resolution row says, anddlss_out.compscales the result to the game's upscale output.Reflex
A new NVIDIA Reflex row: Off / On / On + Boost (
RX_VK_REFLEX=0/1/2).vkLatencySleepNV, simulation end and render-submit start at the game's present, render-submit end before the present's submit, and present start/end aroundvkQueuePresentKHR.VK_NV_low_latency2andVK_KHR_present_idare still enabled whenever the device has them, so the row works without a restart. Enabled alone they do nothing: nothing of them is used until the row is on.RX_VK_REFLEX=-leaves them off.RX_VK_REFLEX_LOG=1(opt-in) prints the driver's own timings (vkGetLatencyTimingsNV) every 300 frames while Reflex is on.Status
scripts/ngx_sdk.pyelsewhereSince the review
vk_dlss.cppnow includesvk_work.hand counts NGX's own commands (note_work()after the feature's creation and the evaluation), sofull_barrier's dedupe no longer leaves them out.Runner.Info's newngxSdkargument.error_codeoverload: a folder that cannot be made no longer ends the game. Windows paths are wide all the way.descriptors_disturbed()on every way out once commands are recorded;failedandlast_frameare atomics;make_pipelinesno longer leaks; a 60 s timeout on each SDK download.RX_VK_DLSS_JITTER_SIGN,RX_VK_DLSS_SQUARE) and the camera dump are gone, stale comments fixed, the jitter's options named (HOS_OPT_DLSS_JITTER_*).gpu/vk/dlss_math.hand tested on the CPU (tests/test_dlss_math.py); the menu's rules are tested by behaviour intest_upscaler_rows.cpp.vulkan-dlssCI job is in its own workflow: manual, or on DLSS's files only.ngx-sdk/is git-ignored.host/rx_backend.cnow includesgpu/vk/dlss_math.h, so the host objects' cache key hashes it and the Linux AppImage carries it.016d582, with the start-up screen #860). Conflicts invk_main.cpp,vk_replay.cpp,nx2/build.pyandtest_shader_stamp_cache.py, all resolved keeping both sides.vk_menu.cpp: #946 moved the Insert menu's value changes intoset_row(keys, clicks, the wheel and slider drags all go through it), and the Upscaler's rules (rows that cannot change here stay as they are, the Upscaler and Render resolution step throughupscaler_rows.h, another Upscaler snaps the Render resolution) moved intoset_rowwith it, so the mouse follows them too.Checked again on Linux after these changes (RTX 3090): builds with and without the SDK (without it: no NGX in
hookshot_vk.so, nongxfolder, no jitter sites in the lifted code), the Windowshookshot_vk.dllcross-built with the SDK through llvm-mingw (imports only Windows' own DLLs and the UCRT),tests/run_all.pygreen, actionlint clean. In game: DLSS draws the upscale correctly, the jitter steps through its sequence, Reflex On runs with its markers and timings, and with Reflex Off the log has no Reflex line at all.Moving objects
OoT has no velocity buffer: its scene pass writes a single B10G11R11 colour target plus depth, and its upscale network samples only the colour, so DLSS had only the camera's motion and anything that moves by itself ghosted.
Skinned draws (Link, the other characters and animals) are ordinary indexed vertex draws with a recognisable layout: position, bone weights and bone indices, with the bone palette in a uniform buffer.
vk_draw.cpppicks those that draw into the scene, and at the upscale each is drawn again into the motion image, each vertex skinned with this frame's bones and the previous frame's. The vertex and index data are read from the game's own buffers, and the poses are copied on the GPU into two buffers that take turns, so nothing is read back to the CPU. A pixel takes an actor's motion only where its depth matches the scene's; anything else keeps the camera motion.RX_VK_DLSS_ACTORS=0turns it off, andRX_VK_DLSS_DEBUG=motionshows the actors' vectors.Measured by running Link past the camera at a 2048x1152 output (headless, frame clock, same save), the mean error over Link against the game's own upscale drops by 40% (16.0 → 9.7, lower in every frame); over the whole frame 12.5 → 7.9. The runs differ by a few pixels in Link's position, so the numbers are indicative. A control with the camera turning and Link standing is unchanged (13.78 vs 13.81). Cost: about 0.04 ms of GPU and 0.07 ms of CPU a frame.
Still on the camera's motion: particles (Navi), water, the floor mist, foliage moved in its vertex shader and other mesh-shader geometry, Link's face and hair (drawn with another layout), rigid objects without bones, and an actor's first frame on screen.
Two test switches come with it:
RX_VK_DLSS_TRACElogs one frame's draws into the scene (how the above was found), andRX_VK_SHOT_GO=<file>takes a screenshot at every present while that file exists.Settings
DLSS is a choice in the Graphics tab's Upscaler row (Game's own, NVIDIA DLSS, NVIDIA DLAA), which replaces the separate NVIDIA DLSS row. The scaling rows read in the picture's order: Output resolution, Upscaler, Render resolution, Window scaling filter (formerly Upscaling), Sharpness. NVIDIA Reflex sits with Frame pacing.
With DLSS, Render resolution shows DLSS's modes: Auto, Quality (67%), Balanced (58%), Performance (50%) and Ultra Performance (33%). With DLAA it shows Native. DLSS now replaces the game's upscale at every one of these shares, not only at 75%: at the other shares the game runs a different upscale network, which DLSS previously left running.
DLSS and DLAA are offered only where they can run (an RTX GPU, the runtime present), and the help says why when they are not. In a build without NVIDIA's SDK, which includes every official build, the Upscaler row is not shown at all, and Render resolution is the game's own row. The Window scaling filter's help says it matters only when the window's size differs from the Output resolution; while they match, the row shows "Not needed (window = output)" and keeps the saved value. Reflex likewise needs VK_NV_low_latency2. Quality presets leave the Upscaler as chosen (with DLSS, their resolution becomes DLSS's nearest mode), and
RX_VK_DLSS=0/1/2still overrides the row. NVIDIA DLSS and DLAA look softer than the game's own upscaler, so their help says to set Sharpness to around 80%.The menu's help is now a short line on what a row is, plus a separate line for the value chosen (dimmer, with a bar), so the details sit with the value they describe; the panel keeps its height as values change.
The five settings read only at start (GPU device, Output resolution, Handheld profile, Ultrawide, Robust buffers) show "(after restart)" only while they differ from what runs, the Graphics tab lists them at its foot, and closing the menu asks "Restart to apply …?" with [Later] (keeps the change for the next start, asked again only after another change) or [Restart now]. Restart now saves the options and the pipeline cache, closes the game the normal way (the start-up screen's close path), then starts it again with the same arguments and environment: on Linux by re-executing in the same process (a launcher or stream waiting on it keeps it), on Windows with
CreateProcessW. Tested headless: Output resolution 2048x1152 → 2560x1440 across a restart, options and pipeline cache written, saves untouched. Tests:tests/test_menu_restart.py, plus additions totest_menu_hitandtest_upscaler_rows.Measurements
RTX 3090, Linux, driver 615.78, 2560x1440 output, Kokiri Forest start spot, 45 s per run after a 15 s settle, each run alone on the GPU. fps is the median of the renderer's own present counts, with p10–p90 in brackets.
DLSS costs about 2.3 ms a frame over the game's own network, and DLAA about 3 ms. DLAA draws 1.78x the pixels but is only 0.7 ms slower than DLSS, because the frame here is mostly bound by the CPU and replay rather than by the GPU.
Reflex, in a 1280x720 window with DLSS off, using the driver's own
vkGetLatencyTimingsNVreports of simulation start to present end:Reflex saves about 1 ms, close to run-to-run noise: at this CPU-bound frame rate the GPU queue isn't deep enough to add much delay. Boost made no difference. The Off run had a few hitches; with one run per mode, it isn't clear whether Reflex removes those.
Windows
DLSS Super Resolution, DLAA and the camera jitter now build for Windows as well; Reflex needed no change. NVIDIA's SDK is still never committed or bundled: each build downloads it for itself, only after NVIDIA's license is accepted.
scripts/ngx_sdk.pyreplacesscripts/linux/ngx-sdk.sh, which stays as a thin wrapper. It has one file table per platform at the pinned NVIDIA/DLSS commit 9981c635 (v310.9.16), checks every file against its SHA-256, and needs--accept-nvidia-licenseor a typed yes. On Windows it fetches LICENSE.txt, the headers,x64/nvsdk_ngx_s.libandrel/nvngx_dlss.dll.The llvm-mingw build links NVIDIA's static
nvsdk_ngx_s.lib(built for MSVC's static runtime, /MT) intohookshot_vk.dllwith/nodefaultlib:libcpmtand-ladvapi32. What it needs of MSVC's runtime comes fromgpu/vk/vk_ngx_msvc_rt.cppandhost/mingw_msvc_shims.c, compiled only for mingw with the SDK. The DLL still imports only Windows' own DLLs and the UCRT. Without the SDK, the build is unchanged (same objects, imports, exports and section sizes).At run time NGX is given
RX_VK_DLSS_DIR(when set),<game>\ngxand%LOCALAPPDATA%\Hookshot\ngx, and uses the newestnvngx_dlss.dllit finds across them. DLSS's own paths are wide all the way (GetModuleFileNameW,_wgetenv). The game itself does not yet start from a folder whose name has characters outside the system's ANSI code page; that is a separate fix, not part of this PR. NGX's core,_nvngx.dll, is the driver's and is never put beside the game.NGX's parameter object is read and set through the SDK's C functions (
NVSDK_NGX_Parameter_GetI/GetUI/SetUI), not its C++ virtual methods: the object comes from NVIDIA's MSVC-built library, and llvm-mingw's Itanium vtable order differs, so the virtual calls only worked because the overloads they landed on had the same size.The Hookshot Builder has an opt-in tick, "NVIDIA DLSS (downloads NVIDIA's SDK under NVIDIA's license)", off by default. Ticking it shows the license; the build then fetches the SDK into
%LOCALAPPDATA%\HookshotBuilder\ngx-sdk, passesHOOKSHOT_NGX_SDKthrough, andmake_game.pyputsnvngx_dlss.dllin<game>\ngx. Updating a folder built with DLSS keeps DLSS.A new CI workflow,
vulkan-dlss, fetches the headers and .lib only, buildshookshot_vk.dllwith them through llvm-mingw, and checks the link and the imports. It runs by hand, and on pushes and pull requests only when DLSS's files change (gpu/vk/vk_dlss*,vk_reflex*,vk_ngx_msvc_rt.cpp,host/mingw_msvc_shims.c,upscaler_rows.h,dlss_math.h, the DLSS shaders,nx2/oot_jitter.py,nx2/build.py,nx2/make_game.py,scripts/ngx_sdk.pyand the workflow itself). It accepts NVIDIA's license for that run only and uploads nothing.The Builder's C# is compiled by CI (the Compile Windows Builder step: 0 errors), and its builder workers test now passes
Runner.Info's newngxSdkargument.NGX's log (
RX_VK_DLSS_LOG=1) has a few lines that look like errors and are not: "failed to load NGXCore: 126" (twice) is NVIDIA's library looking for its core beside the game before it loads the driver's; "Feature … failed to load from cache" is NGX finding none of its own downloaded models. The readme says so. The two Windows warnings at init, "passed vkGetInstance/DeviceProcAddr to NGX SDK, but snippet is out of date" and the same forNVSDK_NGX_FeatureCommonInfo, come from NGX probing every feature snippet it knows at init (denoiser, inpainting, DLISR, slow-mo and so on, as its log shows on Linux), some of them older ones of the driver's. Our own DLSS snippet is 310.9.16, the SDK's. Hookshot uses the current init (NVSDK_NGX_VULKAN_Init_with_ProjectIDwith both procedure addresses and the feature info), and both are needed: the procedure addresses because the renderer loads Vulkan itself, and the feature info for the search paths and the logging. So the warnings are left as they are.Never share a game folder built with NVIDIA's files. The readme credits NVIDIA DLSS; NVIDIA's files are under NVIDIA's RTX SDKs license.
Known limits of the shims: they don't check /GS cookies in the exception-handler path (the same as the existing
__GSHandlerCheck), and running out of memory inside NGX ends the process with a message instead of throwing.Windows checks (12 of 14 done on Windows 11, RTX 5080, driver 621.14; last run on
842121f)dotnet build builder/HookshotBuilder.slncompiles: a full rebuild gives 0 warnings, 0 errors (.NET SDK 10.0.403, net8.0-windows); CI's Compile Windows Builder step also compiles itnvsdk_ngx_s.libandnvngx_dlss.dll, all hash-checked; the license notice, fetch lines and "with NVIDIA DLSS" in the Builder's log;ngx\nvngx_dlss.dllin the game folder with the right SHA-256; no_nvngx.dllanywhere. (bin\needs a packaged Builder to check: a Builder run from the source tree has none)ngxfolder or NVIDIA files, no NGX code inhookshot_vk.dll, and the menu has no Upscaler row (NVIDIA Reflex is still there: it needs no SDK)make_game.py --updatewithHOOKSHOT_NGX_SDK) rebuilt a DLSS folder "with NVIDIA DLSS" in 7.5 min, putnvngx_dlss.dllback and kept the saves; the launcher's Update button itself only shows when a newer release existsnvngx_dlss.dllanywhere, the log names the folders it looked in, then "the game's upscale runs (DLSS not available)", and DLSS isn't offered; a non-NVIDIA GPU or a missing NGX core is still to tryHookshot-DLSS Zélda, NGX loaded…Hookshot-DLSS Zélda\ngx/nvngx_dlss.dlland started. A name outside the ANSI code page (Japanese on an English Windows) stops the game itself before DLSS runs: that is the host's path handling, fixed in a separate PR%LOCALAPPDATA%\Hookshot\ngx\nvngx_dlss.dllis used when the game folder'sngxhas none;RX_VK_DLSS_DIRwins over both (tested with the same version in each place; with different versions NGX takes the newest)RX_VK_DLSS_LOG=1: NGX's own lines appear in our log (253 to 557 per run: NGX's core from the driver's DriverStore, "called from module hookshot_vk.dll", our snippet and version, "Using App hint Preset K"); its lines are now written as UTF-8 like ourstests/test_ngx_sdk.pyandtests/test_make_game_ngx.pypass, andmake_game.pywithHOOKSHOT_NGX_SDKbuilds with DLSSHOOKSHOT_MSVC=1(clang, MSVC target) withHOOKSHOT_NGX_SDK:hookshot_vk.dllbuilds and links (291 s, MSVC 14.51, Windows SDK 10.0.26100), imports only ADVAPI32, GDI32, KERNEL32 and USER32vulkan-dlsspasses on windows-2022: green on the PR atd378bd0(and every step was also run locally on Windows with CI's pinned llvm-mingw: 187 files, 0 failed, imports check passed)Note for testers: NGX starts on demand (the Insert menu's first opening, or the first upscale with DLSS), so a log from the title screen has no NGX lines yet.
How to build it
python -I scripts/ngx_sdk.py --accept-nvidia-license <sdk folder> --game <game folder>(or the Builder's NVIDIA DLSS tick on Windows;scripts/linux/ngx-sdk.shstill works). It fetches NVIDIA's DLSS SDK headers, library and runtime from NVIDIA/DLSS at one pinned commit, checks each file's SHA-256 and copies the runtime into the game folder. NVIDIA's files are under NVIDIA's own license (LICENSE.txt is fetched beside them) and are never committed here.HOOKSHOT_NGX_SDK=build-linux/ngx-sdk. Without that variable the build is the same as before: no Upscaler row, and no camera jitter sites in the lifted code.RX_VK_DLSS=1/2), and Reflex in its row (RX_VK_REFLEX).Tested on Linux with an RTX 3090, driver 615.78.08. Windows: tested on Windows 11 with an RTX 5080 (driver 621.14), see the checklist.
Thank you to everyone on this collaboration branch! It's marked work-in-progress, overlaps #850, and its script fetches NVIDIA SDK files from raw.githubusercontent.com/NVIDIA/DLSS at build time. Closing to keep the queue clear; please reopen when it's ready for review as a focused PR.
Re-opening, it was tested on Windows, will update with results shortly
Update:
HOOKSHOT_MSVC=1link. 6 of the 14 Windows checks are done; the description has the details.vulkan-dlssCI job becomes manual-only, so CI never fetches NVIDIA's files on its own;I'll post again when those are in.
Update: the review's findings are fixed, and the Windows test results are in. Main is merged again.
HOOKSHOT_MSVC=1build links too. The checklist in the description is updated.descriptors_disturbedon every path.dlss_math.hwith CPU tests.vulkan-dlssis now its own workflow. It runs by hand, or on pushes and PRs that touch DLSS's files. The builder workers test is fixed for the newRunner.Infoargument.vk_menu.cpp. #946'sset_rownow carries the Upscaler rules, so the mouse follows them too.Re-checked on Linux (RTX 3090):
tests/run_all.pypasses;Still open: per-object motion vectors (objects that move by themselves can trail). That work is in progress and will be a separate update.
Update: moving characters no longer ghost under DLSS.
OoT has no velocity buffer (one B10G11R11 colour target, and the upscale network samples only colour), so DLSS only had the camera's motion and Link trailed when he moved. Now the skinned draws (Link, the other characters and animals) are drawn again at the upscale, each vertex skinned with this frame's and the previous frame's bones. The data is read straight from the game's buffers and the poses are copied on the GPU, so each actor's pixels get their own motion vectors. A pixel takes the actor's motion only where its depth matches the scene. Everything else keeps the camera's motion.
RX_VK_DLSS_ACTORS=0turns it off.RX_VK_DLSS_DEBUG=motionshows the vectors.Details are in the description's new "Moving objects" section. Tests pass (120 passed, 7 skipped).
Notes from a parallel DLSS test on v2.0.7 (Streamline 2.14.16, RTX 5080, driver 621.14), where I ported this PR's frustum-offset jitter (
nx2/oot_jitter.py+hos_dlss_jitter_cam) as is: stable and sharp in DLAA. A viewport-offset jitter I tried first shook badly, since the fog / lighting / AO passes rebuild positions with the unjittered camera.Two things I saw with the jitter on, in case they show here too:
Unrelated but very visible under DLSS: the blocky light halos and the checkerboard smoke go away when the few NEAREST samplers are forced linear, see #1117.
Thanks for the detailed notes, and good to hear the jitter holds up in your build.
Shadows: your guess was right. Our jitter went into the game's camera projection itself, so the CPU side saw it too, and the shadow cascades (fitted to the view frustum) followed it. With a still camera at DLAA 3840x2160, the shadow map's origin moved by about 0.17 shadow texels every frame (up to 0.4), against 0.003 with the jitter off.
The jitter now goes only into the GPU's copy of the projection: it's added in registers where the game fills each view's uniform buffers, and nothing in the game's memory changes. DLSS gets the same jitter and picture detail is unchanged. The cascades, culling and everything else on the CPU see the real camera, and the cascade movement is back to the jitter-off level. This is pushed now (
4ee204a).In my tests (RTX 3090, Kokiri Forest's dappled light) the on-screen difference was small. If you can, please check whether it's visibly calmer on your side, ideally somewhere with crisp sunlit shadows.
fps: I couldn't reproduce the jitter cost. At DLAA 3840x2160 I get 38.5–39.4 fps with the jitter on or off, before and after this change, so it may be specific to the Streamline path or the GPU. Here the shadow maps are re-rendered every frame either way.
#1117: thanks for the pointer, I'll try it together with DLSS.
Update: merged main again (
016d582, with the start-up screen), plus three changes.4ee204a.Checked on Linux:
The menu agent's earlier run also cross-built
hookshot_vk.dllfor Windows. The full Windows exe could not be linked here (no Windows FFmpeg headers on this machine).The description now says that DLSS's paths are wide but the game itself doesn't yet start from a folder outside the ANSI code page. That will be its own PR.
Thanks for the thorough Windows run on
842121f: 11 of 14 now checked. The description's checklist is updated with your results.Fixed from your findings (pushed as
d378bd0):ngx:lines are now written as UTF-8 like the rest of the log. Thefs:lines are the host's, and they go with the separate path fix.Folders outside the ANSI code page (the game reading its own path as
???and exiting with code 2) are a host issue, not DLSS. That fix is coming as its own PR, and it also covers the command line and thefs:log lines.CI: this push also merges the latest main (the v2.0.9 hotfix). Main had changed
vk_draw.cpp's per-thread objects into functions, which broke three checks on the PR,vulkan-dlssamong them. It builds again on Linux, and the Windows DLL cross-builds with the SDK; CI should confirmvulkan-dlsson windows-2022 now.Also in the description: newer NGX releases offer DLSS Frame Generation on Linux too, so it's noted as a possible follow-up rather than Windows-only.
Thanks for the retest on
d378bd0. Pushed asde67a56:hookshot_log.txtopen, so moving it to.1failed and the new run overwrote it. The old process now passes its process id (HOS_RESTART_OF), and the new one waits for it to end (up to 10 s) before it moves the logs and opens its own. A restart should now leave the run before it inhookshot_log.1.txt, with no gaps. This was compiled for Windows but not run there yet, so a quick check would help: restart twice, then look at.1and.2.Z�ldalines (fs:mounts, and the program and pipeline cache paths) come from the host's ANSI path calls, outside DLSS. #1191 fixes them for the whole program, by making UTF-8 the game's code page on Windows 10 1903+. It also lets the game start from folders outside the ANSI code page (the???case from your first run).RX_VK_DLSS_JITTER=0).Also merged main again (rumble strength #1169: both kept in the option table).
Test report from an RTX 4080 SUPER (Ada) at a 3840x2160 output, which covers the "with jitter, and DLAA" part of the quality item.
Setup. RTX 4080 SUPER, driver 616.92, Windows 11, Ryzen 7 5800X3D, 64 GB. Built from
de67a56with llvm-mingw 20261104 andscripts/ngx_sdk.py(v310.9.16), with the 2.0.8 builder's hot list and PGO profile inwork/. Kokiri Forest from a save at Saria's spot. AnHOS_INPUT_SCRIPTwithHOS_INPUT_FRAME_CLOCK=1loads it and swings the camera sideways for 200 s. Output 3840x2160 in a 3840x2160 window, Reflex off, frame generation off. Every number is from a second run, on a warm driver cache.RX_VK_WB_DIFF=1RX_VK_WB_DIFF=1b784c68).RX_VK_PASS_TIMING=1shows the same 68 MB a frame ofwb copiestaking 5.2 ms without the diff and 0.55 ms with it. It is unrelated to this PR. The diff ran 200 s twice on 616.92 without losing the device; I'll post that on #1161.NGX started,2560x1440 (up to 3840x2160) -> 3840x2160, mode 2, preset Kand DLAA as mode 5. The jitter changes from frame to frame, and the actor motion takes 47-111k draws per 600 frames at 0.11-0.20 ms of CPU a frame. No NGX errors.Quality, still camera, 3840x2160 output. Same spawn view, screenshots at presents 2000-2002 (
RX_VK_SHOT_W/H=3840x2160):Merge with current main. The branch conflicts in
gpu/vk/vk_menu.cpp,gpu/vk/vk_menu.h,readme.mdandtests/run_all.py, mostly with #1144's 1920x1080 output (kOutputs,output_choice,step_output_choice). A local resolution that keeps this branch's rows works:0..kLastOutput, with its label fromkOutputs;row_fixed, thenstep_output_choice, then the Upscaler and Render resolution steps;HOS_OUTPUT_RESgoes throughoutput_choice, thenrestart_init().After that,
tests/test_output_resolution.pyno longer compiles. It cutsvk_menu.cppfromstruct Out {totx_speed(, a span that now holds the upscaler code (opts.dlss,ur::,dlss_why), and it expects main's "(game, restart)" labels.upscaler_rows,menu_restart,menu_hit,dlss_math,dlss_actor,ngx_sdk,make_game_ngxandoot_jitterpass on the merged tree on Windows with llvm-mingw.Not checked here: DLSS together with frame generation, Reflex latency, fullscreen on the display itself (the runs were in a background window), the update offer, and non-NVIDIA GPUs.
Thanks to everyone who tested this: the Windows reports on the RTX 5080, which caught the restart log loss, the shadow flicker and the start-up quirk; the RTX 3090 runs on Linux; and @itaskaev2's detailed 4080 SUPER report at 3840x2160. That one confirmed the jitter and shadows on a third card generation, measured DLSS at about 1.6 ms of GPU and DLAA at about 4 ms, and showed 2.5x less shimmer.
The last commits before the merge:
@itaskaev2, about the one 1.5 s stall in your DLSS Quality +
RX_VK_WB_DIFF=1run: I couldn't reproduce it here. The feature is only made again when the output size changes, the render size leaves the mode's range, the preset changes, or after the 120-frame idle release, and my runs made it exactly once. If you can run the same script again on v2.0.11 (or current main), thehookshot_log.txtlines around the stall would show which it was:vk: NVIDIA DLSS: feature <n> made (<reason>; ...)after the first one;not used for 120 frames ... let goline;vk: status:lines (their "the slowest" field, and "left to the game's network");the game's upscale runs (<reason>)line.A 1.5 s slowest frame next to a "made" or "let go" line means DLSS made its feature again; frames left to the game's network point to a shader compile on the fallback path instead. Either way, a new issue is the best place for it now that this is merged.
Still untested, if anyone has the setup: DLSS together with frame generation, Reflex latency, true fullscreen, the DLSS update offer, and 8 GB cards.
PR-841-VALIDATION-REPORT-EN.md
codex found 2 issues in the code, attaching report
Thanks for the validation report. Both bugs are fixed in #1364:
Café, putlibnvidia-ngx-dlss.so.*in~/.local/share/hookshot/ngx(or setRX_VK_DLSS_DIR); the log and menu now say this instead of "needs an RTX GPU".