diff --git a/docs/releases/v0.10.1.md b/docs/releases/v0.10.1.md index 3ff9df59..d70046ad 100644 --- a/docs/releases/v0.10.1.md +++ b/docs/releases/v0.10.1.md @@ -12,13 +12,19 @@ game and 1.5 GB for the launcher; a GPU with Vulkan 1.3 and `VK_EXT_external_memory_host` (current NVIDIA and AMD cards). -## Changed +## Fixed -- **Every setting under the Game tab's Testing heading is off by default again:** - - *CPU helper threads* (`replay_workers = 0`; it was Automatic in 0.10.0); - - *Start next frame early* (`tail_early = 0`; it was on in 0.10.0); - - *Helpers work ahead* and *Helpers take small jobs* (`replay_pipe` and `replay_small`, off as before). +- **Video memory no longer fills up while you walk or turn the camera** (by epicmeme546). In 0.10.0 the video memory + in use climbed by several gigabytes within seconds of moving, in any area, until the card was full: the frame rate + fell to 2 to 4 frames a second and the game could end. The game lays its render targets out anew in every frame, one + behind the other. One of them, a shadow map, changes its size with the view, and every target behind it then lies at + a new address in each frame. A moved target should take over the image of the one it replaces, but that image counted + as in use until the game recycled the old target's texture object, so every frame got about a dozen new images and + each old one stayed for 120 frames or more: 6.7 GiB of them at 3416x1440 and 12.2 GiB at 3840x2160, on top of the + 10 GiB an area needs at those sizes. Such an image now goes to the next target of its size once nothing has drawn + with it or sampled it for 16 frames, and sooner once the card is past 80 % of its memory. Walking through Kokiri + Forest at 3416x1440 on a 20 GiB card: 15.9 GiB in use before, 9.7 to 10.7 GiB now. The same walk at 3840x2160 with + the memory budget of a 16 GiB card: 10.9 to 11.4 GiB, where a player's 16 GiB card had 22.2 GiB asked of it. - They are experimental and were measured on few cards. A value you chose yourself, in the settings menu or in - nx2navi.ini, stays as you set it: to keep 0.10.0's behaviour, set *CPU helper threads* to Automatic and *Start next - frame early* to On. Everything else is as in 0.10.0; see its notes. +Everything else is as in 0.10.0, the settings under the Game tab's Testing heading included: *CPU helper threads* is +Automatic (half the processor's cores less one: 3 on 8 cores) and *Start next frame early* is on. See 0.10.0's notes. diff --git a/docs/releases/v0.10.2.md b/docs/releases/v0.10.2.md deleted file mode 100644 index dc1fbe47..00000000 --- a/docs/releases/v0.10.2.md +++ /dev/null @@ -1,16 +0,0 @@ -## Fixed - -- **Video memory no longer fills up while the camera moves** (by epicmeme546). The game lays its render targets out anew - in every frame, one behind the other in one block of memory. One of them, a shadow map, changes its size with the view - (1141x1141 to 1917x1917 in Kokiri Forest, a texel or two a frame), and every target behind it then lies at a new - address in each frame. A moved target should take over the image of the one it replaces, but that image counted as in - use for as long as the game had not recycled the old target's texture object, so every frame got about a dozen new - images and each old one stayed for 120 frames or more: 6.7 GiB of them at 3416x1440 and 12.2 GiB at 3840x2160, on top - of the 10 GiB the area needs. A 20 GiB card ran full twice in five minutes of Kokiri Forest (images that could not be - made, 4 frames a second, then the game ended) and a 16 GiB card in Castle Town (images in system memory, 2 frames a - second). An image that another target was drawn over now goes to the next target of its size once nothing has drawn - with it or sampled it for 16 frames, or for 8 once the card is past 80 % of its memory, where such images are also - freed after 32 frames instead of ten seconds. Walking 28 metres from a save in Kokiri Forest and then around it at - 3416x1440: 15.9 GiB of video memory in use before and 14 GiB again on each lap; 9.7 to 10.7 GiB now, with at most 2.2 - GiB of released targets where there were 6.9 GiB, and 3,609 images made in the run where there were 6,970. The same - walk at 3840x2160 with the memory budget of a 16 GiB card: 10.9 to 11.4 GiB, at most 1.6 GiB of them released. diff --git a/nx2navi.ini.example b/nx2navi.ini.example index e107edb2..374b5d06 100644 --- a/nx2navi.ini.example +++ b/nx2navi.ini.example @@ -86,23 +86,23 @@ # the game has sometimes rewritten by then. # replay_async = 0 # EXPERIMENTAL. Record the large groups of draws of a submission on this many replay worker threads beside the -# submitting one: auto or 0 to 16. Default: 0, the replay records everything on one thread. auto (the default in -# 0.10.0 only): half the CPU's physical cores less one (2 on 6 cores, 3 on 8, 5 on 12, at most 6), none on four cores or -# fewer and none on AMD's driver for RX 6000 and older Radeon cards, where a player's game lost its graphics device with -# workers on; the log's "replay workers automatic" line says how many. 3 gave 51.7 instead of 43.6 fps standing in Hyrule Field on an RX +# submitting one: auto or 0 to 16. Default: auto, half the CPU's physical cores less one (2 on 6 cores, 3 on 8, 5 on +# 12, at most 6), none on four cores or fewer and none on AMD's driver for RX 6000 and older Radeon cards, where a +# player's game lost its graphics device with workers on; the log's "replay workers automatic" line says how many. +# 0: the replay records everything on one thread. 3 gave 51.7 instead of 43.6 fps standing in Hyrule Field on an RX # 7900 XT, and more than 3 gave nothing more there. Also in the menu: Game, Testing, CPU helper threads. # With 1 a worker records each long run of draws while the submitting thread waits for it: no faster, it checks that # the pictures stay the same. -# replay_workers = 0 -# EXPERIMENTAL. 1 lets the game start on its next frame while the graphics card still runs the end of the last one: the +# replay_workers = auto +# 1, the default, lets the game start on its next frame while the graphics card still runs the end of the last one: the # upscaler (FSR 4, FSR 3.1 or DLSS) and the interface drawn after it. The graphics card runs the same work, with the # copies of what it wrote for the game moved before that end, and the game's waits end once those copies and the -# results it reads are there. A frame whose end hands the game anything else runs as before. Default: 0 (1 in 0.10.0 -# only). Standing in Hyrule Field on an RX 7900 XT with FSR 4: 50.7 instead of 42.5 fps, and 63.5 +# results it reads are there. A frame whose end hands the game anything else runs as before. Default: 1 (0 up to +# 0.9.2); 0 turns it off. Standing in Hyrule Field on an RX 7900 XT with FSR 4: 50.7 instead of 42.5 fps, and 63.5 # instead of 49.4 with replay_workers = 3. # Does nothing without one of those upscalers, nor with the lazy write-back (the default on NVIDIA and Intel cards). # Also in the menu: Game, Testing, Start next frame early. -# tail_early = 0 +# tail_early = 1 # EXPERIMENTAL, with replay_workers. replay_pipe = N (1 to 4, default 0): the submitting thread goes on past up to N # groups its workers still record. replay_small = N (0 to 63, default 0, needs replay_pipe): a group of N draws or more # that is too small to share out (fewer than 64 draws) goes whole to one worker; 64 or more reads as 63. Kokiri Forest diff --git a/runtime/cfg.c b/runtime/cfg.c index e655d99d..aef5b0b8 100644 --- a/runtime/cfg.c +++ b/runtime/cfg.c @@ -296,9 +296,9 @@ static const CfgMeta metas[] = { // Advanced: scheduling {"ASYNC_PREEMPT", "1", "0|1|2", RESTART}, {"REPLAY_ASYNC", "0", "0|1", RESTART}, {"REPLAY_PIPE", "0", "0..4", RESTART}, - {"REPLAY_WORKERS", "0", "auto|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16", RESTART}, // vk_exec.c rw_init, vk_exec_replay_workers_auto - // vk_exec.c "the early tail"; off by default (on in 0.10.0 only) - {"TAIL_EARLY", "0", "0|1", RESTART}, + {"REPLAY_WORKERS", "auto", "auto|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16", RESTART}, // vk_exec.c rw_init, vk_exec_replay_workers_auto + // vk_exec.c "the early tail"; on by default since 0.10.0 + {"TAIL_EARLY", "1", "0|1", RESTART}, {"REPLAY_SMALL", "0", "0..63", RESTART}, // vk_exec.c group_start {"FREE_CORES", "0", "0|1", RESTART}, {"TIMER_1MS", "1", "0|1", RESTART}, // dynamic resolution (dynres.c): the scene follows the GPU time toward DYN_RES_TARGET milliseconds diff --git a/runtime/ui/menu.cpp b/runtime/ui/menu.cpp index cf4760ed..abf4603e 100644 --- a/runtime/ui/menu.cpp +++ b/runtime/ui/menu.cpp @@ -1475,7 +1475,7 @@ static void tab_game(float scale) { opt_group_text("Testing"); // vk_exec.c rw_init and tail_enabled read these at start: each row notes the restart and the bar's Restart does // it. A row whose setting does nothing without another one (rw_init) is greyed out until that one is set. - // Automatic first (vk_exec.c vk_exec_replay_workers_auto), named with the count it gives on this PC; 0 is the default + // Automatic first, the default (vk_exec.c vk_exec_replay_workers_auto), named with the count it gives on this PC { static const char *const vals[] = {"auto", "0", "1", "2", "3", "4", "5", "6", "7", "8"}; static char auto_name[64]; diff --git a/runtime/vk_exec.c b/runtime/vk_exec.c index 62e37966..7f59ddbe 100644 --- a/runtime/vk_exec.c +++ b/runtime/vk_exec.c @@ -1135,7 +1135,7 @@ static int split_n = -1, split_idle, split_in_pass, split_draws, split_at, part_ static uint64_t split_ns, part_t0; static uint64_t n_parts, n_subs, n_idle_parts, n_pass_splits, n_cuts; -// ---- the early tail (NX2NAVI_TAIL_EARLY, default 0; on by default in 0.10.0 only) +// ---- the early tail (NX2NAVI_TAIL_EARLY, default 1 since 0.10.0; 0 turns it off) // Standing in Hyrule Field with FSR 4 (RX 7900 XT, 2026-11-13) a frame's main submission ends with one part of 4.7 ms // of GPU time, the temporal upscaler and the interface drawn after it, and one of 1.4 ms, the write-backs of what the // shaders wrote into VRAM mirrors. The game waits for all of it before it writes the next frame's data (the wait after @@ -1849,9 +1849,9 @@ static void op_one(VkExec *ex, const op_hdr *h) { } } -// ---- replay workers (NX2NAVI_REPLAY_WORKERS, default 0: the replay records every op on the submitting thread; auto: -// as many as the CPU's cores make worth it, vk_exec_replay_workers_auto, the default in 0.10.0 only; the Game tab's CPU -// helper threads row sets it) +// ---- replay workers (NX2NAVI_REPLAY_WORKERS, default auto: as many as the CPU's cores make worth it, +// vk_exec_replay_workers_auto; 0: the replay records every op on the submitting thread; the Game tab's CPU helper +// threads row sets it) // 3 workers: on an RX 7900 XT with a Ryzen 7 5800X3D, Hyrule Field standing went from 41.2 to 50.4 fps (2026-11-12, one // batch), with the same pictures there and in Kokiri Forest, Kakariko, Goron City, a graveyard house and Gerudo // Valley; 5 or 7 workers measured the same as 3. Default 0 again after players' games crashed with 3 on by default