d3d11memory: Add support for ID3D11Buffer
authorSeungha Yang <seungha@centricular.com>
Sun, 6 Feb 2022 12:36:28 +0000 (21:36 +0900)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Tue, 8 Feb 2022 10:05:35 +0000 (10:05 +0000)
Allow wrap ID3D11Buffer via GstD3D11Memory object
At the moment, only staging ID3D11Buffer is supported.

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

subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11bufferpool.cpp
subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11memory.cpp
subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11memory.h
subprojects/gst-plugins-bad/gst-libs/gst/d3d11/gstd3d11stagingbufferpool.cpp
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11pluginutils.cpp

index 14cc8b1..eb72f2f 100644 (file)
@@ -278,7 +278,7 @@ gst_d3d11_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
       return FALSE;
     }
 
-    if (!gst_d3d11_memory_get_texture_stride (GST_D3D11_MEMORY_CAST (mem),
+    if (!gst_d3d11_memory_get_resource_stride (GST_D3D11_MEMORY_CAST (mem),
             &stride) || stride < desc[i].Width) {
       GST_ERROR_OBJECT (self, "Failed to calculate stride");
 
index 77d26fc..417015f 100644 (file)
@@ -247,9 +247,12 @@ gst_d3d11_allocation_params_init (GType type)
 struct _GstD3D11MemoryPrivate
 {
   ID3D11Texture2D *texture;
-  ID3D11Texture2D *staging;
+  ID3D11Buffer *buffer;
+
+  ID3D11Resource *staging;
 
   D3D11_TEXTURE2D_DESC desc;
+  D3D11_BUFFER_DESC buffer_desc;
 
   guint subresource_index;
 
@@ -265,6 +268,7 @@ struct _GstD3D11MemoryPrivate
 
   D3D11_MAPPED_SUBRESOURCE map;
 
+  GstD3D11MemoryNativeType native_type;
 
   GMutex lock;
   gint cpu_map_count;
@@ -320,11 +324,10 @@ gst_d3d11_memory_map_cpu_access (GstD3D11Memory * dmem, D3D11_MAP map_type)
 {
   GstD3D11MemoryPrivate *priv = dmem->priv;
   HRESULT hr;
-  ID3D11Resource *staging = (ID3D11Resource *) priv->staging;
   ID3D11DeviceContext *device_context =
       gst_d3d11_device_get_device_context_handle (dmem->device);
 
-  hr = device_context->Map (staging, 0, map_type, 0, &priv->map);
+  hr = device_context->Map (priv->staging, 0, map_type, 0, &priv->map);
 
   if (!gst_d3d11_result (hr, dmem->device)) {
     GST_ERROR_OBJECT (GST_MEMORY_CAST (dmem)->allocator,
@@ -379,36 +382,46 @@ gst_d3d11_memory_map_full (GstMemory * mem, GstMapInfo * info, gsize maxsize)
   GST_D3D11_MEMORY_LOCK (dmem);
 
   if ((flags & GST_MAP_D3D11) == GST_MAP_D3D11) {
-    gst_d3d11_memory_upload (dmem);
-    GST_MEMORY_FLAG_UNSET (dmem, GST_D3D11_MEMORY_TRANSFER_NEED_UPLOAD);
+    if (priv->native_type == GST_D3D11_MEMORY_NATIVE_TYPE_BUFFER) {
+      /* FIXME: handle non-staging buffer */
+      g_assert (priv->buffer != nullptr);
+      ret = priv->buffer;
+    } else {
+      gst_d3d11_memory_upload (dmem);
+      GST_MEMORY_FLAG_UNSET (dmem, GST_D3D11_MEMORY_TRANSFER_NEED_UPLOAD);
 
-    if ((flags & GST_MAP_WRITE) == GST_MAP_WRITE)
-      GST_MINI_OBJECT_FLAG_SET (dmem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD);
+      if ((flags & GST_MAP_WRITE) == GST_MAP_WRITE)
+        GST_MINI_OBJECT_FLAG_SET (dmem,
+            GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD);
 
-    g_assert (priv->texture != NULL);
-    ret = priv->texture;
-    goto out;
+      g_assert (priv->texture != NULL);
+      ret = priv->texture;
+      goto out;
+    }
   }
 
   if (priv->cpu_map_count == 0) {
     D3D11_MAP map_type;
 
-    /* Allocate staging texture for CPU access */
-    if (!priv->staging) {
-      priv->staging = gst_d3d11_allocate_staging_texture (dmem->device,
-          &priv->desc);
+    /* FIXME: handle non-staging buffer */
+    if (priv->native_type == GST_D3D11_MEMORY_NATIVE_TYPE_TEXTURE_2D) {
+      /* Allocate staging texture for CPU access */
       if (!priv->staging) {
-        GST_ERROR_OBJECT (mem->allocator, "Couldn't create staging texture");
-        goto out;
+        priv->staging = gst_d3d11_allocate_staging_texture (dmem->device,
+            &priv->desc);
+        if (!priv->staging) {
+          GST_ERROR_OBJECT (mem->allocator, "Couldn't create staging texture");
+          goto out;
+        }
+
+        /* first memory, always need download to staging */
+        GST_MINI_OBJECT_FLAG_SET (mem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD);
       }
 
-      /* first memory, always need download to staging */
-      GST_MINI_OBJECT_FLAG_SET (mem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD);
+      gst_d3d11_memory_download (dmem);
     }
 
-    gst_d3d11_memory_download (dmem);
     map_type = gst_d3d11_map_flags_to_d3d11 (flags);
-
     if (!gst_d3d11_memory_map_cpu_access (dmem, map_type)) {
       GST_ERROR_OBJECT (mem->allocator, "Couldn't map staging texture");
       goto out;
@@ -436,11 +449,10 @@ static void
 gst_d3d11_memory_unmap_cpu_access (GstD3D11Memory * dmem)
 {
   GstD3D11MemoryPrivate *priv = dmem->priv;
-  ID3D11Resource *staging = (ID3D11Resource *) priv->staging;
   ID3D11DeviceContext *device_context =
       gst_d3d11_device_get_device_context_handle (dmem->device);
 
-  device_context->Unmap (staging, 0);
+  device_context->Unmap (priv->staging, 0);
 }
 
 static void
@@ -541,6 +553,23 @@ gst_is_d3d11_memory (GstMemory * mem)
 }
 
 /**
+ * gst_d3d11_memory_get_native_type:
+ * @mem: a #GstD3D11Memory
+ *
+ * Returns: a #GstD3D11MemoryNativeType
+ *
+ * Since: 1.22
+ */
+GstD3D11MemoryNativeType
+gst_d3d11_memory_get_native_type (GstD3D11Memory * mem)
+{
+  if (!gst_is_d3d11_memory (GST_MEMORY_CAST (mem)))
+    return GST_D3D11_MEMORY_NATIVE_TYPE_INVALID;
+
+  return mem->priv->native_type;
+}
+
+/**
  * gst_d3d11_memory_init_once:
  *
  * Initializes the Direct3D11 Texture allocator. It is safe to call
@@ -569,20 +598,29 @@ gst_d3d11_memory_init_once (void)
 }
 
 /**
- * gst_d3d11_memory_get_texture_handle:
+ * gst_d3d11_memory_get_resource_handle:
  * @mem: a #GstD3D11Memory
  *
- * Returns: (transfer none): a ID3D11Texture2D handle. Caller must not release
+ * Returns: (transfer none): a ID3D11Resource handle. Caller must not release
  * returned handle.
  *
- * Since: 1.20
+ * Since: 1.22
  */
-ID3D11Texture2D *
-gst_d3d11_memory_get_texture_handle (GstD3D11Memory * mem)
+ID3D11Resource *
+gst_d3d11_memory_get_resource_handle (GstD3D11Memory * mem)
 {
   g_return_val_if_fail (gst_is_d3d11_memory (GST_MEMORY_CAST (mem)), NULL);
 
-  return mem->priv->texture;
+  switch (mem->priv->native_type) {
+    case GST_D3D11_MEMORY_NATIVE_TYPE_BUFFER:
+      return mem->priv->buffer;
+    case GST_D3D11_MEMORY_NATIVE_TYPE_TEXTURE_2D:
+      return mem->priv->texture;
+    default:
+      break;
+  }
+
+  return nullptr;
 }
 
 /**
@@ -598,6 +636,9 @@ gst_d3d11_memory_get_subresource_index (GstD3D11Memory * mem)
 {
   g_return_val_if_fail (gst_is_d3d11_memory (GST_MEMORY_CAST (mem)), 0);
 
+  if (mem->priv->native_type != GST_D3D11_MEMORY_NATIVE_TYPE_TEXTURE_2D)
+    return 0;
+
   return mem->priv->subresource_index;
 }
 
@@ -619,13 +660,51 @@ gst_d3d11_memory_get_texture_desc (GstD3D11Memory * mem,
   g_return_val_if_fail (gst_is_d3d11_memory (GST_MEMORY_CAST (mem)), FALSE);
   g_return_val_if_fail (desc != NULL, FALSE);
 
+  if (mem->priv->native_type != GST_D3D11_MEMORY_NATIVE_TYPE_TEXTURE_2D)
+    return FALSE;
+
   *desc = mem->priv->desc;
 
   return TRUE;
 }
 
+/**
+ * gst_d3d11_memory_get_buffer_desc:
+ * @mem: a #GstD3D11Memory
+ * @desc: (out): a D3D11_BUFFER_DESC
+ *
+ * Fill @desc with D3D11_BUFFER_DESC for ID3D11Buffer
+ *
+ * Returns: %TRUE if successeed
+ *
+ * Since: 1.22
+ */
+gboolean
+gst_d3d11_memory_get_buffer_desc (GstD3D11Memory * mem,
+    D3D11_BUFFER_DESC * desc)
+{
+  g_return_val_if_fail (gst_is_d3d11_memory (GST_MEMORY_CAST (mem)), FALSE);
+  g_return_val_if_fail (desc != NULL, FALSE);
+
+  if (mem->priv->native_type != GST_D3D11_MEMORY_NATIVE_TYPE_BUFFER)
+    return FALSE;
+
+  *desc = mem->priv->buffer_desc;
+
+  return TRUE;
+}
+
+/**
+ * gst_d3d11_memory_get_resource_stride:
+ * @mem: a #GstD3D11Memory
+ * @stride: (out): stride of resource
+ *
+ * Returns: %TRUE if successeed
+ *
+ * Since: 1.22
+ */
 gboolean
-gst_d3d11_memory_get_texture_stride (GstD3D11Memory * mem, guint * stride)
+gst_d3d11_memory_get_resource_stride (GstD3D11Memory * mem, guint * stride)
 {
   g_return_val_if_fail (gst_is_d3d11_memory (GST_MEMORY_CAST (mem)), FALSE);
   g_return_val_if_fail (stride != NULL, FALSE);
@@ -732,6 +811,9 @@ gst_d3d11_memory_ensure_shader_resource_view (GstD3D11Memory * mem)
   GstD3D11MemoryPrivate *priv = mem->priv;
   gboolean ret = FALSE;
 
+  if (mem->priv->native_type != GST_D3D11_MEMORY_NATIVE_TYPE_TEXTURE_2D)
+    return FALSE;
+
   if (!(priv->desc.BindFlags & D3D11_BIND_SHADER_RESOURCE)) {
     GST_LOG_OBJECT (GST_MEMORY_CAST (mem)->allocator,
         "Need BindFlags, current flag 0x%x", priv->desc.BindFlags);
@@ -888,6 +970,9 @@ gst_d3d11_memory_ensure_render_target_view (GstD3D11Memory * mem)
   GstD3D11MemoryPrivate *priv = mem->priv;
   gboolean ret = FALSE;
 
+  if (mem->priv->native_type != GST_D3D11_MEMORY_NATIVE_TYPE_TEXTURE_2D)
+    return FALSE;
+
   if (!(priv->desc.BindFlags & D3D11_BIND_RENDER_TARGET)) {
     GST_WARNING_OBJECT (GST_MEMORY_CAST (mem)->allocator,
         "Need BindFlags, current flag 0x%x", priv->desc.BindFlags);
@@ -969,6 +1054,9 @@ gst_d3d11_memory_ensure_decoder_output_view (GstD3D11Memory * mem,
   HRESULT hr;
   gboolean ret = FALSE;
 
+  if (mem->priv->native_type != GST_D3D11_MEMORY_NATIVE_TYPE_TEXTURE_2D)
+    return FALSE;
+
   allocator = GST_D3D11_ALLOCATOR (GST_MEMORY_CAST (mem)->allocator);
 
   if (!(dmem_priv->desc.BindFlags & D3D11_BIND_DECODER)) {
@@ -1066,6 +1154,9 @@ gst_d3d11_memory_ensure_processor_input_view (GstD3D11Memory * mem,
   HRESULT hr;
   gboolean ret = FALSE;
 
+  if (mem->priv->native_type != GST_D3D11_MEMORY_NATIVE_TYPE_TEXTURE_2D)
+    return FALSE;
+
   allocator = GST_D3D11_ALLOCATOR (GST_MEMORY_CAST (mem)->allocator);
 
   if (!check_bind_flags_for_processor_input_view (dmem_priv->desc.BindFlags)) {
@@ -1139,6 +1230,9 @@ gst_d3d11_memory_ensure_processor_output_view (GstD3D11Memory * mem,
   HRESULT hr;
   gboolean ret;
 
+  if (mem->priv->native_type != GST_D3D11_MEMORY_NATIVE_TYPE_TEXTURE_2D)
+    return FALSE;
+
   memset (&desc, 0, sizeof (D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC));
 
   allocator = GST_D3D11_ALLOCATOR (GST_MEMORY_CAST (mem)->allocator);
@@ -1253,6 +1347,9 @@ gst_d3d11_memory_copy (GstMemory * mem, gssize offset, gssize size)
   UINT bind_flags = 0;
   UINT supported_flags = 0;
 
+  if (dmem->priv->native_type != GST_D3D11_MEMORY_NATIVE_TYPE_TEXTURE_2D)
+    return priv->fallback_copy (mem, offset, size);
+
   /* non-zero offset or different size is not supported */
   if (offset != 0 || (size != -1 && (gsize) size != mem->size)) {
     GST_DEBUG_OBJECT (alloc, "Different size/offset, try fallback copy");
@@ -1364,6 +1461,7 @@ gst_d3d11_allocator_free (GstAllocator * allocator, GstMemory * mem)
   GST_D3D11_CLEAR_COM (dmem_priv->processor_output_view);
   GST_D3D11_CLEAR_COM (dmem_priv->texture);
   GST_D3D11_CLEAR_COM (dmem_priv->staging);
+  GST_D3D11_CLEAR_COM (dmem_priv->buffer);
 
   gst_clear_object (&dmem->device);
   g_mutex_clear (&dmem_priv->lock);
@@ -1386,6 +1484,7 @@ gst_d3d11_allocator_alloc_wrapped (GstD3D11Allocator * self,
   g_mutex_init (&mem->priv->lock);
   mem->priv->texture = texture;
   mem->priv->desc = *desc;
+  mem->priv->native_type = GST_D3D11_MEMORY_NATIVE_TYPE_TEXTURE_2D;
   mem->device = (GstD3D11Device *) gst_object_ref (device);
 
   /* This is staging texture as well */
@@ -1449,6 +1548,59 @@ gst_d3d11_allocator_alloc (GstD3D11Allocator * allocator,
   return mem;
 }
 
+/**
+ * gst_d3d11_allocator_alloc_buffer:
+ * @allocator: a #GstD3D11Allocator
+ * @device: a #GstD3D11Device
+ * @desc: a D3D11_BUFFER_DESC struct
+ *
+ * Returns: a newly allocated #GstD3D11Memory with given parameters.
+ *
+ * Since: 1.22
+ */
+GstMemory *
+gst_d3d11_allocator_alloc_buffer (GstD3D11Allocator * allocator,
+    GstD3D11Device * device, const D3D11_BUFFER_DESC * desc)
+{
+  GstD3D11Memory *mem;
+  ID3D11Buffer *buffer;
+  ID3D11Device *device_handle;
+  HRESULT hr;
+
+  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 (desc != nullptr, nullptr);
+
+  if (desc->Usage != D3D11_USAGE_STAGING) {
+    GST_FIXME_OBJECT (allocator, "Non staging buffer is not supported");
+    return nullptr;
+  }
+
+  device_handle = gst_d3d11_device_get_device_handle (device);
+
+  hr = device_handle->CreateBuffer (desc, nullptr, &buffer);
+  if (!gst_d3d11_result (hr, device)) {
+    GST_ERROR_OBJECT (allocator, "Couldn't create buffer");
+    return nullptr;
+  }
+
+  mem = g_new0 (GstD3D11Memory, 1);
+  mem->priv = g_new0 (GstD3D11MemoryPrivate, 1);
+
+  gst_memory_init (GST_MEMORY_CAST (mem),
+      (GstMemoryFlags) 0, GST_ALLOCATOR_CAST (allocator), nullptr, 0, 0, 0, 0);
+  g_mutex_init (&mem->priv->lock);
+  mem->priv->buffer = buffer;
+  mem->priv->buffer_desc = *desc;
+  mem->priv->native_type = GST_D3D11_MEMORY_NATIVE_TYPE_BUFFER;
+  mem->device = (GstD3D11Device *) gst_object_ref (device);
+
+  GST_MEMORY_CAST (mem)->maxsize = GST_MEMORY_CAST (mem)->size =
+      desc->ByteWidth;
+
+  return GST_MEMORY_CAST (mem);
+}
+
 gboolean
 gst_d3d11_allocator_set_active (GstD3D11Allocator * allocator, gboolean active)
 {
index a80bf7b..841188c 100644 (file)
@@ -106,6 +106,21 @@ typedef enum
   GST_D3D11_MEMORY_TRANSFER_NEED_UPLOAD     = (GST_MEMORY_FLAG_LAST << 1)
 } GstD3D11MemoryTransfer;
 
+/**
+ * GstD3D11MemoryNativeType:
+ * @GST_D3D11_MEMORY_NATIVE_TYPE_INVALID: not a valid object type
+ * @GST_D3D11_MEMORY_OBJECT_TYPE_BUFFER: memory holds ID3D11Buffer object
+ * @GST_D3D11_MEMORY_OBJECT_TYPE_TEXTURE_2D: memory holds ID3D11Texture2D object
+ *
+ * Since: 1.22
+ */
+typedef enum
+{
+  GST_D3D11_MEMORY_NATIVE_TYPE_INVALID = 0,
+  GST_D3D11_MEMORY_NATIVE_TYPE_BUFFER,
+  GST_D3D11_MEMORY_NATIVE_TYPE_TEXTURE_2D,
+} GstD3D11MemoryNativeType;
+
 struct _GstD3D11AllocationParams
 {
   /* Texture description per plane */
@@ -162,15 +177,22 @@ GST_D3D11_API
 gboolean                   gst_is_d3d11_memory        (GstMemory * mem);
 
 GST_D3D11_API
-ID3D11Texture2D *          gst_d3d11_memory_get_texture_handle (GstD3D11Memory * mem);
+GstD3D11MemoryNativeType   gst_d3d11_memory_get_native_type (GstD3D11Memory * mem);
+
+GST_D3D11_API
+ID3D11Resource *           gst_d3d11_memory_get_resource_handle (GstD3D11Memory * mem);
 
 GST_D3D11_API
 gboolean                   gst_d3d11_memory_get_texture_desc (GstD3D11Memory * mem,
                                                               D3D11_TEXTURE2D_DESC * desc);
 
 GST_D3D11_API
-gboolean                   gst_d3d11_memory_get_texture_stride (GstD3D11Memory * mem,
-                                                                guint * stride);
+gboolean                   gst_d3d11_memory_get_buffer_desc  (GstD3D11Memory * mem,
+                                                              D3D11_BUFFER_DESC * desc);
+
+GST_D3D11_API
+gboolean                   gst_d3d11_memory_get_resource_stride (GstD3D11Memory * mem,
+                                                                 guint * stride);
 
 GST_D3D11_API
 guint                      gst_d3d11_memory_get_subresource_index (GstD3D11Memory * mem);
@@ -234,6 +256,11 @@ GstMemory * gst_d3d11_allocator_alloc     (GstD3D11Allocator * allocator,
                                            const D3D11_TEXTURE2D_DESC * desc);
 
 GST_D3D11_API
+GstMemory * gst_d3d11_allocator_alloc_buffer (GstD3D11Allocator * allocator,
+                                              GstD3D11Device * device,
+                                              const D3D11_BUFFER_DESC * desc);
+
+GST_D3D11_API
 gboolean    gst_d3d11_allocator_set_active (GstD3D11Allocator * allocator,
                                             gboolean active);
 
index 40912f9..fc87521 100644 (file)
@@ -225,7 +225,7 @@ gst_d3d11_staging_buffer_pool_set_config (GstBufferPool * pool,
       return FALSE;
     }
 
-    if (!gst_d3d11_memory_get_texture_stride (GST_D3D11_MEMORY_CAST (mem),
+    if (!gst_d3d11_memory_get_resource_stride (GST_D3D11_MEMORY_CAST (mem),
             &stride) || stride < priv->desc[i].Width) {
       GST_ERROR_OBJECT (self, "Failed to calculate stride");
 
index 6c17748..7a253d4 100644 (file)
@@ -649,7 +649,7 @@ gst_d3d11_allocate_staging_buffer_for (GstBuffer * buffer,
       goto error;
     }
 
-    if (!gst_d3d11_memory_get_texture_stride (new_mem, &cur_stride) ||
+    if (!gst_d3d11_memory_get_resource_stride (new_mem, &cur_stride) ||
         cur_stride < staging_desc.Width) {
       GST_ERROR ("Failed to calculate memory size");
       gst_memory_unref (GST_MEMORY_CAST (mem));