Commit 42011b9f authored by Steve Lhomme's avatar Steve Lhomme
Browse files

direct3d11: rework the rendering wait

The core needs to know how long the rendering takes place to estimate when a
frame needs to be dropped preemptively or not.

So far we waited until the render (plus decoding and filtering?) is done before
we allowed the picture swap to happen. Now we only wait until (almost) the swap
date. If we still have to wait, we'll do it after the swap, hoping it will
still happen in time.

It is reversing the strict waiting (all?) commands issued to be processed,
including all decoder threads and filters on the ID3D11DeviceContext. We no
longer allow waiting past the display date and we do the swap when we're told.

We no longer release the ID3D11DeviceContext lock either as it allows more
commands in and makes the waiting time/performance worse.

We do wait until the initial wait condition is done, if anything to silence
some D3D11 warnings saying we wanted to wait for something but never got to the
point it was actually finished. It also keeps the waiting in the display thread
so it doesn't think it can do more things when it's still busy with the
previous call. This will allow it do drop frames more accurately.

A cleaner way would be to count the Display call in the time to render of the
core, but it's not possible as in some case we wait and the work is actually
finished and in some others we wait and the work is not finished. We can't tell
the difference in the core.

Fixes #21600
parent 2ec4cd4a
...@@ -468,7 +468,8 @@ static bool SelectRenderPlane(void *opaque, size_t plane) ...@@ -468,7 +468,8 @@ static bool SelectRenderPlane(void *opaque, size_t plane)
return sys->selectPlaneCb(sys->outside_opaque, plane); return sys->selectPlaneCb(sys->outside_opaque, plane);
} }
static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture) static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture,
vlc_tick_t date)
{ {
vout_display_sys_t *sys = vd->sys; vout_display_sys_t *sys = vd->sys;
...@@ -617,9 +618,15 @@ static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t ...@@ -617,9 +618,15 @@ static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t
while (S_FALSE == ID3D11DeviceContext_GetData(sys->d3d_dev->d3dcontext, while (S_FALSE == ID3D11DeviceContext_GetData(sys->d3d_dev->d3dcontext,
sys->prepareWait, NULL, 0, 0)) sys->prepareWait, NULL, 0, 0))
{ {
d3d11_device_unlock( sys->d3d_dev ); vlc_tick_t sleep_duration = (date - vlc_tick_now()) / 4;
SleepEx(2, TRUE); if (sleep_duration <= VLC_TICK_FROM_MS(2))
d3d11_device_lock( sys->d3d_dev ); {
// 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(MS_FROM_VLC_TICK(sleep_duration), TRUE);
} }
} }
} }
...@@ -629,8 +636,6 @@ static void Prepare(vout_display_t *vd, picture_t *picture, ...@@ -629,8 +636,6 @@ static void Prepare(vout_display_t *vd, picture_t *picture,
{ {
vout_display_sys_t *sys = vd->sys; vout_display_sys_t *sys = vd->sys;
VLC_UNUSED(date);
d3d11_device_lock( sys->d3d_dev ); d3d11_device_lock( sys->d3d_dev );
#if VLC_WINSTORE_APP #if VLC_WINSTORE_APP
if ( sys->swapCb == LocalSwapchainSwap ) if ( sys->swapCb == LocalSwapchainSwap )
...@@ -666,7 +671,7 @@ static void Prepare(vout_display_t *vd, picture_t *picture, ...@@ -666,7 +671,7 @@ static void Prepare(vout_display_t *vd, picture_t *picture,
sys->sendMetadataCb( sys->outside_opaque, libvlc_video_metadata_frame_hdr10, &hdr10 ); sys->sendMetadataCb( sys->outside_opaque, libvlc_video_metadata_frame_hdr10, &hdr10 );
} }
PreparePicture(vd, picture, subpicture); PreparePicture(vd, picture, subpicture, date);
sys->startEndRenderingCb( sys->outside_opaque, false ); sys->startEndRenderingCb( sys->outside_opaque, false );
} }
...@@ -680,6 +685,23 @@ static void Display(vout_display_t *vd, picture_t *picture) ...@@ -680,6 +685,23 @@ static void Display(vout_display_t *vd, picture_t *picture)
d3d11_device_lock( sys->d3d_dev ); d3d11_device_lock( sys->d3d_dev );
sys->swapCb(sys->outside_opaque); sys->swapCb(sys->outside_opaque);
if (sys->prepareWait)
{
vlc_tick_t start = 0;
while (S_FALSE == ID3D11DeviceContext_GetData(sys->d3d_dev->d3dcontext,
sys->prepareWait, NULL, 0, 0))
{
if (start == 0)
start = vlc_tick_now();
// keep waiting until all rendering (plus extra) is known to be finished
// to let the vout thread things are not as smooth as it may think
SleepEx(2, TRUE);
}
if (start != 0 && var_InheritInteger(vd, "verbose") >= 4)
msg_Dbg(vd, "rendering wasn't finished, waited extra %lld ms", MS_FROM_VLC_TICK(vlc_tick_now() - start));
}
d3d11_device_unlock( sys->d3d_dev ); d3d11_device_unlock( sys->d3d_dev );
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment