d3d11: Add support for Array typed texture memory
authorSeungha Yang <seungha.yang@navercorp.com>
Fri, 20 Dec 2019 13:50:55 +0000 (22:50 +0900)
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Tue, 31 Dec 2019 02:13:48 +0000 (02:13 +0000)
A ID3D11Texture2D memory can consist of multiple planes with array.
For array typed memory, GstD3D11Allocator will allocate new GstD3D11Memory
with increased reference count to the ID3D11Texture2D but different array index.

sys/d3d11/gstd3d11bufferpool.c
sys/d3d11/gstd3d11memory.c
sys/d3d11/gstd3d11memory.h

index 123ef8f..63bd683 100644 (file)
@@ -109,6 +109,8 @@ gst_d3d11_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
   guint min_buffers, max_buffers;
   GstAllocator *allocator = NULL;
   gboolean ret = TRUE;
+  D3D11_TEXTURE2D_DESC *desc;
+  gint i;
 
   if (!gst_buffer_pool_config_get_params (config, &caps, NULL, &min_buffers,
           &max_buffers))
@@ -155,11 +157,11 @@ gst_d3d11_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
   }
 #ifndef GST_DISABLE_GST_DEBUG
   {
-    D3D11_TEXTURE2D_DESC *desc;
-    gint i;
     desc = priv->d3d11_params->desc;
 
     GST_LOG_OBJECT (self, "Direct3D11 Allocation params");
+    GST_LOG_OBJECT (self, "\tD3D11AllocationFlags: 0x%x",
+        priv->d3d11_params->flags);
     for (i = 0; GST_VIDEO_MAX_PLANES; i++) {
       if (desc[i].Format == DXGI_FORMAT_UNKNOWN)
         break;
@@ -181,6 +183,26 @@ gst_d3d11_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
   }
 #endif
 
+  if ((priv->d3d11_params->flags & GST_D3D11_ALLOCATION_FLAG_TEXTURE_ARRAY)) {
+    guint max_array_size = 0;
+    desc = priv->d3d11_params->desc;
+
+    for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
+      if (desc[i].Format == DXGI_FORMAT_UNKNOWN)
+        break;
+
+      if (desc[i].ArraySize > max_array_size)
+        max_array_size = desc[i].ArraySize;
+    }
+
+    if (max_buffers == 0 || max_buffers > max_array_size) {
+      GST_WARNING_OBJECT (pool,
+          "Array pool is requested but allowed pool size %d > ArraySize %d",
+          max_buffers, max_array_size);
+      max_buffers = max_array_size;
+    }
+  }
+
   gst_d3d11_buffer_pool_alloc (pool, &priv->initial_buffer, NULL);
 
   if (!priv->initial_buffer) {
index 13e4818..b2eacf4 100644 (file)
@@ -212,7 +212,7 @@ map_cpu_access_data (GstD3D11Memory * dmem, D3D11_MAP map_type)
   gst_d3d11_device_lock (dmem->device);
   if (GST_MEMORY_FLAG_IS_SET (dmem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD)) {
     ID3D11DeviceContext_CopySubresourceRegion (device_context,
-        staging, 0, 0, 0, 0, texture, 0, NULL);
+        staging, 0, 0, 0, 0, texture, dmem->subresource_index, NULL);
   }
 
   hr = ID3D11DeviceContext_Map (device_context,
@@ -249,7 +249,7 @@ gst_d3d11_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags)
 
       gst_d3d11_device_lock (dmem->device);
       ID3D11DeviceContext_CopySubresourceRegion (device_context,
-          (ID3D11Resource *) dmem->texture, 0, 0, 0, 0,
+          (ID3D11Resource *) dmem->texture, dmem->subresource_index, 0, 0, 0,
           (ID3D11Resource *) dmem->staging, 0, NULL);
       gst_d3d11_device_unlock (dmem->device);
     }
@@ -396,6 +396,11 @@ gst_d3d11_allocator_dispose (GObject * object)
 {
   GstD3D11Allocator *alloc = GST_D3D11_ALLOCATOR (object);
 
+  if (alloc->device && alloc->texture) {
+    gst_d3d11_device_release_texture (alloc->device, alloc->texture);
+    alloc->texture = NULL;
+  }
+
   gst_clear_object (&alloc->device);
 
   G_OBJECT_CLASS (parent_class)->dispose (object);
@@ -636,6 +641,8 @@ gst_d3d11_allocator_alloc (GstD3D11Allocator * allocator,
   gsize *size;
   gboolean is_first = FALSE;
   GstMemoryFlags memory_flags;
+  guint index_to_use = 0;
+  GstD3D11MemoryType type = GST_D3D11_MEMORY_TYPE_TEXTURE;
 
   g_return_val_if_fail (GST_IS_D3D11_ALLOCATOR (allocator), NULL);
   g_return_val_if_fail (params != NULL, NULL);
@@ -657,10 +664,38 @@ gst_d3d11_allocator_alloc (GstD3D11Allocator * allocator,
   if (*size == 0)
     is_first = TRUE;
 
-  texture = gst_d3d11_device_create_texture (device, desc, NULL);
-  if (!texture) {
-    GST_ERROR_OBJECT (allocator, "Couldn't create texture");
-    goto error;
+  if ((params->flags & GST_D3D11_ALLOCATION_FLAG_TEXTURE_ARRAY)) {
+    gint i;
+    for (i = 0; i < desc->ArraySize; i++) {
+      if (allocator->array_in_use[i] == 0) {
+        index_to_use = i;
+        break;
+      }
+    }
+
+    if (i == desc->ArraySize) {
+      GST_ERROR_OBJECT (allocator, "All elements in array are used now");
+      goto error;
+    }
+
+    if (!allocator->texture) {
+      allocator->texture = gst_d3d11_device_create_texture (device, desc, NULL);
+      if (!allocator->texture) {
+        GST_ERROR_OBJECT (allocator, "Couldn't create texture");
+        goto error;
+      }
+    }
+
+    ID3D11Texture2D_AddRef (allocator->texture);
+    texture = allocator->texture;
+
+    type = GST_D3D11_MEMORY_TYPE_ARRAY;
+  } else {
+    texture = gst_d3d11_device_create_texture (device, desc, NULL);
+    if (!texture) {
+      GST_ERROR_OBJECT (allocator, "Couldn't create texture");
+      goto error;
+    }
   }
 
   /* per plane, allocated staging texture to calculate actual size,
@@ -713,6 +748,10 @@ gst_d3d11_allocator_alloc (GstD3D11Allocator * allocator,
   mem->texture = texture;
   mem->staging = staging;
   mem->device = gst_object_ref (device);
+  mem->type = type;
+  mem->subresource_index = index_to_use;
+  if (type == GST_D3D11_MEMORY_TYPE_ARRAY)
+    allocator->array_in_use[index_to_use] = 1;
 
   if (staging)
     GST_MINI_OBJECT_FLAG_SET (mem, GST_D3D11_MEMORY_TRANSFER_NEED_DOWNLOAD);
index dc0515d..74a3d36 100644 (file)
@@ -57,10 +57,12 @@ G_BEGIN_DECLS
  * GstD3D11AllocationFlags:
  * GST_D3D11_ALLOCATION_FLAG_USE_RESOURCE_FORMAT: Allocate texture with resource format
  *                                                per planes instead of the direct use of DXGI format
+ * GST_D3D11_ALLOCATION_FLAG_TEXTURE_ARRAY: Indicates each allocated texture should be array type
  */
 typedef enum
 {
   GST_D3D11_ALLOCATION_FLAG_USE_RESOURCE_FORMAT = (1 << 0),
+  GST_D3D11_ALLOCATION_FLAG_TEXTURE_ARRAY = (1 << 1),
 } GstD3D11AllocationFlags;
 
 /**
@@ -97,6 +99,12 @@ struct _GstD3D11AllocationParams
   gpointer _gst_reserved[GST_PADDING_LARGE];
 };
 
+typedef enum
+{
+  GST_D3D11_MEMORY_TYPE_TEXTURE = 0,
+  GST_D3D11_MEMORY_TYPE_ARRAY = 1,
+} GstD3D11MemoryType;
+
 struct _GstD3D11Memory
 {
   GstMemory mem;
@@ -116,6 +124,10 @@ struct _GstD3D11Memory
   GstVideoInfo info;
 
   guint plane;
+  GstD3D11MemoryType type;
+
+  /* > 0 if this is Array typed memory */
+  guint subresource_index;
 
   D3D11_TEXTURE2D_DESC desc;
   D3D11_MAPPED_SUBRESOURCE map;
@@ -131,6 +143,10 @@ struct _GstD3D11Allocator
 
   GstD3D11Device *device;
 
+  /* parent textrure when array typed memory is used */
+  ID3D11Texture2D *texture;
+  guint8 array_in_use [D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION];
+
   /*< private >*/
   gpointer _gst_reserved[GST_PADDING];
 };