frontends: va: fix vaQuerySurfaceStatus and vaSyncSurface for decode

Use the new get_decoder_fence vfunc to  implement
vaQuerySurfaceStatus and vaSyncSurface in the va state tracker.

A pointer to the surface's fence is passed to the codecs before the
end_frame vfunc and the codec is responsible for allocating a fence on
command stream submission.

This fence is then queried on vaQuerySurfaceStatus and waited on in
vaSyncSurface.

Notably both functions were not implemented as per the VA-API docs for
PIPE_VIDEO_ENTRYPOINT_BITSTREAM.

Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com>
Reviewed-by: Sil Vilerino <sivileri@microsoft.com>
Reviewed-by: Leo Liu <leo.liu@amd.com>
Reviewed-by: Boyuan Zhang <Boyuan.Zhang@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20133>
This commit is contained in:
Daniel Almeida
2022-12-04 09:18:52 -03:00
committed by Marge Bot
parent 3a0d1f9fdc
commit 4246bcfc7a
3 changed files with 55 additions and 3 deletions
+2
View File
@@ -1024,6 +1024,8 @@ vlVaEndPicture(VADriverContextP ctx, VAContextID context_id)
surf->feedback = feedback;
surf->coded_buf = coded_buf;
coded_buf->associated_encode_input_surf = context->target_id;
} else if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
context->desc.base.fence = &surf->fence;
}
context->decoder->end_frame(context->decoder, context->target, &context->desc.base);
+52 -3
View File
@@ -114,8 +114,14 @@ vlVaSyncSurface(VADriverContextP ctx, VASurfaceID render_target)
return VA_STATUS_ERROR_INVALID_SURFACE;
}
if (!surf->feedback) {
// No outstanding operation: nothing to do.
/* 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->feedback) && (!surf->fence)) {
// No outstanding encode/decode operation: nothing to do.
mtx_unlock(&drv->mutex);
return VA_STATUS_SUCCESS;
}
@@ -126,7 +132,18 @@ vlVaSyncSurface(VADriverContextP ctx, VASurfaceID render_target)
return VA_STATUS_ERROR_INVALID_CONTEXT;
}
if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
int ret = 0;
if (context->decoder->get_decoder_fence)
ret = context->decoder->get_decoder_fence(context->decoder,
surf->fence,
PIPE_DEFAULT_DECODER_FEEDBACK_TIMEOUT_NS);
mtx_unlock(&drv->mutex);
// Assume that the GPU has hung otherwise.
return ret ? VA_STATUS_SUCCESS : VA_STATUS_ERROR_TIMEDOUT;
} else if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
if (!drv->pipe->screen->get_video_param(drv->pipe->screen,
context->decoder->profile,
context->decoder->entrypoint,
@@ -176,6 +193,19 @@ vlVaQuerySurfaceStatus(VADriverContextP ctx, VASurfaceID render_target, VASurfac
return VA_STATUS_ERROR_INVALID_SURFACE;
}
/* 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->feedback) && (!surf->fence)) {
// No outstanding encode/decode operation: nothing to do.
*status = VASurfaceReady;
mtx_unlock(&drv->mutex);
return VA_STATUS_SUCCESS;
}
context = handle_table_get(drv->htab, surf->ctx);
if (!context) {
mtx_unlock(&drv->mutex);
@@ -187,6 +217,25 @@ vlVaQuerySurfaceStatus(VADriverContextP ctx, VASurfaceID render_target, VASurfac
*status=VASurfaceReady;
else
*status=VASurfaceRendering;
} else if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
int ret = 0;
if (context->decoder->get_decoder_fence)
ret = context->decoder->get_decoder_fence(context->decoder,
surf->fence, 0);
if (ret)
*status = VASurfaceReady;
else
/* An approach could be to just tell the client that this is not
* implemented, but this breaks other code. Compromise by at least
* conservatively setting the status to VASurfaceRendering if we can't
* query the hardware. Note that we _must_ set the status here, otherwise
* it comes out of the function unchanged. As we are returning
* VA_STATUS_SUCCESS, the client would be within his/her rights to use a
* potentially uninitialized/invalid status value unknowingly.
*/
*status = VASurfaceRendering;
}
mtx_unlock(&drv->mutex);
+1
View File
@@ -374,6 +374,7 @@ typedef struct {
bool force_flushed;
struct pipe_video_buffer *obsolete_buf;
enum pipe_format encoder_format;
struct pipe_fence_handle *fence;
} vlVaSurface;
typedef struct {