mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-24 04:54:14 +01:00
[d3d9] Implement latency tracking
This commit is contained in:
parent
970378a267
commit
a537ecf421
@ -4270,7 +4270,7 @@ namespace dxvk {
|
|||||||
m_implicitSwapchain->Invalidate(pPresentationParameters->hDeviceWindow);
|
m_implicitSwapchain->Invalidate(pPresentationParameters->hDeviceWindow);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto* swapchain = new D3D9SwapChainEx(this, pPresentationParameters, pFullscreenDisplayMode);
|
auto* swapchain = new D3D9SwapChainEx(this, pPresentationParameters, pFullscreenDisplayMode, false);
|
||||||
*ppSwapChain = ref(swapchain);
|
*ppSwapChain = ref(swapchain);
|
||||||
m_losableResourceCounter++;
|
m_losableResourceCounter++;
|
||||||
}
|
}
|
||||||
@ -6098,11 +6098,29 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void D3D9DeviceEx::EndFrame() {
|
void D3D9DeviceEx::BeginFrame(Rc<DxvkLatencyTracker> LatencyTracker, uint64_t FrameId) {
|
||||||
D3D9DeviceLock lock = LockDevice();
|
D3D9DeviceLock lock = LockDevice();
|
||||||
|
|
||||||
EmitCs<false>([] (DxvkContext* ctx) {
|
EmitCs<false>([
|
||||||
|
cTracker = std::move(LatencyTracker),
|
||||||
|
cFrameId = FrameId
|
||||||
|
] (DxvkContext* ctx) {
|
||||||
|
if (cTracker && cTracker->needsAutoMarkers())
|
||||||
|
ctx->beginLatencyTracking(cTracker, cFrameId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void D3D9DeviceEx::EndFrame(Rc<DxvkLatencyTracker> LatencyTracker) {
|
||||||
|
D3D9DeviceLock lock = LockDevice();
|
||||||
|
|
||||||
|
EmitCs<false>([
|
||||||
|
cTracker = std::move(LatencyTracker)
|
||||||
|
] (DxvkContext* ctx) {
|
||||||
ctx->endFrame();
|
ctx->endFrame();
|
||||||
|
|
||||||
|
if (cTracker && cTracker->needsAutoMarkers())
|
||||||
|
ctx->endLatencyTracking(cTracker);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8445,7 +8463,7 @@ namespace dxvk {
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_implicitSwapchain = new D3D9SwapChainEx(this, pPresentationParameters, pFullscreenDisplayMode);
|
m_implicitSwapchain = new D3D9SwapChainEx(this, pPresentationParameters, pFullscreenDisplayMode, true);
|
||||||
m_mostRecentlyUsedSwapchain = m_implicitSwapchain.ptr();
|
m_mostRecentlyUsedSwapchain = m_implicitSwapchain.ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -800,7 +800,8 @@ namespace dxvk {
|
|||||||
void Flush();
|
void Flush();
|
||||||
void FlushAndSync9On12();
|
void FlushAndSync9On12();
|
||||||
|
|
||||||
void EndFrame();
|
void BeginFrame(Rc<DxvkLatencyTracker> LatencyTracker, uint64_t FrameId);
|
||||||
|
void EndFrame(Rc<DxvkLatencyTracker> LatencyTracker);
|
||||||
|
|
||||||
void UpdateActiveRTs(uint32_t index);
|
void UpdateActiveRTs(uint32_t index);
|
||||||
|
|
||||||
|
@ -23,10 +23,12 @@ namespace dxvk {
|
|||||||
D3D9SwapChainEx::D3D9SwapChainEx(
|
D3D9SwapChainEx::D3D9SwapChainEx(
|
||||||
D3D9DeviceEx* pDevice,
|
D3D9DeviceEx* pDevice,
|
||||||
D3DPRESENT_PARAMETERS* pPresentParams,
|
D3DPRESENT_PARAMETERS* pPresentParams,
|
||||||
const D3DDISPLAYMODEEX* pFullscreenDisplayMode)
|
const D3DDISPLAYMODEEX* pFullscreenDisplayMode,
|
||||||
|
bool EnableLatencyTracking)
|
||||||
: D3D9SwapChainExBase(pDevice)
|
: D3D9SwapChainExBase(pDevice)
|
||||||
, m_device (pDevice->GetDXVKDevice())
|
, m_device (pDevice->GetDXVKDevice())
|
||||||
, m_frameLatencyCap (pDevice->GetOptions()->maxFrameLatency)
|
, m_frameLatencyCap (pDevice->GetOptions()->maxFrameLatency)
|
||||||
|
, m_latencyTracking (EnableLatencyTracking)
|
||||||
, m_swapchainExt (this) {
|
, m_swapchainExt (this) {
|
||||||
this->NormalizePresentParameters(pPresentParams);
|
this->NormalizePresentParameters(pPresentParams);
|
||||||
m_presentParams = *pPresentParams;
|
m_presentParams = *pPresentParams;
|
||||||
@ -186,7 +188,7 @@ namespace dxvk {
|
|||||||
#define DCX_USESTYLE 0x00010000
|
#define DCX_USESTYLE 0x00010000
|
||||||
|
|
||||||
HRESULT D3D9SwapChainEx::PresentImageGDI(HWND Window) {
|
HRESULT D3D9SwapChainEx::PresentImageGDI(HWND Window) {
|
||||||
m_parent->EndFrame();
|
m_parent->EndFrame(nullptr);
|
||||||
m_parent->Flush();
|
m_parent->Flush();
|
||||||
|
|
||||||
if (!std::exchange(m_warnedAboutGDIFallback, true))
|
if (!std::exchange(m_warnedAboutGDIFallback, true))
|
||||||
@ -717,6 +719,9 @@ namespace dxvk {
|
|||||||
if (entry->second.presenter) {
|
if (entry->second.presenter) {
|
||||||
entry->second.presenter->destroyResources();
|
entry->second.presenter->destroyResources();
|
||||||
entry->second.presenter = nullptr;
|
entry->second.presenter = nullptr;
|
||||||
|
|
||||||
|
if (m_presentParams.hDeviceWindow == hWindow)
|
||||||
|
DestroyLatencyTracker();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_wctx == &entry->second)
|
if (m_wctx == &entry->second)
|
||||||
@ -802,10 +807,15 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void D3D9SwapChainEx::PresentImage(UINT SyncInterval) {
|
void D3D9SwapChainEx::PresentImage(UINT SyncInterval) {
|
||||||
m_parent->EndFrame();
|
m_parent->EndFrame(m_latencyTracker);
|
||||||
m_parent->Flush();
|
m_parent->Flush();
|
||||||
|
|
||||||
|
if (m_latencyTracker)
|
||||||
|
m_latencyTracker->notifyCpuPresentBegin(m_wctx->frameId + 1u);
|
||||||
|
|
||||||
// Retrieve the image and image view to present
|
// Retrieve the image and image view to present
|
||||||
|
VkResult status = VK_SUCCESS;
|
||||||
|
|
||||||
Rc<DxvkImage> swapImage = m_backBuffers[0]->GetCommonTexture()->GetImage();
|
Rc<DxvkImage> swapImage = m_backBuffers[0]->GetCommonTexture()->GetImage();
|
||||||
Rc<DxvkImageView> swapImageView = m_backBuffers[0]->GetImageView(false);
|
Rc<DxvkImageView> swapImageView = m_backBuffers[0]->GetImageView(false);
|
||||||
|
|
||||||
@ -814,10 +824,12 @@ namespace dxvk {
|
|||||||
PresenterSync sync = { };
|
PresenterSync sync = { };
|
||||||
Rc<DxvkImage> backBuffer;
|
Rc<DxvkImage> backBuffer;
|
||||||
|
|
||||||
VkResult status = m_wctx->presenter->acquireNextImage(sync, backBuffer);
|
status = m_wctx->presenter->acquireNextImage(sync, backBuffer);
|
||||||
|
|
||||||
if (status < 0 || status == VK_NOT_READY)
|
if (status < 0 || status == VK_NOT_READY) {
|
||||||
|
status = i ? VK_SUCCESS : status;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
VkRect2D srcRect = {
|
VkRect2D srcRect = {
|
||||||
{ int32_t(m_srcRect.left), int32_t(m_srcRect.top) },
|
{ int32_t(m_srcRect.left), int32_t(m_srcRect.top) },
|
||||||
@ -854,7 +866,8 @@ namespace dxvk {
|
|||||||
cDstRect = dstRect,
|
cDstRect = dstRect,
|
||||||
cRepeat = i,
|
cRepeat = i,
|
||||||
cSync = sync,
|
cSync = sync,
|
||||||
cFrameId = m_wctx->frameId
|
cFrameId = m_wctx->frameId,
|
||||||
|
cLatency = m_latencyTracker
|
||||||
] (DxvkContext* ctx) {
|
] (DxvkContext* ctx) {
|
||||||
// Update back buffer color space as necessary
|
// Update back buffer color space as necessary
|
||||||
if (cSrcView->image()->info().colorSpace != cColorSpace) {
|
if (cSrcView->image()->info().colorSpace != cColorSpace) {
|
||||||
@ -876,14 +889,33 @@ namespace dxvk {
|
|||||||
|
|
||||||
uint64_t frameId = cRepeat ? 0 : cFrameId;
|
uint64_t frameId = cRepeat ? 0 : cFrameId;
|
||||||
|
|
||||||
cDevice->presentImage(cPresenter, nullptr, frameId, nullptr);
|
cDevice->presentImage(cPresenter, cLatency, frameId, nullptr);
|
||||||
});
|
});
|
||||||
|
|
||||||
m_parent->FlushCsChunk();
|
m_parent->FlushCsChunk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_latencyTracker) {
|
||||||
|
if (status == VK_SUCCESS)
|
||||||
|
m_latencyTracker->notifyCpuPresentEnd(m_wctx->frameId);
|
||||||
|
else
|
||||||
|
m_latencyTracker->discardTimings();
|
||||||
|
}
|
||||||
|
|
||||||
SyncFrameLatency();
|
SyncFrameLatency();
|
||||||
|
|
||||||
|
DxvkLatencyStats latencyStats = { };
|
||||||
|
|
||||||
|
if (m_latencyTracker && status == VK_SUCCESS) {
|
||||||
|
latencyStats = m_latencyTracker->getStatistics(m_wctx->frameId);
|
||||||
|
m_latencyTracker->sleepAndBeginFrame(m_wctx->frameId + 1, std::abs(m_targetFrameRate));
|
||||||
|
|
||||||
|
m_parent->BeginFrame(m_latencyTracker, m_wctx->frameId + 1u);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_latencyHud)
|
||||||
|
m_latencyHud->accumulateStats(latencyStats);
|
||||||
|
|
||||||
// Rotate swap chain buffers so that the back
|
// Rotate swap chain buffers so that the back
|
||||||
// buffer at index 0 becomes the front buffer.
|
// buffer at index 0 becomes the front buffer.
|
||||||
for (uint32_t i = 1; i < m_backBuffers.size(); i++)
|
for (uint32_t i = 1; i < m_backBuffers.size(); i++)
|
||||||
@ -941,6 +973,9 @@ namespace dxvk {
|
|||||||
|
|
||||||
entry->second.frameLatencySignal = new sync::Fence(entry->second.frameId);
|
entry->second.frameLatencySignal = new sync::Fence(entry->second.frameId);
|
||||||
entry->second.presenter = CreatePresenter(m_window, entry->second.frameLatencySignal);
|
entry->second.presenter = CreatePresenter(m_window, entry->second.frameLatencySignal);
|
||||||
|
|
||||||
|
if (m_presentParams.hDeviceWindow == m_window && m_latencyTracking)
|
||||||
|
m_latencyTracker = m_device->createLatencyTracker(entry->second.presenter);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_wctx = &entry->second;
|
m_wctx = &entry->second;
|
||||||
@ -1017,6 +1052,10 @@ namespace dxvk {
|
|||||||
|
|
||||||
if (hud) {
|
if (hud) {
|
||||||
m_apiHud = hud->addItem<hud::HudClientApiItem>("api", 1, GetApiName());
|
m_apiHud = hud->addItem<hud::HudClientApiItem>("api", 1, GetApiName());
|
||||||
|
|
||||||
|
if (m_latencyTracking)
|
||||||
|
m_latencyHud = hud->addItem<hud::HudLatencyItem>("latency", 4);
|
||||||
|
|
||||||
hud->addItem<hud::HudSamplerCount>("samplers", -1, m_parent);
|
hud->addItem<hud::HudSamplerCount>("samplers", -1, m_parent);
|
||||||
hud->addItem<hud::HudFixedFunctionShaders>("ffshaders", -1, m_parent);
|
hud->addItem<hud::HudFixedFunctionShaders>("ffshaders", -1, m_parent);
|
||||||
hud->addItem<hud::HudSWVPState>("swvp", -1, m_parent);
|
hud->addItem<hud::HudSWVPState>("swvp", -1, m_parent);
|
||||||
@ -1041,6 +1080,18 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void D3D9SwapChainEx::DestroyLatencyTracker() {
|
||||||
|
if (!m_latencyTracker)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_parent->InjectCs([
|
||||||
|
cTracker = std::move(m_latencyTracker)
|
||||||
|
] (DxvkContext* ctx) {
|
||||||
|
ctx->endLatencyTracking(cTracker);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void D3D9SwapChainEx::UpdateTargetFrameRate(uint32_t SyncInterval) {
|
void D3D9SwapChainEx::UpdateTargetFrameRate(uint32_t SyncInterval) {
|
||||||
double frameRateOption = double(m_parent->GetOptions()->maxFrameRate);
|
double frameRateOption = double(m_parent->GetOptions()->maxFrameRate);
|
||||||
double frameRate = std::max(frameRateOption, 0.0);
|
double frameRate = std::max(frameRateOption, 0.0);
|
||||||
@ -1049,6 +1100,7 @@ namespace dxvk {
|
|||||||
frameRate = -m_displayRefreshRate / double(SyncInterval);
|
frameRate = -m_displayRefreshRate / double(SyncInterval);
|
||||||
|
|
||||||
m_wctx->presenter->setFrameRateLimit(frameRate, GetActualFrameLatency());
|
m_wctx->presenter->setFrameRateLimit(frameRate, GetActualFrameLatency());
|
||||||
|
m_targetFrameRate = frameRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,7 +69,8 @@ namespace dxvk {
|
|||||||
D3D9SwapChainEx(
|
D3D9SwapChainEx(
|
||||||
D3D9DeviceEx* pDevice,
|
D3D9DeviceEx* pDevice,
|
||||||
D3DPRESENT_PARAMETERS* pPresentParams,
|
D3DPRESENT_PARAMETERS* pPresentParams,
|
||||||
const D3DDISPLAYMODEEX* pFullscreenDisplayMode);
|
const D3DDISPLAYMODEEX* pFullscreenDisplayMode,
|
||||||
|
bool EnableLatencyTracking);
|
||||||
|
|
||||||
~D3D9SwapChainEx();
|
~D3D9SwapChainEx();
|
||||||
|
|
||||||
@ -173,12 +174,17 @@ namespace dxvk {
|
|||||||
wsi::DxvkWindowState m_windowState;
|
wsi::DxvkWindowState m_windowState;
|
||||||
|
|
||||||
double m_displayRefreshRate = 0.0;
|
double m_displayRefreshRate = 0.0;
|
||||||
|
double m_targetFrameRate = 0.0;
|
||||||
|
|
||||||
bool m_warnedAboutGDIFallback = false;
|
bool m_warnedAboutGDIFallback = false;
|
||||||
|
|
||||||
VkColorSpaceKHR m_colorspace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
|
VkColorSpaceKHR m_colorspace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
|
||||||
|
|
||||||
|
bool m_latencyTracking = false;
|
||||||
|
Rc<DxvkLatencyTracker> m_latencyTracker = nullptr;
|
||||||
|
|
||||||
Rc<hud::HudClientApiItem> m_apiHud;
|
Rc<hud::HudClientApiItem> m_apiHud;
|
||||||
|
Rc<hud::HudLatencyItem> m_latencyHud;
|
||||||
|
|
||||||
std::optional<VkHdrMetadataEXT> m_hdrMetadata;
|
std::optional<VkHdrMetadataEXT> m_hdrMetadata;
|
||||||
bool m_unlockAdditionalFormats = false;
|
bool m_unlockAdditionalFormats = false;
|
||||||
@ -197,6 +203,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
void CreateBlitter();
|
void CreateBlitter();
|
||||||
|
|
||||||
|
void DestroyLatencyTracker();
|
||||||
|
|
||||||
void InitRamp();
|
void InitRamp();
|
||||||
|
|
||||||
void UpdateTargetFrameRate(uint32_t SyncInterval);
|
void UpdateTargetFrameRate(uint32_t SyncInterval);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user