d3d11: Port to GstD3D11Fence
authorSeungha Yang <seungha@centricular.com>
Fri, 22 Jul 2022 15:41:49 +0000 (00:41 +0900)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Sat, 23 Jul 2022 16:53:14 +0000 (16:53 +0000)
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2790>

subprojects/gst-plugins-bad/sys/amfcodec/gstamfencoder.cpp
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11screencapture.cpp
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window_dummy.cpp
subprojects/gst-plugins-bad/sys/mediafoundation/gstmfvideoencoder.cpp
subprojects/gst-plugins-bad/sys/mediafoundation/gstmfvideoencoder.h
subprojects/gst-plugins-bad/sys/nvcodec/gstnvencoder.cpp

index 0fdd78c..a14cb92 100644 (file)
@@ -58,6 +58,7 @@ struct _GstAmfEncoderPrivate
   const wchar_t *codec_id;
 
   GstD3D11Device *device;
+  GstD3D11Fence *fence;
   AMFContext *context;
   AMFComponent *comp;
   GstBufferPool *internal_pool;
@@ -439,6 +440,7 @@ gst_amf_encoder_close (GstVideoEncoder * encoder)
     priv->context = nullptr;
   }
 
+  gst_clear_d3d11_fence (&priv->fence);
   gst_clear_object (&priv->device);
 
   return TRUE;
@@ -617,9 +619,6 @@ gst_amf_encoder_copy_d3d11 (GstAmfEncoder * self, GstBuffer * src_buffer,
   GstFlowReturn ret;
   ComPtr < IDXGIResource > dxgi_resource;
   ComPtr < ID3D11Texture2D > shared_texture;
-  ComPtr < ID3D11Query > query;
-  D3D11_QUERY_DESC query_desc;
-  BOOL sync_done = FALSE;
   HANDLE shared_handle;
   GstD3D11Device *device;
   HRESULT hr;
@@ -699,13 +698,14 @@ gst_amf_encoder_copy_d3d11 (GstAmfEncoder * self, GstBuffer * src_buffer,
   src_box.bottom = MIN (src_desc.Height, dst_desc.Height);
 
   if (shared) {
-    query_desc.Query = D3D11_QUERY_EVENT;
-    query_desc.MiscFlags = 0;
+    if (priv->fence && priv->fence->device != device)
+      gst_clear_d3d11_fence (&priv->fence);
 
-    hr = device_handle->CreateQuery (&query_desc, &query);
-    if (!gst_d3d11_result (hr, device)) {
-      GST_ERROR_OBJECT (self, "Couldn't Create event query, hr: 0x%x",
-          (guint) hr);
+    if (!priv->fence)
+      priv->fence = gst_d3d11_device_create_fence (device);
+
+    if (!priv->fence) {
+      GST_ERROR_OBJECT (self, "Couldn't crete fence");
       goto error;
     }
 
@@ -716,15 +716,11 @@ gst_amf_encoder_copy_d3d11 (GstAmfEncoder * self, GstBuffer * src_buffer,
       0, 0, 0, src_tex, subresource_idx, &src_box);
 
   if (shared) {
-    device_context->End (query.Get ());
-    do {
-      hr = device_context->GetData (query.Get (), &sync_done, sizeof (BOOL), 0);
-    } while (!sync_done && (hr == S_OK || hr == S_FALSE));
-
-    if (!gst_d3d11_result (hr, device)) {
-      GST_ERROR_OBJECT (self, "Couldn't sync GPU operation, hr: 0x%x",
-          (guint) hr);
+    if (!gst_d3d11_fence_signal (priv->fence) ||
+        !gst_d3d11_fence_wait (priv->fence)) {
+      GST_ERROR_OBJECT (self, "Couldn't sync GPU operation");
       gst_d3d11_device_unlock (device);
+      gst_clear_d3d11_fence (&priv->fence);
       goto error;
     }
 
index 3bbfd18..14b7c06 100644 (file)
@@ -231,6 +231,7 @@ class D3D11DesktopDupObject
 public:
   D3D11DesktopDupObject ()
     : device_(nullptr)
+    , fence_(nullptr)
     , metadata_buffer_(nullptr)
     , metadata_buffer_size_(0)
     , vertex_buffer_(nullptr)
@@ -246,6 +247,7 @@ public:
     if (vertex_buffer_)
       delete[] vertex_buffer_;
 
+    gst_clear_d3d11_fence (&fence_);
     gst_clear_object (&device_);
   }
 
@@ -545,8 +547,8 @@ public:
   {
     ID3D11DeviceContext *context_handle = nullptr;
     ComPtr <ID3D11Texture2D> tex;
-    ComPtr < ID3D11Query > query;
     HRESULT hr;
+    gboolean is_shared = FALSE;
 
     context_handle = gst_d3d11_device_get_device_context_handle (device);
 
@@ -555,7 +557,6 @@ public:
     } else {
       ID3D11Device *device_handle = nullptr;
       ComPtr < IDXGIResource > dxgi_resource;
-      D3D11_QUERY_DESC query_desc;
       HANDLE shared_handle;
 
       device_handle = gst_d3d11_device_get_device_handle (device);
@@ -573,24 +574,24 @@ public:
       if (!gst_d3d11_result (hr, device))
         return GST_FLOW_ERROR;
 
-      query_desc.Query = D3D11_QUERY_EVENT;
-      query_desc.MiscFlags = 0;
+      if (fence_ && fence_->device != device)
+        gst_clear_d3d11_fence (&fence_);
 
-      hr = device_handle->CreateQuery (&query_desc, &query);
-      if (!gst_d3d11_result (hr, device))
+      if (!fence_)
+        fence_ = gst_d3d11_device_create_fence (device);
+
+      if (!fence_)
         return GST_FLOW_ERROR;
+
+      is_shared = TRUE;
     }
 
     context_handle->CopySubresourceRegion (texture, 0, 0, 0, 0,
-      tex.Get(), 0, cropBox);
+        tex.Get(), 0, cropBox);
 
-    if (query) {
-      BOOL sync_done = FALSE;
-
-      do {
-        hr = context_handle->GetData (query.Get (),
-            &sync_done, sizeof (BOOL), 0);
-      } while (!sync_done && (hr == S_OK || hr == S_FALSE));
+    if (is_shared) {
+      if (!gst_d3d11_fence_signal (fence_) || !gst_d3d11_fence_wait (fence_))
+        return GST_FLOW_ERROR;
     }
 
     return GST_FLOW_OK;
@@ -1471,6 +1472,7 @@ private:
   PTR_INFO ptr_info_;
   DXGI_OUTDUPL_DESC output_desc_;
   GstD3D11Device * device_;
+  GstD3D11Fence * fence_;
 
   ComPtr<ID3D11Texture2D> shared_texture_;
   ComPtr<ID3D11RenderTargetView> rtv_;
index d8028f5..c92ccd0 100644 (file)
@@ -40,6 +40,8 @@ struct _GstD3D11WindowDummy
   ID3D11Texture2D *fallback_texture;
   ID3D11VideoProcessorOutputView *fallback_pov;
   ID3D11RenderTargetView *fallback_rtv;
+
+  GstD3D11Fence *fence;
 };
 
 #define gst_d3d11_window_dummy_parent_class parent_class
@@ -50,6 +52,7 @@ static void gst_d3d11_window_dummy_on_resize (GstD3D11Window * window,
     guint width, guint height);
 static gboolean gst_d3d11_window_dummy_prepare (GstD3D11Window * window,
     guint display_width, guint display_height, GstCaps * caps, GError ** error);
+static void gst_d3d11_window_dummy_unprepare (GstD3D11Window * window);
 static gboolean
 gst_d3d11_window_dummy_open_shared_handle (GstD3D11Window * window,
     GstD3D11WindowSharedHandleData * data);
@@ -65,6 +68,8 @@ gst_d3d11_window_dummy_class_init (GstD3D11WindowDummyClass * klass)
   window_class->on_resize =
       GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_on_resize);
   window_class->prepare = GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_prepare);
+  window_class->unprepare =
+      GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_unprepare);
   window_class->open_shared_handle =
       GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_open_shared_handle);
   window_class->release_shared_handle =
@@ -145,6 +150,14 @@ gst_d3d11_window_dummy_prepare (GstD3D11Window * window,
 }
 
 static void
+gst_d3d11_window_dummy_unprepare (GstD3D11Window * window)
+{
+  GstD3D11WindowDummy *self = GST_D3D11_WINDOW_DUMMY (window);
+
+  gst_clear_d3d11_fence (&self->fence);
+}
+
+static void
 gst_d3d11_window_dummy_on_resize (GstD3D11Window * window,
     guint width, guint height)
 {
@@ -286,34 +299,19 @@ gst_d3d11_window_dummy_release_shared_handle (GstD3D11Window * window,
 
     GST_D3D11_CLEAR_COM (data->keyed_mutex);
   } else {
-    /* *INDENT-OFF* */
-    ComPtr<ID3D11Query> query;
-    /* *INDENT-ON* */
-    D3D11_QUERY_DESC query_desc;
-    ID3D11Device *device_handle = gst_d3d11_device_get_device_handle (device);
-    ID3D11DeviceContext *context_handle =
-        gst_d3d11_device_get_device_context_handle (device);
-    BOOL sync_done = FALSE;
-
     /* If keyed mutex is not used, let's handle sync manually by using
-     * ID3D11Query. Issued GPU commands might not be finished yet */
-    query_desc.Query = D3D11_QUERY_EVENT;
-    query_desc.MiscFlags = 0;
+     * fence. Issued GPU commands might not be finished yet */
 
-    hr = device_handle->CreateQuery (&query_desc, &query);
-    if (!gst_d3d11_result (hr, device)) {
+    if (!self->fence)
+      self->fence = gst_d3d11_device_create_fence (device);
+
+    if (!self->fence) {
       GST_ERROR_OBJECT (self, "Couldn't Create event query");
       return FALSE;
     }
 
-    context_handle->End (query.Get ());
-
-    /* Wait until all issued GPU commands are finished */
-    do {
-      hr = context_handle->GetData (query.Get (), &sync_done, sizeof (BOOL), 0);
-    } while (!sync_done && (hr == S_OK || hr == S_FALSE));
-
-    if (!gst_d3d11_result (hr, device)) {
+    if (!gst_d3d11_fence_signal (self->fence) ||
+        !gst_d3d11_fence_wait (self->fence)) {
       GST_ERROR_OBJECT (self, "Couldn't sync GPU operation");
       return FALSE;
     }
index 01f657c..11566f1 100644 (file)
@@ -264,6 +264,7 @@ gst_mf_video_encoder_close (GstVideoEncoder * enc)
 
   gst_clear_object (&self->other_d3d11_device);
   gst_clear_object (&self->d3d11_device);
+  gst_clear_d3d11_fence (&self->fence);
 #endif
 
   return TRUE;
@@ -1064,9 +1065,6 @@ gst_mf_video_encoder_create_input_sample_d3d11 (GstMFVideoEncoder * self,
   ComPtr < ID3D11Texture2D > mf_texture;
   ComPtr < IDXGIResource > dxgi_resource;
   ComPtr < ID3D11Texture2D > shared_texture;
-  ComPtr < ID3D11Query > query;
-  D3D11_QUERY_DESC query_desc;
-  BOOL sync_done = FALSE;
   HANDLE shared_handle;
   GstMemory *mem;
   GstD3D11Memory *dmem;
@@ -1171,30 +1169,27 @@ gst_mf_video_encoder_create_input_sample_d3d11 (GstMFVideoEncoder * self,
   src_box.right = MIN (src_desc.Width, dst_desc.Width);
   src_box.bottom = MIN (src_desc.Height, dst_desc.Height);
 
-  /* CopySubresourceRegion() might not be able to guarantee
-   * copying. To ensure it, we will make use of d3d11 query */
-  query_desc.Query = D3D11_QUERY_EVENT;
-  query_desc.MiscFlags = 0;
+  gst_d3d11_device_lock (dmem->device);
+  if (self->fence && self->fence->device != dmem->device)
+    gst_clear_d3d11_fence (&self->fence);
+
+  if (!self->fence)
+    self->fence = gst_d3d11_device_create_fence (dmem->device);
 
-  hr = device_handle->CreateQuery (&query_desc, &query);
-  if (!gst_d3d11_result (hr, dmem->device)) {
-    GST_ERROR_OBJECT (self, "Couldn't Create event query");
+  if (!self->fence) {
+    GST_ERROR_OBJECT (self, "Couldn't create fence object");
+    gst_d3d11_device_unlock (dmem->device);
     gst_memory_unmap (mem, &info);
     return FALSE;
   }
 
-  gst_d3d11_device_lock (dmem->device);
   context_handle->CopySubresourceRegion (shared_texture.Get (), 0, 0, 0, 0,
       texture, subidx, &src_box);
-  context_handle->End (query.Get ());
-
-  /* Wait until all issued GPU commands are finished */
-  do {
-    hr = context_handle->GetData (query.Get (), &sync_done, sizeof (BOOL), 0);
-  } while (!sync_done && (hr == S_OK || hr == S_FALSE));
 
-  if (!gst_d3d11_result (hr, dmem->device)) {
+  if (!gst_d3d11_fence_signal (self->fence) ||
+      !gst_d3d11_fence_wait (self->fence)) {
     GST_ERROR_OBJECT (self, "Couldn't sync GPU operation");
+    gst_clear_d3d11_fence (&self->fence);
     gst_d3d11_device_unlock (dmem->device);
     gst_memory_unmap (mem, &info);
 
index 69892bd..dc4b11c 100644 (file)
@@ -116,6 +116,7 @@ struct _GstMFVideoEncoder
   IMFDXGIDeviceManager *device_manager;
   UINT reset_token;
   IMFVideoSampleAllocatorEx *mf_allocator;
+  GstD3D11Fence *fence;
 #endif
 };
 
index 3ea8203..7c84378 100644 (file)
@@ -60,6 +60,7 @@ struct _GstNvEncoderPrivate
   GstCudaContext *context;
 #ifdef GST_CUDA_HAS_D3D
   GstD3D11Device *device;
+  GstD3D11Fence *fence;
 #endif
 
   GstNvEncoderDeviceMode subclass_device_mode;
@@ -439,6 +440,7 @@ gst_nv_encoder_close (GstVideoEncoder * encoder)
 
   gst_clear_object (&priv->context);
 #ifdef GST_CUDA_HAS_D3D
+  gst_clear_d3d11_fence (&priv->fence);
   gst_clear_object (&priv->device);
 #endif
 
@@ -1558,9 +1560,6 @@ gst_nv_encoder_copy_d3d11 (GstNvEncoder * self,
   GstFlowReturn ret;
   ComPtr < IDXGIResource > dxgi_resource;
   ComPtr < ID3D11Texture2D > shared_texture;
-  ComPtr < ID3D11Query > query;
-  D3D11_QUERY_DESC query_desc;
-  BOOL sync_done = FALSE;
   HANDLE shared_handle;
   GstD3D11Device *device;
   HRESULT hr;
@@ -1639,13 +1638,14 @@ gst_nv_encoder_copy_d3d11 (GstNvEncoder * self,
   src_box.bottom = MIN (src_desc.Height, dst_desc.Height);
 
   if (shared) {
-    query_desc.Query = D3D11_QUERY_EVENT;
-    query_desc.MiscFlags = 0;
+    if (priv->fence && priv->fence->device != device)
+      gst_clear_d3d11_fence (&priv->fence);
 
-    hr = device_handle->CreateQuery (&query_desc, &query);
-    if (!gst_d3d11_result (hr, device)) {
-      GST_ERROR_OBJECT (self, "Couldn't Create event query, hr: 0x%x",
-          (guint) hr);
+    if (!priv->fence)
+      priv->fence = gst_d3d11_device_create_fence (device);
+
+    if (!priv->fence) {
+      GST_ERROR_OBJECT (self, "Couldn't crete fence");
       goto error;
     }
 
@@ -1656,15 +1656,11 @@ gst_nv_encoder_copy_d3d11 (GstNvEncoder * self,
       0, 0, 0, src_tex, subresource_idx, &src_box);
 
   if (shared) {
-    device_context->End (query.Get ());
-    do {
-      hr = device_context->GetData (query.Get (), &sync_done, sizeof (BOOL), 0);
-    } while (!sync_done && (hr == S_OK || hr == S_FALSE));
-
-    if (!gst_d3d11_result (hr, device)) {
-      GST_ERROR_OBJECT (self, "Couldn't sync GPU operation, hr: 0x%x",
-          (guint) hr);
+    if (!gst_d3d11_fence_signal (priv->fence) ||
+        !gst_d3d11_fence_wait (priv->fence)) {
+      GST_ERROR_OBJECT (self, "Couldn't sync GPU operation");
       gst_d3d11_device_unlock (device);
+      gst_clear_d3d11_fence (&priv->fence);
       goto error;
     }