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

[d3d11] Implement latency tracking

This commit is contained in:
Philip Rebohle 2025-01-17 22:21:55 +01:00
parent 7c88807790
commit ac8868594f
4 changed files with 72 additions and 6 deletions

View File

@ -861,11 +861,17 @@ namespace dxvk {
} }
void D3D11ImmediateContext::EndFrame() { void D3D11ImmediateContext::EndFrame(
Rc<DxvkLatencyTracker> LatencyTracker) {
D3D10DeviceLock lock = LockContext(); D3D10DeviceLock lock = LockContext();
EmitCs<false>([] (DxvkContext* ctx) { EmitCs<false>([
cTracker = std::move(LatencyTracker)
] (DxvkContext* ctx) {
ctx->endFrame(); ctx->endFrame();
if (cTracker && cTracker->needsAutoMarkers())
ctx->endLatencyTracking(cTracker);
}); });
} }

View File

@ -169,7 +169,8 @@ namespace dxvk {
void SynchronizeDevice(); void SynchronizeDevice();
void EndFrame(); void EndFrame(
Rc<DxvkLatencyTracker> LatencyTracker);
bool WaitForResource( bool WaitForResource(
const DxvkPagedResource& Resource, const DxvkPagedResource& Resource,

View File

@ -2,6 +2,8 @@
#include "d3d11_device.h" #include "d3d11_device.h"
#include "d3d11_swapchain.h" #include "d3d11_swapchain.h"
#include "../dxvk/dxvk_latency_builtin.h"
#include "../util/util_win32_compat.h" #include "../util/util_win32_compat.h"
namespace dxvk { namespace dxvk {
@ -80,6 +82,7 @@ namespace dxvk {
m_presenter->destroyResources(); m_presenter->destroyResources();
DestroyFrameLatencyEvent(); DestroyFrameLatencyEvent();
DestroyLatencyTracker();
} }
@ -279,6 +282,18 @@ namespace dxvk {
// applications using the semaphore may deadlock. This works because // applications using the semaphore may deadlock. This works because
// we do not increment the frame ID in those situations. // we do not increment the frame ID in those situations.
SyncFrameLatency(); SyncFrameLatency();
// Ignore latency stuff if presentation failed
DxvkLatencyStats latencyStats = { };
if (hr == S_OK && m_latency) {
latencyStats = m_latency->getStatistics(m_frameId);
m_latency->sleepAndBeginFrame(m_frameId + 1, std::abs(m_targetFrameRate));
}
if (m_latencyHud)
m_latencyHud->accumulateStats(latencyStats);
return hr; return hr;
} }
@ -364,17 +379,23 @@ namespace dxvk {
auto immediateContext = m_parent->GetContext(); auto immediateContext = m_parent->GetContext();
auto immediateContextLock = immediateContext->LockContext(); auto immediateContextLock = immediateContext->LockContext();
immediateContext->EndFrame(); immediateContext->EndFrame(m_latency);
immediateContext->Flush(); immediateContext->Flush();
m_presenter->setSyncInterval(SyncInterval); m_presenter->setSyncInterval(SyncInterval);
// Presentation semaphores and WSI swap chain image // Presentation semaphores and WSI swap chain image
if (m_latency)
m_latency->notifyCpuPresentBegin(m_frameId + 1u);
PresenterSync sync; PresenterSync sync;
Rc<DxvkImage> backBuffer; Rc<DxvkImage> backBuffer;
VkResult status = m_presenter->acquireNextImage(sync, backBuffer); VkResult status = m_presenter->acquireNextImage(sync, backBuffer);
if (status != VK_SUCCESS && m_latency)
m_latency->discardTimings();
if (status < 0) if (status < 0)
return E_FAIL; return E_FAIL;
@ -402,6 +423,7 @@ namespace dxvk {
cSwapImage = GetBackBufferView(), cSwapImage = GetBackBufferView(),
cSync = sync, cSync = sync,
cPresenter = m_presenter, cPresenter = m_presenter,
cLatency = m_latency,
cColorSpace = m_colorSpace, cColorSpace = m_colorSpace,
cFrameId = m_frameId cFrameId = m_frameId
] (DxvkContext* ctx) { ] (DxvkContext* ctx) {
@ -425,13 +447,27 @@ namespace dxvk {
ctx->synchronizeWsi(cSync); ctx->synchronizeWsi(cSync);
ctx->flushCommandList(nullptr); ctx->flushCommandList(nullptr);
cDevice->presentImage(cPresenter, nullptr, cFrameId, nullptr); cDevice->presentImage(cPresenter, cLatency, cFrameId, nullptr);
}); });
if (m_backBuffers.size() > 1u) if (m_backBuffers.size() > 1u)
RotateBackBuffers(immediateContext); RotateBackBuffers(immediateContext);
immediateContext->FlushCsChunk(); immediateContext->FlushCsChunk();
if (m_latency) {
m_latency->notifyCpuPresentEnd(m_frameId);
if (m_latency->needsAutoMarkers()) {
immediateContext->EmitCs([
cLatency = m_latency,
cFrameId = m_frameId
] (DxvkContext* ctx) {
ctx->beginLatencyTracking(cLatency, cFrameId + 1u);
});
}
}
return S_OK; return S_OK;
} }
@ -479,6 +515,8 @@ namespace dxvk {
m_presenter->setSurfaceFormat(GetSurfaceFormat(m_desc.Format)); m_presenter->setSurfaceFormat(GetSurfaceFormat(m_desc.Format));
m_presenter->setSurfaceExtent({ m_desc.Width, m_desc.Height }); m_presenter->setSurfaceExtent({ m_desc.Width, m_desc.Height });
m_presenter->setFrameRateLimit(m_targetFrameRate, GetActualFrameLatency()); m_presenter->setFrameRateLimit(m_targetFrameRate, GetActualFrameLatency());
m_latency = m_device->createLatencyTracker(m_presenter);
} }
@ -555,9 +593,13 @@ namespace dxvk {
void D3D11SwapChain::CreateBlitter() { void D3D11SwapChain::CreateBlitter() {
Rc<hud::Hud> hud = hud::Hud::createHud(m_device); Rc<hud::Hud> hud = hud::Hud::createHud(m_device);
if (hud) if (hud) {
hud->addItem<hud::HudClientApiItem>("api", 1, GetApiName()); hud->addItem<hud::HudClientApiItem>("api", 1, GetApiName());
if (m_latency)
m_latencyHud = hud->addItem<hud::HudLatencyItem>("latency", 4);
}
m_blitter = new DxvkSwapchainBlitter(m_device, std::move(hud)); m_blitter = new DxvkSwapchainBlitter(m_device, std::move(hud));
} }
@ -567,6 +609,17 @@ namespace dxvk {
} }
void D3D11SwapChain::DestroyLatencyTracker() {
// Need to make sure the context stops using
// the tracker for submissions
m_parent->GetContext()->InjectCs([
cLatency = m_latency
] (DxvkContext* ctx) {
ctx->endLatencyTracking(cLatency);
});
}
void D3D11SwapChain::SyncFrameLatency() { void D3D11SwapChain::SyncFrameLatency() {
// Wait for the sync event so that we respect the maximum frame latency // Wait for the sync event so that we respect the maximum frame latency
m_frameLatencySignal->wait(m_frameId - GetActualFrameLatency()); m_frameLatencySignal->wait(m_frameId - GetActualFrameLatency());

View File

@ -4,6 +4,7 @@
#include "../dxvk/hud/dxvk_hud.h" #include "../dxvk/hud/dxvk_hud.h"
#include "../dxvk/dxvk_latency.h"
#include "../dxvk/dxvk_swapchain_blitter.h" #include "../dxvk/dxvk_swapchain_blitter.h"
#include "../util/sync/sync_signal.h" #include "../util/sync/sync_signal.h"
@ -107,6 +108,7 @@ namespace dxvk {
Rc<Presenter> m_presenter; Rc<Presenter> m_presenter;
Rc<DxvkSwapchainBlitter> m_blitter; Rc<DxvkSwapchainBlitter> m_blitter;
Rc<DxvkLatencyTracker> m_latency;
small_vector<Com<D3D11Texture2D, false>, 4> m_backBuffers; small_vector<Com<D3D11Texture2D, false>, 4> m_backBuffers;
@ -123,6 +125,8 @@ namespace dxvk {
dxvk::mutex m_frameStatisticsLock; dxvk::mutex m_frameStatisticsLock;
DXGI_VK_FRAME_STATISTICS m_frameStatistics = { }; DXGI_VK_FRAME_STATISTICS m_frameStatistics = { };
Rc<hud::HudLatencyItem> m_latencyHud;
Rc<DxvkImageView> GetBackBufferView(); Rc<DxvkImageView> GetBackBufferView();
HRESULT PresentImage(UINT SyncInterval); HRESULT PresentImage(UINT SyncInterval);
@ -139,6 +143,8 @@ namespace dxvk {
void DestroyFrameLatencyEvent(); void DestroyFrameLatencyEvent();
void DestroyLatencyTracker();
void SyncFrameLatency(); void SyncFrameLatency();
uint32_t GetActualFrameLatency(); uint32_t GetActualFrameLatency();