d3d11memory: Update alloc_wrapped() API to avoid staging texture alloc
authorSeungha Yang <seungha@centricular.com>
Mon, 4 Jul 2022 12:57:42 +0000 (21:57 +0900)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Mon, 4 Jul 2022 18:46:51 +0000 (18:46 +0000)
Add size parameter and use it for CPU accessible memory size
instead of allocating staging texture per API call.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2713>

subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11_private.h
subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11memory.cpp
subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11memory.h
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window.cpp
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window_dummy.cpp
subprojects/gst-plugins-bad/tests/examples/d3d11/d3d11videosink-appsrc.cpp

index 3aff9c8..872b169 100644 (file)
@@ -41,16 +41,6 @@ void  gst_d3d11_device_dxgi_debug  (GstD3D11Device * device,
                                     const gchar * function,
                                     gint line);
 
-/* Memory allocated by this method does not hold correct size.
- * So this is private method and only plugins in -bad are expected to call
- * this method */
-GST_D3D11_API
-GstMemory * gst_d3d11_allocator_alloc_wrapped_native_size (GstD3D11Allocator * allocator,
-                                                           GstD3D11Device * device,
-                                                           ID3D11Texture2D * texture,
-                                                           gpointer user_data,
-                                                           GDestroyNotify notify);
-
 #define GST_D3D11_CLEAR_COM(obj) G_STMT_START { \
     if (obj) { \
       (obj)->Release (); \
index 8a1ceb9..bf7b42e 100644 (file)
@@ -1639,12 +1639,21 @@ gst_d3d11_allocator_alloc_buffer (GstD3D11Allocator * allocator,
  * @allocator: a #GstD3D11Allocator
  * @device: a #GstD3D11Device
  * @texture: a ID3D11Texture2D
+ * @size: CPU accessible memory size
  * @user_data: (allow-none): user data
  * @notify: (allow-none): called with @user_data when the memory is freed
  *
  * Allocates memory object with @texture. The refcount of @texture
  * will be increased by one.
  *
+ * Caller should set valid CPU acessible memory value to @size
+ * (which is typically calculated by using staging texture and Map/Unmap)
+ * or zero is allowed. In that case, allocator will create a temporary staging
+ * texture to get the size and the temporary staging texture will be released.
+ *
+ * Caller must not be confused that @size is CPU accessible size, not raw
+ * texture size.
+ *
  * Returns: a newly allocated #GstD3D11Memory with given @texture
  * if successful, or %NULL if @texture is not a valid handle or configuration
  * is not supported.
@@ -1653,8 +1662,8 @@ gst_d3d11_allocator_alloc_buffer (GstD3D11Allocator * allocator,
  */
 GstMemory *
 gst_d3d11_allocator_alloc_wrapped (GstD3D11Allocator * allocator,
-    GstD3D11Device * device, ID3D11Texture2D * texture, gpointer user_data,
-    GDestroyNotify notify)
+    GstD3D11Device * device, ID3D11Texture2D * texture, gsize size,
+    gpointer user_data, GDestroyNotify notify)
 {
   GstMemory *mem;
   GstD3D11Memory *dmem;
@@ -1678,52 +1687,16 @@ gst_d3d11_allocator_alloc_wrapped (GstD3D11Allocator * allocator,
   if (!mem)
     return nullptr;
 
-  if (!gst_d3d11_memory_update_size (mem)) {
-    GST_ERROR_OBJECT (allocator, "Failed to calculate size");
-    gst_memory_unref (mem);
-    return nullptr;
-  }
-
-  dmem = GST_D3D11_MEMORY_CAST (mem);
-
-  dmem->priv->user_data = user_data;
-  dmem->priv->notify = notify;
-
-  return mem;
-}
-
-GstMemory *
-gst_d3d11_allocator_alloc_wrapped_native_size (GstD3D11Allocator * allocator,
-    GstD3D11Device * device, ID3D11Texture2D * texture, gpointer user_data,
-    GDestroyNotify notify)
-{
-  GstMemory *mem;
-  GstD3D11Memory *dmem;
-  D3D11_TEXTURE2D_DESC desc = { 0, };
-  ID3D11Texture2D *tex = nullptr;
-  HRESULT hr;
-  gsize size;
-
-  g_return_val_if_fail (GST_IS_D3D11_ALLOCATOR (allocator), nullptr);
-  g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), nullptr);
-  g_return_val_if_fail (texture != nullptr, nullptr);
-
-  hr = texture->QueryInterface (IID_PPV_ARGS (&tex));
-  if (FAILED (hr)) {
-    GST_WARNING_OBJECT (allocator, "Not a valid texture handle");
-    return nullptr;
+  if (size == 0) {
+    if (!gst_d3d11_memory_update_size (mem)) {
+      GST_ERROR_OBJECT (allocator, "Failed to calculate size");
+      gst_memory_unref (mem);
+      return nullptr;
+    }
+  } else {
+    mem->maxsize = mem->size = size;
   }
 
-  tex->GetDesc (&desc);
-  mem = gst_d3d11_allocator_alloc_internal (allocator, device, &desc, tex);
-
-  if (!mem)
-    return nullptr;
-
-  /* XXX: This is not correct memory size */
-  size = desc.Width * desc.Height;
-  mem->maxsize = mem->size = size;
-
   dmem = GST_D3D11_MEMORY_CAST (mem);
 
   dmem->priv->user_data = user_data;
index 0219672..dca39a5 100644 (file)
@@ -263,6 +263,7 @@ GST_D3D11_API
 GstMemory * gst_d3d11_allocator_alloc_wrapped (GstD3D11Allocator * allocator,
                                                GstD3D11Device * device,
                                                ID3D11Texture2D * texture,
+                                               gsize size,
                                                gpointer user_data,
                                                GDestroyNotify notify);
 
index 484ff79..7b3b35b 100644 (file)
@@ -281,6 +281,7 @@ gst_d3d11_window_on_resize_default (GstD3D11Window * self, guint width,
   GstMemory *mem;
   GstD3D11Memory *dmem;
   ID3D11RenderTargetView *rtv;
+  gsize size;
 
   gst_d3d11_device_lock (device);
 
@@ -304,8 +305,19 @@ gst_d3d11_window_on_resize_default (GstD3D11Window * self, guint width,
     goto done;
   }
 
-  mem = gst_d3d11_allocator_alloc_wrapped_native_size (self->allocator,
-      self->device, backbuffer.Get (), nullptr, nullptr);
+  backbuffer->GetDesc (&desc);
+  size = desc.Width * desc.Height;
+  /* flip mode swapchain supports only 4 formats, rgba/bgra/rgb10a2/rgba64.
+   * The size passed in alloc_wrapped() is not important here, since we never
+   * try mapping this for CPU access */
+  if (desc.Format == DXGI_FORMAT_R16G16B16A16_FLOAT) {
+    size *= 8;
+  } else {
+    size *= 4;
+  }
+
+  mem = gst_d3d11_allocator_alloc_wrapped (self->allocator,
+      self->device, backbuffer.Get (), size, nullptr, nullptr);
   if (!mem) {
     GST_ERROR_OBJECT (self, "Couldn't allocate wrapped memory");
     goto done;
@@ -322,7 +334,6 @@ gst_d3d11_window_on_resize_default (GstD3D11Window * self, guint width,
   self->backbuffer = gst_buffer_new ();
   gst_buffer_append_memory (self->backbuffer, mem);
 
-  backbuffer->GetDesc (&desc);
   self->surface_width = desc.Width;
   self->surface_height = desc.Height;
 
index cb1d696..595e40a 100644 (file)
@@ -238,8 +238,8 @@ gst_d3d11_window_dummy_open_shared_handle (GstD3D11Window * window,
     }
   }
 
-  mem = gst_d3d11_allocator_alloc_wrapped_native_size (window->allocator,
-      device, texture.Get (), nullptr, nullptr);
+  mem = gst_d3d11_allocator_alloc_wrapped (window->allocator,
+      device, texture.Get (), desc.Width * desc.Height * 4, nullptr, nullptr);
   if (!mem) {
     GST_ERROR_OBJECT (window, "Couldn't allocate memory");
     return FALSE;
index 0538333..54fce35 100644 (file)
@@ -42,6 +42,7 @@ typedef struct
 
   ID3D11Device *device;
   ID3D11DeviceContext *context;
+  gsize mem_size;
 
   D3D11_TEXTURE2D_DESC desc;
   GstVideoInfo video_info;
@@ -282,7 +283,8 @@ on_need_data (GstAppSrc * appsrc, guint length, gpointer user_data)
    * ID3D11Texture2D object, but in this example, we pass ownership via
    * user data */
   mem = gst_d3d11_allocator_alloc_wrapped (allocator, app_data->d3d11_device,
-      texture, memory_data, (GDestroyNotify) on_memory_freed);
+      texture, app_data->mem_size, memory_data,
+      (GDestroyNotify) on_memory_freed);
   gst_object_unref (allocator);
 
   if (!mem) {
@@ -290,6 +292,10 @@ on_need_data (GstAppSrc * appsrc, guint length, gpointer user_data)
     exit (1);
   }
 
+  /* update memory size with calculated value by allocator, and reuse it
+   * for later alloc_wrapped() call to avoid allocating staging texture */
+  app_data->mem_size = mem->size;
+
   /* Calculates CPU accessible (via staging texture) memory layout.
    * GstD3D11Memory allows CPU access but application must calculate the layout
    * pitch would be likely different from width */