mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
cudautils: Add GstCudaGraphicsResource structure for better openGL interoperability
Introduce GstCudaGraphicsResource structure to represent registered CUDA graphics resources and to enable sharing the information among nvdec and nvenc. This structure can reduce the number of resource registration which cause high overhead.
This commit is contained in:
parent
8dc2b4a393
commit
da075b94a9
5 changed files with 324 additions and 2 deletions
|
@ -82,6 +82,8 @@ typedef struct _GstNvCodecCudaVTable
|
|||
unsigned int image, unsigned int target, unsigned int Flags);
|
||||
CUresult (*CuGraphicsGLRegisterBuffer) (CUgraphicsResource * pCudaResource,
|
||||
unsigned int buffer, unsigned int Flags);
|
||||
CUresult (*CuGraphicsResourceSetMapFlags) (CUgraphicsResource resource,
|
||||
unsigned int flags);
|
||||
} GstNvCodecCudaVTable;
|
||||
|
||||
static GstNvCodecCudaVTable gst_cuda_vtable = { 0, };
|
||||
|
@ -139,6 +141,7 @@ gst_cuda_load_library (void)
|
|||
/* cudaGL.h */
|
||||
LOAD_SYMBOL (cuGraphicsGLRegisterImage, CuGraphicsGLRegisterImage);
|
||||
LOAD_SYMBOL (cuGraphicsGLRegisterBuffer, CuGraphicsGLRegisterBuffer);
|
||||
LOAD_SYMBOL (cuGraphicsResourceSetMapFlags, CuGraphicsResourceSetMapFlags);
|
||||
|
||||
vtable->loaded = TRUE;
|
||||
|
||||
|
@ -370,3 +373,11 @@ CuGraphicsGLRegisterBuffer (CUgraphicsResource * pCudaResource,
|
|||
return gst_cuda_vtable.CuGraphicsGLRegisterBuffer (pCudaResource, buffer,
|
||||
Flags);
|
||||
}
|
||||
|
||||
CUresult
|
||||
CuGraphicsResourceSetMapFlags (CUgraphicsResource resource, unsigned int flags)
|
||||
{
|
||||
g_assert (gst_cuda_vtable.CuGraphicsResourceSetMapFlags != NULL);
|
||||
|
||||
return gst_cuda_vtable.CuGraphicsResourceSetMapFlags (resource, flags);
|
||||
}
|
||||
|
|
|
@ -137,5 +137,9 @@ CUresult CuGraphicsGLRegisterBuffer (CUgraphicsResource * pCudaResource,
|
|||
unsigned int buffer,
|
||||
unsigned int Flags);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
CUresult CuGraphicsResourceSetMapFlags (CUgraphicsResource resource,
|
||||
unsigned int flags);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* __GST_CUDA_LOADER_H__ */
|
||||
|
|
|
@ -24,6 +24,11 @@
|
|||
#include "gstcudautils.h"
|
||||
#include "gstcudacontext.h"
|
||||
|
||||
#ifdef HAVE_NVCODEC_GST_GL
|
||||
#include <gst/gl/gl.h>
|
||||
#include <gst/gl/gstglfuncs.h>
|
||||
#endif
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_cuda_utils_debug);
|
||||
#define GST_CAT_DEFAULT gst_cuda_utils_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_CONTEXT);
|
||||
|
@ -340,3 +345,241 @@ gst_context_new_cuda_context (GstCudaContext * cuda_ctx)
|
|||
|
||||
return context;
|
||||
}
|
||||
|
||||
static const gchar *gst_cuda_quark_strings[] =
|
||||
{ "GstCudaQuarkGraphicsResource" };
|
||||
|
||||
static GQuark gst_cuda_quark_table[GST_CUDA_QUARK_MAX];
|
||||
|
||||
static void
|
||||
init_cuda_quark_once (void)
|
||||
{
|
||||
static volatile gsize once_init = 0;
|
||||
|
||||
if (g_once_init_enter (&once_init)) {
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < GST_CUDA_QUARK_MAX; i++) {
|
||||
gst_cuda_quark_table[i] =
|
||||
g_quark_from_static_string (gst_cuda_quark_strings[i]);
|
||||
|
||||
g_once_init_leave (&once_init, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_cuda_quark_from_id: (skip)
|
||||
* @id: a #GstCudaQuarkId
|
||||
*
|
||||
* Returns: the GQuark for given @id or 0 if @id is unknown value
|
||||
*/
|
||||
GQuark
|
||||
gst_cuda_quark_from_id (GstCudaQuarkId id)
|
||||
{
|
||||
g_return_val_if_fail (id < GST_CUDA_QUARK_MAX, 0);
|
||||
|
||||
init_cuda_quark_once ();
|
||||
_init_debug ();
|
||||
|
||||
return gst_cuda_quark_table[id];
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_cuda_graphics_resource_new: (skip)
|
||||
* @context: (transfer none): a #GstCudaContext
|
||||
* @graphics_context: (transfer none) (nullable): a grapics API specific context object
|
||||
* @type: a #GstCudaGraphicsResourceType of resource registration
|
||||
*
|
||||
* Create new #GstCudaGraphicsResource with given @context and @type
|
||||
*
|
||||
* Returns: a new #GstCudaGraphicsResource.
|
||||
* Free with gst_cuda_graphics_resource_free
|
||||
*/
|
||||
GstCudaGraphicsResource *
|
||||
gst_cuda_graphics_resource_new (GstCudaContext *
|
||||
context, GstObject * graphics_context, GstCudaGraphicsResourceType type)
|
||||
{
|
||||
GstCudaGraphicsResource *resource;
|
||||
|
||||
g_return_val_if_fail (GST_IS_CUDA_CONTEXT (context), NULL);
|
||||
|
||||
_init_debug ();
|
||||
|
||||
resource = g_new0 (GstCudaGraphicsResource, 1);
|
||||
resource->cuda_context = gst_object_ref (context);
|
||||
if (graphics_context)
|
||||
resource->graphics_context = gst_object_ref (graphics_context);
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_cuda_graphics_resource_register_gl_buffer: (skip)
|
||||
* @resource a #GstCudaGraphicsResource
|
||||
* @buffer: a GL buffer object
|
||||
* @flags: a #CUgraphicsRegisterFlags
|
||||
*
|
||||
* Register the @buffer for access by CUDA.
|
||||
* Must be called from the gl context thread with current cuda context was
|
||||
* pushed on the current thread
|
||||
*
|
||||
* Returns: whether @buffer was registered or not
|
||||
*/
|
||||
gboolean
|
||||
gst_cuda_graphics_resource_register_gl_buffer (GstCudaGraphicsResource *
|
||||
resource, guint buffer, CUgraphicsRegisterFlags flags)
|
||||
{
|
||||
CUresult cuda_ret;
|
||||
|
||||
g_return_val_if_fail (resource != NULL, FALSE);
|
||||
g_return_val_if_fail (resource->registered == FALSE, FALSE);
|
||||
|
||||
_init_debug ();
|
||||
|
||||
cuda_ret = CuGraphicsGLRegisterBuffer (&resource->resource, buffer, flags);
|
||||
|
||||
if (!gst_cuda_result (cuda_ret))
|
||||
return FALSE;
|
||||
|
||||
resource->registered = TRUE;
|
||||
resource->type = GST_CUDA_GRAPHICS_RESOURCE_GL_BUFFER;
|
||||
resource->flags = flags;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_cuda_graphics_resource_unregister: (skip)
|
||||
* @resource: a #GstCudaGraphicsResource
|
||||
*
|
||||
* Unregister previously registered resource.
|
||||
* For GL resource, this method must be called from gl context thread.
|
||||
* Also, current cuda context should be pushed on the current thread
|
||||
* before calling this method.
|
||||
*/
|
||||
void
|
||||
gst_cuda_graphics_resource_unregister (GstCudaGraphicsResource * resource)
|
||||
{
|
||||
g_return_if_fail (resource != NULL);
|
||||
|
||||
_init_debug ();
|
||||
|
||||
if (!resource->registered)
|
||||
return;
|
||||
|
||||
gst_cuda_result (CuGraphicsUnregisterResource (resource->resource));
|
||||
resource->resource = NULL;
|
||||
resource->registered = FALSE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_cuda_graphics_resource_map: (skip)
|
||||
* @resource: a #GstCudaGraphicsResource
|
||||
* @stream: a #CUstream
|
||||
* @flags: a #CUgraphicsMapResourceFlags
|
||||
*
|
||||
* Map previously registered resource with map flags
|
||||
*
|
||||
* Returns: the #CUgraphicsResource if successful or %NULL when failed
|
||||
*/
|
||||
CUgraphicsResource
|
||||
gst_cuda_graphics_resource_map (GstCudaGraphicsResource * resource,
|
||||
CUstream stream, CUgraphicsMapResourceFlags flags)
|
||||
{
|
||||
CUresult cuda_ret;
|
||||
|
||||
g_return_val_if_fail (resource != NULL, NULL);
|
||||
g_return_val_if_fail (resource->registered != FALSE, NULL);
|
||||
|
||||
_init_debug ();
|
||||
|
||||
cuda_ret = CuGraphicsResourceSetMapFlags (resource->resource, flags);
|
||||
if (!gst_cuda_result (cuda_ret))
|
||||
return NULL;
|
||||
|
||||
cuda_ret = CuGraphicsMapResources (1, &resource->resource, stream);
|
||||
if (!gst_cuda_result (cuda_ret))
|
||||
return NULL;
|
||||
|
||||
resource->mapped = TRUE;
|
||||
|
||||
return resource->resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_cuda_graphics_resource_unmap: (skip)
|
||||
* @resource: a #GstCudaGraphicsResource
|
||||
* @stream: a #CUstream
|
||||
*
|
||||
* Unmap previously mapped resource
|
||||
*/
|
||||
void
|
||||
gst_cuda_graphics_resource_unmap (GstCudaGraphicsResource * resource,
|
||||
CUstream stream)
|
||||
{
|
||||
g_return_if_fail (resource != NULL);
|
||||
g_return_if_fail (resource->registered != FALSE);
|
||||
|
||||
_init_debug ();
|
||||
|
||||
if (!resource->mapped)
|
||||
return;
|
||||
|
||||
gst_cuda_result (CuGraphicsUnmapResources (1, &resource->resource, stream));
|
||||
|
||||
resource->mapped = FALSE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_NVCODEC_GST_GL
|
||||
static void
|
||||
unregister_resource_from_gl_thread (GstGLContext * gl_context,
|
||||
GstCudaGraphicsResource * resource)
|
||||
{
|
||||
GstCudaContext *cuda_context = resource->cuda_context;
|
||||
|
||||
if (!gst_cuda_context_push (cuda_context)) {
|
||||
GST_WARNING_OBJECT (cuda_context, "failed to push CUDA context");
|
||||
return;
|
||||
}
|
||||
|
||||
gst_cuda_graphics_resource_unregister (resource);
|
||||
|
||||
if (!gst_cuda_context_pop (NULL)) {
|
||||
GST_WARNING_OBJECT (cuda_context, "failed to pop CUDA context");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* gst_cuda_graphics_resource_free: (skip)
|
||||
* @resource: a #GstCudaGraphicsResource
|
||||
*
|
||||
* Free @resource
|
||||
*/
|
||||
void
|
||||
gst_cuda_graphics_resource_free (GstCudaGraphicsResource * resource)
|
||||
{
|
||||
g_return_if_fail (resource != NULL);
|
||||
|
||||
if (resource->registered) {
|
||||
#ifdef HAVE_NVCODEC_GST_GL
|
||||
if (resource->type == GST_CUDA_GRAPHICS_RESOURCE_GL_BUFFER) {
|
||||
gst_gl_context_thread_add ((GstGLContext *) resource->graphics_context,
|
||||
(GstGLContextThreadFunc) unregister_resource_from_gl_thread,
|
||||
resource);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/* FIXME: currently opengl only */
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
gst_object_unref (resource->cuda_context);
|
||||
if (resource->graphics_context)
|
||||
gst_object_unref (resource->graphics_context);
|
||||
g_free (resource);
|
||||
}
|
||||
|
|
|
@ -71,6 +71,34 @@ _gst_cuda_debug(CUresult result, GstDebugCategory * category,
|
|||
_gst_cuda_debug(result, NULL, __FILE__, GST_FUNCTION, __LINE__)
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GST_CUDA_QUARK_GRAPHICS_RESOURCE = 0,
|
||||
|
||||
/* end of quark list */
|
||||
GST_CUDA_QUARK_MAX = 1
|
||||
} GstCudaQuarkId;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GST_CUDA_GRAPHICS_RESOURCE_NONE = 0,
|
||||
GST_CUDA_GRAPHICS_RESOURCE_GL_BUFFER = 1,
|
||||
} GstCudaGraphicsResourceType;
|
||||
|
||||
typedef struct _GstCudaGraphicsResource
|
||||
{
|
||||
GstCudaContext *cuda_context;
|
||||
/* GL context (or d3d11 context in the future) */
|
||||
GstObject *graphics_context;
|
||||
|
||||
GstCudaGraphicsResourceType type;
|
||||
CUgraphicsResource resource;
|
||||
CUgraphicsRegisterFlags flags;
|
||||
|
||||
gboolean registered;
|
||||
gboolean mapped;
|
||||
} GstCudaGraphicsResource;
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
gboolean gst_cuda_ensure_element_context (GstElement * element,
|
||||
gint device_id,
|
||||
|
@ -90,6 +118,33 @@ gboolean gst_cuda_handle_context_query (GstElement * element,
|
|||
G_GNUC_INTERNAL
|
||||
GstContext * gst_context_new_cuda_context (GstCudaContext * context);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
GQuark gst_cuda_quark_from_id (GstCudaQuarkId id);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
GstCudaGraphicsResource * gst_cuda_graphics_resource_new (GstCudaContext * context,
|
||||
GstObject * graphics_context,
|
||||
GstCudaGraphicsResourceType type);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
gboolean gst_cuda_graphics_resource_register_gl_buffer (GstCudaGraphicsResource * resource,
|
||||
guint buffer,
|
||||
CUgraphicsRegisterFlags flags);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void gst_cuda_graphics_resource_unregister (GstCudaGraphicsResource * resource);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
CUgraphicsResource gst_cuda_graphics_resource_map (GstCudaGraphicsResource * resource,
|
||||
CUstream stream,
|
||||
CUgraphicsMapResourceFlags flags);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void gst_cuda_graphics_resource_unmap (GstCudaGraphicsResource * resource,
|
||||
CUstream stream);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void gst_cuda_graphics_resource_free (GstCudaGraphicsResource * resource);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
@ -52,10 +52,18 @@ typedef enum
|
|||
|
||||
typedef enum
|
||||
{
|
||||
CU_GRAPHICS_REGISTER_FLAGS_READ_ONLY = 1,
|
||||
CU_GRAPHICS_REGISTER_FLAGS_WRITE_DISCARD = 2
|
||||
CU_GRAPHICS_REGISTER_FLAGS_NONE = 0x00,
|
||||
CU_GRAPHICS_REGISTER_FLAGS_READ_ONLY = 0x01,
|
||||
CU_GRAPHICS_REGISTER_FLAGS_WRITE_DISCARD = 0x02,
|
||||
} CUgraphicsRegisterFlags;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE = 0x00,
|
||||
CU_GRAPHICS_MAP_RESOURCE_FLAGS_READ_ONLY = 0x01,
|
||||
CU_GRAPHICS_MAP_RESOURCE_FLAGS_WRITE_DISCARD = 0x02,
|
||||
} CUgraphicsMapResourceFlags;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CU_STREAM_DEFAULT = 0x0,
|
||||
|
@ -92,6 +100,7 @@ typedef struct
|
|||
#define cuCtxPopCurrent cuCtxPopCurrent_v2
|
||||
#define cuCtxPushCurrent cuCtxPushCurrent_v2
|
||||
#define cuGraphicsResourceGetMappedPointer cuGraphicsResourceGetMappedPointer_v2
|
||||
#define cuGraphicsResourceSetMapFlags cuGraphicsResourceSetMapFlags_v2
|
||||
|
||||
#define cuMemAlloc cuMemAlloc_v2
|
||||
#define cuMemAllocPitch cuMemAllocPitch_v2
|
||||
|
|
Loading…
Reference in a new issue