From adbd19e6fa15a1013961ab9d557db7fd87f50694 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Mon, 19 Jan 2026 16:01:50 -0600 Subject: [PATCH] Remove the previous frame rendered fence - Waiting on this fence prior to rendering introduces pipeline bubbles which can impact rendering performance on low-end GPUs - Pacer simply waiting to release the previous frame until after the current frame is rendered already means any decoder stall should be very short --- .../video/ffmpeg-renderers/d3d11va.cpp | 61 ------------------- .../video/ffmpeg-renderers/d3d11va.h | 4 -- 2 files changed, 65 deletions(-) diff --git a/app/streaming/video/ffmpeg-renderers/d3d11va.cpp b/app/streaming/video/ffmpeg-renderers/d3d11va.cpp index 96b2d9f4..16e716b1 100644 --- a/app/streaming/video/ffmpeg-renderers/d3d11va.cpp +++ b/app/streaming/video/ffmpeg-renderers/d3d11va.cpp @@ -107,7 +107,6 @@ D3D11VARenderer::~D3D11VARenderer() m_OverlayBlendState.Reset(); m_VideoBlendState.Reset(); - m_PreviousFrameRenderedFence.Reset(); m_DecodeD2RFence.Reset(); m_DecodeR2DFence.Reset(); m_RenderD2RFence.Reset(); @@ -363,30 +362,6 @@ bool D3D11VARenderer::createDeviceByAdapterIndex(int adapterIndex, bool* adapter } } } - - if (m_FenceType != SupportedFenceType::None) { - // If this GPU supports monitored fences, use one to wait until the previous frame - // has finished rendering before starting on the next one. This reduces latency by - // avoiding stalling during rendering after we've already grabbed the next frame - // to render, and also avoids stalling the decoder by releasing a surface back to - // the pool before we've finished reading from it (causing a stall if the decoder - // tries to write again). - if (m_FenceType == SupportedFenceType::Monitored) { - m_PreviousFrameRenderedFenceValue = 0; - hr = m_RenderDevice->CreateFence(m_PreviousFrameRenderedFenceValue, - D3D11_FENCE_FLAG_NONE, - IID_PPV_ARGS(&m_PreviousFrameRenderedFence)); - if (FAILED(hr)) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, - "ID3D11Device5::CreateFence() failed: %x", - hr); - // Non-fatal - } - - // Create an auto-reset event for our fence to signal - m_PreviousFrameRenderedEvent.Attach(CreateEvent(NULL, FALSE, TRUE, NULL)); - } - } } if (Utils::getEnvironmentVariableOverride("D3D11VA_FORCE_BIND", &m_BindDecoderOutputTextures)) { @@ -1071,16 +1046,6 @@ void D3D11VARenderer::renderVideo(AVFrame* frame) unlockContext(this); } } - - // Trigger our fence to signal after this video frame has been rendered - if (m_PreviousFrameRenderedFence) { - ComPtr deviceContext4; - if (SUCCEEDED(m_RenderDeviceContext.As(&deviceContext4))) { - if (SUCCEEDED(deviceContext4->Signal(m_PreviousFrameRenderedFence.Get(), m_PreviousFrameRenderedFenceValue + 1))) { - m_PreviousFrameRenderedFenceValue++; - } - } - } } // This function must NOT use any DXGI or ID3D11DeviceContext methods @@ -1302,32 +1267,6 @@ bool D3D11VARenderer::notifyWindowChanged(PWINDOW_STATE_CHANGE_INFO stateInfo) return stateInfo->stateChangeFlags == 0; } -void D3D11VARenderer::waitToRender() -{ - if (m_PreviousFrameRenderedFence && m_PreviousFrameRenderedEvent.IsValid()) { - SDL_assert(m_FenceType == SupportedFenceType::Monitored); - - // Check if the GPU is already finished - if (m_PreviousFrameRenderedFence->GetCompletedValue() < m_PreviousFrameRenderedFenceValue) { - HRESULT hr; - - hr = m_PreviousFrameRenderedFence->SetEventOnCompletion(m_PreviousFrameRenderedFenceValue, m_PreviousFrameRenderedEvent.Get()); - if (SUCCEEDED(hr)) { - // If we don't wake within 2 seconds, something is probably wrong - if (WaitForSingleObject(m_PreviousFrameRenderedEvent.Get(), 2000) != WAIT_OBJECT_0) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "Failed to wait on fence event!"); - } - } - else { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, - "ID3D11Fence::SetEventOnCompletion() failed: %x", - hr); - } - } - } -} - bool D3D11VARenderer::checkDecoderSupport(IDXGIAdapter* adapter) { HRESULT hr; diff --git a/app/streaming/video/ffmpeg-renderers/d3d11va.h b/app/streaming/video/ffmpeg-renderers/d3d11va.h index fd4f268f..72db9846 100644 --- a/app/streaming/video/ffmpeg-renderers/d3d11va.h +++ b/app/streaming/video/ffmpeg-renderers/d3d11va.h @@ -23,7 +23,6 @@ public: virtual void renderFrame(AVFrame* frame) override; virtual void notifyOverlayUpdated(Overlay::OverlayType) override; virtual bool notifyWindowChanged(PWINDOW_STATE_CHANGE_INFO stateInfo) override; - virtual void waitToRender() override; virtual int getRendererAttributes() override; virtual int getDecoderCapabilities() override; virtual InitFailureReason getInitFailureReason() override; @@ -79,9 +78,6 @@ private: Microsoft::WRL::ComPtr m_OverlayBlendState; SupportedFenceType m_FenceType; - Microsoft::WRL::ComPtr m_PreviousFrameRenderedFence; - Microsoft::WRL::Wrappers::Event m_PreviousFrameRenderedEvent; - UINT64 m_PreviousFrameRenderedFenceValue; Microsoft::WRL::ComPtr m_DecodeD2RFence, m_RenderD2RFence; Microsoft::WRL::ComPtr m_DecodeR2DFence, m_RenderR2DFence; UINT64 m_DecodeRenderSyncFenceValue;