diff --git a/runtime/cfg.c b/runtime/cfg.c index ac6d7b94..01261137 100644 --- a/runtime/cfg.c +++ b/runtime/cfg.c @@ -259,7 +259,7 @@ static const CfgMeta metas[] = { {"COOP_ACCEPT", "ask", NULL, LIVE}, // Advanced: scheduling {"ASYNC_PREEMPT", "1", "0|1|2", RESTART}, {"REPLAY_ASYNC", "0", "0|1", RESTART}, - {"REPLAY_WORKERS", "3", "0..16", RESTART}, {"REPLAY_PIPE", "0", "0..4", RESTART}, + {"REPLAY_WORKERS", "0", "0..16", RESTART}, {"REPLAY_PIPE", "0", "0..4", RESTART}, {"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 {"DYN_RES", "0", "0|1", LIVE}, {"DYN_RES_TARGET", "16.7", "1..100", LIVE}, {"DYN_RES_STEP", "45", "8..600", LIVE}, diff --git a/runtime/ui/menu.cpp b/runtime/ui/menu.cpp index 14acb19b..fd5eff5c 100644 --- a/runtime/ui/menu.cpp +++ b/runtime/ui/menu.cpp @@ -1410,6 +1410,8 @@ static void tab_game(float scale) { // discord_rpc.c reads the setting on its own thread and connects or clears the status within half a second opt_toggle("NX2NAVI_DISCORD_RPC", UI_MENU_DISCORD_RPC, UI_MENU_DISCORD_RPC_DESC); rows_saves(); + // vk_exec.c rw_init reads it at start: the row notes the restart and the bar's Restart does it + opt_slider("NX2NAVI_REPLAY_WORKERS", UI_MENU_REPLAY_WORKERS, 0, 8, UI_MENU_REPLAY_WORKERS_DESC, 1, "%.0f"); // The debug menu, a tool for testing with English text of its own: off unless switched on here if (dbg_supported()) { opt_group_text("Testing"); diff --git a/runtime/ui_text.c b/runtime/ui_text.c index 808bc33e..3b5de514 100644 --- a/runtime/ui_text.c +++ b/runtime/ui_text.c @@ -470,6 +470,11 @@ static const char *const text_en[UI_TEXT_COUNT] = { "where the card has none, keeps video memory within what the driver reports free, waits less for the GPU and " "prepares frames on a thread of their own. Measured on a Radeon RX 580 only: it can show a dark or flickering " "frame now and then, so leave it off on a newer card.", + [UI_MENU_REPLAY_WORKERS] = "Replay workers (experimental)", + [UI_MENU_REPLAY_WORKERS_DESC] = "CPU threads that help translate each frame's draws for the GPU, beside the game's own " + "thread. 3 gave about 20% more frames a second in Hyrule Field on an 8-core CPU; more " + "than 3 gave nothing more. Some players' games crashed with them on: 0 (off) is the " + "safe choice. Takes effect after a restart.", [UI_MENU_DISCORD_RPC] = "Discord Rich Presence", [UI_MENU_DISCORD_RPC_DESC] = "Shows \"Playing NX2navi\" with the play time in your Discord status while the " "game runs. discord_app_id and discord_image in nx2navi.ini choose the application.", diff --git a/runtime/ui_text.h b/runtime/ui_text.h index 4de41427..13cfb95e 100644 --- a/runtime/ui_text.h +++ b/runtime/ui_text.h @@ -165,6 +165,7 @@ typedef enum { // Menu tab UI_MENU_MENU_LANG, UI_MENU_MENU_LANG_DESC, UI_MENU_MENU_LANG_AUTO, UI_MENU_DISCORD_RPC, UI_MENU_DISCORD_RPC_DESC, UI_MENU_LOW_END_GPU, UI_MENU_LOW_END_GPU_DESC, + UI_MENU_REPLAY_WORKERS, UI_MENU_REPLAY_WORKERS_DESC, // the Game tab, English only // Language names, each in its own language and the same in every row (game language and menu language lists) UI_MENU_LANGNAME_EN, UI_MENU_LANGNAME_JA, UI_MENU_LANGNAME_FR, UI_MENU_LANGNAME_DE, UI_MENU_LANGNAME_IT, diff --git a/runtime/vk_exec.c b/runtime/vk_exec.c index bd9d6785..76404c49 100644 --- a/runtime/vk_exec.c +++ b/runtime/vk_exec.c @@ -1782,10 +1782,13 @@ static void op_one(VkExec *ex, const op_hdr *h) { } } -// ---- replay workers (NX2NAVI_REPLAY_WORKERS, default 3; 0: the replay records every op on the submitting thread) -// Default 3: 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 +// ---- replay workers (NX2NAVI_REPLAY_WORKERS, default 0: the replay records every op on the submitting thread; the +// Game tab's Replay workers 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. +// Valley; 5 or 7 workers measured the same as 3. Default 0 again after players' games crashed with 3 on by default +// (0.9.1, 0.9.2): an RX 6700 XT lost its device after about 18,000 frames, its last mark a compute dispatch of the +// replay's own, with an occlusion query slot found unavailable after its fence just before; the cause is not known. // A submission's draws come in runs between ops that have to stay in the replay's order on its own thread (dispatches, // copies, texture and buffer clears, events, the game's barriers, calls). Hyrule Field, standing (NX2NAVI_REPLAY_RUNS, // 2026-11-11): about 3,500 draws a frame in 82 runs, 96% of them in runs of 16 draws or more and 67% in runs of 256 or