1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-24 04:54:14 +01:00

[dxvk] Add latency tracker to presenter

This commit is contained in:
Philip Rebohle 2025-01-18 00:23:24 +01:00
parent 26ff3d9817
commit fa6c32684a
3 changed files with 31 additions and 10 deletions

View File

@ -228,7 +228,10 @@ namespace dxvk {
} }
void Presenter::signalFrame(VkResult result, uint64_t frameId) { void Presenter::signalFrame(
VkResult result,
uint64_t frameId,
const Rc<DxvkLatencyTracker>& tracker) {
if (m_signal == nullptr || !frameId) if (m_signal == nullptr || !frameId)
return; return;
@ -236,15 +239,19 @@ namespace dxvk {
std::lock_guard<dxvk::mutex> lock(m_frameMutex); std::lock_guard<dxvk::mutex> lock(m_frameMutex);
PresenterFrame frame = { }; PresenterFrame frame = { };
frame.result = result;
frame.mode = m_presentMode;
frame.frameId = frameId; frame.frameId = frameId;
frame.tracker = tracker;
frame.mode = m_presentMode;
frame.result = result;
m_frameQueue.push(frame); m_frameQueue.push(frame);
m_frameCond.notify_one(); m_frameCond.notify_one();
} else { } else {
m_fpsLimiter.delay(); m_fpsLimiter.delay();
m_signal->signal(frameId); m_signal->signal(frameId);
if (tracker)
tracker->notifyGpuPresentEnd(frameId);
} }
m_lastFrameId.store(frameId, std::memory_order_release); m_lastFrameId.store(frameId, std::memory_order_release);
@ -1058,6 +1065,13 @@ namespace dxvk {
Logger::err(str::format("Presenter: vkWaitForPresentKHR failed: ", vr)); 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.frameId);
frame.tracker = nullptr;
}
// Apply FPS limtier here to align it as closely with scanout as we can, // 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 // and delay signaling the frame latency event to emulate behaviour of a
// low refresh rate display as closely as we can. // low refresh rate display as closely as we can.

View File

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

View File

@ -260,7 +260,8 @@ namespace dxvk {
// Signal the frame and then immediately destroy the reference. // Signal the frame and then immediately destroy the reference.
// This is necessary since the front-end may want to explicitly // This is necessary since the front-end may want to explicitly
// destroy the presenter object. // 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.present.presenter = nullptr; entry.present.presenter = nullptr;
} }