hip: Add GstHipGraphicsResource object

hipGraphicsResource_t wrapper object for graphics api interop

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8923>
This commit is contained in:
Seungha Yang 2025-06-03 19:51:47 +09:00
parent 04fb36b2f9
commit baa9bc9d95
6 changed files with 388 additions and 0 deletions

View File

@ -0,0 +1,34 @@
/* GStreamer
* Copyright (C) 2025 Seungha Yang <seungha@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#pragma once
#include <gst/gst.h>
#include "gsthip-interop.h"
#include <gst/gl/gl.h>
G_BEGIN_DECLS
hipError_t
gst_hip_get_graphics_resource_from_gl_memory (GstHipDevice * device,
GstMemory * mem,
GstHipGraphicsResource ** resource);
G_END_DECLS

View File

@ -0,0 +1,303 @@
/* GStreamer
* Copyright (C) 2025 Seungha Yang <seungha@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "gsthip-config.h"
#include "gsthip.h"
#include <mutex>
#include <condition_variable>
#ifdef HAVE_GST_GL
#include "gsthip-interop-gl.h"
#include "gsthiploader-gl.h"
#endif
#ifndef GST_DISABLE_GST_DEBUG
#define GST_CAT_DEFAULT ensure_debug_category()
static GstDebugCategory *
ensure_debug_category (void)
{
static GstDebugCategory *cat = nullptr;
static std::once_flag once;
std::call_once (once,[&] {
cat = _gst_debug_category_new ("hip-interop", 0, "hip-interop");
});
return cat;
}
#endif
#ifdef HAVE_GST_GL
static void
unregister_resource_on_gl_thread (GstGLContext * gl_context,
GstHipGraphicsResource * resource);
#endif
/* *INDENT-OFF* */
struct _GstHipGraphicsResource : public GstMiniObject
{
_GstHipGraphicsResource ()
{
}
~_GstHipGraphicsResource ()
{
#ifdef HAVE_GST_GL
if (gl_context) {
gst_gl_context_thread_add (gl_context,
(GstGLContextThreadFunc) unregister_resource_on_gl_thread,
this);
gst_object_unref (gl_context);
} else
#else
if (gst_hip_device_set_current (device))
HipGraphicsUnregisterResource (vendor, handle);
#endif
gst_object_unref (device);
}
GstHipDevice *device = nullptr;
GstHipVendor vendor = GST_HIP_VENDOR_UNKNOWN;
hipGraphicsResource_t handle = nullptr;
std::mutex lock;
std::condition_variable cond;
guint64 map_count = 0;
void *mapped_dev_ptr = nullptr;
size_t mapped_size = 0;
hipStream_t mapped_stream = nullptr;
#ifdef HAVE_GST_GL
GstGLContext *gl_context = nullptr;
#endif
};
/* *INDENT-ON* */
#ifdef HAVE_GST_GL
static void
unregister_resource_on_gl_thread (GstGLContext * gl_context,
GstHipGraphicsResource * resource)
{
if (gst_hip_device_set_current (resource->device))
HipGraphicsUnregisterResource (resource->vendor, resource->handle);
}
#endif
GST_DEFINE_MINI_OBJECT_TYPE (GstHipGraphicsResource, gst_hip_graphics_resource);
hipError_t
gst_hip_graphics_resource_map (GstHipGraphicsResource * resource,
hipStream_t stream)
{
g_return_val_if_fail (resource, hipErrorInvalidValue);
std::unique_lock < std::mutex > lk (resource->lock);
if (resource->map_count > 0) {
if (stream == resource->mapped_stream) {
resource->map_count++;
return hipSuccess;
}
while (resource->map_count > 0)
resource->cond.wait (lk);
}
auto ret = HipGraphicsMapResources (resource->vendor, 1, &resource->handle,
stream);
if (!gst_hip_result (ret, resource->vendor))
return ret;
resource->map_count++;
resource->mapped_stream = stream;
return hipSuccess;
}
hipError_t
gst_hip_graphics_resource_unmap (GstHipGraphicsResource * resource,
hipStream_t stream)
{
g_return_val_if_fail (resource, hipErrorInvalidValue);
std::lock_guard < std::mutex > lk (resource->lock);
if (resource->map_count == 0) {
GST_WARNING ("resource %p is not mapped", resource);
return hipErrorNotMapped;
}
resource->map_count--;
if (resource->map_count > 0)
return hipSuccess;
auto ret = HipGraphicsUnmapResources (resource->vendor, 1, &resource->handle,
stream);
resource->mapped_stream = nullptr;
resource->mapped_dev_ptr = nullptr;
resource->mapped_size = 0;
resource->cond.notify_all ();
return ret;
}
hipError_t
gst_hip_graphics_resource_get_mapped_pointer (GstHipGraphicsResource * resource,
void **dev_ptr, size_t *size)
{
g_return_val_if_fail (resource, hipErrorInvalidValue);
std::lock_guard < std::mutex > lk (resource->lock);
if (resource->map_count == 0) {
GST_WARNING ("resource %p is not mapped", resource);
return hipErrorNotMapped;
}
if (!resource->mapped_dev_ptr) {
auto ret = HipGraphicsResourceGetMappedPointer (resource->vendor,
&resource->mapped_dev_ptr, &resource->mapped_size, resource->handle);
if (!gst_hip_result (ret, resource->vendor))
return ret;
}
if (dev_ptr)
*dev_ptr = resource->mapped_dev_ptr;
if (size)
*size = resource->mapped_size;
return hipSuccess;
}
GstHipGraphicsResource *
gst_hip_graphics_resource_ref (GstHipGraphicsResource * resource)
{
return (GstHipGraphicsResource *) gst_mini_object_ref (resource);
}
void
gst_hip_graphics_resource_unref (GstHipGraphicsResource * resource)
{
gst_mini_object_unref (resource);
}
void
gst_clear_hip_graphics_resource (GstHipGraphicsResource ** resource)
{
gst_clear_mini_object (resource);
}
#ifdef HAVE_GST_GL
static void
gst_hip_graphics_resource_free (GstHipGraphicsResource * resource)
{
delete resource;
}
struct GetResourceData
{
GstHipGraphicsResource *resource = nullptr;
hipError_t ret = hipSuccess;
GstMemory *gl_mem;
GstHipDevice *device;
};
static void
get_resource_on_gl_thread (GstGLContext * gl_context, GetResourceData * data)
{
static GQuark gl_quark = 0;
static std::once_flag once;
std::call_once (once,[&] {
gl_quark = g_quark_from_static_string ("GstHipGraphicsResourceGL");
});
auto resource = (GstHipGraphicsResource *)
gst_mini_object_get_qdata ((GstMiniObject *) data->gl_mem, gl_quark);
if (resource) {
data->resource = gst_hip_graphics_resource_ref (resource);
data->ret = hipSuccess;
return;
}
auto vendor = gst_hip_device_get_vendor (data->device);
auto ret = HipSetDevice (vendor, gst_hip_device_get_device_id (data->device));
if (!gst_hip_result (ret, vendor)) {
data->ret = ret;
return;
}
auto pbo = (GstGLMemoryPBO *) data->gl_mem;
hipGraphicsResource *handle;
ret = HipGraphicsGLRegisterBuffer (vendor,
&handle, pbo->pbo->id, hipGraphicsRegisterFlagsNone);
if (!gst_hip_result (ret, vendor)) {
data->ret = ret;
return;
}
auto new_resource = new GstHipGraphicsResource ();
new_resource->device = (GstHipDevice *) gst_object_ref (data->device);
new_resource->gl_context = (GstGLContext *) gst_object_ref (gl_context);
new_resource->vendor = vendor;
new_resource->handle = handle;
gst_mini_object_init (new_resource, 0, gst_hip_graphics_resource_get_type (),
nullptr, nullptr,
(GstMiniObjectFreeFunction) gst_hip_graphics_resource_free);
gst_mini_object_set_qdata ((GstMiniObject *) data->gl_mem, gl_quark,
gst_hip_graphics_resource_ref (new_resource),
(GDestroyNotify) gst_mini_object_unref);
data->resource = new_resource;
data->ret = hipSuccess;
}
hipError_t
gst_hip_get_graphics_resource_from_gl_memory (GstHipDevice * device,
GstMemory * mem, GstHipGraphicsResource ** resource)
{
g_return_val_if_fail (GST_IS_HIP_DEVICE (device), hipErrorInvalidValue);
g_return_val_if_fail (gst_is_gl_memory_pbo (mem), hipErrorInvalidValue);
g_return_val_if_fail (resource, hipErrorInvalidValue);
GetResourceData data;
data.device = device;
data.gl_mem = mem;
gst_gl_context_thread_add (GST_GL_BASE_MEMORY_CAST (mem)->context,
(GstGLContextThreadFunc) get_resource_on_gl_thread, &data);
if (data.ret != hipSuccess)
return data.ret;
*resource = data.resource;
return hipSuccess;
}
#endif

View File

@ -0,0 +1,47 @@
/* GStreamer
* Copyright (C) 2025 Seungha Yang <seungha@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#pragma once
#include <gst/gst.h>
#include "gsthip_fwd.h"
#include <hip/hip_runtime.h>
G_BEGIN_DECLS
GType gst_hip_graphics_resource_get_type (void);
hipError_t gst_hip_graphics_resource_map (GstHipGraphicsResource * resource,
hipStream_t stream);
hipError_t gst_hip_graphics_resource_unmap (GstHipGraphicsResource * resource,
hipStream_t stream);
hipError_t gst_hip_graphics_resource_get_mapped_pointer (GstHipGraphicsResource * resource,
void ** dev_ptr,
size_t * size);
GstHipGraphicsResource * gst_hip_graphics_resource_ref (GstHipGraphicsResource * resource);
void gst_hip_graphics_resource_unref (GstHipGraphicsResource * resource);
void gst_clear_hip_graphics_resource (GstHipGraphicsResource ** resource);
G_END_DECLS

View File

@ -29,4 +29,5 @@
#include "gsthipbufferpool.h"
#include "gsthiputils.h"
#include "gsthiploader.h"
#include "gsthip-interop.h"

View File

@ -42,5 +42,7 @@ typedef struct _GstHipBufferPool GstHipBufferPool;
typedef struct _GstHipBufferPoolClass GstHipBufferPoolClass;
typedef struct _GstHipBufferPoolPrivate GstHipBufferPoolPrivate;
typedef struct _GstHipGraphicsResource GstHipGraphicsResource;
G_END_DECLS

View File

@ -10,6 +10,7 @@ hip_sources = [
'gsthipmemorycopy.cpp',
'gsthiprtc.cpp',
'gsthiputils.cpp',
'gsthip-interop.cpp',
'plugin.cpp',
]