From patchwork Thu Oct 28 11:15:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 14404 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 1B78AC324F for ; Thu, 28 Oct 2021 11:14:51 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B9AB660128; Thu, 28 Oct 2021 13:14:50 +0200 (CEST) Received: from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net [217.70.183.199]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 964DA60325 for ; Thu, 28 Oct 2021 13:14:42 +0200 (CEST) Received: (Authenticated sender: jacopo@jmondi.org) by relay9-d.mail.gandi.net (Postfix) with ESMTPSA id 21D27FF802; Thu, 28 Oct 2021 11:14:41 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Thu, 28 Oct 2021 13:15:19 +0200 Message-Id: <20211028111520.256612-10-jacopo@jmondi.org> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211028111520.256612-1-jacopo@jmondi.org> References: <20211028111520.256612-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 09/10] libcamera: pipeline_handler: Handle fences X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" 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. If any fence in the Request has expired cancel the request and do not queue it to the device. Signed-off-by: Jacopo Mondi --- 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> 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 #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(); + + 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(); }