[vlc-devel] [PATCH 3.0 4/4] d3d11: remove Query based rendering wait

Steve Lhomme robux4 at ycbcr.xyz
Tue May 25 08:44:20 UTC 2021


It is imprecise and on seek it may wait a lot of time as, while it's waiting,
the decoder threads will flood new frames, delaying that much longer until the
ID3D11DeviceContext is finished doing things. This workaround did more harm
than good.

Now that we have ID3D11Fence support (any recent Win10) the query based system
should not be used. For older Windows using D3D11 we'll have less precise
estimation of the time it took to actually render, meaning the frame drop will
be less effective.

(cherry picked from commit 141e07e12fd73ebd957d3d1227aa9bdbe58e3ef3) (edited)
- the 3.0 code differed from the 4.0 one
- date is not passed to Prepare()
---
 modules/video_output/win32/direct3d11.c | 68 +++----------------------
 1 file changed, 6 insertions(+), 62 deletions(-)

diff --git a/modules/video_output/win32/direct3d11.c b/modules/video_output/win32/direct3d11.c
index 2867e0200f..5c8654b507 100644
--- a/modules/video_output/win32/direct3d11.c
+++ b/modules/video_output/win32/direct3d11.c
@@ -103,7 +103,6 @@ struct vout_display_sys_t
     d3d11_device_t           d3d_dev;
     d3d_quad_t               picQuad;
 
-    ID3D11Asynchronous       *prepareWait;
 #ifdef HAVE_D3D11_4_H
     ID3D11Fence              *d3dRenderFence;
     ID3D11DeviceContext4     *d3dcontext4;
@@ -1004,14 +1003,12 @@ static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
         }
     }
 
-    mtime_t render_start;
-    const char *wait_method = NULL;
-    if (sys->log_level >= 4)
-        render_start = mdate();
 #ifdef HAVE_D3D11_4_H
     if (sys->d3dcontext4)
     {
-        wait_method = "fence";
+        mtime_t render_start;
+        if (sys->log_level >= 4)
+            render_start = mdate();
         if (sys->renderFence == UINT64_MAX)
             sys->renderFence;
         else
@@ -1022,35 +1019,11 @@ static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
         ID3D11DeviceContext4_Signal(sys->d3dcontext4, sys->d3dRenderFence, sys->renderFence);
 
         WaitForSingleObject(sys->renderFinished, INFINITE);
+        if (sys->log_level >= 4)
+            msg_Dbg(vd, "waited %" PRId64 " ms for the render fence",
+                    (mdate() - render_start) * 1000 / CLOCK_FREQ);
     }
-    else
 #endif
-    if (sys->prepareWait)
-    {
-        wait_method = "query";
-        ID3D11DeviceContext_End(sys->d3d_dev.d3dcontext, sys->prepareWait);
-
-        while (S_FALSE == ID3D11DeviceContext_GetData(sys->d3d_dev.d3dcontext,
-                                                      sys->prepareWait, NULL, 0, 0))
-        {
-            d3d11_device_unlock( &sys->d3d_dev );
-            mtime_t sleep_duration = (picture->date - mdate()) / 4;
-            if (sleep_duration <= 2 * CLOCK_FREQ / 1000)
-            {
-                // don't wait any longer, the display will likely be late
-                // we'll finish waiting during the Display call
-                break;
-            }
-            // wait a little until the rendering is done
-            SleepEx(sleep_duration * 1000 / CLOCK_FREQ, TRUE);
-            d3d11_device_lock( &sys->d3d_dev );
-        }
-    }
-    if (sys->log_level >= 4 && wait_method != NULL)
-    {
-        msg_Dbg(vd, "waited %" PRId64 " ms for the render %s",
-            (mdate() - render_start) * 1000 / CLOCK_FREQ, wait_method);
-    }
 
     if (is_d3d11_opaque(picture->format.i_chroma))
         d3d11_device_unlock( &sys->d3d_dev );
@@ -1070,23 +1043,6 @@ static void Display(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
         msg_Err(vd, "SwapChain Present failed. (hr=0x%lX)", hr);
     }
 
-    if (sys->prepareWait)
-    {
-        mtime_t start = 0;
-        while (S_FALSE == ID3D11DeviceContext_GetData(sys->d3d_dev.d3dcontext,
-                                                      sys->prepareWait, NULL, 0, 0))
-        {
-            d3d11_device_unlock( &sys->d3d_dev );
-            if (start == 0)
-                start = mdate();
-            SleepEx(2, TRUE);
-            d3d11_device_lock( &sys->d3d_dev );
-        }
-        if (start != 0 && sys->log_level >= 4)
-            msg_Dbg(vd, "rendering wasn't finished, waited extra %lld ms",
-                        (mdate() - start) * 1000 / CLOCK_FREQ);
-    }
-
     d3d11_device_unlock( &sys->d3d_dev );
 
     picture_Release(picture);
@@ -1706,13 +1662,7 @@ static int Direct3D11CreateGenericResources(vout_display_t *vd)
     {
         msg_Dbg(vd, "using GPU render fence");
     }
-    else
 #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 };
@@ -1926,13 +1876,7 @@ static void Direct3D11DestroyResources(vout_display_t *vd)
         CloseHandle(sys->renderFinished);
         sys->renderFinished = NULL;
     }
-    else
 #endif
-    if (sys->prepareWait)
-    {
-        ID3D11Query_Release(sys->prepareWait);
-        sys->prepareWait = NULL;
-    }
 
     msg_Dbg(vd, "Direct3D11 resources destroyed");
 }
-- 
2.29.2



More information about the vlc-devel mailing list