From c700d764773501421391b3061f9dda4843c843cd Mon Sep 17 00:00:00 2001
From: Philip Rebohle <philip.rebohle@tu-dortmund.de>
Date: Sun, 19 Jan 2025 02:26:17 +0100
Subject: [PATCH] [dxvk] Add option to disable VK_NV_low_latency2

---
 dxvk.conf                 | 10 ++++++++++
 src/dxvk/dxvk_adapter.cpp |  8 ++++++++
 src/dxvk/dxvk_options.cpp |  1 +
 src/dxvk/dxvk_options.h   |  4 ++++
 4 files changed, 23 insertions(+)

diff --git a/dxvk.conf b/dxvk.conf
index 55cc232f3..a3ddf3ea6 100644
--- a/dxvk.conf
+++ b/dxvk.conf
@@ -106,6 +106,16 @@
 # dxvk.latencyTolerance = 1000
 
 
+# Disables the use of VK_NV_low_latency2. This will make Reflex unavailable
+# in games, and if dxvk.latencySleep is set to True, a custom algorithm will
+# be used for latency control. By default, the extension will not be used in
+# 32-bit applications due to driver issues.
+#
+# Supported values: Auto, True, False
+
+# dxvk.disableNvLowLatency2 = Auto
+
+
 # Override PCI vendor and device IDs reported to the application. Can
 # cause the app to adjust behaviour depending on the selected values.
 #
diff --git a/src/dxvk/dxvk_adapter.cpp b/src/dxvk/dxvk_adapter.cpp
index 28f629059..12ede57b0 100644
--- a/src/dxvk/dxvk_adapter.cpp
+++ b/src/dxvk/dxvk_adapter.cpp
@@ -293,6 +293,14 @@ namespace dxvk {
       enabledFeatures.vk12.bufferDeviceAddress = VK_TRUE;
     }
 
+    // Disable NV_low_latency2 on 32-bit due to buggy latency sleep
+    // behaviour, or if explicitly set via the onfig file.
+    bool disableNvLowLatency2 = env::is32BitHostPlatform();
+    applyTristate(disableNvLowLatency2, instance->options().disableNvLowLatency2);
+
+    if (disableNvLowLatency2)
+      devExtensions.nvLowLatency2.setMode(DxvkExtMode::Disabled);
+
     // If we don't have pageable device memory support, at least use
     // the legacy AMD extension to ensure we can oversubscribe VRAM
     if (!m_deviceExtensions.supports(devExtensions.extPageableDeviceLocalMemory.name()))
diff --git a/src/dxvk/dxvk_options.cpp b/src/dxvk/dxvk_options.cpp
index 8fbf20bb6..8fb901f31 100644
--- a/src/dxvk/dxvk_options.cpp
+++ b/src/dxvk/dxvk_options.cpp
@@ -14,6 +14,7 @@ namespace dxvk {
     tearFree              = config.getOption<Tristate>("dxvk.tearFree",               Tristate::Auto);
     latencySleep          = config.getOption<Tristate>("dxvk.latencySleep",           Tristate::Auto);
     latencyTolerance      = config.getOption<int32_t> ("dxvk.latencyTolerance",       1000);
+    disableNvLowLatency2  = config.getOption<Tristate>("dxvk.disableNvLowLatency2",   Tristate::Auto);
     hideIntegratedGraphics = config.getOption<bool>   ("dxvk.hideIntegratedGraphics", false);
     zeroMappedMemory      = config.getOption<bool>    ("dxvk.zeroMappedMemory",       false);
     allowFse              = config.getOption<bool>    ("dxvk.allowFse",               false);
diff --git a/src/dxvk/dxvk_options.h b/src/dxvk/dxvk_options.h
index dcbd52230..36f920377 100644
--- a/src/dxvk/dxvk_options.h
+++ b/src/dxvk/dxvk_options.h
@@ -43,6 +43,10 @@ namespace dxvk {
     /// Latency tolerance, in microseconds
     int32_t latencyTolerance = 0u;
 
+    /// Disable VK_NV_low_latency2. This extension
+    /// appears to be all sorts of broken on 32-bit.
+    Tristate disableNvLowLatency2 = Tristate::Auto;
+
     // Hides integrated GPUs if dedicated GPUs are
     // present. May be necessary for some games that
     // incorrectly assume monitor layouts.