aboutsummaryrefslogtreecommitdiff
path: root/src/strategies/low_latency2/device_strategy.cc
diff options
context:
space:
mode:
authorNicolas James <nj3ahxac@gmail.com>2026-04-06 17:03:35 +1000
committerNicolas James <nj3ahxac@gmail.com>2026-04-06 17:03:35 +1000
commit312d8736ae0df55c9f33e4eb5c00e4cd77e1c33f (patch)
tree170816e372c43ddc6522e059f7d6fdc8757330f2 /src/strategies/low_latency2/device_strategy.cc
parenta9a083ea5c649498d2f12e611dbc7c767d152130 (diff)
Add refactored VK_NV_low_latency2 impl, (fixes many threading issues)
Diffstat (limited to 'src/strategies/low_latency2/device_strategy.cc')
-rw-r--r--src/strategies/low_latency2/device_strategy.cc83
1 files changed, 82 insertions, 1 deletions
diff --git a/src/strategies/low_latency2/device_strategy.cc b/src/strategies/low_latency2/device_strategy.cc
index 3a970a2..18ea21f 100644
--- a/src/strategies/low_latency2/device_strategy.cc
+++ b/src/strategies/low_latency2/device_strategy.cc
@@ -1,4 +1,6 @@
#include "device_strategy.hh"
+#include "device_context.hh"
+#include "queue_strategy.hh"
#include "helper.hh"
#include <mutex>
@@ -15,7 +17,10 @@ void LowLatency2DeviceStrategy::notify_create_swapchain(
// VK_NV_low_latency2 allows a swapchain to be created with the low latency
// mode already on via VkSwapchainLatencyCreateInfoNV.
- auto was_low_latency_requested = bool{false};
+ // Default to enabled - if the app is using VK_NV_low_latency2 at all it
+ // wants pacing. VkSwapchainLatencyCreateInfoNV can override this, but
+ // apps like CS2 recreate swapchains without it (apparent app bug).
+ auto was_low_latency_requested = bool{true};
if (const auto slci = find_next<VkSwapchainLatencyCreateInfoNV>(
&info, VK_STRUCTURE_TYPE_SWAPCHAIN_LATENCY_CREATE_INFO_NV);
slci) {
@@ -38,4 +43,80 @@ void LowLatency2DeviceStrategy::notify_destroy_swapchain(
this->swapchain_monitors.erase(swapchain);
}
+void LowLatency2DeviceStrategy::notify_latency_sleep_mode(
+ const VkSwapchainKHR& swapchain,
+ const VkLatencySleepModeInfoNV* const info) {
+
+ const auto lock = std::shared_lock{this->mutex};
+
+ const auto iter = this->swapchain_monitors.find(swapchain);
+ assert(iter != std::end(this->swapchain_monitors));
+
+ using namespace std::chrono;
+ if (info) {
+ iter->second.update_params(info->lowLatencyMode,
+ microseconds{info->minimumIntervalUs});
+ } else {
+ iter->second.update_params(false, 0us);
+ }
+}
+
+void LowLatency2DeviceStrategy::submit_swapchain_present_id(
+ const VkSwapchainKHR& swapchain, const std::uint64_t& present_id) {
+
+ // Iterate through all queues and grab any work that's associated with this
+ // present_id. Turn it into a vector of work that we give to our swapchain
+ // monitor.
+ auto work = [&]() -> std::vector<std::deque<std::unique_ptr<Submission>>> {
+ auto work = std::vector<std::deque<std::unique_ptr<Submission>>>{};
+ const auto lock = std::scoped_lock{this->device.mutex};
+ for (const auto& queue_iter : this->device.queues) {
+ const auto& queue = queue_iter.second;
+
+ const auto strategy =
+ dynamic_cast<LowLatency2QueueStrategy*>(queue->strategy.get());
+ assert(strategy);
+
+ if (strategy->is_out_of_band.load(std::memory_order::relaxed)) {
+ continue;
+ }
+
+ // Need the lock now - we're modifying it.
+ const auto strategy_lock = std::unique_lock{strategy->mutex};
+ const auto iter = strategy->present_id_submissions.find(present_id);
+ if (iter == std::end(strategy->present_id_submissions)) {
+ continue;
+ }
+
+ // Make sure we clean it up from the present as well.
+ work.push_back(std::move(iter->second));
+ strategy->present_id_submissions.erase(iter);
+ }
+ return work;
+ }();
+
+ const auto lock = std::scoped_lock{this->mutex};
+
+ // Fail hard here, the swapchain must exist or something has gone wrong with
+ // Vulkan bookkeeping.
+ const auto iter = this->swapchain_monitors.find(swapchain);
+ assert(iter != std::end(this->swapchain_monitors));
+
+ // Notify our monitor that this work has to be completed before they signal
+ // whatever semaphore is currently sitting in it.
+ iter->second.attach_work(std::move(work));
+}
+
+void LowLatency2DeviceStrategy::notify_latency_sleep_nv(
+ const VkSwapchainKHR& swapchain, const VkLatencySleepInfoNV& info) {
+
+ const auto lock = std::scoped_lock{this->mutex};
+
+ // Again, fail hard here - something has gone terribly wrong.
+ const auto iter = this->swapchain_monitors.find(swapchain);
+ assert(iter != std::end(this->swapchain_monitors));
+
+ iter->second.notify_semaphore(info.signalSemaphore, info.value);
+}
+
} // namespace low_latency