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:
@@ -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);
|
||||
|
@@ -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))
|
||||
|
@@ -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
|
||||
|
@@ -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.
|
||||
*
|
||||
|
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user