d3d11allocator: Work as if buffer pool when running on texture array mode

Because the size of texture array cannot be updated dynamically,
allocator should block the allocation request. This cannot be
done at buffer pool side if this d3d11 memory is shared among
multiple buffer objects. Note that setting NO_SHARE flag to
d3d11 memory is very inefficient. It would cause most likey
copy of the d3d11 texture.
This commit is contained in:
Seungha Yang 2020-01-30 18:11:52 +09:00 committed by GStreamer Merge Bot
parent 4d02858f66
commit 8ff667e463
4 changed files with 116 additions and 18 deletions

View file

@ -63,6 +63,7 @@ typedef struct _GstD3D11AllocationParams GstD3D11AllocationParams;
typedef struct _GstD3D11Memory GstD3D11Memory;
typedef struct _GstD3D11Allocator GstD3D11Allocator;
typedef struct _GstD3D11AllocatorClass GstD3D11AllocatorClass;
typedef struct _GstD3D11AllocatorPrivate GstD3D11AllocatorPrivate;
typedef struct _GstD3D11BufferPool GstD3D11BufferPool;
typedef struct _GstD3D11BufferPoolClass GstD3D11BufferPoolClass;

View file

@ -50,6 +50,8 @@ static gboolean gst_d3d11_buffer_pool_set_config (GstBufferPool * pool,
GstStructure * config);
static GstFlowReturn gst_d3d11_buffer_pool_alloc (GstBufferPool * pool,
GstBuffer ** buffer, GstBufferPoolAcquireParams * params);
static void gst_d3d11_buffer_pool_flush_start (GstBufferPool * pool);
static void gst_d3d11_buffer_pool_flush_stop (GstBufferPool * pool);
static void
gst_d3d11_buffer_pool_class_init (GstD3D11BufferPoolClass * klass)
@ -62,6 +64,8 @@ gst_d3d11_buffer_pool_class_init (GstD3D11BufferPoolClass * klass)
bufferpool_class->get_options = gst_d3d11_buffer_pool_get_options;
bufferpool_class->set_config = gst_d3d11_buffer_pool_set_config;
bufferpool_class->alloc_buffer = gst_d3d11_buffer_pool_alloc;
bufferpool_class->flush_start = gst_d3d11_buffer_pool_flush_start;
bufferpool_class->flush_stop = gst_d3d11_buffer_pool_flush_stop;
GST_DEBUG_CATEGORY_INIT (gst_d3d11_buffer_pool_debug, "d3d11bufferpool", 0,
"d3d11bufferpool object");
@ -311,6 +315,26 @@ error:
return GST_FLOW_ERROR;
}
static void
gst_d3d11_buffer_pool_flush_start (GstBufferPool * pool)
{
GstD3D11BufferPool *self = GST_D3D11_BUFFER_POOL (pool);
GstD3D11BufferPoolPrivate *priv = self->priv;
if (priv->allocator)
gst_d3d11_allocator_set_flushing (priv->allocator, TRUE);
}
static void
gst_d3d11_buffer_pool_flush_stop (GstBufferPool * pool)
{
GstD3D11BufferPool *self = GST_D3D11_BUFFER_POOL (pool);
GstD3D11BufferPoolPrivate *priv = self->priv;
if (priv->allocator)
gst_d3d11_allocator_set_flushing (priv->allocator, FALSE);
}
GstBufferPool *
gst_d3d11_buffer_pool_new (GstD3D11Device * device)
{

View file

@ -146,8 +146,21 @@ G_DEFINE_BOXED_TYPE_WITH_CODE (GstD3D11AllocationParams,
(GBoxedFreeFunc) gst_d3d11_allocation_params_free,
_init_alloc_params (g_define_type_id));
struct _GstD3D11AllocatorPrivate
{
/* parent textrure when array typed memory is used */
ID3D11Texture2D *texture;
guint8 array_in_use[D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION];
GMutex lock;
GCond cond;
gboolean flushing;
};
#define gst_d3d11_allocator_parent_class parent_class
G_DEFINE_TYPE (GstD3D11Allocator, gst_d3d11_allocator, GST_TYPE_ALLOCATOR);
G_DEFINE_TYPE_WITH_PRIVATE (GstD3D11Allocator,
gst_d3d11_allocator, GST_TYPE_ALLOCATOR);
static inline D3D11_MAP
gst_map_flags_to_d3d11 (GstMapFlags flags)
@ -337,9 +350,16 @@ gst_d3d11_allocator_dummy_alloc (GstAllocator * allocator, gsize size,
static void
gst_d3d11_allocator_free (GstAllocator * allocator, GstMemory * mem)
{
GstD3D11Allocator *self = GST_D3D11_ALLOCATOR (allocator);
GstD3D11AllocatorPrivate *priv = self->priv;
GstD3D11Memory *dmem = (GstD3D11Memory *) mem;
gint i;
g_mutex_lock (&priv->lock);
priv->array_in_use[dmem->subresource_index] = 0;
g_cond_broadcast (&priv->cond);
g_mutex_unlock (&priv->lock);
for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
if (dmem->render_target_view[i])
ID3D11RenderTargetView_Release (dmem->render_target_view[i]);
@ -366,10 +386,11 @@ static void
gst_d3d11_allocator_dispose (GObject * object)
{
GstD3D11Allocator *alloc = GST_D3D11_ALLOCATOR (object);
GstD3D11AllocatorPrivate *priv = alloc->priv;
if (alloc->device && alloc->texture) {
gst_d3d11_device_release_texture (alloc->device, alloc->texture);
alloc->texture = NULL;
if (alloc->device && priv->texture) {
gst_d3d11_device_release_texture (alloc->device, priv->texture);
priv->texture = NULL;
}
gst_clear_object (&alloc->device);
@ -377,6 +398,18 @@ gst_d3d11_allocator_dispose (GObject * object)
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
gst_d3d11_allocator_finalize (GObject * object)
{
GstD3D11Allocator *alloc = GST_D3D11_ALLOCATOR (object);
GstD3D11AllocatorPrivate *priv = alloc->priv;
g_mutex_clear (&priv->lock);
g_cond_clear (&priv->cond);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gst_d3d11_allocator_class_init (GstD3D11AllocatorClass * klass)
{
@ -384,6 +417,7 @@ gst_d3d11_allocator_class_init (GstD3D11AllocatorClass * klass)
GstAllocatorClass *allocator_class = GST_ALLOCATOR_CLASS (klass);
gobject_class->dispose = gst_d3d11_allocator_dispose;
gobject_class->finalize = gst_d3d11_allocator_finalize;
allocator_class->alloc = gst_d3d11_allocator_dummy_alloc;
allocator_class->free = gst_d3d11_allocator_free;
@ -396,6 +430,7 @@ static void
gst_d3d11_allocator_init (GstD3D11Allocator * allocator)
{
GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
GstD3D11AllocatorPrivate *priv;
alloc->mem_type = GST_D3D11_MEMORY_NAME;
alloc->mem_map = gst_d3d11_memory_map;
@ -404,6 +439,12 @@ gst_d3d11_allocator_init (GstD3D11Allocator * allocator)
/* fallback copy */
GST_OBJECT_FLAG_SET (alloc, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
priv = gst_d3d11_allocator_get_instance_private (allocator);
g_mutex_init (&priv->lock);
g_cond_init (&priv->cond);
allocator->priv = priv;
}
GstD3D11Allocator *
@ -614,11 +655,13 @@ gst_d3d11_allocator_alloc (GstD3D11Allocator * allocator,
gsize *size;
gboolean is_first = FALSE;
guint index_to_use = 0;
GstD3D11AllocatorPrivate *priv;
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);
priv = allocator->priv;
device = allocator->device;
desc = &params->desc[params->plane];
size = &params->size[params->plane];
@ -628,28 +671,44 @@ gst_d3d11_allocator_alloc (GstD3D11Allocator * allocator,
if ((params->flags & GST_D3D11_ALLOCATION_FLAG_TEXTURE_ARRAY)) {
gint i;
do_again:
g_mutex_lock (&priv->lock);
if (priv->flushing) {
GST_DEBUG_OBJECT (allocator, "we are flushing");
g_mutex_unlock (&priv->lock);
return NULL;
}
for (i = 0; i < desc->ArraySize; i++) {
if (allocator->array_in_use[i] == 0) {
if (priv->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;
GST_DEBUG_OBJECT (allocator, "All elements in array are used now");
g_cond_wait (&priv->cond, &priv->lock);
g_mutex_unlock (&priv->lock);
goto do_again;
}
if (!allocator->texture) {
allocator->texture = gst_d3d11_device_create_texture (device, desc, NULL);
if (!allocator->texture) {
priv->array_in_use[index_to_use] = 1;
g_mutex_unlock (&priv->lock);
if (!priv->texture) {
priv->texture = gst_d3d11_device_create_texture (device, desc, NULL);
if (!priv->texture) {
GST_ERROR_OBJECT (allocator, "Couldn't create texture");
goto error;
}
}
ID3D11Texture2D_AddRef (allocator->texture);
texture = allocator->texture;
ID3D11Texture2D_AddRef (priv->texture);
texture = priv->texture;
type = GST_D3D11_MEMORY_TYPE_ARRAY;
} else {
@ -701,8 +760,6 @@ gst_d3d11_allocator_alloc (GstD3D11Allocator * allocator,
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);
@ -719,6 +776,22 @@ error:
return NULL;
}
void
gst_d3d11_allocator_set_flushing (GstD3D11Allocator * allocator,
gboolean flushing)
{
GstD3D11AllocatorPrivate *priv;
g_return_if_fail (GST_IS_D3D11_ALLOCATOR (allocator));
priv = allocator->priv;
g_mutex_lock (&priv->lock);
priv->flushing = flushing;
g_cond_broadcast (&priv->cond);
g_mutex_unlock (&priv->lock);
}
gboolean
gst_is_d3d11_memory (GstMemory * mem)
{

View file

@ -140,11 +140,8 @@ 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 >*/
GstD3D11AllocatorPrivate *priv;
gpointer _gst_reserved[GST_PADDING];
};
@ -174,6 +171,9 @@ GstD3D11Allocator * gst_d3d11_allocator_new (GstD3D11Device *device);
GstMemory * gst_d3d11_allocator_alloc (GstD3D11Allocator * allocator,
GstD3D11AllocationParams * params);
void gst_d3d11_allocator_set_flushing (GstD3D11Allocator * allocator,
gboolean flushing);
gboolean gst_is_d3d11_memory (GstMemory * mem);
gboolean gst_d3d11_memory_ensure_shader_resource_view (GstD3D11Memory * mem);