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->synchronizeWsi(cSync);
ctx->flushCommandList(nullptr); ctx->flushCommandList(nullptr);
cDevice->presentImage(cPresenter, cFrameId, nullptr); cDevice->presentImage(cPresenter, nullptr, cFrameId, nullptr);
}); });
if (m_backBuffers.size() > 1u) if (m_backBuffers.size() > 1u)

View File

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

View File

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

View File

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

View File

@ -496,11 +496,13 @@ namespace dxvk {
* the submission thread. The status of this operation * the submission thread. The status of this operation
* can be retrieved with \ref waitForSubmission. * can be retrieved with \ref waitForSubmission.
* \param [in] presenter The presenter * \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 * \param [out] status Present status
*/ */
void presentImage( void presentImage(
const Rc<Presenter>& presenter, const Rc<Presenter>& presenter,
const Rc<DxvkLatencyTracker>& tracker,
uint64_t frameId, uint64_t frameId,
DxvkSubmitStatus* status); DxvkSubmitStatus* status);
@ -510,10 +512,14 @@ namespace dxvk {
* Submits the given command list to the device using * Submits the given command list to the device using
* the given set of optional synchronization primitives. * the given set of optional synchronization primitives.
* \param [in] commandList The command list to submit * \param [in] commandList The command list to submit
* \param [in] tracker Latency tracker
* \param [in] frameId Frame ID
* \param [out] status Submission feedback * \param [out] status Submission feedback
*/ */
void submitCommandList( void submitCommandList(
const Rc<DxvkCommandList>& commandList, const Rc<DxvkCommandList>& commandList,
const Rc<DxvkLatencyTracker>& tracker,
uint64_t frameId,
DxvkSubmitStatus* status); 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); std::unique_lock<dxvk::mutex> lock(m_mutex);
m_finishCond.wait(lock, [this] { m_finishCond.wait(lock, [this] {
@ -52,18 +55,23 @@ namespace dxvk {
DxvkSubmitEntry entry = { }; DxvkSubmitEntry entry = { };
entry.status = status; entry.status = status;
entry.submit = std::move(submitInfo); entry.submit = std::move(submitInfo);
entry.latency = std::move(latencyInfo);
m_submitQueue.push(std::move(entry)); m_submitQueue.push(std::move(entry));
m_appendCond.notify_all(); 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); std::unique_lock<dxvk::mutex> lock(m_mutex);
DxvkSubmitEntry entry = { }; DxvkSubmitEntry entry = { };
entry.status = status; entry.status = status;
entry.present = std::move(presentInfo); entry.present = std::move(presentInfo);
entry.latency = std::move(latencyInfo);
m_submitQueue.push(std::move(entry)); m_submitQueue.push(std::move(entry));
m_appendCond.notify_all(); m_appendCond.notify_all();
@ -142,10 +150,21 @@ namespace dxvk {
m_callback(true); m_callback(true);
if (entry.submit.cmdList != nullptr) { 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.result = entry.submit.cmdList->submit(m_semaphores, m_timelines);
entry.timelines = m_timelines; entry.timelines = m_timelines;
} else if (entry.present.presenter != nullptr) { } 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); 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) if (m_callback)
@ -217,12 +236,18 @@ namespace dxvk {
std::array<VkSemaphore, 2> semaphores = { m_semaphores.graphics, m_semaphores.transfer }; std::array<VkSemaphore, 2> semaphores = { m_semaphores.graphics, m_semaphores.transfer };
std::array<uint64_t, 2> timelines = { entry.timelines.graphics, entry.timelines.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 }; VkSemaphoreWaitInfo waitInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO };
waitInfo.semaphoreCount = semaphores.size(); waitInfo.semaphoreCount = semaphores.size();
waitInfo.pSemaphores = semaphores.data(); waitInfo.pSemaphores = semaphores.data();
waitInfo.pValues = timelines.data(); waitInfo.pValues = timelines.data();
status = vk->vkWaitSemaphores(vk->device(), &waitInfo, ~0ull); 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) { if (status != VK_SUCCESS) {

View File

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