mirror of
https://github.com/tangerineturtle1/NX2navi.git
synced 2026-11-15 19:19:58 -04:00
Enable the drivers' low-latency extensions only in a run that starts with the setting on.
With the setting off the device is made exactly as before the mode existed, so the mode cannot change anything for a player who never turns it on. Turning it on in the menu then takes a restart, and the row says so; in a run that started with it on, changes still apply at once. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
This commit is contained in:
@@ -233,6 +233,8 @@ keeps per-core data without locks and relies on that, so the host models it (`ru
|
||||
limit back while a movie plays, while no present goes out, and for the rest of the run when the frames show that the
|
||||
driver does not hold it. DLSS Frame Generation brings its own low latency (`vk_dlssg.c`), and the direct path is off
|
||||
in such a run; NVIDIA's is also off while another frame generation presents the frames.
|
||||
The device gets the drivers' extensions only in a run that starts with the setting on (`vk_device.c`
|
||||
`create_device`): turning it on takes a restart, and with it off the device is made as it was before the mode.
|
||||
- ASTC textures are uploaded as they are where the device samples ASTC, and decoded by a compute shader everywhere
|
||||
else (`vk_astc.c`); under 20 GiB of video memory the decoder encodes them to BC3.
|
||||
- Texture detail (`texture_detail`, `vk_texture.c` "texture detail"): on a card with little video memory the large
|
||||
|
||||
@@ -641,8 +641,9 @@
|
||||
# (VK_AMD_anti_lag), whichever the driver has. On a driver with neither the setting does nothing. While it is on the
|
||||
# driver holds the game to fps_limit, in place of the game's own limiter and of RivaTuner Statistics Server (rtss).
|
||||
# With framegen = dlss on Windows, DLSS Frame Generation's own low latency is used and this setting is not; with
|
||||
# framegen = fsr3 it runs on AMD GPUs and is off on NVIDIA ones while frames are generated. Changes while the game runs
|
||||
# take effect at once.
|
||||
# framegen = fsr3 it runs on AMD GPUs and is off on NVIDIA ones while frames are generated. Turning it on takes effect
|
||||
# at the next start: a run that starts with 0 leaves the driver's mode off the graphics device altogether. In a run
|
||||
# that started with it on, changes take effect at once.
|
||||
# low_latency = 0
|
||||
|
||||
# HDR output, two kinds (both need HDR on in Windows, "Use HDR", or a Wayland compositor with colour management;
|
||||
|
||||
@@ -883,6 +883,7 @@ static const char *vsync_note(void) {
|
||||
// the driver's mode is NVIDIA's (AMD's has no boost; a 2 set there shows as on, which is what it does). Greyed out with
|
||||
// the reason where it cannot run: a driver with neither mode, a run in which DLSS frame generation brings its own, and
|
||||
// NVIDIA's while a frame generation presents the frames (vk_lowlat_status). Set and refused by the driver, it says so.
|
||||
// In a run that started with it off the driver's mode is not on the device: the row can be set and says "after restart".
|
||||
static void row_low_latency(void) {
|
||||
static const char *const values[] = {"0", "1", "2"};
|
||||
const char *names[] = {menu_text(UI_MENU_OFF), menu_text(UI_MENU_ON), menu_text(UI_MENU_LOW_LATENCY_BOOST)};
|
||||
@@ -892,7 +893,8 @@ static void row_low_latency(void) {
|
||||
if (st == VK_LOWLAT_NO_DRIVER) opt_disable_next(UI_MENU_LOW_LATENCY_NO_DRIVER);
|
||||
else if (st == VK_LOWLAT_DLSSG) opt_disable_next(UI_MENU_LOW_LATENCY_DLSSG);
|
||||
else if (st == VK_LOWLAT_FG) opt_disable_next(UI_MENU_LOW_LATENCY_FG);
|
||||
const char *note = st == VK_LOWLAT_FAILED && cur ? menu_text(UI_MENU_LOW_LATENCY_FAILED) : nullptr;
|
||||
const char *note = st == VK_LOWLAT_FAILED && cur ? menu_text(UI_MENU_LOW_LATENCY_FAILED)
|
||||
: st == VK_LOWLAT_RESTART && cur ? menu_text(UI_MENU_AFTER_RESTART) : nullptr;
|
||||
int nv = opt_choice_index("NX2NAVI_LOW_LATENCY", UI_MENU_LOW_LATENCY, names, n, cur, 0, UI_MENU_LOW_LATENCY_DESC, note);
|
||||
if (nv >= 0 && nv < n) opt_apply("NX2NAVI_LOW_LATENCY", values[nv]);
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ typedef struct VkCtx {
|
||||
has_low_latency2, // VK_NV_low_latency2 with VK_KHR_present_id, which it needs (vk_lowlat.c)
|
||||
has_present_id, // ... and the presentId feature: presents may carry a frame's number
|
||||
has_anti_lag, // VK_AMD_anti_lag with its antiLag feature (vk_lowlat.c)
|
||||
lists_low_latency, // the driver lists one of the two, left out: the run started with the mode off
|
||||
has_mesh_queries; // meshShaderQueries, kept while NX2NAVI_GPU_PASSES or NX2NAVI_DUMP is set
|
||||
int mesh_fallback; // task and mesh programs run as compute passes and are drawn from buffers
|
||||
// (mesh_fallback: auto without has_mesh_shader; vk_exec_draw.c "mesh fallback")
|
||||
|
||||
@@ -513,14 +513,22 @@ static int create_device(void) {
|
||||
// Low latency without frame generation (vk_lowlat.c): NVIDIA's extension, which needs VK_KHR_present_id enabled
|
||||
// with it, or AMD's, whose calls need its feature. Each only where the driver lists it; a driver lists one of them
|
||||
// at most. Not on a device the DLSS Frame Generation proxies make (vk_dlssg_create_device): that path's own
|
||||
// low-latency plugin asks for what it needs there, and the direct path stays off for the run.
|
||||
// low-latency plugin asks for what it needs there, and the direct path stays off for the run. And only in a run
|
||||
// that starts with NX2NAVI_LOW_LATENCY on: with it off the device is made exactly as before the mode existed, and
|
||||
// a driver that lists one of the two is only remembered (lists_low_latency), so the menu can say that turning the
|
||||
// setting on takes a restart.
|
||||
g_vk.lists_low_latency = 0;
|
||||
if (!vk_dlssg_dpa() && n_ext + 2 <= sizeof ext / sizeof *ext) {
|
||||
if (has_ext(ep, ne, VK_NV_LOW_LATENCY_2_EXTENSION_NAME) && has_ext(ep, ne, VK_KHR_PRESENT_ID_EXTENSION_NAME)) {
|
||||
int nv = has_ext(ep, ne, VK_NV_LOW_LATENCY_2_EXTENSION_NAME) && has_ext(ep, ne, VK_KHR_PRESENT_ID_EXTENSION_NAME);
|
||||
int amd = !nv && has_ext(ep, ne, VK_AMD_ANTI_LAG_EXTENSION_NAME);
|
||||
if (cfg_int("NX2NAVI_LOW_LATENCY") <= 0) {
|
||||
g_vk.lists_low_latency = nv || amd;
|
||||
} else if (nv) {
|
||||
g_vk.has_low_latency2 = 1;
|
||||
ext[n_ext++] = VK_KHR_PRESENT_ID_EXTENSION_NAME;
|
||||
ext[n_ext++] = VK_NV_LOW_LATENCY_2_EXTENSION_NAME;
|
||||
CHAIN(pid, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR);
|
||||
} else if (has_ext(ep, ne, VK_AMD_ANTI_LAG_EXTENSION_NAME)) {
|
||||
} else if (amd) {
|
||||
g_vk.has_anti_lag = 1;
|
||||
ext[n_ext++] = VK_AMD_ANTI_LAG_EXTENSION_NAME;
|
||||
CHAIN(antilag, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ANTI_LAG_FEATURES_AMD);
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
// Low latency without frame generation (NX2NAVI_LOW_LATENCY: 0 off, 1 on, 2 on with boost; default 0; live).
|
||||
// Low latency without frame generation (NX2NAVI_LOW_LATENCY: 0 off, 1 on, 2 on with boost; default 0). In a run that
|
||||
// starts with it on, a change takes effect at once; a run that starts with it off makes its device without the
|
||||
// drivers' extensions (vk_device.c create_device), so turning it on then takes a restart.
|
||||
//
|
||||
// A frame's delay from the pad to the screen has two parts the runtime can shorten. The first is the time the frame
|
||||
// waits after it is drawn: the frame limit used to hold a finished picture back until its slot (vk_backend.c
|
||||
@@ -504,6 +506,12 @@ void vk_lowlat_init(VkCtx *c) {
|
||||
}
|
||||
rt_log("lowlat: VK_AMD_anti_lag is enabled but its entry point is missing");
|
||||
}
|
||||
if (c->lists_low_latency) {
|
||||
L.why = VK_LOWLAT_RESTART;
|
||||
rt_log("lowlat: the driver has a low-latency mode; this run started with NX2NAVI_LOW_LATENCY off and made its "
|
||||
"device without it, so the setting takes effect at the next start");
|
||||
return;
|
||||
}
|
||||
rt_log("lowlat: this driver has neither VK_NV_low_latency2 nor VK_AMD_anti_lag: no low-latency mode%s",
|
||||
level ? " (NX2NAVI_LOW_LATENCY does nothing here)" : "");
|
||||
}
|
||||
|
||||
@@ -14,8 +14,10 @@ void vk_lowlat_release(void);
|
||||
// What the menu's row shows (ui/menu.cpp row_low_latency). The first two are the paths that can run; the others say
|
||||
// why none does: the driver has neither extension, DLSS Frame Generation's interposer owns low latency in this run
|
||||
// (vk_dlssg.c, NX2NAVI_REFLEX), a frame generation presents the frames in the window swapchain's place, or the driver
|
||||
// refused the mode or never ended its sleep (the log says which).
|
||||
enum { VK_LOWLAT_NV, VK_LOWLAT_AMD, VK_LOWLAT_NO_DRIVER, VK_LOWLAT_DLSSG, VK_LOWLAT_FG, VK_LOWLAT_FAILED };
|
||||
// refused the mode or never ended its sleep (the log says which), or the driver has a mode but the run started with
|
||||
// the setting off, so the device was made without it (vk_device.c create_device): the next start with it on has it.
|
||||
enum { VK_LOWLAT_NV, VK_LOWLAT_AMD, VK_LOWLAT_NO_DRIVER, VK_LOWLAT_DLSSG, VK_LOWLAT_FG, VK_LOWLAT_FAILED,
|
||||
VK_LOWLAT_RESTART };
|
||||
int vk_lowlat_status(void);
|
||||
// The direct path is in effect now: the setting is on and nothing else owns the presents. Any thread, one atomic load.
|
||||
int vk_lowlat_on(void);
|
||||
|
||||
Reference in New Issue
Block a user