From 2a14793ee1c0d93bf0cb44f12a60a06a2200d1ec Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Sat, 27 Apr 2024 19:46:51 +0900 Subject: [PATCH] d3d12converter: Add support for GPU-side external fence waiting Ideally, GPU waiting should be scheduled just before executing command list. But handling the case outside of converter is a bit complicated. Under an assumption that constructed command list will be executed immediately, schedules GPU-side waiting inside of conversion method to simplify the flow. Part-of: --- .../gst-libs/gst/d3d12/gstd3d12converter.cpp | 13 +++++++++++- .../gst-libs/gst/d3d12/gstd3d12converter.h | 3 ++- .../sys/d3d12/gstd3d12compositor.cpp | 5 ++++- .../sys/d3d12/gstd3d12convert.cpp | 6 +++++- .../sys/d3d12/gstd3d12dxgicapture.cpp | 20 +++++++++---------- .../sys/d3d12/gstd3d12testsrc.cpp | 3 ++- .../sys/d3d12/gstd3d12window.cpp | 5 ++++- .../sys/dwrite/gstdwriterender_d3d12.cpp | 12 +++++++---- 8 files changed, 46 insertions(+), 21 deletions(-) diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/d3d12/gstd3d12converter.cpp b/subprojects/gst-plugins-bad/gst-libs/gst/d3d12/gstd3d12converter.cpp index 495b74e961..ea3e02eb06 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/d3d12/gstd3d12converter.cpp +++ b/subprojects/gst-plugins-bad/gst-libs/gst/d3d12/gstd3d12converter.cpp @@ -2149,11 +2149,16 @@ gst_d3d12_converter_check_needs_upload (GstD3D12Converter * self, * @out_buf: a #GstBuffer * @fence_data: a #GstD3D12FenceData * @cl: a ID3D12GraphicsCommandList + * @queue: (allow-none): a ID3D12CommandQueue * * Records command list for conversion operation. converter will attach * conversion command associated resources such as command allocator * to @fence_data. * + * If @queue is passed and @in_buf needs external fence wait, + * ID3D12CommandQueue::Wait() method for each external fence object + * will be executed in this method + * * Returns: %TRUE if successful * * Since: 1.26 @@ -2161,7 +2166,7 @@ gst_d3d12_converter_check_needs_upload (GstD3D12Converter * self, gboolean gst_d3d12_converter_convert_buffer (GstD3D12Converter * converter, GstBuffer * in_buf, GstBuffer * out_buf, GstD3D12FenceData * fence_data, - ID3D12GraphicsCommandList * cl) + ID3D12GraphicsCommandList * cl, ID3D12CommandQueue * queue) { g_return_val_if_fail (GST_IS_D3D12_CONVERTER (converter), FALSE); g_return_val_if_fail (GST_IS_BUFFER (in_buf), FALSE); @@ -2202,6 +2207,12 @@ gst_d3d12_converter_convert_buffer (GstD3D12Converter * converter, auto ret = gst_d3d12_converter_execute (converter, &in_frame, &out_frame, fence_data, cl); + + if (ret && queue) { + gst_d3d12_frame_fence_gpu_wait (&in_frame, queue); + gst_d3d12_frame_fence_gpu_wait (&out_frame, queue); + } + gst_d3d12_frame_unmap (&in_frame); gst_d3d12_frame_unmap (&out_frame); diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/d3d12/gstd3d12converter.h b/subprojects/gst-plugins-bad/gst-libs/gst/d3d12/gstd3d12converter.h index 46cd05eef0..a3ced294fa 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/d3d12/gstd3d12converter.h +++ b/subprojects/gst-plugins-bad/gst-libs/gst/d3d12/gstd3d12converter.h @@ -164,7 +164,8 @@ gboolean gst_d3d12_converter_convert_buffer (GstD3D12Converter * conv GstBuffer * in_buf, GstBuffer * out_buf, GstD3D12FenceData * fence_data, - ID3D12GraphicsCommandList * command_list); + ID3D12GraphicsCommandList * command_list, + ID3D12CommandQueue * queue); GST_D3D12_API gboolean gst_d3d12_converter_update_blend_state (GstD3D12Converter * converter, diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12compositor.cpp b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12compositor.cpp index bd1738f236..216d6af724 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12compositor.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12compositor.cpp @@ -1156,9 +1156,12 @@ gst_d3d12_compositor_preprare_func (GstVideoAggregatorPad * pad, } } + auto cq = gst_d3d12_device_get_command_queue (priv->ctx->device, + D3D12_COMMAND_LIST_TYPE_DIRECT); + auto cq_handle = gst_d3d12_command_queue_get_handle (cq); if (!gst_d3d12_converter_convert_buffer (priv->ctx->conv, buffer, self->priv->generated_output_buf, fence_data, - priv->ctx->cl.Get ())) { + priv->ctx->cl.Get (), cq_handle)) { GST_ERROR_OBJECT (self, "Couldn't build command list"); gst_d3d12_fence_data_unref (fence_data); return FALSE; diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12convert.cpp b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12convert.cpp index eb7530fc87..5f0b2b8242 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12convert.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12convert.cpp @@ -2010,8 +2010,12 @@ gst_d3d12_convert_transform (GstBaseTransform * trans, GstBuffer * inbuf, gst_d3d12_fence_data_pool_acquire (priv->fence_data_pool, &fence_data); gst_d3d12_fence_data_add_notify_mini_object (fence_data, gst_ca); + auto cq = gst_d3d12_device_get_command_queue (priv->ctx->device, + D3D12_COMMAND_LIST_TYPE_DIRECT); + auto cq_handle = gst_d3d12_command_queue_get_handle (cq); + if (!gst_d3d12_converter_convert_buffer (priv->ctx->conv, - inbuf, outbuf, fence_data, priv->ctx->cl.Get ())) { + inbuf, outbuf, fence_data, priv->ctx->cl.Get (), cq_handle)) { GST_ERROR_OBJECT (self, "Couldn't build command list"); gst_d3d12_fence_data_unref (fence_data); return GST_FLOW_ERROR; diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12dxgicapture.cpp b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12dxgicapture.cpp index 353e68c23b..d21bb24cc3 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12dxgicapture.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12dxgicapture.cpp @@ -1379,8 +1379,12 @@ gst_d3d12_dxgi_capture_draw_mouse (GstD3D12DxgiCapture * self, ptr_w, "src-height", ptr_h, "dest-x", ptr_x, "dest-y", ptr_y, "dest-width", ptr_w, "dest-height", ptr_h, nullptr); + auto cq = gst_d3d12_device_get_command_queue (priv->device, + D3D12_COMMAND_LIST_TYPE_DIRECT); + auto cq_handle = gst_d3d12_command_queue_get_handle (cq); + if (!gst_d3d12_converter_convert_buffer (priv->mouse_blend, - priv->mouse_buf, buffer, fence_data, cl.Get ())) { + priv->mouse_buf, buffer, fence_data, cl.Get (), cq_handle)) { GST_ERROR_OBJECT (self, "Couldn't build mouse blend command"); gst_d3d12_fence_data_unref (fence_data); return FALSE; @@ -1392,7 +1396,7 @@ gst_d3d12_dxgi_capture_draw_mouse (GstD3D12DxgiCapture * self, "dest-width", ptr_w, "dest-height", ptr_h, nullptr); if (!gst_d3d12_converter_convert_buffer (priv->mouse_xor_blend, - priv->mouse_xor_buf, buffer, fence_data, cl.Get ())) { + priv->mouse_xor_buf, buffer, fence_data, cl.Get (), nullptr)) { GST_ERROR_OBJECT (self, "Couldn't build mouse blend command"); gst_d3d12_fence_data_unref (fence_data); return FALSE; @@ -1406,10 +1410,6 @@ gst_d3d12_dxgi_capture_draw_mouse (GstD3D12DxgiCapture * self, return FALSE; } - auto cq = gst_d3d12_device_get_command_queue (priv->device, - D3D12_COMMAND_LIST_TYPE_DIRECT); - gst_d3d12_command_queue_execute_wait (cq, priv->shared_fence.Get (), - priv->fence_val); ID3D12CommandList *cmd_list[] = { cl.Get () }; guint64 fence_val = 0; @@ -1480,15 +1480,13 @@ gst_d3d12_dxgi_capture_do_capture (GstD3D12DxgiCapture * capture, return ret; } + gst_d3d12_memory_set_external_fence (dmem, priv->shared_fence.Get (), + priv->fence_val); + if (draw_mouse && !gst_d3d12_dxgi_capture_draw_mouse (self, buffer, crop_box)) { priv->WaitGPU (); return GST_FLOW_ERROR; } - /* Set external fence after drawing mouse. - * Otherwise converter will wait for fence value */ - gst_d3d12_memory_set_external_fence (dmem, priv->shared_fence.Get (), - priv->fence_val); - return GST_FLOW_OK; } diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12testsrc.cpp b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12testsrc.cpp index 40f95823fb..512ed07a60 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12testsrc.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12testsrc.cpp @@ -2203,7 +2203,8 @@ gst_d3d12_test_src_create (GstBaseSrc * bsrc, guint64 offset, gst_d3d12_test_src_draw_pattern (self, pts, cl.Get ()); if (!gst_d3d12_converter_convert_buffer (priv->ctx->conv, - priv->ctx->render_buffer, convert_buffer, fence_data, cl.Get ())) { + priv->ctx->render_buffer, convert_buffer, fence_data, cl.Get (), + nullptr)) { GST_ERROR_OBJECT (self, "Couldn't build convert command"); gst_clear_buffer (&convert_buffer); gst_d3d12_fence_data_unref (fence_data); diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12window.cpp b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12window.cpp index b99d3bd934..a204583d05 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12window.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12window.cpp @@ -1559,8 +1559,11 @@ gst_d3d12_window_set_buffer (GstD3D12Window * window, GstBuffer * buffer) cl->ResourceBarrier (1, &barrier); } + auto cq_handle = gst_d3d12_command_queue_get_handle (priv->ctx->queue); + if (!gst_d3d12_converter_convert_buffer (priv->ctx->conv, - priv->ctx->cached_buf, conv_outbuf, fence_data, cl.Get ())) { + priv->ctx->cached_buf, conv_outbuf, fence_data, cl.Get (), + cq_handle)) { GST_ERROR_OBJECT (window, "Couldn't build convert command"); gst_d3d12_fence_data_unref (fence_data); return GST_FLOW_ERROR; diff --git a/subprojects/gst-plugins-bad/sys/dwrite/gstdwriterender_d3d12.cpp b/subprojects/gst-plugins-bad/sys/dwrite/gstdwriterender_d3d12.cpp index 04bc33f54d..ecee3a904e 100644 --- a/subprojects/gst-plugins-bad/sys/dwrite/gstdwriterender_d3d12.cpp +++ b/subprojects/gst-plugins-bad/sys/dwrite/gstdwriterender_d3d12.cpp @@ -454,10 +454,14 @@ gst_dwrite_d3d12_render_blend (GstDWriteRender * render, GstBuffer * layout_buf, gboolean ret = TRUE; GstBuffer *bgra_buf = nullptr; + auto cq = gst_d3d12_device_get_command_queue (priv->device, + D3D12_COMMAND_LIST_TYPE_DIRECT); + auto cq_handle = gst_d3d12_command_queue_get_handle (cq); + if (priv->direct_blend) { GST_LOG_OBJECT (self, "Direct blend"); ret = gst_d3d12_converter_convert_buffer (priv->blend_conv, - layout_buf, output, fence_data, priv->cl.Get ()); + layout_buf, output, fence_data, priv->cl.Get (), cq_handle); } else { GST_LOG_OBJECT (self, "Need conversion for blending"); @@ -469,7 +473,7 @@ gst_dwrite_d3d12_render_blend (GstDWriteRender * render, GstBuffer * layout_buf, if (ret) { ret = gst_d3d12_converter_convert_buffer (priv->pre_conv, - output, bgra_buf, fence_data, priv->cl.Get ()); + output, bgra_buf, fence_data, priv->cl.Get (), cq_handle); } if (ret) { @@ -486,7 +490,7 @@ gst_dwrite_d3d12_render_blend (GstDWriteRender * render, GstBuffer * layout_buf, priv->cl->ResourceBarrier (1, &barrier); ret = gst_d3d12_converter_convert_buffer (priv->blend_conv, - layout_buf, bgra_buf, fence_data, priv->cl.Get ()); + layout_buf, bgra_buf, fence_data, priv->cl.Get (), nullptr); } if (ret) { @@ -517,7 +521,7 @@ gst_dwrite_d3d12_render_blend (GstDWriteRender * render, GstBuffer * layout_buf, priv->cl->ResourceBarrier (barriers.size (), barriers.data ()); ret = gst_d3d12_converter_convert_buffer (priv->post_conv, - bgra_buf, output, fence_data, priv->cl.Get ()); + bgra_buf, output, fence_data, priv->cl.Get (), nullptr); } gst_clear_buffer (&bgra_buf);