mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-23 19:54:16 +01:00
[dxvk] Add NV_low_latency2 path to latency tracker
This commit is contained in:
parent
00fc4af7ca
commit
d1c33c3328
@ -311,8 +311,8 @@ namespace dxvk {
|
||||
if (m_options.latencySleep != Tristate::True)
|
||||
return nullptr;
|
||||
|
||||
return new DxvkBuiltInLatencyTracker(
|
||||
m_options.latencyTolerance);
|
||||
return new DxvkBuiltInLatencyTracker(presenter,
|
||||
m_options.latencyTolerance, m_features.nvLowLatency2);
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,10 +10,16 @@
|
||||
namespace dxvk {
|
||||
|
||||
DxvkBuiltInLatencyTracker::DxvkBuiltInLatencyTracker(
|
||||
int32_t toleranceUs)
|
||||
: m_tolerance(std::chrono::duration_cast<duration>(
|
||||
std::chrono::microseconds(std::max(toleranceUs, 0)))) {
|
||||
Logger::info("Latency control enabled, using built-in algorithm");
|
||||
Rc<Presenter> presenter,
|
||||
int32_t toleranceUs,
|
||||
bool useNvLowLatency2)
|
||||
: m_presenter(std::move(presenter)),
|
||||
m_tolerance(std::chrono::duration_cast<duration>(
|
||||
std::chrono::microseconds(std::max(toleranceUs, 0)))),
|
||||
m_useNvLowLatency2(useNvLowLatency2) {
|
||||
Logger::info(str::format("Latency control enabled, using ",
|
||||
useNvLowLatency2 ? "VK_NV_low_latency2" : "built-in algorithm"));
|
||||
|
||||
auto limit = FpsLimiter::getEnvironmentOverride();
|
||||
|
||||
if (limit)
|
||||
@ -53,13 +59,23 @@ namespace dxvk {
|
||||
|
||||
void DxvkBuiltInLatencyTracker::notifyCsRenderBegin(
|
||||
uint64_t frameId) {
|
||||
// Not interesting here
|
||||
std::unique_lock lock(m_mutex);
|
||||
auto frame = findFrame(frameId);
|
||||
|
||||
if (frame && m_useNvLowLatency2) {
|
||||
m_presenter->setLatencyMarkerNv(frameId, VK_LATENCY_MARKER_SIMULATION_END_NV);
|
||||
m_presenter->setLatencyMarkerNv(frameId, VK_LATENCY_MARKER_RENDERSUBMIT_START_NV);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkBuiltInLatencyTracker::notifyCsRenderEnd(
|
||||
uint64_t frameId) {
|
||||
// Not interesting here
|
||||
std::unique_lock lock(m_mutex);
|
||||
auto frame = findFrame(frameId);
|
||||
|
||||
if (frame && m_useNvLowLatency2)
|
||||
m_presenter->setLatencyMarkerNv(frameId, VK_LATENCY_MARKER_RENDERSUBMIT_END_NV);
|
||||
}
|
||||
|
||||
|
||||
@ -75,7 +91,11 @@ namespace dxvk {
|
||||
|
||||
void DxvkBuiltInLatencyTracker::notifyQueuePresentBegin(
|
||||
uint64_t frameId) {
|
||||
// Not overly interesting
|
||||
std::unique_lock lock(m_mutex);
|
||||
auto frame = findFrame(frameId);
|
||||
|
||||
if (frame && m_useNvLowLatency2)
|
||||
m_presenter->setLatencyMarkerNv(frameId, VK_LATENCY_MARKER_PRESENT_START_NV);
|
||||
}
|
||||
|
||||
|
||||
@ -88,6 +108,9 @@ namespace dxvk {
|
||||
if (frame) {
|
||||
frame->presentStatus = status;
|
||||
frame->queuePresent = dxvk::high_resolution_clock::now();
|
||||
|
||||
if (m_useNvLowLatency2)
|
||||
m_presenter->setLatencyMarkerNv(frameId, VK_LATENCY_MARKER_PRESENT_END_NV);
|
||||
}
|
||||
|
||||
m_cond.notify_one();
|
||||
@ -142,13 +165,20 @@ namespace dxvk {
|
||||
void DxvkBuiltInLatencyTracker::sleepAndBeginFrame(
|
||||
uint64_t frameId,
|
||||
double maxFrameRate) {
|
||||
auto duration = sleep(frameId, maxFrameRate);
|
||||
auto duration = m_useNvLowLatency2
|
||||
? sleepNv(frameId, maxFrameRate)
|
||||
: sleepBuiltin(frameId, maxFrameRate);
|
||||
|
||||
std::unique_lock lock(m_mutex);
|
||||
|
||||
auto next = initFrame(frameId);
|
||||
next->frameStart = dxvk::high_resolution_clock::now();
|
||||
next->sleepDuration = duration;
|
||||
|
||||
if (m_useNvLowLatency2) {
|
||||
m_presenter->setLatencyMarkerNv(frameId, VK_LATENCY_MARKER_SIMULATION_START_NV);
|
||||
m_presenter->setLatencyMarkerNv(frameId, VK_LATENCY_MARKER_INPUT_SAMPLE_NV);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -178,7 +208,48 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
DxvkBuiltInLatencyTracker::duration DxvkBuiltInLatencyTracker::sleep(
|
||||
DxvkBuiltInLatencyTracker::duration DxvkBuiltInLatencyTracker::sleepNv(
|
||||
uint64_t frameId,
|
||||
double maxFrameRate) {
|
||||
bool presentSuccessful = false;
|
||||
|
||||
{ std::unique_lock lock(m_mutex);
|
||||
|
||||
// Set up low latency mode for subsequent frames
|
||||
VkLatencySleepModeInfoNV latencyMode = { VK_STRUCTURE_TYPE_LATENCY_SLEEP_MODE_INFO_NV };
|
||||
latencyMode.lowLatencyMode = VK_TRUE;
|
||||
latencyMode.lowLatencyBoost = VK_TRUE;
|
||||
latencyMode.minimumIntervalUs = 0;
|
||||
|
||||
if (m_envFpsLimit > 0.0)
|
||||
maxFrameRate = m_envFpsLimit;
|
||||
|
||||
if (maxFrameRate > 0.0)
|
||||
latencyMode.minimumIntervalUs = uint64_t(1'000'000.0 / maxFrameRate);
|
||||
|
||||
m_presenter->setLatencySleepModeNv(latencyMode);
|
||||
|
||||
// Wait for previous present call to complete in order to
|
||||
// avoid potential issues with oscillating frame times
|
||||
auto curr = findFrame(frameId - 1u);
|
||||
|
||||
if (curr && curr->cpuPresentEnd != time_point()) {
|
||||
m_cond.wait(lock, [curr] {
|
||||
return curr->presentStatus != VK_NOT_READY;
|
||||
});
|
||||
|
||||
presentSuccessful = curr->presentStatus >= 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!presentSuccessful)
|
||||
return duration(0u);
|
||||
|
||||
return m_presenter->latencySleepNv();
|
||||
}
|
||||
|
||||
|
||||
DxvkBuiltInLatencyTracker::duration DxvkBuiltInLatencyTracker::sleepBuiltin(
|
||||
uint64_t frameId,
|
||||
double maxFrameRate) {
|
||||
// Wait for all relevant timings to become available. This should
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <array>
|
||||
|
||||
#include "dxvk_latency.h"
|
||||
#include "dxvk_presenter.h"
|
||||
|
||||
#include "../util/thread.h"
|
||||
|
||||
@ -53,7 +54,9 @@ namespace dxvk {
|
||||
public:
|
||||
|
||||
DxvkBuiltInLatencyTracker(
|
||||
int32_t toleranceUs);
|
||||
Rc<Presenter> presenter,
|
||||
int32_t toleranceUs,
|
||||
bool useNvLowLatency2);
|
||||
|
||||
~DxvkBuiltInLatencyTracker();
|
||||
|
||||
@ -101,19 +104,26 @@ namespace dxvk {
|
||||
|
||||
private:
|
||||
|
||||
Rc<Presenter> m_presenter;
|
||||
|
||||
dxvk::mutex m_mutex;
|
||||
dxvk::condition_variable m_cond;
|
||||
|
||||
duration m_tolerance;
|
||||
|
||||
double m_envFpsLimit = 0.0;
|
||||
bool m_useNvLowLatency2 = false;
|
||||
|
||||
std::array<DxvkLatencyFrameData, FrameCount> m_frames = { };
|
||||
|
||||
uint64_t m_validRangeBegin = 0u;
|
||||
uint64_t m_validRangeEnd = 0u;
|
||||
|
||||
duration sleep(
|
||||
duration sleepNv(
|
||||
uint64_t frameId,
|
||||
double maxFrameRate);
|
||||
|
||||
duration sleepBuiltin(
|
||||
uint64_t frameId,
|
||||
double maxFrameRate);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user