24 Commits

Author SHA1 Message Date
chrg6
fb648acef9 Say where frame generation's acquire queue comes from when the graphics family has one queue.
The review found vk_fg.cpp's header saying both of frame generation's queues come from another family that can present
when the graphics family lacks them. vk_device.c create_device takes only the present queue from a family that can
present; the acquire queue, which needs no capability, is a second queue of that family or of any other family, or the
present queue itself when there is none. The header now says so.

Comment only: vk_fg.cpp compiles, check_content passes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 18:41:39 -05:00
chrg6
7613b7ade6 Bring the comments on frame generation, its restarts and RivaTuner Statistics Server's exit up to date.
vk_dlssg.c said frame_rate.c divides the frame limit by the multiplier, but the limit counts the frames the game draws
and only a limit of display is divided (frame_rate.c limit_game_hz). vk_fg.cpp said FSR 3.1 frame generation applies
after a restart, but FRAMEGEN is live (gfx_present.c window_settings_live makes the swapchain again; only a device made
for DLSS Frame Generation waits for a restart, vk_fg_wanted), and that its two queues come from the graphics family,
while vk_device.c create_device takes them from another family that can present where the graphics family has one
queue. rtss_limit.c's header said the profile is put back "from every path that ends the process" and stays "until the
next run changes it", and named only the setting and frame generation as keeping RTSS out: it now names the exits that
skip the restore (a kill, the device-lost watchdog, a crash inside the crash handler), that the next run takes the
leftover limit for the player's own, low latency, the read-only thread of a kept-out run, and the lookup on the
worker. (rtss_limit_want's "both reasons need a restart" went with the change that starts the worker for a kept-out
first want.)

Comments only: the three files compile, and check_content passes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 18:41:39 -05:00
chrg6
d9429b0c00 Break the memory report down past VMA, by owner in system memory, and by growth over a session.
Every report adds a line for video memory outside VMA (the driver's usage and budget per heap against VMA's blocks, and counts of pipelines by kind and by last use, stage libraries, compute pipelines, layouts and descriptor pools, with the swapchain, DLSS and FSR sizes), a line that splits the process's commit by owner (the game's heap and maps, device-local memory, VMA's host blocks, the C runtime heap with the shader caches, pipeline tables, texture cache, log queue and flight recorder in it, the driver's pipeline cache data and the rest), and a line naming what grew by more than 64 MiB since the report before and since play began. Every ten minutes of play and at exit a ranking line orders the categories by growth and marks those that only climbed; tests/mem_growth_check.py checks that bookkeeping.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 06:46:31 -05:00
chrg6
58c7baaa9e Bring frame generation without an upscaler from the 0.10.0 line into the VRAM pass.
The release of what the upscaler leaves now waits for frame generation's own inputs too: in that mode the DLSS sizes
are made for frame generation alone while the upscaler does not run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 00:52:36 -05:00
chrg6
e89cc4d430 Let frame generation run without a temporal upscaler, from inputs made for it alone.
With frame generation running and no DLSS or FSR upscaling, vk_dlaa.c arms and ends the frame in the same places and,
where the upscaler's evaluation would run, makes only frame generation's inputs (fg_only_frame): the scene's depth and
camera found as before, motion vectors from the same pass at the scene's size, no jitter at all, and the picture without
the HUD copied from the game's own scaled picture. DLSS Frame Generation and AMD's frame generation no longer need an
upscaler set; NVIDIA's through NGX still needs DLSS at the start and then keeps running when the upscaler is switched
off. The menu's Frame generation row stays usable with every Upscaling choice and the Upscaling row keeps frame
generation as set, with texts in all four menu languages. The log says at the start and at each change whether frame
generation takes its inputs from the upscaler or runs without one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 00:49:30 -05:00
chrg6
c7de484a72 Free what DLSS and FSR hold some presents after the upscaler is switched off, and the HUD-less picture once frame generation is off.
Switched off in the menu or failed, the upscaler kept everything it had made for the process: per scene size its
output, motion vector, mask and sharpening images and a DLSS feature (81 MiB of images at 2560x1440 with DLAA, 182 MiB
at 2160 lines, and about 0.5 GB per DLSS feature), the reactive mask's snapshots, the HUD-less pair and the FSR 3.1
and FSR 4 upscale contexts. Eight presents after it goes off they are freed on the replay thread, which makes every
evaluation, after a wait for the device to be idle, as the code already does for a size it replaces. Switched on
again, it makes them anew with a new history, as any switch on does.

The HUD-less picture was made and copied every frame, and kept, after frame generation went off, since the flag that
asks for it was never cleared on Windows: the frame generator's release clears it now, and the pair goes once no frame
generation swapchain is up.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-13 00:44:01 -05:00
chrg6
a464ffafbc Merge Tobim6's work for older graphics cards: mesh shaders emulated with compute, video memory kept within the heaps' budgets, staged mirror uploads and the submit wait that goes with them.
Conflicts: the settings key lists take both sides; frame generation keeps the camera-cut handling and logs its counters every 600 frames with the cuts among them; the pass-time mark moves into draw_viewport; mo_desc keeps the pose depth and notes the reader.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
2026-11-12 12:14:58 -05:00
FIocker
f0d0fae13b Tell FSR 3.1 frame generation of camera cuts, so a generated frame is never blended from two unrelated pictures.
vk_dlaa_fg_inputs hands out DLSS's new history with the frame's depth and motion, and FSR 4's and NVIDIA's frame
generation pass it on, but vk_fg_frame dropped it: FSR 3.1 takes a cut only in the generation callback, which its
swapchain calls later on its own thread. vk_fg_frame now notes each frame id's cut in a small ring
(runtime/vk_fg_reset.h), and generate sets the callback's reset from it. A frame after one that was not prepared (the
menu open, no inputs) counts as a cut too, and so does an id the ring no longer holds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 12:07:19 -05:00
Tobim6
046c2f6812 Frame generation: its counters every 600 frames, whether the frame generates or not
The line was logged only from a generating frame (the second, then every 3600th): a run whose frames never generated
said nothing about why.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 16:23:13 +01:00
Tobim6
293731d083 Frame generation: present and acquire queues from another family where the graphics family has one queue
AMD's Windows driver gives the graphics family a single queue. vk_device.c then made no frame generation queues, and
vk_fg_create_swapchain returned without a log line: AMD FSR 3.1 frame generation set in the menu did nothing on an
RX 580. The present queue (which nothing else may submit to) and the image acquire queue now come from a family that
can present, compute families first, with their families passed to AMD's swapchain; the log names them, or says that
there are none, and the menu offers FSR 3.1 frame generation only where they exist.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 16:23:12 +01:00
tangerineturtle1
e1cb6301ab Give frame generation and FSR the scene's own near and far planes, field of view and units.
DLSS frame generation (Streamline and the NGX path) and FSR 3.1 and 4 upscaling and frame generation were told the depth came from a camera with near 0.1 and no far plane. Ocarina's projection has a finite far plane that changes with the camera: in Hyrule Field its z row is (-1.00001, -0.200001), near 0.1 and far about 25,000; the camera before it had far about 1,000. With the far plane taken as missing, a surface 10,000 units away was read as 16,650. The planes, and whether the depth is inverted, now come from the frame's projection and the device's depth mode every frame (vk_dlaa.c proj_planes), with one log line when they change. The stored depth is already 0 near and 1 far: the -w..w clip depth the pipelines keep maps to exactly what a 0..w projection with the same planes stores, and a frame dump's scene depth spans 0.975 to 1.0.

FSR's contexts lose their infinite-depth flag and take the far plane from each dispatch. FSR frame generation now gets the camera's field of view instead of a fixed 1 radian, and the upscaler gets it too (its caller passed 0). The view's units are metres, not the centimetres FSR was told: the camera orbits Link about 4 units behind him at about 3 units a second.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 15:09:15 -05:00
chrg6
3d394dd84e Merge the fixes line: the stutter, memory, flicker and crash fixes, co-op, the mesh shader fallback and the launcher fixes.
Brought onto the line with FSR 4, its frame generation and the debug menu. Where both sides had added to the same
place, both stay: the patch table keeps the pickup count and the free camera, the settings list keeps both sides'
names, the menu includes the co-op page and the debug menu, and the launcher builder takes the pipeline list and the
FSR 4 folder. Both sides had added the menu's typed-character event; one definition stays, with the window code that
passes characters outside the basic plane.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
2026-11-11 08:18:01 -05:00
chrg6
d073d80e70 Create FSR 3.1's pipelines through the pipeline caches kept across runs, so a context is not compiled again at every start the driver's own cache does not serve.
The library creates its pipelines itself and names no pipeline cache. It is now handed pipeline creates of the runtime's in the place of the device's two, and a create without a cache is asked of the pipeline cache first and compiled into the play cache otherwise. ffx_pipe_cache = 0 turns it off. --probe-ffx-cache makes one upscaling context without a window or the game and says where its pipelines came from, and tests/ffx_cache_check.py runs it.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
2026-11-11 05:22:56 -05:00
epicmeme546
5bdf583331 Add frame generation through AMD's FSR SDK 2.4 as a setting to try with FSR 4, and never generate a frame without the HUD-less picture.
runtime/vk_fg4.cpp makes the frame generation swapchain and context with the libraries FSR 4 comes with
(amd_fidelityfx_loader_vk.dll and amd_fidelityfx_framegeneration_vk.dll beside the executable). vk_fg.cpp takes
that path only with fsr4_fg = 1 while FSR 4 is the upscaler; the default stays the FSR 3.1 library. The loader
picks the version for the card: the machine-learned FSR Frame Generation 4 on Radeon RX 9000 cards with Windows 11,
which is untested, and 3.1.6 elsewhere. On an RX 7900 XT (driver 26.10.1) it lists frame generation 3.1.6 and the
swapchains 4.0.0, which the driver brings and the loader chooses, and 3.1.7. The swapchain in place is wanted only
while its library is the one to use, so a change of the setting or of the upscaler, or a failure of this path,
takes it down as switching frame generation off does and the next present makes it with the other library.

The preparation gives this library the camera's position and axes, which FSR Frame Generation 4 requires, and a
scene scale of one metre a unit: with the 0.01 the FSR 3.1 path uses, version 3.1.6 drew grey translucent shapes
into the sky of its frames while the camera turned (160 captures of the screen during a camera sweep; clean with 1).

Both paths now generate a frame only when the picture without the HUD is there for it: generated from the
presented picture alone, the HUD would be warped with the scene behind it. In four configurations (21:9 with either
library, a 16:9 picture in a 21:9 window, a 1080 picture without HDR) every generated frame had it, and the log
counts the frames without. On screen, of the 6,404 pixels of the HUD's item button that stayed fixed through a
camera sweep with the FSR 3.1 library, 6,162 stayed fixed with this one.

Standing in Hyrule Field at 3440x1440 with FSR 4 Quality the game draws 43.0 frames a second with this path and
42.2 with the FSR 3.1 library, each shown twice over. One run changed the present mode, HDR, fullscreen, frame
generation, FSR 4, this setting and the upscaler in turn: 216 screenshots without a bad frame, and no failure.

The SDK's frame generation headers join runtime/third_party/ffx_sdk, unmodified. tools/make_kit.py and
tools/make_launcher.py take the third library from the --ffx4 folder when it is there, and tools/make_game.py
copies it beside the game.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
2026-11-11 04:49:01 -05:00
chrg6
d985e0ecb0 Offer FSR 3.1 in the Screen tab only where its library can load.
On Linux the Screen tab listed the five FSR 3.1 upscaling modes and AMD's frame generation, but only the
Windows build loads amd_fidelityfx_vk.dll: a player who picked a mode got the scene at the mode's share of
the picture with nothing to scale it back up. vk_ffx_available answers from the load's result once it ran,
and before that from the library file being there, so the menu can ask every frame. Where it says no,
the menu lists neither, a mode that is still set shows "in use: off", the scene keeps the game's own
share (vk_dlaa_fsr3), frame generation keeps the plain swapchain with one log line, and the texts name
what does run.

Pull request #371 by mooki000, taken as it is; two hunks merged by hand (vk_fg_wanted, which now also
stays off after a failure, and a README line that had gained Texture filtering). It touches vk_dlaa.c,
which another session is changing: vk_dlaa_fsr3 gains the availability test and one log text changes.

On Windows the menu changes only where the DLL is missing. The Windows files compile; nothing was run.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
2026-11-10 06:33:22 -05:00
chrg6
00f06e669e Fix nine runtime faults a tester's report named: a stack overrun on mesh draws, lost YMM halves on preemption, and seven more.
- The mesh stage's storage table starts 0x90 bytes before the end of the 2 KiB constant bank, and all sixteen slots
  were written: 0x6C bytes past a stack buffer on every mesh draw. It holds the nine slots that fit.
- The prebuilt runtime is compiled without AVX, so its preemption stub saved only XMM0-15 while the lifted code of
  an AVX2 processor keeps data in the upper YMM halves, which the stub's callees may clear. Both bodies are built
  now and the one for the processor is chosen at the start.
- After an FSR 3.1 frame generation error the window's swapchain was still AMD's object but went to the plain Vulkan
  calls. Swapchain calls follow whose swapchain it is, and a failure takes it down as a switch in the menu does.
- A movie is paced at its own 60 fps under a lower limit too: at 40 fps it ended 25 s behind its sound.
- A lost device left the wait for an upload spinning for good; it ends the run with the device's report.
- The compute pipeline key had four bytes of padding that were hashed and compared, so a prebuilt pipeline could be
  missed and built again.
- A thread's TLS pointer was published before the TLS was allocated, so the slot was always 0.
- A fatal exit puts RivaTuner Statistics Server's profile back, and an ini saved as UTF-16 is read.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
2026-11-09 21:54:40 -05:00
chrg6
813f256dbc Keep AMD frame generation off while NVIDIA's frame generation holds the device, so switching between them no longer crashes.
With frame generation set to NVIDIA DLSS at the start, the device is made through Streamline's proxies. Switching the menu to AMD FSR 3.1 then made AMD's frame generation swapchain on that device at once, and NVIDIA's driver crashed with an access violation. vk_fg_wanted now stays false while Streamline's proxies are in use, so the switch takes effect at the next start, as the menu's Frame generation row already says.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 12:31:28 -05:00
epicmeme546
754ded99e0 Raise the frame rate in Kokiri Forest and apply more settings during a run.
The foliage's sun shadows took most of the GPU time: one mesh draw shaded about 1,000 million fragments in the far cascade. The far cascade now shades them at a 2x2 rate, and the two far cascades drop one side of the double-sided cards. At the forest entrance the frame rate went from 18 to about 43 fps on an RX 7900 XT.

FSR 3.1, its frame generation and the console mode now take effect without a restart. The full performance overlay lists the settings shown in the options menu.

NX2NAVI_GPU_PASSES times each pass and counts its fragments, and NX2NAVI_SET_AT changes settings at a given frame for test runs. Both are off by default.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 02:40:51 -05:00
chrg6
5aa3bc4119 Render widescreen pictures at the DLSS mode's real share, and size frame generation for the scene it is given.
The game sizes its scene from the scale at the patch page against its own 1440-line picture, so on a 2160-line
picture native DLAA rendered a 1440-line scene and Quality 44 %. The page now gets the share times the picture's
height over 1440, and DLAA is native at any picture size. Switching dlaa off in the menu also gives the scene back
the game's own scale instead of leaving it small with nothing to enlarge it.

FSR 3.1 frame generation was created with the window as its largest render size, but it is given the scene's depth
and motion vectors, up to the picture's size. A 3414x1440 or 5120x2160 scene in a 1920x1080 window wrote past its
resources: a crash in amd_fidelityfx_vk.dll, device faults, striped frames. The context is now made for the picture's
size once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 04:10:35 -05:00
chrg6
432cbdffe8 Hold the frame limit on screen while FSR 3.1 frame generation runs.
Frame generation presents a generated frame between each two of the game's, so a limit of 60 showed 120. While
generation is on (not paused for the menu or for want of depth and motion), the game is paced at half the limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 04:10:34 -05:00
chrg6
c327dc07d8 Generate frames inside the picture only, so a window of another shape keeps its black bars clean, and use the Triforce as the icon.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 17:36:21 -05:00
chrg6
501d5bd084 Release pass: fix crashes, freezes and races, cut VRAM use, and translate more shaders.
Crashes: the render-target heap (HeapDef DynamicTextureAllocatorMem and its parent) grows with the widescreen
picture, so the pause menu no longer reads a null block at 5120x2160; texture uploads keep the game's memory mapped
while they copy it, so UnmapPhysicalMemory no longer pulls it away mid-copy; DLSS Frame Generation no longer crashes
in Streamline's set-up (physical devices and the window surface go through its proxies, its swapchain images are
counted first, resources are tagged per frame); a stale core-wait target is cleared before its thread is freed.

Freezes and races: a resize during a swapchain rebuild is kept, a failed frame generation swapchain is retried
instead of replaced by a plain one, three acquire timeouts in a row rebuild the swapchain, device waits take the
queue lock, a translator child that stops answering times out, an in-flight compute pipeline builds at normal
priority, a save Commit started before the window closes finishes and none starts after, a settings change just
before closing is saved, and a movie sample taken before a flush is dropped.

HDR: Enhanced HDR extends the game's own tonemap so highlights go above the picture's white (the hue slider,
which no longer applies, is gone from the menu); frame generation gets a HUD-less picture, the HDR flag and the HDR10
metadata under HDR too.

Memory: ASTC textures are encoded to BC3 unless the PC has 20 GiB of VRAM and 48 GiB of RAM, as Windows charges video
memory to the commit charge (a long session held 17 GiB of RGBA8 textures and 45.7 GiB of commit on a 32 GiB PC).

Shaders: the translator lowers spill-mode programs with more than eight uniform register groups in a wider spill
layout, and local loads and stores with a uniform-register address (36029 of the game's 36031 variants translate,
20 failed before).

The launcher release ships the shader tools and AMD's FidelityFX library (make_launcher.py --ffx); windres there gets
the toolchain on PATH.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 16:02:30 -05:00
chrg6
b9a042969e Keep the HUD out of frame generation, show the frame generation rate, and start DLSS Frame Generation.
Frame generation now gets the picture without the HUD each frame: the upscaler's output before the HUD is drawn over
it, encoded to sRGB as the game's last pass encodes its picture and put through the same colour, scaling and borders
as the presented frame, so it tells the HUD apart and leaves it unwarped in the generated frames
(NX2NAVI_FG_HUDLESS_SHOW=1 shows that picture, a test). The performance overlay gains an FG row and the fps line the
display's rate, generated frames included. The device enables VK_KHR_get_memory_requirements2 whenever AMD's frame
generation is on, which crashed at start with DLSS upscaling.

DLSS Frame Generation through NVIDIA Streamline (vk_dlssg.c, and nx2navi_dlssg.dll from runtime/dlssg, built with
MSVC by tools/build_dlssg.py against the SDK kept outside the repository) creates the instance and device through
Streamline's proxies and calls its swapchain hooks; Streamline still fails in its plugin start-up here, so the menu
lists it only while it is set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 13:31:07 -05:00
chrg6
7c11ff6816 Add AMD FSR 3.1 frame generation: a generated frame between every two the game draws.
With Frame generation set to AMD FSR 3.1 (after a restart), AMD's frame generation swapchain takes the place of the
present path's own: the device creates two more graphics queues for its presents and image acquires, the present
path acquires, gets images and presents through its replacement functions, and every frame configures generation
and records its preparation from the depth and camera motion vectors the DLSS or FSR 3.1 upscaling pass made (one of
them must be on). Generation pauses while the menu is open. On an RTX 5090 at a 60 fps game, about one frame was
generated for every frame drawn in play.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 13:31:06 -05:00