[libcamera-devel] [PATCH 09/10] libcamera: pipeline_handler: Handle fences
Umang Jain
umang.jain at ideasonboard.com
Wed Nov 10 14:09:15 CET 2021
Hi Jacopo,
Thank you for the patch
On 10/28/21 4:45 PM, Jacopo Mondi wrote:
> Before queueing a request to the device, any synchronization fence from
> the Request framebuffers has to be waited on.
>
> Start by moving the fences to the Request, in order to reset the ones
> in the FrameBuffers and then enable all of them one by one.
>
> When a fence completes, make sure all fences in the Request have been
> waited on or have expired and only after that actually queue the Request
> to the device.
Here it's said:
waited on OR expired => queue the Request to device
>
> If any fence in the Request has expired cancel the request and do not
> queue it to the device.
And here it's said:
If fence expired => Cancel the request and do not queue.
Am I missing something?
The patch looks good to me overall.
>
> Signed-off-by: Jacopo Mondi <jacopo at jmondi.org>
> ---
> include/libcamera/internal/pipeline_handler.h | 2 +
> src/libcamera/pipeline_handler.cpp | 78 ++++++++++++++++++-
> 2 files changed, 77 insertions(+), 3 deletions(-)
>
> diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h
> index 5c3c0bc5a8b3..5b98011ac4f6 100644
> --- a/include/libcamera/internal/pipeline_handler.h
> +++ b/include/libcamera/internal/pipeline_handler.h
> @@ -29,6 +29,7 @@ class CameraConfiguration;
> class CameraManager;
> class DeviceEnumerator;
> class DeviceMatch;
> +class Fence;
> class FrameBuffer;
> class MediaDevice;
> class PipelineHandler;
> @@ -79,6 +80,7 @@ private:
> void mediaDeviceDisconnected(MediaDevice *media);
> virtual void disconnect();
>
> + void fenceCompleted(Request *request, FrameBuffer *buffer, Fence *fence);
> void doQueueRequest();
>
> std::vector<std::shared_ptr<MediaDevice>> mediaDevices_;
> diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
> index 0f9fec1b618f..39cb680e5386 100644
> --- a/src/libcamera/pipeline_handler.cpp
> +++ b/src/libcamera/pipeline_handler.cpp
> @@ -18,6 +18,7 @@
> #include <libcamera/framebuffer.h>
>
> #include "libcamera/internal/camera.h"
> +#include "libcamera/internal/framebuffer.h"
> #include "libcamera/internal/device_enumerator.h"
> #include "libcamera/internal/media_device.h"
> #include "libcamera/internal/request.h"
> @@ -336,11 +337,70 @@ void PipelineHandler::queueRequest(Request *request)
> {
> LIBCAMERA_TRACEPOINT(request_queue, request);
>
> + Request::Private *data = request->_d();
> +
> {
> MutexLocker lock(waitingRequestsMutex_);
> waitingRequests_.push_back(request);
> }
>
> + for (FrameBuffer *buffer : request->pending_) {
> + if (buffer->fence() == -1)
> + continue;
> +
> + /*
> + * Move the Fence into the Request::Private list of
> + * fences. This resets the file descriptor fence in the
> + * FrameBuffer to -1.
> + */
> + data->addFence(std::move(buffer->_d()->fence()));
> +
> + Fence *fence = &data->fences().back();
> + fence->complete.connect(this,
> + [this, request, buffer, fence]() {
> + fenceCompleted(request, buffer, fence);
> + });
> + }
> +
> + /* If no fences to wait on, we can queue the request immediately. */
> + if (!data->pendingFences()) {
> + doQueueRequest();
> +
> + return;
> + }
> +
> + /*
> + * Now that we have added all fences, enable them one by one.
> + * Enabling fences while adding them to the Request would race on the
> + * number of pending fences.
> + */
> + for (Fence &fence : data->fences())
> + fence.enable();
> +}
> +
> +void PipelineHandler::fenceCompleted(Request *request, FrameBuffer *buffer,
> + Fence *fence)
> +{
> + Request::Private *data = request->_d();
> +
> + if (fence->expired()) {
> + /*
> + * Move the fence back to the framebuffer, so that it doesn't
> + * get closed and the file descriptor number is made
> + * available again to applications.
> + */
> + FrameBuffer::Private *bufferData = buffer->_d();
> + bufferData->fence() = std::move(*fence);
> +
> + data->fenceExpired();
> + } else {
> + data->fenceCompleted();
> + }
> +
> + if (data->pendingFences())
> + return;
> +
> + data->clearFences();
> doQueueRequest();
> }
>
> @@ -357,23 +417,35 @@ void PipelineHandler::doQueueRequest()
> return;
>
> request = waitingRequests_.front();
> + if (request->_d()->pendingFences())
> + return;
> +
> waitingRequests_.pop_front();
> }
>
> - /* Queue Request to the pipeline handler. */
> Camera *camera = request->_d()->camera();
> Camera::Private *camData = camera->_d();
>
> request->sequence_ = camData->requestSequence_++;
> - camData->queuedRequests_.push_back(request);
>
> + /* Cancel the request if one of the fences has failed. */
> + if (request->_d()->expiredFences()) {
> + request->cancel();
> + completeRequest(request);
> +
> + doQueueRequest();
A bit-off to read doQueueRequest() in this codepath here, but okay I guess
> +
> + return;
> + }
> +
> + /* Queue Request to the pipeline handler. */
> + camData->queuedRequests_.push_back(request);
> int ret = queueRequestDevice(camera, request);
> if (ret) {
> request->cancel();
> completeRequest(request);
> }
>
> - /* Try to queue the next Request in the queue, if ready. */
> doQueueRequest();
> }
>
More information about the libcamera-devel
mailing list