d3d11memory: Update alloc_wrapped() API to avoid staging texture alloc

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>
This commit is contained in:
Seungha Yang 2022-07-04 21:57:42 +09:00 committed by GStreamer Marge Bot
parent 76dbe45b83
commit 347ad181be
6 changed files with 43 additions and 62 deletions

View 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 (); \

View 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,10 +1687,14 @@ 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;
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;
}
dmem = GST_D3D11_MEMORY_CAST (mem);
@ -1692,46 +1705,6 @@ gst_d3d11_allocator_alloc_wrapped (GstD3D11Allocator * allocator,
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;
}
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;
dmem->priv->notify = notify;
return mem;
}
/**
* gst_d3d11_allocator_set_active:
* @allocator: a #GstD3D11Allocator

View 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);

View 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;

View 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;

View 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 */