[dxvk] Add latency tracker to presenter

This commit is contained in:
Philip Rebohle 2025-01-18 00:23:24 +01:00
parent 778eef385e
commit 648bb510ea
3 changed files with 36 additions and 10 deletions

View file

@ -224,7 +224,11 @@ namespace dxvk {
}
void Presenter::signalFrame(VkResult result, uint64_t frameId) {
void Presenter::signalFrame(
VkResult result,
uint64_t frameId,
const Rc<DxvkLatencyTracker>& tracker,
uint64_t trackedId) {
if (m_signal == nullptr || !frameId)
return;
@ -232,15 +236,20 @@ namespace dxvk {
std::lock_guard<dxvk::mutex> lock(m_frameMutex);
PresenterFrame frame = { };
frame.result = result;
frame.mode = m_presentMode;
frame.frameId = frameId;
frame.tracker = tracker;
frame.trackedId = trackedId;
frame.mode = m_presentMode;
frame.result = result;
m_frameQueue.push(frame);
m_frameCond.notify_one();
} else {
m_fpsLimiter.delay();
m_signal->signal(frameId);
if (tracker)
tracker->notifyGpuPresentEnd(trackedId);
}
m_lastFrameId.store(frameId, std::memory_order_release);
@ -1054,6 +1063,13 @@ namespace dxvk {
Logger::err(str::format("Presenter: vkWaitForPresentKHR failed: ", vr));
}
// Signal latency tracker right away to get more accurate
// measurements if the frame rate limiter is enabled.
if (frame.tracker) {
frame.tracker->notifyGpuPresentEnd(frame.trackedId);
frame.tracker = nullptr;
}
// Apply FPS limtier here to align it as closely with scanout as we can,
// and delay signaling the frame latency event to emulate behaviour of a
// low refresh rate display as closely as we can.

View file

@ -18,6 +18,7 @@
#include "dxvk_format.h"
#include "dxvk_image.h"
#include "dxvk_latency.h"
namespace dxvk {
@ -56,6 +57,8 @@ namespace dxvk {
*/
struct PresenterFrame {
uint64_t frameId = 0u;
Rc<DxvkLatencyTracker> tracker = nullptr;
uint64_t trackedId = 0u;
VkPresentModeKHR mode = VK_PRESENT_MODE_FIFO_KHR;
VkResult result = VK_NOT_READY;
};
@ -135,9 +138,15 @@ namespace dxvk {
* called before GPU work prior to the present submission has
* completed in order to maintain consistency.
* \param [in] result Presentation result
* \param [in] frameId Frame number
* \param [in] frameId Frame ID
* \param [in] tracker Latency tracker
* \param [in] trackedId Latency frame ID
*/
void signalFrame(VkResult result, uint64_t frameId);
void signalFrame(
VkResult result,
uint64_t frameId,
const Rc<DxvkLatencyTracker>& tracker,
uint64_t trackedId);
/**
* \brief Changes sync interval

View file

@ -260,7 +260,8 @@ namespace dxvk {
// Signal the frame and then immediately destroy the reference.
// This is necessary since the front-end may want to explicitly
// destroy the presenter object.
entry.present.presenter->signalFrame(entry.result, entry.present.frameId);
entry.present.presenter->signalFrame(entry.result, entry.present.frameId,
entry.latency.tracker, entry.latency.trackedId);
entry.present.presenter = nullptr;
}