<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, 15 Dec 2022 at 09:52, Kieran Bingham <<a href="mailto:kieran.bingham@ideasonboard.com">kieran.bingham@ideasonboard.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Quoting Naushir Patuck via libcamera-devel (2022-12-15 09:43:55)<br>
> Hi all,<br>
> <br>
> On Thu, 15 Dec 2022 at 05:18, Paul Elder via libcamera-devel <<br>
> <a href="mailto:libcamera-devel@lists.libcamera.org" target="_blank">libcamera-devel@lists.libcamera.org</a>> wrote:<br>
> <br>
> > Hi Jacopo,<br>
> ><br>
> > On Wed, Dec 14, 2022 at 02:41:30PM +0100, Jacopo Mondi wrote:<br>
> > > Hi Paul<br>
> > ><br>
> > > On Wed, Dec 14, 2022 at 09:13:06PM +0900, Paul Elder wrote:<br>
> > > > Hi,<br>
> > > ><br>
> > > > On Wed, Dec 14, 2022 at 10:19:54AM +0100, Jacopo Mondi via<br>
> > libcamera-devel wrote:<br>
> > > > > Hi Umang<br>
> > > > ><br>
> > > > > On Wed, Dec 14, 2022 at 02:11:12PM +0530, Umang Jain wrote:<br>
> > > > > > Hi Jacopo<br>
> > > > > ><br>
> > > > > > On 12/14/22 1:29 PM, Jacopo Mondi wrote:<br>
> > > > > > > Hi Umang<br>
> > > > > > ><br>
> > > > > > > On Wed, Dec 14, 2022 at 11:07:25AM +0530, Umang Jain wrote:<br>
> > > > > > > > Hi Jacopo,<br>
> > > > > > > ><br>
> > > > > > > > On 12/13/22 9:25 PM, Jacopo Mondi wrote:<br>
> > > > > > > > > Hi Umang,<br>
> > > > > > > > ><br>
> > > > > > > > > On Mon, Dec 12, 2022 at 08:32:56PM +0530, Umang Jain via<br>
> > libcamera-devel wrote:<br>
> > > > > > > > > > This patch introduces a new constraint in the pipeline<br>
> > handler base<br>
> > > > > > > > > > class which allows various derived pipeline handlers to<br>
> > set and<br>
> > > > > > > > > > restrict the number of maximum in-flight requests that can<br>
> > be queued to<br>
> > > > > > > > > > the underlying components (for e.g. the IPA).<br>
> > > > > > > > > It's my understanding that the max number of in-flight<br>
> > requests is<br>
> > > > > > > > > what the properties::PipelineDepth property expresses.<br>
> > > > > > > > Indeed, that's why understanding as well. The<br>
> > properties::PipelineDepth<br>
> > > > > > > > should be set by the pipeline-handlers.<br>
> > > ><br>
> > > > (Besides the fact that I can't find properties::PipelineDepth)<br>
> > > > controls::PipelineDepth says that it "Specifies the number of pipeline<br>
> > > > stages the frame went through from when it was exposed to when the<br>
> > final<br>
> > > > completed result was available to the framework.", which to me sounds<br>
> > > > like the *minimum* amount of in-flight requests.<br>
> > ><br>
> > > It's a draft control copied in to please Android.<br>
> > > My understanding was that it had to be made a non-mutable property<br>
> ><br>
> > Ah, indeed it says that :)<br>
> ><br>
> > ><br>
> > > ><br>
> > > > I thought that here we're defining the *maximum* allowed in-flight<br>
> > > > requests. Not that all of the requests have to actually be doing<br>
> > > > something in hardware, but that it's the amount of requests the the<br>
> > > > pipeline handler is capable of handling internally without overflowing.<br>
> > > ><br>
> > > > > > > ><br>
> > > > > > > > We need to identify and atleast agree upon the correct<br>
> > PipelineDepth for the<br>
> > > > > > > > two platforms that uses the FCQueue (IPU3 and RkISP1) as well.<br>
> > Some grey<br>
> > > > > > > > areas there as well<br>
> > > > > > > I think 16 is fine for now. At least doesn't change what we<br>
> > already<br>
> > > > > > > have today<br>
> > > > > > ><br>
> > > > > > > > > Can't we access that property at queue request time, or<br>
> > maybe better we<br>
> > > > > > > > > could cache it at camera registration time, since it's<br>
> > constant ?<br>
> > > > > > > > If we intent to use the properties::PipelineDepth, as the size<br>
> > of the<br>
> > > > > > > > FCQueue - it needs to exist / set before IPA is constructed.<br>
> > > > > > > ><br>
> > > > > > > > (See IPAIPU3::IPAIPU3() for context)<br>
> > > > > > > ><br>
> > > > > > > The property can still be defined in the IPA header as IPA can<br>
> > access<br>
> > > > > > > it safely.<br>
> > > > > ><br>
> > > > > > You mean via a global const variable like it's done in Patch 1/2 ?<br>
> > > > ><br>
> > > > > Yes, like in patch 1/2<br>
> > > > ><br>
> > > > ><br>
> > > > > > ><br>
> > > > > > > Pipeline Handlers will have to register the property -before- the<br>
> > > > > > > camera is registered, but looking at IPU3 that's already the<br>
> > case now<br>
> > > > > > > (data->properties_ gets populated before calling<br>
> > registerCamera())<br>
> > > > > > ><br>
> > > > > > ><br>
> > > > > > > > So I think queue request time is quite late there. Camera<br>
> > registeration time<br>
> > > > > > > > might be possible with some changes (looking at<br>
> > > > > > > > PipelineHandlerIPU3::registerCameras())<br>
> > > > > > > What I meant is either<br>
> > > > > > ><br>
> > > > > > > 1) At PipelineHandler::queueRequest() time, the PipelineHandler<br>
> > base<br>
> > > > > > > class accesses Camera::properties() and fetches<br>
> > > > > > > properties::PipelineDepth<br>
> > > > > ><br>
> > > > > > I think it's a over-kill here. queueRequest() is a recurring call<br>
> > and I<br>
> > > > > > don't want fetching of PipelineDepth here.<br>
> > > ><br>
> > > > Oh one hand, yeah imo getting it from Camera::properties() is more<br>
> > > > correct, but on the other hand it does indeed seem overkill.<br>
> > > ><br>
> > > > ><br>
> > > > > While I consider a lookup on an unordered_map<> of a few items not<br>
> > > > > that expensive, I agree it's in an hot path, and it would be better<br>
> > to<br>
> > > > > cache the value somewhere. Caching it inside Camera or<br>
> > Camera::Private<br>
> > > > > is a duplication, as it's already part of<br>
> > > > > Camera::Private::properties_, but I would be fine with the<br>
> > > > > PipelineHandler base class doing something like this (as proposed in<br>
> > > > > my previous 2) point below)<br>
> > > > ><br>
> > > > > void PipelineHandler::registerCamera(std::shared_ptr<Camera> camera)<br>
> > > > > {<br>
> > > > ><br>
> > > > > /* Cache the pipeline depth in the Camera private data. */<br>
> > > > > const auto &pipelineDepth =<br>
> > camera->properties().get(properties::PipelineDepth);<br>
> > > > ><br>
> > > > > Camera::Private *data = camera->_d();<br>
> > > > > data->pipelineDepth = pipelineDepth ? 0 : *pipelineDepth;<br>
> > > > ><br>
> > > > > ...<br>
> > > > > }<br>
> > > > ><br>
> > > > > Otherwise the PipelineHandler base class can be added with a class<br>
> > > > > member, and each registred camera will overwrite that value, it's<br>
> > less<br>
> > > > > nice, but all cameras from the same PH instance will have the same<br>
> > > > > pipeline depth, so...<br>
> > > ><br>
> > > > Perhaps caching would be a good middle ground.<br>
> > > ><br>
> > > > ><br>
> > > > ><br>
> > > > > > > 2) At PipelineHandler::registerCamera() time the property value<br>
> > is<br>
> > > > > > > cached, but this would require to cache per-camera data in<br>
> > > > > > > PipelineHandler, something we don't have, or to populate a class<br>
> > > > > > > member of Camera::Private for that purpose..<br>
> > > > > ><br>
> > > > > > That's interesting because I initially didn't think of multiple<br>
> > cameras<br>
> > > > > > registered with one instance of pipeline-handler.<br>
> > > > > > It also makes me wonder -<br>
> > > > > ><br>
> > > > > > - Is properties::PipelineDepth Camera specific or<br>
> > platform-specific ? Seems<br>
> > > > > > now it's Camera specific<br>
> > > > > > - Then defining it IPA headers won't be a good option, in cases<br>
> > where<br>
> > > > > > PipelineDepth for different cameras differ.<br>
> > > > ><br>
> > > > > Why camera specific ? Each camera will indeed register it as a<br>
> > > > > property for applications to retrieve it, but the<br>
> > > > > value depends on the platform afaict and it can be a compile-time<br>
> > constant<br>
> > > > > defined by the IPA headers. Even better, the same compile-time<br>
> > > > > constant will be used to size the FCQ.<br>
> > > ><br>
> > > > If it's platform-specific then wouldn't the pipeline handler have to<br>
> > > > report it based on what platform it's running on? So we can't really<br>
> > > >hardcode a constant. Maybe putting it in properties is indeed better.<br>
> > ><br>
> > > As far as I get it, this property applies to pipelines with an ISP (no<br>
> > > uvc, no simple) and those pipelines by definition runs on a single<br>
> > > platform, don't they ?<br>
> ><br>
> > Well, the rkisp1 pipeline runs on imx8mp too... (with a few on-the-list<br>
> > but out-of-tree kernel patches)<br>
> ><br>
> > ><br>
> > > ><br>
> > > > ><br>
> > > > > ><br>
> > > > > > Need some thinking ...<br>
> > > > > ><br>
> > > > > > But none the less, this is a something that can be done on top<br>
> > with wider<br>
> > > > > > discussion / context on PipelineDepth. It shouldn't necessarily<br>
> > block the<br>
> > > > > > series.<br>
> > > > ><br>
> > > > > My whole point is that I think we should find a better mechanism for<br>
> > > > > registering pipeline depth compared to having pipeline handlers call<br>
> > > > > setMaxQueueRequests() as it requires an explicit action that can<br>
> > > > > easily be overlooked, while we want the queue overflow protection to<br>
> > > ><br>
> > > > I mean, we could initialize kMaxFrameContexts to an invalid value (-1?)<br>
> > > > and then force *all* pipeline handlers to explictly set it, even if to<br>
> > > > zero. Then it becomes really easy to catch.<br>
> > ><br>
> > > The property doesn't make much sense for UVC, right ?<br>
> > ><br>
> > > Not all pipelines will use libipa and have an FCQ (RPi in example at<br>
> > > the moment). I don't think forcing all of them is actually necessary.<br>
> ><br>
> > Hm, that's true. No initial invalid value then.<br>
> ><br>
> > ><br>
> > > But the pipelines that do need to throttle the number of requests in<br>
> > > flight with the help of the PipelineHandler base class should ideally<br>
> > > get it for free by simply registering the property ?<br>
> ><br>
> > Yeah that does sound more nice.<br>
> ><br>
> > ><br>
> > > ><br>
> > > > Or note it down as a compliancy thing and have lc-compliance test for<br>
> > > > it. I presume this will become a required property to be exposed<br>
> > anyway.<br>
> > > ><br>
> > > > In any case, the goal is to report to the user the "maximum number of<br>
> > > > requests that are allowed to be queued in the camera", right? So it'll<br>
> > > > have to go through properties anyway. Perhaps then it's best to expose<br>
> > > > it via properties (as it's already the interface we have for exposing<br>
> > > > properties to the user), and then the base PipelineHandler can cache it<br>
> > > > for the queuing guard. That would get rid of the special explicit call,<br>
> > > > and would still achieve the goal.<br>
> > ><br>
> > > That would be my preference. There might be a discussions if<br>
> > > properties::PipelineDepth is the right property to report it or it<br>
> > > will conflict with Android's pipeline depth, which is different.<br>
> ><br>
> > +1<br>
> ><br>
> > Although to me this sounds separate from PipelineDepth, because my<br>
> > understanding is that that is the maximum amount of Requests that can be<br>
> > in-flight, while what we want here is that plus some extra that the<br>
> > application is allowed to "overqueue" that the pipeline handler will<br>
> > automagically handle internally.<br>
> ><br>
> <br>
> My understanding of PipelineDepth is in-line with the above - it gives a<br>
> minimum<br>
> number of in-flight requests needed for the pipeline handler. This new<br>
> property must give an upper bound on the number of in-flight requests the<br>
> pipeline<br>
> handler can handle. For the RPi case, the min is 1 and max is unbounded.<br>
> <br>
> I can see a possible bug(?) introduced in this series however. Say a<br>
> pipeline<br>
> handler sets maxQueueRequest to 16. An application comes along and queues<br>
> 20<br>
> requests and then just waits for completion of those 20 requests. The<br>
> PipelineHandler base class calls queueRequestDevice for the first 16<br>
> requests,<br>
> but nothing that I can see will trigger queuing of the last 4 requests once<br>
> the<br>
> pipeline handler has completed the first N requests. Unless I've missed<br>
> something?<br>
<br>
I think I saw Jacopo confirm the same in a parallel reply here, but I<br>
understood this to be something we shouldn't expose to applications.<br>
Applications can always choose to queue an unlimited number of requests<br>
to a Camera (within the limits of the universe) ... but it's the<br>
pipeline handlers responsibility to ensure that requests are not queued<br>
beyond the capabilities of the IPA. As such - requests may stay 'queued'<br>
in the pipeline handler or CameraData object until the IPA is ready to<br>
process the next one.<br></blockquote><div><br></div><div>I agree that the application never needs to know the maximum bound for requests.</div><div>But I still see a problem where any pending requests queued in PipelineHandler::waitingRequests_</div><div>will never make it to PipelineHandlerXXX::queueRequestDevice() if the application</div><div>does not queue any further requests to the camera.</div><div><br></div><div>Regards,</div><div>Naush</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
--<br>
Kieran<br>
<br>
<br>
<br>
> <br>
> Regards,<br>
> Naush<br>
> <br>
> <br>
> > Am I misunderstanding something?<br>
> ><br>
> ><br>
> > Paul<br>
> ><br>
> > ><br>
> > > ><br>
> > > > I suppose then we'd actually need a compliance test for the property,<br>
> > > > but I guess we have a few more of those anyway.<br>
> > > ><br>
> > > > My two cents.<br>
> > ><br>
> > > Thanks ;)<br>
> > > j<br>
> > ><br>
> > > ><br>
> > > ><br>
> > > > Paul<br>
> > > ><br>
> > > > > happen transparently if a pipeline handler register<br>
> > > > > properties::PipelineDepth ? Am I overthinking this ?<br>
> > > > ><br>
> > > > ><br>
> > > > > > ><br>
> > > > > > > Sorry for not having been clear<br>
> > > > > > ><br>
> > > > > > ><br>
> > > > > > > ><br>
> > > > > > > > > Also, can this feature be tested in test/ ? Probably not, as<br>
> > it<br>
> > > > > > > > > requires a compliant pipeline handler ? Maybe vimc can be<br>
> > instrumented<br>
> > > > > > > > I have been thinking about that as well. It's shouldn't be too<br>
> > difficult.<br>
> > > > > > > > > ?<br>
> > > > > > > > ><br>
> > > > > > > > > > The pipeline handler is now equipped with the<br>
> > responsibility of not to<br>
> > > > > > > > > > over queue the requests to the underlying layers. The<br>
> > derived<br>
> > > > > > > > > > pipeline handler (or even IPA) can also have various kind<br>
> > of requests<br>
> > > > > > > > > > queue(arrays, queues or ring-buffer) hence, it might be an<br>
> > issue where<br>
> > > > > > > > > > the application queues the requests at a rate where these<br>
> > kind of<br>
> > > > > > > > > > queues can over-flow. The patch ensures that the base<br>
> > PipelineHandler<br>
> > > > > > > > > > will never let the requests overflow to underlying layers,<br>
> > once the<br>
> > > > > > > > > > derived pipeline handler sets its maximum capacity of<br>
> > handling<br>
> > > > > > > > > > in-flight requests using<br>
> > PipelineHandler::setMaxQueueRequests().<br>
> > > > > > > > > ><br>
> > > > > > > > > > The queue request management introduced in the pipeline<br>
> > handler base<br>
> > > > > > > > > > class is now used by the IPU3 and RkISP1 pipeline<br>
> > handlers. This will<br>
> > > > > > > > > > prevent over-writing of frame contexts (i.e. FCQueue) in<br>
> > these two<br>
> > > > > > > > > > pipeline handlers.<br>
> > > > > > > > > ><br>
> > > > > > > > > > Signed-off-by: Umang Jain <<a href="mailto:umang.jain@ideasonboard.com" target="_blank">umang.jain@ideasonboard.com</a>><br>
> > > > > > > > > > ---<br>
> > > > > > > > > > include/libcamera/internal/pipeline_handler.h | 4 ++<br>
> > > > > > > > > > src/libcamera/pipeline/ipu3/ipu3.cpp | 1 +<br>
> > > > > > > > > > src/libcamera/pipeline/rkisp1/rkisp1.cpp | 1 +<br>
> > > > > > > > > > src/libcamera/pipeline_handler.cpp | 51<br>
> > ++++++++++++++++++-<br>
> > > > > > > > > > 4 files changed, 56 insertions(+), 1 deletion(-)<br>
> > > > > > > > > ><br>
> > > > > > > > > > diff --git a/include/libcamera/internal/pipeline_handler.h<br>
> > b/include/libcamera/internal/pipeline_handler.h<br>
> > > > > > > > > > index ec4f662d..83f8bd9f 100644<br>
> > > > > > > > > > --- a/include/libcamera/internal/pipeline_handler.h<br>
> > > > > > > > > > +++ b/include/libcamera/internal/pipeline_handler.h<br>
> > > > > > > > > > @@ -70,6 +70,7 @@ public:<br>
> > > > > > > > > > protected:<br>
> > > > > > > > > > void registerCamera(std::shared_ptr<Camera><br>
> > camera);<br>
> > > > > > > > > > void hotplugMediaDevice(MediaDevice *media);<br>
> > > > > > > > > > + void setMaxQueueRequests(uint32_t maxRequests);<br>
> > > > > > > > > ><br>
> > > > > > > > > > virtual int queueRequestDevice(Camera *camera,<br>
> > Request *request) = 0;<br>
> > > > > > > > > > virtual void stopDevice(Camera *camera) = 0;<br>
> > > > > > > > > > @@ -97,6 +98,9 @@ private:<br>
> > > > > > > > > > Mutex lock_;<br>
> > > > > > > > > > unsigned int useCount_<br>
> > LIBCAMERA_TSA_GUARDED_BY(lock_);<br>
> > > > > > > > > ><br>
> > > > > > > > > > + uint32_t maxQueueRequests_;<br>
> > > > > > > > > > + uint32_t requestsQueueCounter_;<br>
> > > > > > > > > > +<br>
> > > > > > > > > > friend class PipelineHandlerFactoryBase;<br>
> > > > > > > > > > };<br>
> > > > > > > > > ><br>
> > > > > > > > > > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp<br>
> > b/src/libcamera/pipeline/ipu3/ipu3.cpp<br>
> > > > > > > > > > index e4d79ea4..d1d42f78 100644<br>
> > > > > > > > > > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp<br>
> > > > > > > > > > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp<br>
> > > > > > > > > > @@ -422,6 +422,7 @@ CameraConfiguration::Status<br>
> > IPU3CameraConfiguration::validate()<br>
> > > > > > > > > > PipelineHandlerIPU3::PipelineHandlerIPU3(CameraManager<br>
> > *manager)<br>
> > > > > > > > > > : PipelineHandler(manager),<br>
> > cio2MediaDev_(nullptr), imguMediaDev_(nullptr)<br>
> > > > > > > > > > {<br>
> > > > > > > > > > + setMaxQueueRequests(ipa::ipu3::kMaxFrameContexts);<br>
> > > > > > > > > > }<br>
> > > > > > > > > ><br>
> > > > > > > > > > std::unique_ptr<CameraConfiguration><br>
> > > > > > > > > > diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp<br>
> > b/src/libcamera/pipeline/rkisp1/rkisp1.cpp<br>
> > > > > > > > > > index eb9ad65c..a48adba9 100644<br>
> > > > > > > > > > --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp<br>
> > > > > > > > > > +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp<br>
> > > > > > > > > > @@ -599,6 +599,7 @@ CameraConfiguration::Status<br>
> > RkISP1CameraConfiguration::validate()<br>
> > > > > > > > > ><br>
> > PipelineHandlerRkISP1::PipelineHandlerRkISP1(CameraManager *manager)<br>
> > > > > > > > > > : PipelineHandler(manager), hasSelfPath_(true)<br>
> > > > > > > > > > {<br>
> > > > > > > > > > +<br>
> > setMaxQueueRequests(ipa::rkisp1::kMaxFrameContexts);<br>
> > > > > > > > > > }<br>
> > > > > > > > > ><br>
> > > > > > > > > > std::unique_ptr<CameraConfiguration><br>
> > > > > > > > > > diff --git a/src/libcamera/pipeline_handler.cpp<br>
> > b/src/libcamera/pipeline_handler.cpp<br>
> > > > > > > > > > index cfade490..103f9db0 100644<br>
> > > > > > > > > > --- a/src/libcamera/pipeline_handler.cpp<br>
> > > > > > > > > > +++ b/src/libcamera/pipeline_handler.cpp<br>
> > > > > > > > > > @@ -67,7 +67,8 @@ LOG_DEFINE_CATEGORY(Pipeline)<br>
> > > > > > > > > > * through the PipelineHandlerFactoryBase::create()<br>
> > function.<br>
> > > > > > > > > > */<br>
> > > > > > > > > > PipelineHandler::PipelineHandler(CameraManager *manager)<br>
> > > > > > > > > > - : manager_(manager), useCount_(0)<br>
> > > > > > > > > > + : manager_(manager), useCount_(0),<br>
> > maxQueueRequests_(0),<br>
> > > > > > > > > > + requestsQueueCounter_(0)<br>
> > > > > > > > > > {<br>
> > > > > > > > > > }<br>
> > > > > > > > > ><br>
> > > > > > > > > > @@ -428,6 +429,9 @@ void<br>
> > PipelineHandler::doQueueRequest(Request *request)<br>
> > > > > > > > > > Camera::Private *data = camera->_d();<br>
> > > > > > > > > > data->queuedRequests_.push_back(request);<br>
> > > > > > > > > ><br>
> > > > > > > > > > + if (maxQueueRequests_)<br>
> > > > > > > > > > + requestsQueueCounter_++;<br>
> > > > > > > > > > +<br>
> > > > > > > > > > request->_d()->sequence_ =<br>
> > data->requestSequence_++;<br>
> > > > > > > > > ><br>
> > > > > > > > > > if (request->_d()->cancelled_) {<br>
> > > > > > > > > > @@ -455,6 +459,10 @@ void<br>
> > PipelineHandler::doQueueRequests()<br>
> > > > > > > > > > if (!request->_d()->prepared_)<br>
> > > > > > > > > > break;<br>
> > > > > > > > > ><br>
> > > > > > > > > > + if (maxQueueRequests_ &&<br>
> > > > > > > > > > + requestsQueueCounter_ >=<br>
> > maxQueueRequests_)<br>
> > > > > > > > > > + break;<br>
> > > > > > > > > > +<br>
> > > > > > > > > > doQueueRequest(request);<br>
> > > > > > > > > > waitingRequests_.pop();<br>
> > > > > > > > > > }<br>
> > > > > > > > > > @@ -531,6 +539,9 @@ void<br>
> > PipelineHandler::completeRequest(Request *request)<br>
> > > > > > > > > > ASSERT(!req->hasPendingBuffers());<br>
> > > > > > > > > > data->queuedRequests_.pop_front();<br>
> > > > > > > > > > camera->requestComplete(req);<br>
> > > > > > > > > > +<br>
> > > > > > > > > > + if (maxQueueRequests_)<br>
> > > > > > > > > > + requestsQueueCounter_--;<br>
> > > > > > > > > > }<br>
> > > > > > > > > > }<br>
> > > > > > > > > ><br>
> > > > > > > > > > @@ -647,6 +658,44 @@ void PipelineHandler::disconnect()<br>
> > > > > > > > > > * constant for the whole lifetime of the pipeline<br>
> > handler.<br>
> > > > > > > > > > */<br>
> > > > > > > > > ><br>
> > > > > > > > > > +/**<br>
> > > > > > > > > > + * \var PipelineHandler::maxQueueRequests_<br>
> > > > > > > > > > + * \brief Maximum number of in-flight requests that can<br>
> > be queued<br>
> > > > > > > > > > + *<br>
> > > > > > > > > > + * A hardware can handle a certain number of maximum<br>
> > requests at a given<br>
> > > > > > > > > > + * point. If such a constraint exists, set<br>
> > maxQueueRequests_ via<br>
> > > > > > > > > > + * \a setMaxQueueRequests() in the derived pipeline<br>
> > handler.<br>
> > > > > > > > > > + *<br>
> > > > > > > > > > + * The derived pipeline handler can choose not to define<br>
> > such constraint as<br>
> > > > > > > > > > + * well. In that case, the derived pipeline handler can<br>
> > avoid setting<br>
> > > > > > > > > > + * \a setMaxQueueReqeuests(), hence \a maxQueueRequests_<br>
> > and<br>
> > > > > > > > > > + * \a requestsQueueCounter_ will be 0.<br>
> > > > > > > > > > + */<br>
> > > > > > > > > > +<br>
> > > > > > > > > > +/**<br>
> > > > > > > > > > + * \var PipelineHandler::requestsQueueCounter_<br>
> > > > > > > > > > + * \brief Number of requests queued to the underlying<br>
> > hardware<br>
> > > > > > > > > > + *<br>
> > > > > > > > > > + * If \a setMaxQueueRequests() is set by the derived<br>
> > pipeline handler,<br>
> > > > > > > > > > + * requestsQueueCounter_ reflects the number of requests<br>
> > queued<br>
> > > > > > > > > > + * to the underlying hardware by the pipeline handler.<br>
> > > > > > > > > > + */<br>
> > > > > > > > > > +<br>
> > > > > > > > > > +/**<br>
> > > > > > > > > > + * \brief Sets the maximum number of requests that can be<br>
> > queued<br>
> > > > > > > > > > + * \param[in] maxRequests Maximum number of in-flight<br>
> > requests<br>
> > > > > > > > > > + *<br>
> > > > > > > > > > + * A hardware can handle a certain number of requests at<br>
> > a given point.<br>
> > > > > > > > > > + * This function sets the maximum number of in-flight<br>
> > requests that can<br>
> > > > > > > > > > + * be queued to the hardware by the pipeline handler.<br>
> > Each derived pipeline<br>
> > > > > > > > > > + * handler should set the maximum number of in-flight<br>
> > requests it can handle<br>
> > > > > > > > > > + * at a given point using this function, if at all such a<br>
> > constraint exists.<br>
> > > > > > > > > > + */<br>
> > > > > > > > > > +void PipelineHandler::setMaxQueueRequests(uint32_t<br>
> > maxRequests)<br>
> > > > > > > > > > +{<br>
> > > > > > > > > > + maxQueueRequests_ = maxRequests;<br>
> > > > > > > > > > +}<br>
> > > > > > > > > > +<br>
> > > > > > > > > > /**<br>
> > > > > > > > > > * \fn PipelineHandler::name()<br>
> > > > > > > > > > * \brief Retrieve the pipeline handler name<br>
> > > > > > > > > > --<br>
> > > > > > > > > > 2.38.1<br>
> > > > > > > > > ><br>
> > > > > ><br>
> ><br>
</blockquote></div></div>