diff --git a/src/dxvk/dxvk_cmdlist.cpp b/src/dxvk/dxvk_cmdlist.cpp index ca27a017e..b60d8f75d 100644 --- a/src/dxvk/dxvk_cmdlist.cpp +++ b/src/dxvk/dxvk_cmdlist.cpp @@ -50,9 +50,13 @@ namespace dxvk { VkResult DxvkCommandSubmission::submit( DxvkDevice* device, - VkQueue queue) { + VkQueue queue, + uint64_t frameId) { auto vk = device->vkd(); + VkLatencySubmissionPresentIdNV latencyInfo = { VK_STRUCTURE_TYPE_LATENCY_SUBMISSION_PRESENT_ID_NV }; + latencyInfo.presentID = frameId; + VkSubmitInfo2 submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO_2 }; if (!m_semaphoreWaits.empty()) { @@ -70,6 +74,9 @@ namespace dxvk { submitInfo.pSignalSemaphoreInfos = m_semaphoreSignals.data(); } + if (frameId && device->features().nvLowLatency2) + latencyInfo.pNext = std::exchange(submitInfo.pNext, &latencyInfo); + VkResult vr = VK_SUCCESS; if (!this->isEmpty()) @@ -200,7 +207,8 @@ namespace dxvk { VkResult DxvkCommandList::submit( const DxvkTimelineSemaphores& semaphores, - DxvkTimelineSemaphoreValues& timelines) { + DxvkTimelineSemaphoreValues& timelines, + uint64_t trackedId) { VkResult status = VK_SUCCESS; static const std::array SdmaCmdBuffers = @@ -259,7 +267,7 @@ namespace dxvk { m_commandSubmission.signalSemaphore(semaphores.transfer, ++timelines.transfer, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT); - if ((status = m_commandSubmission.submit(m_device, transfer.queueHandle))) + if ((status = m_commandSubmission.submit(m_device, transfer.queueHandle, trackedId))) return status; m_commandSubmission.waitSemaphore(semaphores.transfer, @@ -301,7 +309,7 @@ namespace dxvk { ++timelines.graphics, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT); // Finally, submit all graphics commands of the current submission - if ((status = m_commandSubmission.submit(m_device, graphics.queueHandle))) + if ((status = m_commandSubmission.submit(m_device, graphics.queueHandle, trackedId))) return status; // If there are WSI semaphores involved, do another submit only @@ -311,7 +319,7 @@ namespace dxvk { m_commandSubmission.signalSemaphore(semaphores.graphics, ++timelines.graphics, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT); - if ((status = m_commandSubmission.submit(m_device, graphics.queueHandle))) + if ((status = m_commandSubmission.submit(m_device, graphics.queueHandle, trackedId))) return status; } @@ -321,7 +329,7 @@ namespace dxvk { m_commandSubmission.waitSemaphore(semaphores.graphics, timelines.graphics, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT); - if (isLast && (status = m_commandSubmission.submit(m_device, transfer.queueHandle))) + if (isLast && (status = m_commandSubmission.submit(m_device, transfer.queueHandle, trackedId))) return status; } } diff --git a/src/dxvk/dxvk_cmdlist.h b/src/dxvk/dxvk_cmdlist.h index 31f4a1bc5..57ff7aa96 100644 --- a/src/dxvk/dxvk_cmdlist.h +++ b/src/dxvk/dxvk_cmdlist.h @@ -103,11 +103,13 @@ namespace dxvk { * * \param [in] device DXVK device * \param [in] queue Queue to submit to + * \param [in] frameId Latency frame ID * \returns Submission return value */ VkResult submit( DxvkDevice* device, - VkQueue queue); + VkQueue queue, + uint64_t frameId); /** * \brief Resets object @@ -215,11 +217,13 @@ namespace dxvk { * * \param [in] semaphores Timeline semaphore pair * \param [in] timelines Timeline semaphore values + * \param [in] frameId Latency frame ID * \returns Submission status */ VkResult submit( const DxvkTimelineSemaphores& semaphores, - DxvkTimelineSemaphoreValues& timelines); + DxvkTimelineSemaphoreValues& timelines, + uint64_t frameId); /** * \brief Stat counters diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 6cbfcf75b..b85939807 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -113,7 +113,7 @@ namespace dxvk { void DxvkContext::beginLatencyTracking( const Rc& tracker, uint64_t frameId) { - if (tracker && !m_latencyTracker) { + if (tracker && (!m_latencyTracker || m_latencyTracker == tracker)) { tracker->notifyCsRenderBegin(frameId); m_latencyTracker = tracker; diff --git a/src/dxvk/dxvk_queue.cpp b/src/dxvk/dxvk_queue.cpp index 4e3855ba9..8313af6b5 100644 --- a/src/dxvk/dxvk_queue.cpp +++ b/src/dxvk/dxvk_queue.cpp @@ -131,6 +131,9 @@ namespace dxvk { std::unique_lock lock(m_mutex); + uint64_t trackedSubmitId = 0u; + uint64_t trackedPresentId = 0u; + while (!m_stopped.load()) { m_appendCond.wait(lock, [this] { return m_stopped.load() || !m_submitQueue.empty(); @@ -150,10 +153,15 @@ namespace dxvk { m_callback(true); if (entry.submit.cmdList != nullptr) { - if (entry.latency.tracker) + if (entry.latency.tracker) { entry.latency.tracker->notifyQueueSubmit(entry.latency.frameId); - entry.result = entry.submit.cmdList->submit(m_semaphores, m_timelines); + if (!trackedSubmitId && entry.latency.frameId > trackedPresentId) + trackedSubmitId = entry.latency.frameId; + } + + entry.result = entry.submit.cmdList->submit( + m_semaphores, m_timelines, trackedSubmitId); entry.timelines = m_timelines; } else if (entry.present.presenter != nullptr) { if (entry.latency.tracker) @@ -164,6 +172,9 @@ namespace dxvk { if (entry.latency.tracker) { entry.latency.tracker->notifyQueuePresentEnd( entry.latency.frameId, entry.result); + + trackedPresentId = entry.latency.frameId; + trackedSubmitId = 0u; } }