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;
|
coded_buf->associated_encode_input_surf = context->target_id;
|
||||||
} else if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
|
} else if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
|
||||||
context->desc.base.fence = &surf->fence;
|
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);
|
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);
|
src_region = vlVaRegionDefault(param->surface_region, src_surface, &def_src_region);
|
||||||
dst_region = vlVaRegionDefault(param->output_region, dst_surface, &def_dst_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 the driver supports video engine post proc, attempt to do that
|
||||||
* if it fails, fallback to the other existing implementations below
|
* 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;
|
return VA_STATUS_ERROR_ALLOCATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context->desc.vidproc.src_surface_fence = src_surface->fence;
|
||||||
/* Perform VPBlit, if fail, fallback to other implementations below */
|
/* Perform VPBlit, if fail, fallback to other implementations below */
|
||||||
if (VA_STATUS_SUCCESS == vlVaVidEngineBlit(drv, context, src_region, dst_region,
|
if (VA_STATUS_SUCCESS == vlVaVidEngineBlit(drv, context, src_region, dst_region,
|
||||||
src, context->target, deinterlace, param))
|
src, context->target, deinterlace, param))
|
||||||
|
@@ -137,7 +137,18 @@ vlVaSyncSurface(VADriverContextP ctx, VASurfaceID render_target)
|
|||||||
return VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
|
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;
|
int ret = 0;
|
||||||
|
|
||||||
if (context->decoder->get_decoder_fence)
|
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,
|
ret = context->decoder->get_decoder_fence(context->decoder,
|
||||||
surf->fence, 0);
|
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)
|
if (ret)
|
||||||
*status = VASurfaceReady;
|
*status = VASurfaceReady;
|
||||||
else
|
else
|
||||||
|
@@ -133,6 +133,21 @@ struct pipe_video_codec
|
|||||||
int (*get_decoder_fence)(struct pipe_video_codec *codec,
|
int (*get_decoder_fence)(struct pipe_video_codec *codec,
|
||||||
struct pipe_fence_handle *fence,
|
struct pipe_fence_handle *fence,
|
||||||
uint64_t timeout);
|
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.
|
* Update target buffer address.
|
||||||
*
|
*
|
||||||
|
@@ -187,7 +187,7 @@ struct pipe_picture_desc
|
|||||||
uint32_t key_size;
|
uint32_t key_size;
|
||||||
enum pipe_format input_format;
|
enum pipe_format input_format;
|
||||||
enum pipe_format output_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;
|
struct pipe_fence_handle **fence;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1379,6 +1379,9 @@ struct pipe_vpp_desc
|
|||||||
struct u_rect dst_region;
|
struct u_rect dst_region;
|
||||||
enum pipe_video_vpp_orientation orientation;
|
enum pipe_video_vpp_orientation orientation;
|
||||||
struct pipe_vpp_blend blend;
|
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