diff options
| author | Nicolas James <nj3ahxac@gmail.com> | 2026-04-06 17:03:35 +1000 |
|---|---|---|
| committer | Nicolas James <nj3ahxac@gmail.com> | 2026-04-06 17:03:35 +1000 |
| commit | 312d8736ae0df55c9f33e4eb5c00e4cd77e1c33f (patch) | |
| tree | 170816e372c43ddc6522e059f7d6fdc8757330f2 /src/strategies/low_latency2/device_strategy.cc | |
| parent | a9a083ea5c649498d2f12e611dbc7c767d152130 (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.cc | 83 |
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 |
