From 99209958b90b7341b510d7d700b1084b29eb7440 Mon Sep 17 00:00:00 2001 From: Austin Shafer Date: Thu, 26 Oct 2023 13:33:34 -0400 Subject: [PATCH] cogl: Store latest GPU work completed sync fd This keeps an internal sync_fd for the latest work submitted to the GPU. This can then be fetched with cogl_context_get_latest_sync_fd for use. This is intended for use with linux-drm-syncobj-v1 Part-of: --- cogl/cogl/cogl-context-private.h | 3 ++ cogl/cogl/cogl-context.c | 22 ++++++++++++ cogl/cogl/cogl-context.h | 14 ++++++++ cogl/cogl/winsys/cogl-onscreen-egl.c | 3 ++ .../cogl-winsys-egl-feature-functions.h | 9 +++++ cogl/cogl/winsys/cogl-winsys-egl-private.h | 4 +++ cogl/cogl/winsys/cogl-winsys-egl-x11.c | 1 + cogl/cogl/winsys/cogl-winsys-egl.c | 36 +++++++++++++++++++ cogl/cogl/winsys/cogl-winsys-private.h | 6 ++++ 9 files changed, 98 insertions(+) diff --git a/cogl/cogl/cogl-context-private.h b/cogl/cogl/cogl-context-private.h index 4c0bc4bea..cd5db0ee3 100644 --- a/cogl/cogl/cogl-context-private.h +++ b/cogl/cogl/cogl-context-private.h @@ -311,3 +311,6 @@ _cogl_context_set_current_projection_entry (CoglContext *context, void _cogl_context_set_current_modelview_entry (CoglContext *context, CoglMatrixEntry *entry); + +void +_cogl_context_update_sync (CoglContext *context); diff --git a/cogl/cogl/cogl-context.c b/cogl/cogl/cogl-context.c index be13933ec..492d49542 100644 --- a/cogl/cogl/cogl-context.c +++ b/cogl/cogl/cogl-context.c @@ -463,6 +463,28 @@ _cogl_context_set_current_modelview_entry (CoglContext *context, context->current_modelview_entry = entry; } +void +_cogl_context_update_sync (CoglContext *context) +{ + const CoglWinsysVtable *winsys = _cogl_context_get_winsys (context); + + if (!winsys->update_sync) + return; + + winsys->update_sync (context); +} + +int +cogl_context_get_latest_sync_fd (CoglContext *context) +{ + const CoglWinsysVtable *winsys = _cogl_context_get_winsys (context); + + if (!winsys->get_sync_fd) + return -1; + + return winsys->get_sync_fd (context); +} + CoglGraphicsResetStatus cogl_get_graphics_reset_status (CoglContext *context) { diff --git a/cogl/cogl/cogl-context.h b/cogl/cogl/cogl-context.h index 614a351fe..fba7bedf2 100644 --- a/cogl/cogl/cogl-context.h +++ b/cogl/cogl/cogl-context.h @@ -367,4 +367,18 @@ cogl_context_timestamp_query_get_time_ns (CoglContext *context, COGL_EXPORT int64_t cogl_context_get_gpu_time_ns (CoglContext *context); +/** + * cogl_context_get_latest_sync_fd + * @context: a #CoglContext pointer + * + * This function is used to get support for waiting on previous + * GPU work through sync fds. It will return a sync fd which will + * signal when the previous work has completed. + * + * Return value: sync fd for latest GPU submission if available, + * returns -1 if not. + */ +COGL_EXPORT int +cogl_context_get_latest_sync_fd (CoglContext *context); + G_END_DECLS diff --git a/cogl/cogl/winsys/cogl-onscreen-egl.c b/cogl/cogl/winsys/cogl-onscreen-egl.c index 6c5bf2654..2868fa982 100644 --- a/cogl/cogl/winsys/cogl-onscreen-egl.c +++ b/cogl/cogl/winsys/cogl-onscreen-egl.c @@ -309,6 +309,9 @@ cogl_onscreen_egl_swap_buffers_with_damage (CoglOnscreen *onscreen, COGL_FRAMEBUFFER (onscreen), COGL_FRAMEBUFFER_STATE_BIND); + /* Update our "latest" sync fd to contain all previous work */ + _cogl_context_update_sync (context); + if (cogl_has_feature (context, COGL_FEATURE_ID_TIMESTAMP_QUERY)) { info->gpu_time_before_buffer_swap_ns = diff --git a/cogl/cogl/winsys/cogl-winsys-egl-feature-functions.h b/cogl/cogl/winsys/cogl-winsys-egl-feature-functions.h index 4b74e2088..a0d03a3c4 100644 --- a/cogl/cogl/winsys/cogl-winsys-egl-feature-functions.h +++ b/cogl/cogl/winsys/cogl-winsys-egl-feature-functions.h @@ -162,6 +162,15 @@ COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglDestroySync, (EGLDisplay dpy, EGLSyncKHR sync)) COGL_WINSYS_FEATURE_END () + +COGL_WINSYS_FEATURE_BEGIN (native_fence_sync, + "ANDROID\0", + "native_fence_sync\0", + COGL_EGL_WINSYS_FEATURE_NATIVE_FENCE_SYNC) +COGL_WINSYS_FEATURE_FUNCTION (EGLint, eglDupNativeFenceFD, + (EGLDisplay dpy, + EGLSyncKHR sync)) +COGL_WINSYS_FEATURE_END () #endif COGL_WINSYS_FEATURE_BEGIN (surfaceless_context, diff --git a/cogl/cogl/winsys/cogl-winsys-egl-private.h b/cogl/cogl/winsys/cogl-winsys-egl-private.h index 9b0b168b4..6a31d1ab2 100644 --- a/cogl/cogl/winsys/cogl-winsys-egl-private.h +++ b/cogl/cogl/winsys/cogl-winsys-egl-private.h @@ -101,6 +101,7 @@ typedef enum _CoglEGLWinsysFeature COGL_EGL_WINSYS_FEATURE_SURFACELESS_CONTEXT = 1L << 6, COGL_EGL_WINSYS_FEATURE_CONTEXT_PRIORITY = 1L << 7, COGL_EGL_WINSYS_FEATURE_NO_CONFIG_CONTEXT = 1L << 8, + COGL_EGL_WINSYS_FEATURE_NATIVE_FENCE_SYNC = 1L << 9, } CoglEGLWinsysFeature; typedef struct _CoglRendererEGL @@ -119,6 +120,9 @@ typedef struct _CoglRendererEGL /* vtable for platform specific parts */ const CoglWinsysEGLVtable *platform_vtable; + /* Sync for latest submitted work */ + EGLSyncKHR sync; + /* Function pointers for EGL specific extensions */ #define COGL_WINSYS_FEATURE_BEGIN(a, b, c, d) diff --git a/cogl/cogl/winsys/cogl-winsys-egl-x11.c b/cogl/cogl/winsys/cogl-winsys-egl-x11.c index 5472ba9d9..7a52129c2 100644 --- a/cogl/cogl/winsys/cogl-winsys-egl-x11.c +++ b/cogl/cogl/winsys/cogl-winsys-egl-x11.c @@ -243,6 +243,7 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer, xlib_renderer = _cogl_xlib_renderer_get_data (renderer); egl_renderer->platform_vtable = &_cogl_winsys_egl_vtable; + egl_renderer->sync = EGL_NO_SYNC_KHR; if (!_cogl_xlib_renderer_connect (renderer, error)) goto error; diff --git a/cogl/cogl/winsys/cogl-winsys-egl.c b/cogl/cogl/winsys/cogl-winsys-egl.c index ee7c1df54..66b9940c0 100644 --- a/cogl/cogl/winsys/cogl-winsys-egl.c +++ b/cogl/cogl/winsys/cogl-winsys-egl.c @@ -441,6 +441,9 @@ _cogl_winsys_display_destroy (CoglDisplay *display) g_return_if_fail (egl_display != NULL); + if (egl_renderer->sync != EGL_NO_SYNC_KHR) + egl_renderer->pf_eglDestroySync (egl_renderer->edpy, egl_renderer->sync); + cleanup_context (display); if (egl_renderer->platform_vtable->display_destroy) @@ -573,6 +576,37 @@ _cogl_winsys_fence_destroy (CoglContext *context, void *fence) renderer->pf_eglDestroySync (renderer->edpy, fence); } + +static int +_cogl_winsys_get_sync_fd (CoglContext *context) +{ + CoglRendererEGL *renderer = context->display->renderer->winsys; + int fd; + + if (!renderer->pf_eglDupNativeFenceFD) + return -1; + + fd = renderer->pf_eglDupNativeFenceFD (renderer->edpy, renderer->sync); + if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) + return -1; + + return fd; +} + +static void +_cogl_winsys_update_sync (CoglContext *context) +{ + CoglRendererEGL *renderer = context->display->renderer->winsys; + + if (!renderer->pf_eglDestroySync || !renderer->pf_eglCreateSync) + return; + + if (renderer->sync != EGL_NO_SYNC_KHR) + renderer->pf_eglDestroySync (renderer->edpy, renderer->sync); + + renderer->sync = renderer->pf_eglCreateSync (renderer->edpy, + EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); +} #endif static CoglWinsysVtable _cogl_winsys_vtable = @@ -595,6 +629,8 @@ static CoglWinsysVtable _cogl_winsys_vtable = .fence_add = _cogl_winsys_fence_add, .fence_is_complete = _cogl_winsys_fence_is_complete, .fence_destroy = _cogl_winsys_fence_destroy, + .get_sync_fd = _cogl_winsys_get_sync_fd, + .update_sync = _cogl_winsys_update_sync, #endif }; diff --git a/cogl/cogl/winsys/cogl-winsys-private.h b/cogl/cogl/winsys/cogl-winsys-private.h index 7dfbd13ed..d627617d6 100644 --- a/cogl/cogl/winsys/cogl-winsys-private.h +++ b/cogl/cogl/winsys/cogl-winsys-private.h @@ -141,6 +141,12 @@ typedef struct _CoglWinsysVtable (*fence_destroy) (CoglContext *ctx, void *fence); + void + (*update_sync) (CoglContext *ctx); + + int + (*get_sync_fd) (CoglContext *ctx); + } CoglWinsysVtable; typedef const CoglWinsysVtable *(*CoglWinsysVtableGetter) (void);