frontends/va: Destroy fences when destroying surface or context
authorDavid Rosca <nowrep@gmail.com>
Tue, 19 Sep 2023 08:53:21 +0000 (10:53 +0200)
committerMarge Bot <emma+marge@anholt.net>
Thu, 21 Sep 2023 13:30:28 +0000 (13:30 +0000)
It is valid to destroy VASurface after destroying VAContext, so we need
to destroy fences of all surfaces that are currently being tracked by a
context when deleting this context.

Reviewed-by: Sil Vilerino <sivileri@microsoft.com>
Reviewed-by: Leo Liu <leo.liu@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25296>

src/gallium/frontends/va/context.c
src/gallium/frontends/va/picture.c
src/gallium/frontends/va/surface.c
src/gallium/include/pipe/p_video_codec.h

index adb3270..b206d2a 100644 (file)
@@ -400,6 +400,10 @@ vlVaDestroyContext(VADriverContextP ctx, VAContextID context_id)
       vlVaSurface *surf = (vlVaSurface *)entry->key;
       assert(surf->ctx == context);
       surf->ctx = NULL;
+      if (surf->fence && context->decoder && context->decoder->destroy_fence) {
+         context->decoder->destroy_fence(context->decoder, surf->fence);
+         surf->fence = NULL;
+      }
    }
    _mesa_set_destroy(context->surfaces, NULL);
 
index 952560b..4fc6eeb 100644 (file)
@@ -39,7 +39,7 @@
 #include "va_private.h"
 
 static void
-vlVaSetSurfaceContext(vlVaSurface *surf, vlVaContext *context)
+vlVaSetSurfaceContext(vlVaDriver *drv, vlVaSurface *surf, vlVaContext *context)
 {
    if (surf->ctx == context)
       return;
@@ -47,6 +47,23 @@ vlVaSetSurfaceContext(vlVaSurface *surf, vlVaContext *context)
    if (surf->ctx) {
       assert(_mesa_set_search(surf->ctx->surfaces, surf));
       _mesa_set_remove_key(surf->ctx->surfaces, surf);
+
+      /* Only drivers supporting PIPE_VIDEO_ENTRYPOINT_PROCESSING will create
+       * decoder for postproc context and thus be able to wait on and destroy
+       * the surface fence. On other drivers we need to destroy the fence here
+       * otherwise vaQuerySurfaceStatus/vaSyncSurface will fail and we'll also
+       * potentially leak the fence.
+       */
+      if (surf->fence && !context->decoder &&
+          context->templat.entrypoint == PIPE_VIDEO_ENTRYPOINT_PROCESSING &&
+          surf->ctx->decoder && surf->ctx->decoder->destroy_fence &&
+          !drv->pipe->screen->get_video_param(drv->pipe->screen,
+                                              PIPE_VIDEO_PROFILE_UNKNOWN,
+                                              PIPE_VIDEO_ENTRYPOINT_PROCESSING,
+                                              PIPE_VIDEO_CAP_SUPPORTED)) {
+         surf->ctx->decoder->destroy_fence(surf->ctx->decoder, surf->fence);
+         surf->fence = NULL;
+      }
    }
 
    surf->ctx = context;
@@ -85,7 +102,7 @@ vlVaBeginPicture(VADriverContextP ctx, VAContextID context_id, VASurfaceID rende
       return VA_STATUS_ERROR_INVALID_SURFACE;
 
    context->target_id = render_target;
-   vlVaSetSurfaceContext(surf, context);
+   vlVaSetSurfaceContext(drv, surf, context);
    context->target = surf->buffer;
    context->mjpeg.sampling_factor = 0;
 
@@ -993,7 +1010,7 @@ vlVaEndPicture(VADriverContextP ctx, VAContextID context_id)
    }
 
    if (apply_av1_fg) {
-      vlVaSetSurfaceContext(surf, context);
+      vlVaSetSurfaceContext(drv, surf, context);
       *out_target = surf->buffer;
    }
 
index 62f3adc..baddba3 100644 (file)
@@ -89,6 +89,8 @@ vlVaDestroySurfaces(VADriverContextP ctx, VASurfaceID *surface_list, int num_sur
       if (surf->ctx) {
          assert(_mesa_set_search(surf->ctx->surfaces, surf));
          _mesa_set_remove_key(surf->ctx->surfaces, surf);
+         if (surf->fence && surf->ctx->decoder && surf->ctx->decoder->destroy_fence)
+            surf->ctx->decoder->destroy_fence(surf->ctx->decoder, surf->fence);
       }
       util_dynarray_fini(&surf->subpics);
       FREE(surf);
index 6943029..085dbae 100644 (file)
@@ -149,6 +149,12 @@ struct pipe_video_codec
                               uint64_t timeout);
 
    /**
+    * Destroy fence.
+    */
+   void (*destroy_fence)(struct pipe_video_codec *codec,
+                         struct pipe_fence_handle *fence);
+
+   /**
     * Update target buffer address.
     *
     * Due to reallocation, target buffer address has changed, and the