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

[dxvk] Add latency tracker to queue submissions

This commit is contained in:
Philip Rebohle 2025-01-17 22:17:36 +01:00
parent 9a0057fc45
commit 26ff3d9817
7 changed files with 72 additions and 10 deletions

View File

@ -425,7 +425,7 @@ namespace dxvk {
ctx->synchronizeWsi(cSync);
ctx->flushCommandList(nullptr);
cDevice->presentImage(cPresenter, cFrameId, nullptr);
cDevice->presentImage(cPresenter, nullptr, cFrameId, nullptr);
});
if (m_backBuffers.size() > 1u)

View File

@ -876,7 +876,7 @@ namespace dxvk {
uint64_t frameId = cRepeat ? 0 : cFrameId;
cDevice->presentImage(cPresenter, frameId, nullptr);
cDevice->presentImage(cPresenter, nullptr, frameId, nullptr);
});
m_parent->FlushCsChunk();

View File

@ -111,8 +111,8 @@ namespace dxvk {
void DxvkContext::flushCommandList(DxvkSubmitStatus* status) {
m_device->submitCommandList(
this->endRecording(), status);
m_device->submitCommandList(this->endRecording(),
nullptr, 0, status);
this->beginRecording(
m_device->createCommandList());

View File

@ -318,12 +318,18 @@ namespace dxvk {
void DxvkDevice::presentImage(
const Rc<Presenter>& presenter,
const Rc<DxvkLatencyTracker>& tracker,
uint64_t frameId,
DxvkSubmitStatus* status) {
DxvkPresentInfo presentInfo = { };
presentInfo.presenter = presenter;
presentInfo.frameId = frameId;
m_submissionQueue.present(presentInfo, status);
DxvkLatencyInfo latencyInfo;
latencyInfo.tracker = tracker;
latencyInfo.frameId = frameId;
m_submissionQueue.present(presentInfo, latencyInfo, status);
std::lock_guard<sync::Spinlock> statLock(m_statLock);
m_statCounters.addCtr(DxvkStatCounter::QueuePresentCount, 1);
@ -332,10 +338,17 @@ namespace dxvk {
void DxvkDevice::submitCommandList(
const Rc<DxvkCommandList>& commandList,
const Rc<DxvkLatencyTracker>& tracker,
uint64_t frameId,
DxvkSubmitStatus* status) {
DxvkSubmitInfo submitInfo = { };
submitInfo.cmdList = commandList;
m_submissionQueue.submit(submitInfo, status);
DxvkLatencyInfo latencyInfo;
latencyInfo.tracker = tracker;
latencyInfo.frameId = frameId;
m_submissionQueue.submit(submitInfo, latencyInfo, status);
std::lock_guard<sync::Spinlock> statLock(m_statLock);
m_statCounters.merge(commandList->statCounters());

View File

@ -496,11 +496,13 @@ namespace dxvk {
* the submission thread. The status of this operation
* can be retrieved with \ref waitForSubmission.
* \param [in] presenter The presenter
* \param [in] frameId Optional frame ID
* \param [in] tracker Latency tracker
* \param [in] frameId Frame ID
* \param [out] status Present status
*/
void presentImage(
const Rc<Presenter>& presenter,
const Rc<DxvkLatencyTracker>& tracker,
uint64_t frameId,
DxvkSubmitStatus* status);
@ -510,10 +512,14 @@ namespace dxvk {
* Submits the given command list to the device using
* the given set of optional synchronization primitives.
* \param [in] commandList The command list to submit
* \param [in] tracker Latency tracker
* \param [in] frameId Frame ID
* \param [out] status Submission feedback
*/
void submitCommandList(
const Rc<DxvkCommandList>& commandList,
const Rc<DxvkLatencyTracker>& tracker,
uint64_t frameId,
DxvkSubmitStatus* status);
/**

View File

@ -42,7 +42,10 @@ namespace dxvk {
}
void DxvkSubmissionQueue::submit(DxvkSubmitInfo submitInfo, DxvkSubmitStatus* status) {
void DxvkSubmissionQueue::submit(
DxvkSubmitInfo submitInfo,
DxvkLatencyInfo latencyInfo,
DxvkSubmitStatus* status) {
std::unique_lock<dxvk::mutex> lock(m_mutex);
m_finishCond.wait(lock, [this] {
@ -52,18 +55,23 @@ namespace dxvk {
DxvkSubmitEntry entry = { };
entry.status = status;
entry.submit = std::move(submitInfo);
entry.latency = std::move(latencyInfo);
m_submitQueue.push(std::move(entry));
m_appendCond.notify_all();
}
void DxvkSubmissionQueue::present(DxvkPresentInfo presentInfo, DxvkSubmitStatus* status) {
void DxvkSubmissionQueue::present(
DxvkPresentInfo presentInfo,
DxvkLatencyInfo latencyInfo,
DxvkSubmitStatus* status) {
std::unique_lock<dxvk::mutex> lock(m_mutex);
DxvkSubmitEntry entry = { };
entry.status = status;
entry.present = std::move(presentInfo);
entry.latency = std::move(latencyInfo);
m_submitQueue.push(std::move(entry));
m_appendCond.notify_all();
@ -142,10 +150,21 @@ namespace dxvk {
m_callback(true);
if (entry.submit.cmdList != nullptr) {
if (entry.latency.tracker)
entry.latency.tracker->notifyQueueSubmit(entry.latency.frameId);
entry.result = entry.submit.cmdList->submit(m_semaphores, m_timelines);
entry.timelines = m_timelines;
} else if (entry.present.presenter != nullptr) {
if (entry.latency.tracker)
entry.latency.tracker->notifyQueuePresentBegin(entry.latency.frameId);
entry.result = entry.present.presenter->presentImage(entry.present.frameId);
if (entry.latency.tracker) {
entry.latency.tracker->notifyQueuePresentEnd(
entry.latency.frameId, entry.result);
}
}
if (m_callback)
@ -217,12 +236,18 @@ namespace dxvk {
std::array<VkSemaphore, 2> semaphores = { m_semaphores.graphics, m_semaphores.transfer };
std::array<uint64_t, 2> timelines = { entry.timelines.graphics, entry.timelines.transfer };
if (entry.latency.tracker)
entry.latency.tracker->notifyGpuExecutionBegin(entry.latency.frameId);
VkSemaphoreWaitInfo waitInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO };
waitInfo.semaphoreCount = semaphores.size();
waitInfo.pSemaphores = semaphores.data();
waitInfo.pValues = timelines.data();
status = vk->vkWaitSemaphores(vk->device(), &waitInfo, ~0ull);
if (entry.latency.tracker && status == VK_SUCCESS)
entry.latency.tracker->notifyGpuExecutionEnd(entry.latency.frameId);
}
if (status != VK_SUCCESS) {

View File

@ -7,6 +7,7 @@
#include "../util/thread.h"
#include "dxvk_cmdlist.h"
#include "dxvk_latency.h"
#include "dxvk_presenter.h"
namespace dxvk {
@ -47,6 +48,18 @@ namespace dxvk {
};
/**
* \brief Latency info
*
* Optionally stores a latency tracker
* and the associated frame ID.
*/
struct DxvkLatencyInfo {
Rc<DxvkLatencyTracker> tracker;
uint64_t frameId = 0;
};
/**
* \brief Submission queue entry
*/
@ -55,6 +68,7 @@ namespace dxvk {
DxvkSubmitStatus* status;
DxvkSubmitInfo submit;
DxvkPresentInfo present;
DxvkLatencyInfo latency;
DxvkTimelineSemaphoreValues timelines;
};
@ -102,10 +116,12 @@ namespace dxvk {
* dedicated submission thread. Use this to take
* the submission overhead off the calling thread.
* \param [in] submitInfo Submission parameters
* \param [in] latencyInfo Latency tracker info
* \param [out] status Submission feedback
*/
void submit(
DxvkSubmitInfo submitInfo,
DxvkLatencyInfo latencyInfo,
DxvkSubmitStatus* status);
/**
@ -115,10 +131,12 @@ namespace dxvk {
* and then presents the current swap chain image
* of the presenter. May stall the calling thread.
* \param [in] present Present parameters
* \param [in] latencyInfo Latency tracker info
* \param [out] status Submission feedback
*/
void present(
DxvkPresentInfo presentInfo,
DxvkLatencyInfo latencyInfo,
DxvkSubmitStatus* status);
/**