[vlc-commits] direct3d11: use a ID3D11Fence to tell when the rendering is done
Steve Lhomme
git at videolan.org
Mon Jan 18 08:53:57 UTC 2021
vlc/vlc-3.0 | branch: master | Steve Lhomme <robux4 at ycbcr.xyz> | Fri Jan 15 15:01:22 2021 +0100| [429ff5cebdb43b42783db4116cfd3638e96a243f] | committer: Steve Lhomme
direct3d11: use a ID3D11Fence to tell when the rendering is done
This is a lot more accurate and wastes a lot less time than the Query approach.
The D3D11 Fence value is set when the GPU is done doing the previous
(rendering) commands. Then we can wait in the CPU for this event and return when
it's done. All decoder/filter commands seem to not have any impact so that's
really the signal we're looking for to tell the core we're done rendering.
This is only supported on newer mingw toolchains and only on Windows 10
Creators Update, which should cover pretty much all Win10 installed machines.
Better fixes #21600
(cherry picked from commit 61dbb36ebd3d58f230bfeb1c171eabe770affedd) (edited)
edited:
- the release of resources is done in a more flat function
- this branch didn't use pointers for d3dev
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>
> http://git.videolan.org/gitweb.cgi/vlc/vlc-3.0.git/?a=commit;h=429ff5cebdb43b42783db4116cfd3638e96a243f
---
configure.ac | 2 +-
modules/video_output/win32/direct3d11.c | 83 +++++++++++++++++++++++++++++++--
2 files changed, 81 insertions(+), 4 deletions(-)
diff --git a/configure.ac b/configure.ac
index 63c11509d0..90454edb91 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2573,7 +2573,7 @@ AM_CONDITIONAL([HAVE_AVCODEC_D3D11VA], [test "${have_avcodec_d3d11va}" = "yes"])
dnl
dnl DXGI debug
dnl
-AC_CHECK_HEADERS(dxgidebug.h dxgi1_6.h)
+AC_CHECK_HEADERS(dxgidebug.h dxgi1_6.h d3d11_4.h)
dnl
dnl avformat demuxer/muxer plugin
diff --git a/modules/video_output/win32/direct3d11.c b/modules/video_output/win32/direct3d11.c
index fe659a6d5a..d59b9dc9ea 100644
--- a/modules/video_output/win32/direct3d11.c
+++ b/modules/video_output/win32/direct3d11.c
@@ -45,6 +45,9 @@
#else
# include <dxgi1_5.h>
#endif
+#ifdef HAVE_D3D11_4_H
+#include <d3d11_4.h>
+#endif
/* avoided until we can pass ISwapchainPanel without c++/cx mode
# include <windows.ui.xaml.media.dxinterop.h> */
@@ -99,6 +102,12 @@ struct vout_display_sys_t
d3d_quad_t picQuad;
ID3D11Asynchronous *prepareWait;
+#ifdef HAVE_D3D11_4_H
+ ID3D11Fence *d3dRenderFence;
+ ID3D11DeviceContext4 *d3dcontext4;
+ UINT64 renderFence;
+ HANDLE renderFinished;
+#endif
picture_sys_t stagingSys;
@@ -993,6 +1002,22 @@ static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
}
}
+#ifdef HAVE_D3D11_4_H
+ if (sys->d3dcontext4)
+ {
+ if (sys->renderFence == UINT64_MAX)
+ sys->renderFence;
+ else
+ sys->renderFence++;
+
+ ResetEvent(sys->renderFinished);
+ ID3D11Fence_SetEventOnCompletion(sys->d3dRenderFence, sys->renderFence, sys->renderFinished);
+ ID3D11DeviceContext4_Signal(sys->d3dcontext4, sys->d3dRenderFence, sys->renderFence);
+
+ WaitForSingleObject(sys->renderFinished, INFINITE);
+ }
+ else
+#endif
if (sys->prepareWait)
{
ID3D11DeviceContext_End(sys->d3d_dev.d3dcontext, sys->prepareWait);
@@ -1617,14 +1642,54 @@ static int Direct3D11CreateFormatResources(vout_display_t *vd, const video_forma
return VLC_SUCCESS;
}
+#ifdef HAVE_D3D11_4_H
+static HRESULT InitRenderFence(vout_display_sys_t *sys)
+{
+ HRESULT hr;
+ sys->renderFinished = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (unlikely(sys->renderFinished == NULL))
+ return S_FALSE;
+ ID3D11Device5 *d3ddev5 = NULL;
+ hr = ID3D11DeviceContext_QueryInterface(sys->d3d_dev.d3dcontext, &IID_ID3D11DeviceContext4, (void**)&sys->d3dcontext4);
+ if (FAILED(hr))
+ goto error;
+ hr = ID3D11Device_QueryInterface(sys->d3d_dev.d3ddevice, &IID_ID3D11Device5, (void**)&d3ddev5);
+ if (FAILED(hr))
+ goto error;
+ hr = ID3D11Device5_CreateFence(d3ddev5, sys->renderFence, D3D11_FENCE_FLAG_NONE, &IID_ID3D11Fence, (void**)&sys->d3dRenderFence);
+ if (FAILED(hr))
+ goto error;
+ ID3D11Device5_Release(d3ddev5);
+ return hr;
+error:
+ if (d3ddev5)
+ ID3D11Device5_Release(d3ddev5);
+ if (sys->d3dRenderFence)
+ {
+ ID3D11Fence_Release(sys->d3dRenderFence);
+ sys->d3dRenderFence = NULL;
+ }
+ ID3D11DeviceContext4_Release(sys->d3dcontext4);
+ sys->d3dcontext4 = NULL;
+ CloseHandle(sys->renderFinished);
+ return hr;
+}
+#endif // HAVE_D3D11_4_H
+
static int Direct3D11CreateGenericResources(vout_display_t *vd)
{
vout_display_sys_t *sys = vd->sys;
HRESULT hr;
- D3D11_QUERY_DESC query = { 0 };
- query.Query = D3D11_QUERY_EVENT;
- hr = ID3D11Device_CreateQuery(sys->d3d_dev.d3ddevice, &query, (ID3D11Query**)&sys->prepareWait);
+#ifdef HAVE_D3D11_4_H
+ hr = InitRenderFence(sys);
+ if (FAILED(hr))
+#endif
+ {
+ D3D11_QUERY_DESC query = { 0 };
+ query.Query = D3D11_QUERY_EVENT;
+ hr = ID3D11Device_CreateQuery(sys->d3d_dev.d3ddevice, &query, (ID3D11Query**)&sys->prepareWait);
+ }
ID3D11BlendState *pSpuBlendState;
D3D11_BLEND_DESC spuBlendDesc = { 0 };
@@ -1828,6 +1893,18 @@ static void Direct3D11DestroyResources(vout_display_t *vd)
ID3D11PixelShader_Release(sys->picQuad.d3dpixelShader);
sys->picQuad.d3dpixelShader = NULL;
}
+#ifdef HAVE_D3D11_4_H
+ if (sys->d3dcontext4)
+ {
+ ID3D11Fence_Release(sys->d3dRenderFence);
+ sys->d3dRenderFence = NULL;
+ ID3D11DeviceContext4_Release(sys->d3dcontext4);
+ sys->d3dcontext4 = NULL;
+ CloseHandle(sys->renderFinished);
+ sys->renderFinished = NULL;
+ }
+ else
+#endif
if (sys->prepareWait)
{
ID3D11Query_Release(sys->prepareWait);
More information about the vlc-commits
mailing list