d3d12memory: Update for API interop

Add support for destroy notify in case of wrapped memory, and
allow setting external fence for interop

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6428>
This commit is contained in:
Seungha Yang 2024-03-22 19:05:52 +09:00
parent 0d559bead9
commit 18091f0115
13 changed files with 101 additions and 42 deletions

View file

@ -160,7 +160,7 @@ gst_d3d12_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
priv->d3d12_params =
gst_d3d12_allocation_params_new (self->device,
&info, GST_D3D12_ALLOCATION_FLAG_DEFAULT,
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS);
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS, D3D12_HEAP_FLAG_NONE);
}
auto device = gst_d3d12_device_get_device_handle (self->device);

View file

@ -1970,7 +1970,7 @@ gst_d3d12_compositor_negotiated_src_caps (GstAggregator * agg, GstCaps * caps)
auto params = gst_d3d12_allocation_params_new (self->device, &info,
GST_D3D12_ALLOCATION_FLAG_DEFAULT,
D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET |
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS);
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS, D3D12_HEAP_FLAG_NONE);
gst_buffer_pool_config_set_d3d12_allocation_params (config, params);
gst_d3d12_allocation_params_free (params);
gst_buffer_pool_config_set_params (config, caps, info.size, 0, 0);
@ -2046,7 +2046,7 @@ gst_d3d12_compositor_propose_allocation (GstAggregator * agg,
auto params = gst_d3d12_allocation_params_new (self->device,
&info, GST_D3D12_ALLOCATION_FLAG_DEFAULT,
D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET |
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS);
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS, D3D12_HEAP_FLAG_NONE);
gst_buffer_pool_config_set_d3d12_allocation_params (config, params);
gst_d3d12_allocation_params_free (params);
@ -2150,7 +2150,7 @@ gst_d3d12_compositor_decide_allocation (GstAggregator * agg, GstQuery * query)
params = gst_d3d12_allocation_params_new (self->device, &info,
GST_D3D12_ALLOCATION_FLAG_DEFAULT,
D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET |
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS);
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS, D3D12_HEAP_FLAG_NONE);
} else {
gst_d3d12_allocation_params_set_resource_flags (params,
D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET |

View file

@ -1555,7 +1555,7 @@ gst_d3d12_convert_propose_allocation (GstBaseTransform * trans,
if (!d3d12_params) {
d3d12_params = gst_d3d12_allocation_params_new (filter->device, &info,
GST_D3D12_ALLOCATION_FLAG_DEFAULT,
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS);
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS, D3D12_HEAP_FLAG_NONE);
} else {
gst_d3d12_allocation_params_set_resource_flags (d3d12_params,
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS);
@ -1649,7 +1649,7 @@ gst_d3d12_convert_decide_allocation (GstBaseTransform * trans, GstQuery * query)
d3d12_params = gst_d3d12_allocation_params_new (filter->device, &info,
GST_D3D12_ALLOCATION_FLAG_DEFAULT,
D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET |
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS);
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS, D3D12_HEAP_FLAG_NONE);
} else {
gst_d3d12_allocation_params_set_resource_flags (d3d12_params,
D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET |

View file

@ -2134,7 +2134,7 @@ gst_d3d12_converter_upload_buffer (GstD3D12Converter * self, GstBuffer * in_buf)
auto config = gst_buffer_pool_get_config (priv->fallback_pool);
auto params = gst_d3d12_allocation_params_new (self->device, &in_frame.info,
GST_D3D12_ALLOCATION_FLAG_DEFAULT,
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS);
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS, D3D12_HEAP_FLAG_NONE);
gst_buffer_pool_config_set_d3d12_allocation_params (config, params);
gst_d3d12_allocation_params_free (params);
gst_buffer_pool_config_set_params (config, caps, in_frame.info.size, 0, 0);

View file

@ -722,10 +722,9 @@ gst_d3d12_decoder_configure (GstD3D12Decoder * decoder,
align.padding_bottom = session->aligned_height - info->height;
auto params = gst_d3d12_allocation_params_new (decoder->device, info,
GST_D3D12_ALLOCATION_FLAG_DEFAULT, resource_flags);
gst_d3d12_allocation_params_alignment (params, &align);
gst_d3d12_allocation_params_set_heap_flags (params,
GST_D3D12_ALLOCATION_FLAG_DEFAULT, resource_flags,
D3D12_HEAP_FLAG_CREATE_NOT_ZEROED);
gst_d3d12_allocation_params_alignment (params, &align);
if (!session->array_of_textures)
gst_d3d12_allocation_params_set_array_size (params, session->dpb_size);
@ -755,10 +754,9 @@ gst_d3d12_decoder_configure (GstD3D12Decoder * decoder,
params = gst_d3d12_allocation_params_new (decoder->device, info,
GST_D3D12_ALLOCATION_FLAG_DEFAULT,
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS);
gst_d3d12_allocation_params_alignment (params, &align);
gst_d3d12_allocation_params_set_heap_flags (params,
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS,
D3D12_HEAP_FLAG_CREATE_NOT_ZEROED);
gst_d3d12_allocation_params_alignment (params, &align);
gst_buffer_pool_config_set_d3d12_allocation_params (config, params);
gst_d3d12_allocation_params_free (params);
gst_buffer_pool_config_set_params (config, caps, info->size, 0, 0);
@ -1828,7 +1826,7 @@ gst_d3d12_decoder_decide_allocation (GstD3D12Decoder * decoder,
if (!params) {
params = gst_d3d12_allocation_params_new (decoder->device, &vinfo,
GST_D3D12_ALLOCATION_FLAG_DEFAULT,
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS);
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS, D3D12_HEAP_FLAG_NONE);
} else {
gst_d3d12_allocation_params_set_resource_flags (params,
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS);

View file

@ -1455,13 +1455,13 @@ gst_d3d12_dxgi_capture_draw_mouse (GstD3D12DxgiCapture * self,
priv->mouse_buf = gst_buffer_new ();
auto mem = gst_d3d12_allocator_alloc_wrapped (nullptr, self->device,
mouse_texture.Get (), 0);
mouse_texture.Get (), 0, nullptr, nullptr);
gst_buffer_append_memory (priv->mouse_buf, mem);
if (mouse_xor_texture) {
priv->mouse_xor_buf = gst_buffer_new ();
auto mem = gst_d3d12_allocator_alloc_wrapped (nullptr, self->device,
mouse_xor_texture.Get (), 0);
mouse_xor_texture.Get (), 0, nullptr, nullptr);
gst_buffer_append_memory (priv->mouse_xor_buf, mem);
}

View file

@ -455,7 +455,7 @@ gst_d3d12_encoder_create_upload_pool (GstD3D12Encoder * self)
auto params = gst_d3d12_allocation_params_new (self->device, &info,
GST_D3D12_ALLOCATION_FLAG_DEFAULT,
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS |
D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET);
D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_HEAP_FLAG_NONE);
gst_buffer_pool_config_set_d3d12_allocation_params (config, params);
gst_d3d12_allocation_params_free (params);
gst_buffer_pool_config_set_params (config, caps, info.size, 0, 0);
@ -524,7 +524,7 @@ gst_d3d12_encoder_propose_allocation (GstVideoEncoder * encoder,
auto params = gst_d3d12_allocation_params_new (self->device, &info,
GST_D3D12_ALLOCATION_FLAG_DEFAULT,
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS |
D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET);
D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_HEAP_FLAG_NONE);
gst_d3d12_allocation_params_alignment (params, &align);
gst_buffer_pool_config_set_d3d12_allocation_params (config, params);
gst_d3d12_allocation_params_free (params);

View file

@ -525,9 +525,7 @@ public:
auto params = gst_d3d12_allocation_params_new (device12_, &pool_info_,
GST_D3D12_ALLOCATION_FLAG_DEFAULT,
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS |
D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET);
gst_d3d12_allocation_params_set_heap_flags (params,
D3D12_HEAP_FLAG_SHARED);
D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_HEAP_FLAG_SHARED);
gst_buffer_pool_config_set_d3d12_allocation_params (config, params);
gst_d3d12_allocation_params_free (params);
if (!gst_buffer_pool_set_config (d3d12_pool_, config)) {

View file

@ -78,7 +78,7 @@ G_DEFINE_BOXED_TYPE_WITH_CODE (GstD3D12AllocationParams,
GstD3D12AllocationParams *
gst_d3d12_allocation_params_new (GstD3D12Device * device,
const GstVideoInfo * info, GstD3D12AllocationFlags flags,
D3D12_RESOURCE_FLAGS resource_flags)
D3D12_RESOURCE_FLAGS resource_flags, D3D12_HEAP_FLAGS heap_flags)
{
GstD3D12AllocationParams *ret;
GstD3D12Format d3d12_format;
@ -100,7 +100,7 @@ gst_d3d12_allocation_params_new (GstD3D12Device * device,
ret->d3d12_format = d3d12_format;
ret->array_size = 1;
ret->flags = flags;
ret->heap_flags = D3D12_HEAP_FLAG_NONE;
ret->heap_flags = heap_flags;
ret->resource_flags = resource_flags;
return ret;
@ -220,10 +220,14 @@ struct GstD3D12MemoryTokenData
struct _GstD3D12MemoryPrivate
{
_GstD3D12MemoryPrivate ()
{
event_handle = CreateEventEx (nullptr, nullptr, 0, EVENT_ALL_ACCESS);
}
~_GstD3D12MemoryPrivate ()
{
if (event_handle)
CloseHandle (event_handle);
CloseHandle (event_handle);
if (nt_handle)
CloseHandle (nt_handle);
@ -257,6 +261,12 @@ struct _GstD3D12MemoryPrivate
guint64 cpu_map_count = 0;
std::mutex lock;
gpointer user_data = nullptr;
GDestroyNotify notify = nullptr;
ComPtr<ID3D12Fence> external_fence;
UINT64 external_fence_val = 0;
};
/* *INDENT-ON* */
@ -297,19 +307,43 @@ gst_d3d12_memory_ensure_staging_resource (GstD3D12Memory * dmem)
return TRUE;
}
static void
gst_d3d12_memory_set_external_fence_unlocked (GstD3D12Memory * dmem,
ID3D12Fence * fence, guint64 fence_val)
{
auto priv = dmem->priv;
HRESULT hr;
if (priv->external_fence) {
auto completed = priv->external_fence->GetCompletedValue ();
if (completed < priv->external_fence_val) {
hr = priv->external_fence->SetEventOnCompletion (priv->external_fence_val,
priv->event_handle);
if (SUCCEEDED (hr))
WaitForSingleObjectEx (priv->event_handle, INFINITE, FALSE);
}
priv->external_fence = nullptr;
priv->external_fence_val;
}
if (fence) {
priv->external_fence = fence;
priv->external_fence_val = fence_val;
}
}
static void
gst_d3d12_memory_wait_gpu (GstD3D12Memory * dmem,
D3D12_COMMAND_LIST_TYPE command_type, guint64 fence_value)
{
auto priv = dmem->priv;
gst_d3d12_memory_set_external_fence_unlocked (dmem, nullptr, 0);
auto completed = gst_d3d12_device_get_completed_value (dmem->device,
command_type);
if (completed < fence_value) {
if (!priv->event_handle) {
priv->event_handle =
CreateEventEx (nullptr, nullptr, 0, EVENT_ALL_ACCESS);
}
gst_d3d12_device_fence_wait (dmem->device, command_type,
fence_value, priv->event_handle);
}
@ -399,6 +433,8 @@ gst_d3d12_memory_map_full (GstMemory * mem, GstMapInfo * info, gsize maxsize)
GstMapFlags flags = info->flags;
std::lock_guard < std::mutex > lk (priv->lock);
gst_d3d12_memory_set_external_fence_unlocked (dmem, nullptr, 0);
if ((flags & GST_MAP_D3D12) != 0) {
gst_d3d12_memory_upload (dmem);
@ -707,6 +743,16 @@ gst_d3d12_memory_get_token_data (GstD3D12Memory * mem, gint64 token)
return ret;
}
void
gst_d3d12_memory_set_external_fence (GstD3D12Memory * mem, ID3D12Fence * fence,
guint64 fence_val)
{
auto priv = mem->priv;
std::lock_guard < std::mutex > lk (priv->lock);
gst_d3d12_memory_set_external_fence_unlocked (mem, fence, fence_val);
}
/* GstD3D12Allocator */
#define gst_d3d12_allocator_parent_class alloc_parent_class
G_DEFINE_TYPE (GstD3D12Allocator, gst_d3d12_allocator, GST_TYPE_ALLOCATOR);
@ -760,6 +806,9 @@ gst_d3d12_allocator_free (GstAllocator * allocator, GstMemory * mem)
gst_d3d12_memory_wait_gpu (dmem, D3D12_COMMAND_LIST_TYPE_DIRECT,
dmem->fence_value);
if (dmem->priv->notify)
dmem->priv->notify (dmem->priv->user_data);
delete dmem->priv;
gst_clear_object (&dmem->device);
@ -769,7 +818,8 @@ gst_d3d12_allocator_free (GstAllocator * allocator, GstMemory * mem)
GstMemory *
gst_d3d12_allocator_alloc_wrapped (GstD3D12Allocator * allocator,
GstD3D12Device * device, ID3D12Resource * resource, guint array_slice)
GstD3D12Device * device, ID3D12Resource * resource, guint array_slice,
gpointer user_data, GDestroyNotify notify)
{
g_return_val_if_fail (GST_IS_D3D12_DEVICE (device), nullptr);
g_return_val_if_fail (resource, nullptr);
@ -809,6 +859,8 @@ gst_d3d12_allocator_alloc_wrapped (GstD3D12Allocator * allocator,
priv->rtv_inc_size =
device_handle->GetDescriptorHandleIncrementSize
(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
priv->user_data = user_data;
priv->notify = notify;
mem->device = (GstD3D12Device *) gst_object_ref (device);
@ -895,7 +947,8 @@ gst_d3d12_allocator_alloc_internal (GstD3D12Allocator * self,
}
auto mem =
gst_d3d12_allocator_alloc_wrapped (self, device, resource.Get (), 0);
gst_d3d12_allocator_alloc_wrapped (self, device, resource.Get (), 0,
nullptr, nullptr);
if (!mem)
return nullptr;
@ -1060,7 +1113,7 @@ gst_d3d12_pool_allocator_start (GstD3D12PoolAllocator * self)
GstMemory *mem;
mem = gst_d3d12_allocator_alloc_wrapped (_d3d12_memory_allocator,
self->device, priv->resource.Get (), i);
self->device, priv->resource.Get (), i, nullptr, nullptr);
priv->cur_mems++;
priv->queue.push (mem);

View file

@ -89,7 +89,8 @@ GType gst_d3d12_allocation_params_get_type (void);
GstD3D12AllocationParams * gst_d3d12_allocation_params_new (GstD3D12Device * device,
const GstVideoInfo * info,
GstD3D12AllocationFlags flags,
D3D12_RESOURCE_FLAGS resource_flags);
D3D12_RESOURCE_FLAGS resource_flags,
D3D12_HEAP_FLAGS heap_flags);
GstD3D12AllocationParams * gst_d3d12_allocation_params_copy (GstD3D12AllocationParams * src);
@ -160,6 +161,10 @@ void gst_d3d12_memory_set_token_data (GstD3D12Memory * mem,
gpointer gst_d3d12_memory_get_token_data (GstD3D12Memory * mem,
gint64 token);
void gst_d3d12_memory_set_external_fence (GstD3D12Memory * mem,
ID3D12Fence * fence,
guint64 fence_val);
struct _GstD3D12Allocator
{
GstAllocator allocator;
@ -194,7 +199,9 @@ GstMemory * gst_d3d12_allocator_alloc (GstD3D12Allocator * allocator,
GstMemory * gst_d3d12_allocator_alloc_wrapped (GstD3D12Allocator * allocator,
GstD3D12Device * device,
ID3D12Resource * resource,
guint array_slice);
guint array_slice,
gpointer user_data,
GDestroyNotify notify);
gboolean gst_d3d12_allocator_set_active (GstD3D12Allocator * allocator,
gboolean active);

View file

@ -766,7 +766,8 @@ gst_d3d12_screen_capture_src_decide_allocation (GstBaseSrc * bsrc,
auto params = gst_buffer_pool_config_get_d3d12_allocation_params (config);
if (!params) {
params = gst_d3d12_allocation_params_new (self->device, &vinfo,
GST_D3D12_ALLOCATION_FLAG_DEFAULT, resource_flags);
GST_D3D12_ALLOCATION_FLAG_DEFAULT, resource_flags,
D3D12_HEAP_FLAG_NONE);
} else {
gst_d3d12_allocation_params_set_resource_flags (params, resource_flags);
gst_d3d12_allocation_params_unset_resource_flags (params,
@ -803,7 +804,8 @@ gst_d3d12_screen_capture_src_decide_allocation (GstBaseSrc * bsrc,
D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
auto params = gst_d3d12_allocation_params_new (self->device, &vinfo,
GST_D3D12_ALLOCATION_FLAG_DEFAULT, resource_flags);
GST_D3D12_ALLOCATION_FLAG_DEFAULT, resource_flags,
D3D12_HEAP_FLAG_NONE);
gst_buffer_pool_config_set_d3d12_allocation_params (config, params);
gst_d3d12_allocation_params_free (params);

View file

@ -1587,7 +1587,7 @@ gst_d3d12_test_src_setup_context (GstD3D12TestSrc * self, GstCaps * caps)
}
auto mem = gst_d3d12_allocator_alloc_wrapped (nullptr, self->device,
ctx->texture.Get (), 0);
ctx->texture.Get (), 0, nullptr, nullptr);
if (!mem) {
GST_ERROR_OBJECT (self, "Couldn't wrap texture");
return FALSE;
@ -1610,7 +1610,7 @@ gst_d3d12_test_src_setup_context (GstD3D12TestSrc * self, GstCaps * caps)
auto params = gst_d3d12_allocation_params_new (self->device, &priv->info,
GST_D3D12_ALLOCATION_FLAG_DEFAULT,
D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET |
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS);
D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS, D3D12_HEAP_FLAG_NONE);
gst_buffer_pool_config_set_d3d12_allocation_params (config, params);
gst_d3d12_allocation_params_free (params);
@ -1801,7 +1801,8 @@ gst_d3d12_test_src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query)
auto params = gst_buffer_pool_config_get_d3d12_allocation_params (config);
if (!params) {
params = gst_d3d12_allocation_params_new (self->device, &vinfo,
GST_D3D12_ALLOCATION_FLAG_DEFAULT, resource_flags);
GST_D3D12_ALLOCATION_FLAG_DEFAULT, resource_flags,
D3D12_HEAP_FLAG_NONE);
} else {
gst_d3d12_allocation_params_set_resource_flags (params, resource_flags);
gst_d3d12_allocation_params_unset_resource_flags (params,

View file

@ -1106,7 +1106,7 @@ gst_d3d12_window_on_resize (GstD3D12Window * self)
priv->ctx->buffer_desc = backbuf->GetDesc ();
auto mem = gst_d3d12_allocator_alloc_wrapped (nullptr, self->device,
backbuf.Get (), 0);
backbuf.Get (), 0, nullptr, nullptr);
auto buf = gst_buffer_new ();
gst_buffer_append_memory (buf, mem);
priv->ctx->swap_buffers.push_back (std::make_shared < SwapBuffer > (buf));
@ -1168,7 +1168,7 @@ gst_d3d12_window_on_resize (GstD3D12Window * self)
}
auto mem = gst_d3d12_allocator_alloc_wrapped (nullptr, self->device,
msaa_texture.Get (), 0);
msaa_texture.Get (), 0, nullptr, nullptr);
priv->ctx->msaa_buf = gst_buffer_new ();
gst_buffer_append_memory (priv->ctx->msaa_buf, mem);
}