From 64ca0fd2f2896faa2ec85e454e2ecba2f68390c8 Mon Sep 17 00:00:00 2001 From: David Rosca Date: Mon, 22 Jul 2024 15:38:50 +0200 Subject: [PATCH] frontends/va: Allocate surface buffers on demand This saves memory by not allocating encode DPB surface buffers which are currently not used by drivers. Reviewed-By: Sil Vilerino Part-of: --- src/gallium/frontends/va/image.c | 4 ++- src/gallium/frontends/va/picture.c | 4 ++- src/gallium/frontends/va/postproc.c | 2 ++ src/gallium/frontends/va/surface.c | 39 ++++++++++++++++++--------- src/gallium/frontends/va/va_private.h | 1 + 5 files changed, 36 insertions(+), 14 deletions(-) diff --git a/src/gallium/frontends/va/image.c b/src/gallium/frontends/va/image.c index 777283d4aac..f6e161b544b 100644 --- a/src/gallium/frontends/va/image.c +++ b/src/gallium/frontends/va/image.c @@ -286,7 +286,7 @@ vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image) return VA_STATUS_ERROR_INVALID_CONTEXT; surf = handle_table_get(drv->htab, surface); - + vlVaGetSurfaceBuffer(drv, surf); if (!surf || !surf->buffer) return VA_STATUS_ERROR_INVALID_SURFACE; @@ -538,6 +538,7 @@ vlVaGetImage(VADriverContextP ctx, VASurfaceID surface, int x, int y, mtx_lock(&drv->mutex); surf = handle_table_get(drv->htab, surface); + vlVaGetSurfaceBuffer(drv, surf); if (!surf || !surf->buffer) { mtx_unlock(&drv->mutex); return VA_STATUS_ERROR_INVALID_SURFACE; @@ -679,6 +680,7 @@ vlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image, mtx_lock(&drv->mutex); surf = handle_table_get(drv->htab, surface); + vlVaGetSurfaceBuffer(drv, surf); if (!surf || !surf->buffer) { mtx_unlock(&drv->mutex); return VA_STATUS_ERROR_INVALID_SURFACE; diff --git a/src/gallium/frontends/va/picture.c b/src/gallium/frontends/va/picture.c index 687bb3b7d0a..fe65a09bdd5 100644 --- a/src/gallium/frontends/va/picture.c +++ b/src/gallium/frontends/va/picture.c @@ -97,6 +97,7 @@ vlVaBeginPicture(VADriverContextP ctx, VAContextID context_id, VASurfaceID rende } surf = handle_table_get(drv->htab, render_target); + vlVaGetSurfaceBuffer(drv, surf); if (!surf || !surf->buffer) { mtx_unlock(&drv->mutex); return VA_STATUS_ERROR_INVALID_SURFACE; @@ -174,7 +175,7 @@ vlVaGetReferenceFrame(vlVaDriver *drv, VASurfaceID surface_id, { vlVaSurface *surf = handle_table_get(drv->htab, surface_id); if (surf) - *ref_frame = surf->buffer; + *ref_frame = vlVaGetSurfaceBuffer(drv, surf); else *ref_frame = NULL; } @@ -1161,6 +1162,7 @@ vlVaEndPicture(VADriverContextP ctx, VAContextID context_id) mtx_lock(&drv->mutex); surf = handle_table_get(drv->htab, output_id); + vlVaGetSurfaceBuffer(drv, surf); if (!surf || !surf->buffer) { mtx_unlock(&drv->mutex); return VA_STATUS_ERROR_INVALID_SURFACE; diff --git a/src/gallium/frontends/va/postproc.c b/src/gallium/frontends/va/postproc.c index fcb679cfba4..69977c7f466 100644 --- a/src/gallium/frontends/va/postproc.c +++ b/src/gallium/frontends/va/postproc.c @@ -551,6 +551,8 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex dst_surface = handle_table_get(drv->htab, context->target_id); if (!src_surface || !dst_surface) return VA_STATUS_ERROR_INVALID_SURFACE; + vlVaGetSurfaceBuffer(drv, src_surface); + vlVaGetSurfaceBuffer(drv, dst_surface); if (!src_surface->buffer || !dst_surface->buffer) return VA_STATUS_ERROR_INVALID_SURFACE; diff --git a/src/gallium/frontends/va/surface.c b/src/gallium/frontends/va/surface.c index 52899cecc9d..f1aa45cc069 100644 --- a/src/gallium/frontends/va/surface.c +++ b/src/gallium/frontends/va/surface.c @@ -155,8 +155,7 @@ _vlVaSyncSurface(VADriverContextP ctx, VASurfaceID render_target, uint64_t timeo mtx_lock(&drv->mutex); surf = handle_table_get(drv->htab, render_target); - - if (!surf || !surf->buffer) { + if (!surf) { mtx_unlock(&drv->mutex); return VA_STATUS_ERROR_INVALID_SURFACE; } @@ -167,7 +166,7 @@ _vlVaSyncSurface(VADriverContextP ctx, VASurfaceID render_target, uint64_t timeo * Some apps try to sync/map the surface right after creation and * would get VA_STATUS_ERROR_INVALID_CONTEXT */ - if ((!surf->feedback) && (!surf->fence)) { + if (!surf->buffer || (!surf->feedback && !surf->fence)) { // No outstanding encode/decode operation: nothing to do. mtx_unlock(&drv->mutex); return VA_STATUS_SUCCESS; @@ -271,7 +270,7 @@ vlVaQuerySurfaceStatus(VADriverContextP ctx, VASurfaceID render_target, VASurfac mtx_lock(&drv->mutex); surf = handle_table_get(drv->htab, render_target); - if (!surf || !surf->buffer) { + if (!surf) { mtx_unlock(&drv->mutex); return VA_STATUS_ERROR_INVALID_SURFACE; } @@ -282,7 +281,7 @@ vlVaQuerySurfaceStatus(VADriverContextP ctx, VASurfaceID render_target, VASurfac * Some apps try to sync/map the surface right after creation and * would get VA_STATUS_ERROR_INVALID_CONTEXT */ - if ((!surf->feedback) && (!surf->fence)) { + if (!surf->buffer || (!surf->feedback && !surf->fence)) { // No outstanding encode/decode operation: nothing to do. *status = VASurfaceReady; mtx_unlock(&drv->mutex); @@ -485,7 +484,8 @@ vlVaPutSurface(VADriverContextP ctx, VASurfaceID surface_id, void* draw, short s drv = VL_VA_DRIVER(ctx); mtx_lock(&drv->mutex); surf = handle_table_get(drv->htab, surface_id); - if (!surf) { + vlVaGetSurfaceBuffer(drv, surf); + if (!surf || !surf->buffer) { mtx_unlock(&drv->mutex); return VA_STATUS_ERROR_INVALID_SURFACE; } @@ -1111,6 +1111,17 @@ vlVaHandleSurfaceAllocate(vlVaDriver *drv, vlVaSurface *surface, return VA_STATUS_SUCCESS; } +struct pipe_video_buffer * +vlVaGetSurfaceBuffer(vlVaDriver *drv, vlVaSurface *surface) +{ + if (!surface) + return NULL; + if (surface->buffer) + return surface->buffer; + vlVaHandleSurfaceAllocate(drv, surface, &surface->templat, NULL, 0); + return surface->buffer; +} + VAStatus vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format, unsigned int width, unsigned int height, @@ -1325,12 +1336,14 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format, */ if (memory_attribute && !(memory_attribute->flags & VA_SURFACE_EXTBUF_DESC_ENABLE_TILING)) - templat.bind = PIPE_BIND_LINEAR | PIPE_BIND_SHARED; + surf->templat.bind = PIPE_BIND_LINEAR | PIPE_BIND_SHARED; - vaStatus = vlVaHandleSurfaceAllocate(drv, surf, &templat, modifiers, - modifiers_count); - if (vaStatus != VA_STATUS_SUCCESS) - goto free_surf; + if (modifiers) { + vaStatus = vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, modifiers, + modifiers_count); + if (vaStatus != VA_STATUS_SUCCESS) + goto free_surf; + } /* Delayed allocation from vlVaGetSurfaceBuffer otherwise */ break; #ifdef _WIN32 @@ -1372,7 +1385,8 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format, return VA_STATUS_SUCCESS; destroy_surf: - surf->buffer->destroy(surf->buffer); + if (surf->buffer) + surf->buffer->destroy(surf->buffer); free_surf: FREE(surf); @@ -1644,6 +1658,7 @@ vlVaExportSurfaceHandle(VADriverContextP ctx, mtx_lock(&drv->mutex); surf = handle_table_get(drv->htab, surface_id); + vlVaGetSurfaceBuffer(drv, surf); if (!surf || !surf->buffer) { mtx_unlock(&drv->mutex); return VA_STATUS_ERROR_INVALID_SURFACE; diff --git a/src/gallium/frontends/va/va_private.h b/src/gallium/frontends/va/va_private.h index 2366e868658..bc123a107d1 100644 --- a/src/gallium/frontends/va/va_private.h +++ b/src/gallium/frontends/va/va_private.h @@ -564,6 +564,7 @@ VAStatus vlVaMapBuffer2(VADriverContextP ctx, VABufferID buf_id, void **pbuf, ui VAStatus vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); VAStatus vlVaHandleSurfaceAllocate(vlVaDriver *drv, vlVaSurface *surface, struct pipe_video_buffer *templat, const uint64_t *modifiers, unsigned int modifiers_count); +struct pipe_video_buffer *vlVaGetSurfaceBuffer(vlVaDriver *drv, vlVaSurface *surface); void vlVaSetSurfaceContext(vlVaDriver *drv, vlVaSurface *surf, vlVaContext *context); void vlVaGetReferenceFrame(vlVaDriver *drv, VASurfaceID surface_id, struct pipe_video_buffer **ref_frame); void vlVaHandlePictureParameterBufferMPEG12(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf);