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();
EmitCs<false>([] (DxvkContext* ctx) {
EmitCs<false>([
cTracker = std::move(LatencyTracker)
] (DxvkContext* ctx) {
ctx->endFrame();
if (cTracker && cTracker->needsAutoMarkers())
ctx->endLatencyTracking(cTracker);
});
}

View File

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

View File

@ -2,6 +2,8 @@
#include "d3d11_device.h"
#include "d3d11_swapchain.h"
#include "../dxvk/dxvk_latency_builtin.h"
#include "../util/util_win32_compat.h"
namespace dxvk {
@ -80,6 +82,7 @@ namespace dxvk {
m_presenter->destroyResources();
DestroyFrameLatencyEvent();
DestroyLatencyTracker();
}
@ -279,6 +282,18 @@ namespace dxvk {
// applications using the semaphore may deadlock. This works because
// we do not increment the frame ID in those situations.
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;
}
@ -364,17 +379,23 @@ namespace dxvk {
auto immediateContext = m_parent->GetContext();
auto immediateContextLock = immediateContext->LockContext();
immediateContext->EndFrame();
immediateContext->EndFrame(m_latency);
immediateContext->Flush();
m_presenter->setSyncInterval(SyncInterval);
// Presentation semaphores and WSI swap chain image
if (m_latency)
m_latency->notifyCpuPresentBegin(m_frameId + 1u);
PresenterSync sync;
Rc<DxvkImage> backBuffer;
VkResult status = m_presenter->acquireNextImage(sync, backBuffer);
if (status != VK_SUCCESS && m_latency)
m_latency->discardTimings();
if (status < 0)
return E_FAIL;
@ -402,6 +423,7 @@ namespace dxvk {
cSwapImage = GetBackBufferView(),
cSync = sync,
cPresenter = m_presenter,
cLatency = m_latency,
cColorSpace = m_colorSpace,
cFrameId = m_frameId
] (DxvkContext* ctx) {
@ -425,13 +447,27 @@ namespace dxvk {
ctx->synchronizeWsi(cSync);
ctx->flushCommandList(nullptr);
cDevice->presentImage(cPresenter, nullptr, cFrameId, nullptr);
cDevice->presentImage(cPresenter, cLatency, cFrameId, nullptr);
});
if (m_backBuffers.size() > 1u)
RotateBackBuffers(immediateContext);
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;
}
@ -479,6 +515,8 @@ namespace dxvk {
m_presenter->setSurfaceFormat(GetSurfaceFormat(m_desc.Format));
m_presenter->setSurfaceExtent({ m_desc.Width, m_desc.Height });
m_presenter->setFrameRateLimit(m_targetFrameRate, GetActualFrameLatency());
m_latency = m_device->createLatencyTracker(m_presenter);
}
@ -555,9 +593,13 @@ namespace dxvk {
void D3D11SwapChain::CreateBlitter() {
Rc<hud::Hud> hud = hud::Hud::createHud(m_device);
if (hud)
if (hud) {
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));
}
@ -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() {
// Wait for the sync event so that we respect the maximum frame latency
m_frameLatencySignal->wait(m_frameId - GetActualFrameLatency());

View File

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