frontends/va: Add surface pipe_fence for vl_compositor rendering

Wait on it in SyncSurface. Fixes sync issues when using surfaces from
processing context (shader path) in external APIs (eg. Vulkan interop).

Reviewed-by: Ruijing Dong <ruijing.dong@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33165>
This commit is contained in:
David Rosca 2025-01-02 19:06:32 +01:00 committed by Marge Bot
parent d4a6a22ef4
commit 0f20a3a4f1
4 changed files with 31 additions and 9 deletions

View file

@ -548,6 +548,7 @@ vlVaGetImage(VADriverContextP ctx, VASurfaceID surface, int x, int y,
ret = vlVaPostProcCompositor(drv, &src_rect, &dst_rect,
surf->buffer, tmp_surf.buffer,
VL_COMPOSITOR_NONE, &proc);
drv->pipe->flush(drv->pipe, NULL, 0);
if (ret != VA_STATUS_SUCCESS) {
tmp_surf.buffer->destroy(tmp_surf.buffer);
mtx_unlock(&drv->mutex);
@ -715,14 +716,14 @@ vlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image,
ret = vlVaPostProcCompositor(drv, &src_rect, &dst_rect,
tmp_surf.buffer, surf->buffer,
VL_COMPOSITOR_NONE, &proc);
vlVaSurfaceFlush(drv, surf);
tmp_surf.buffer->destroy(tmp_surf.buffer);
mtx_unlock(&drv->mutex);
return ret;
}
vlVaUploadImage(drv, surf, img_buf, vaimage);
drv->pipe->flush(drv->pipe, NULL, 0);
vlVaSurfaceFlush(drv, surf);
mtx_unlock(&drv->mutex);
return VA_STATUS_SUCCESS;

View file

@ -232,7 +232,6 @@ vlVaPostProcCompositor(vlVaDriver *drv,
drv->cstate.chroma_location = VL_COMPOSITOR_LOCATION_NONE;
drv->pipe->flush(drv->pipe, NULL, 0);
return VA_STATUS_SUCCESS;
}
@ -572,6 +571,8 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex
return VA_STATUS_SUCCESS;
}
return vlVaPostProcCompositor(drv, src_region, dst_region,
src, context->target, deinterlace, param);
VAStatus ret = vlVaPostProcCompositor(drv, src_region, dst_region,
src, context->target, deinterlace, param);
vlVaSurfaceFlush(drv, dst_surface);
return ret;
}

View file

@ -119,6 +119,8 @@ vlVaDestroySurfaces(VADriverContextP ctx, VASurfaceID *surface_list, int num_sur
}
if (surf->buffer)
surf->buffer->destroy(surf->buffer);
if (surf->pipe_fence)
drv->pipe->screen->fence_reference(drv->pipe->screen, &surf->pipe_fence, NULL);
if (surf->ctx) {
assert(_mesa_set_search(surf->ctx->surfaces, surf));
_mesa_set_remove_key(surf->ctx->surfaces, surf);
@ -176,13 +178,22 @@ _vlVaSyncSurface(VADriverContextP ctx, VASurfaceID render_target, uint64_t timeo
fence = surf->fence;
}
if (surf->pipe_fence) {
struct pipe_screen *pscreen = drv->pipe->screen;
if (!pscreen->fence_finish(pscreen, NULL, surf->pipe_fence, timeout_ns)) {
mtx_unlock(&drv->mutex);
return VA_STATUS_ERROR_TIMEDOUT;
}
pscreen->fence_reference(pscreen, &surf->pipe_fence, NULL);
}
/* This is checked before getting the context below as
* surf->ctx is only set in begin_frame
* and not when the surface is created
* Some apps try to sync/map the surface right after creation and
* would get VA_STATUS_ERROR_INVALID_CONTEXT
*/
if (!surf->buffer || !fence) {
if (!surf->fence) {
// No outstanding encode/decode operation: nothing to do.
mtx_unlock(&drv->mutex);
return VA_STATUS_SUCCESS;
@ -441,7 +452,7 @@ vlVaPutSurface(VADriverContextP ctx, VASurfaceID surface_id, void* draw, short s
/* flush before calling flush_frontbuffer so that rendering is flushed
* to back buffer so the texture can be copied in flush_frontbuffer
*/
drv->pipe->flush(drv->pipe, NULL, 0);
vlVaSurfaceFlush(drv, surf);
screen->flush_frontbuffer(screen, drv->pipe, tex, 0, 0,
vscreen->get_private(vscreen), 0, NULL);
@ -996,7 +1007,7 @@ vlVaHandleSurfaceAllocate(vlVaDriver *drv, vlVaSurface *surface,
surfaces[i]->width, surfaces[i]->height,
false);
}
drv->pipe->flush(drv->pipe, NULL, 0);
vlVaSurfaceFlush(drv, surface);
}
return VA_STATUS_SUCCESS;
@ -1013,6 +1024,13 @@ vlVaGetSurfaceBuffer(vlVaDriver *drv, vlVaSurface *surface)
return surface->buffer;
}
void
vlVaSurfaceFlush(vlVaDriver *drv, vlVaSurface *surf)
{
drv->pipe->flush(drv->pipe, &surf->pipe_fence,
drv->has_external_handles ? 0 : PIPE_FLUSH_ASYNC);
}
static int
rt_format_to_fourcc(uint32_t format)
{

View file

@ -448,7 +448,8 @@ typedef struct vlVaSurface {
vlVaContext *ctx;
vlVaBuffer *coded_buf;
bool full_range;
struct pipe_fence_handle *fence;
struct pipe_fence_handle *fence; /* pipe_video_codec fence */
struct pipe_fence_handle *pipe_fence; /* pipe_context fence */
struct vlVaSurface *efc_surface; /* input surface for EFC */
bool is_dpb;
} vlVaSurface;
@ -569,6 +570,7 @@ VAStatus vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContex
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 vlVaSurfaceFlush(vlVaDriver *drv, vlVaSurface *surf);
void vlVaAddRawHeader(struct util_dynarray *headers, uint8_t type, uint32_t size, uint8_t *buf,
bool is_slice, uint32_t emulation_bytes_start);
void vlVaGetBufferFeedback(vlVaBuffer *buf);