frontend/va: Add video processing async fence support

Reviewed-by: Ruijing Dong <ruijing.dong@amd.com>
Reviewed-by: Jesse Natalie <jenatali@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/23969>
This commit is contained in:
Sil Vilerino
2023-06-30 15:26:01 -04:00
committed by Marge Bot
parent c78611c0ab
commit fb1783616e
5 changed files with 58 additions and 2 deletions

View File

@@ -1083,6 +1083,8 @@ vlVaEndPicture(VADriverContextP ctx, VAContextID context_id)
coded_buf->associated_encode_input_surf = context->target_id;
} else if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
context->desc.base.fence = &surf->fence;
} else if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_PROCESSING) {
context->desc.base.fence = &surf->fence;
}
context->decoder->end_frame(context->decoder, context->target, &context->desc.base);

View File

@@ -490,6 +490,11 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex
src_region = vlVaRegionDefault(param->surface_region, src_surface, &def_src_region);
dst_region = vlVaRegionDefault(param->output_region, dst_surface, &def_dst_region);
/* Insert a GPU Wait on the input surface fence to ensure
any pending work is finished before performing the VPBlit */
if (src_surface->fence && drv->pipe->fence_server_sync)
drv->pipe->fence_server_sync(drv->pipe, src_surface->fence);
/* If the driver supports video engine post proc, attempt to do that
* if it fails, fallback to the other existing implementations below
*/
@@ -503,6 +508,7 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
context->desc.vidproc.src_surface_fence = src_surface->fence;
/* Perform VPBlit, if fail, fallback to other implementations below */
if (VA_STATUS_SUCCESS == vlVaVidEngineBlit(drv, context, src_region, dst_region,
src, context->target, deinterlace, param))

View File

@@ -137,7 +137,18 @@ vlVaSyncSurface(VADriverContextP ctx, VASurfaceID render_target)
return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
}
if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_PROCESSING) {
int ret = 0;
if (context->decoder->get_processor_fence)
ret = context->decoder->get_processor_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_BITSTREAM) {
int ret = 0;
if (context->decoder->get_decoder_fence)
@@ -234,6 +245,25 @@ vlVaQuerySurfaceStatus(VADriverContextP ctx, VASurfaceID render_target, VASurfac
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;
} else if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_PROCESSING) {
int ret = 0;
if (context->decoder->get_processor_fence)
ret = context->decoder->get_processor_fence(context->decoder,
surf->fence, 0);
if (ret)
*status = VASurfaceReady;
else

View File

@@ -133,6 +133,21 @@ struct pipe_video_codec
int (*get_decoder_fence)(struct pipe_video_codec *codec,
struct pipe_fence_handle *fence,
uint64_t timeout);
/**
* Get processor fence.
*
* Can be used to query the status of the previous process job denoted by
* 'fence' given 'timeout'.
*
* A pointer to a fence pointer can be passed to the codecs before the
* end_frame vfunc and the codec should then be responsible for allocating a
* fence on command stream submission.
*/
int (*get_processor_fence)(struct pipe_video_codec *codec,
struct pipe_fence_handle *fence,
uint64_t timeout);
/**
* Update target buffer address.
*

View File

@@ -187,7 +187,7 @@ struct pipe_picture_desc
uint32_t key_size;
enum pipe_format input_format;
enum pipe_format output_format;
/* A fence used on PIPE_VIDEO_ENTRYPOINT_DECODE to signal job completion */
/* A fence used on PIPE_VIDEO_ENTRYPOINT_DECODE/PROCESSING to signal job completion */
struct pipe_fence_handle **fence;
};
@@ -1379,6 +1379,9 @@ struct pipe_vpp_desc
struct u_rect dst_region;
enum pipe_video_vpp_orientation orientation;
struct pipe_vpp_blend blend;
/* Fence to wait on for the src surface */
struct pipe_fence_handle *src_surface_fence;
};