[{"id":39374,"web_url":"https://patchwork.libcamera.org/comment/39374/","msgid":"<b35e55c4-1b9e-459c-a48b-9146f5b50dc1@collabora.com>","date":"2026-06-24T11:10:52","subject":"Re: [PATCH 10/10] libcamera: software_isp: debayer_egl: Implement\n\tinput/output frame caching mechanism","submitter":{"id":140,"url":"https://patchwork.libcamera.org/api/people/140/","name":"Robert Mader","email":"robert.mader@collabora.com"},"content":"Thanks a lot!\n\nI tested this on a FP5 and a Pixel 3a and can not only confirm the \nimprovements on the timings but also observed lower CPU usage. In \nparticular in combination with dmabuf imports the CPU usage seems to \nessentially collapse when eyeballing htop, see below.\n\nSo for the whole series I can already give:\n\nTested-by: Robert Mader <robert.mader@collabora.com>\n\nWill now go over the individual commits.\n\n---\n\nFairPhone 5\n\ncam -c 1 -s width=1920,height=1080 --capture=60\n\nINFO SoftwareIsp software_isp.cpp:299 Input 2048x1536-RGGB-10-CSI2P \nstride 2560\ndmabuf import succeeds\n\nbefore:\nINFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 365691us, \n12189 us/frame\n~39% CPU time in Wireplumber/Pipewire when running Snapshot\n\nafter:\nINFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 204924us, \n6830 us/frame\n~13% CPU time in Wireplumber/Pipewire when running Snapshot\n\n-\n\ncam -c 2 -s width=1920,height=1080 --capture=60\n\nINFO SoftwareIsp software_isp.cpp:299 Input 4080x3072-GRBG-10-CSI2P \nstride 5104\ndmabuf import fails\n\nbefore:\nINFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 687332us, \n22911 us/frame\n~63% CPU time in Wireplumber/Pipewire when running Snapshot\n\nafter:\nINFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 579945us, \n19331 us/frame\n~53% CPU time in Wireplumber/Pipewire when running Snapshot\n\n---\n\nPixel 3a\n\ncam -c 1 -s width=1920,height=1080 --capture=60\n\nINFO SoftwareIsp software_isp.cpp:299 Input 1936x1096-RGGB-10-CSI2P \nstride 2432\ndmabuf import succeeds\n\nbefore:\nINFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 489368us, \n16312 us/frame\n~59% CPU time in Wireplumber/Pipewire when running Snapshot\n\nafter:\nINFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 353912us, \n11797 us/frame\n~17% CPU time in Wireplumber/Pipewire when running Snapshot\n\n-\n\ncam -c 2 -s width=1920,height=1080 --capture=60\n\nINFO SoftwareIsp software_isp.cpp:299 Input 4032x3024-RGGB-10-CSI2P \nstride 5040\ndmabuf import fails\n\nbefore:\nINFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 916702us, \n30556 us/frame\n~57% CPU time in Wireplumber/Pipewire when running Snapshot\n\nafter:\nINFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 771620us, \n25720 us/frame\n~47% CPU time in Wireplumber/Pipewire when running Snapshot\n\nOn 24.06.26 10:58, Bryan O'Donoghue wrote:\n> Implement a texture caching mechanism for both input and output frames and\n> for both types of input frame.\n>\n> The before/after on a Qualcomm x1e is:\n>\n> 9.737ms per frame\n> 5.691ms per frame\n>\n> The before/after on a Qualcomm sm8250 is:\n>\n> 21.710ms per frame\n> 17.336ms per frame\n>\n> for i in {1..20} do\n> cam -c /base/soc@0/cci@ac16000/i2c-bus@1/camera@10 -s width=1920,height=1080 --capture=60\n>\n> Interestingly there appears to be an absolute ~ 4.x ms per frame uplift as\n> opposed to what intuition might suggest a proportional.\n>\n> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>\n> ---\n>   src/libcamera/software_isp/debayer_egl.cpp | 108 +++++++++++++++++----\n>   src/libcamera/software_isp/debayer_egl.h   |  12 ++-\n>   2 files changed, 100 insertions(+), 20 deletions(-)\n>\n> diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp\n> index 0568c413b..8ac5cb76f 100644\n> --- a/src/libcamera/software_isp/debayer_egl.cpp\n> +++ b/src/libcamera/software_isp/debayer_egl.cpp\n> @@ -355,6 +355,12 @@ int DebayerEGL::configure(const StreamConfiguration &inputCfg,\n>   \t */\n>   \tstats_->setWindow(Rectangle(window_.size()));\n>   \n> +\tinputBufferCache_ = std::make_unique<V4L2BufferCache>(inputCfg.bufferCount);\n> +\toutputBufferCache_ = std::make_unique<V4L2BufferCache>(outputCfg.bufferCount);\n> +\n> +\teglImageBayerIn_.resize(inputCfg.bufferCount);\n> +\teglImageBayerOut_.resize(outputCfg.bufferCount);\n> +\n>   \treturn 0;\n>   }\n>   \n> @@ -514,34 +520,106 @@ void DebayerEGL::setShaderVariableValues(eGLImage &eglImageIn, const DebayerPara\n>   \treturn;\n>   }\n>   \n> -int DebayerEGL::debayerGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams &params, std::optional<MappedFrameBuffer> *inMapped, std::optional<DmaSyncer> *inDmaSyncer)\n> +int DebayerEGL::getBufferCache(V4L2BufferCache &cache, FrameBuffer *framebuffer, bool &cache_hit)\n>   {\n> -\t/* eGL context switch */\n> -\tegl_.makeCurrent();\n> +\tint cache_idx;\n> +\n> +\tcache_idx = cache.get(*framebuffer, cache_hit);\n> +\tif (cache_idx < 0) {\n> +\t\tLOG(Debayer, Error) << \"buffer exceeds configured cache size\";\n> +\t\treturn -ENODEV;\n> +\t}\n> +\tcache.put(cache_idx);\n> +\n> +\treturn cache_idx;\n> +}\n> +\n> +eGLImage *DebayerEGL::getCachedInputFrameBuffer(FrameBuffer *input, std::optional<MappedFrameBuffer> *inMapped, std::optional<DmaSyncer> *inDmaSyncer)\n> +{\n> +\teGLImage *eglImageIn;\n> +\tbool cache_hit;\n> +\tint cache_idx;\n> +\n> +\tcache_idx = getBufferCache(*inputBufferCache_, input, cache_hit);\n> +\tif (cache_idx < 0)\n> +\t\treturn nullptr;\n> +\n> +\tif (!cache_hit) {\n> +\t\teglImageBayerIn_[cache_idx] = std::make_unique<eGLImage>(glFormat_, inputConfig_.stride / bytesPerPixel_,\n> +\t\t\t\t\t\t\t\t\t height_, inputConfig_.stride, GL_TEXTURE0, 0);\n> +\t}\n> +\n> +\teglImageIn = eglImageBayerIn_[cache_idx].get();\n>   \n>   \t/* Try to create texture for input buffer via dmabuf import */\n> -\tif (use_dmabuf_) {\n> -\t\tif (egl_.createInputDMABufTexture2D(*eglImageBayerIn_, input->planes()[0].fd.get()) != 0) {\n> +\tif (use_dmabuf_ && !cache_hit) {\n> +\t\tif (egl_.createInputDMABufTexture2D(*eglImageIn, input->planes()[0].fd.get()) != 0) {\n>   \t\t\tuse_dmabuf_ = false;\n>   \t\t\tLOG(Debayer, Info) << \"Importing input buffer with DMABuf import failed, falling back to upload\";\n>   \t\t}\n>   \t}\n>   \n> +\t/* Cache hit using dmabuf activate and bind */\n> +\tif (use_dmabuf_ && cache_hit) {\n> +\t\tegl_.activateBindTexture(*eglImageIn);\n> +\t}\n> +\n>   \t/* Otherwise create texture for input buffer via upload from CPU */\n>   \tif (!use_dmabuf_) {\n>   \t\tinDmaSyncer->emplace(input->planes()[0].fd, DmaSyncer::SyncType::Read);\n>   \t\tinMapped->emplace(input, MappedFrameBuffer::MapFlag::Read);\n>   \t\tif (!inMapped->value().isValid()) {\n>   \t\t\tLOG(Debayer, Error) << \"mmap-ing buffer(s) failed\";\n> -\t\t\treturn -ENODEV;\n> +\t\t\treturn nullptr;\n>   \t\t}\n> -\t\tegl_.createInputTexture2D(*eglImageBayerIn_, inMapped->value().planes()[0].data());\n> +\t\tif (cache_hit)\n> +\t\t\tegl_.updateInputTexture2D(*eglImageIn, inMapped->value().planes()[0].data());\n> +\t\telse\n> +\t\t\tegl_.createInputTexture2D(*eglImageIn, inMapped->value().planes()[0].data());\n>   \t}\n>   \n> -\t/* Generate the output render framebuffer as render to texture */\n> -\tegl_.createOutputDMABufTexture2D(*eglImageBayerOut_, output->planes()[0].fd.get());\n> +\treturn eglImageIn;\n> +}\n> +\n> +eGLImage *DebayerEGL::getCachedOutputFrameBuffer(FrameBuffer *output)\n> +{\n> +\teGLImage *eglImageOut;\n> +\tbool cache_hit;\n> +\tint cache_idx;\n> +\n> +\tcache_idx = getBufferCache(*outputBufferCache_, output, cache_hit);\n> +\tif (cache_idx < 0)\n> +\t\treturn nullptr;\n> +\n> +\tif (!cache_hit) {\n> +\t\teglImageBayerOut_[cache_idx] = std::make_unique<eGLImage>(GL_RGBA, outputSize_.width,\n> +\t\t\t\t\t\t\t\t\t  outputSize_.height, outputConfig_.stride, GL_TEXTURE1, 1);\n> +\t\tegl_.createOutputDMABufTexture2D(*eglImageBayerOut_[cache_idx], output->planes()[0].fd.get());\n> +\t}\n> +\teglImageOut = eglImageBayerOut_[cache_idx].get();\n> +\n> +\treturn eglImageOut;\n> +}\n> +\n> +int DebayerEGL::debayerGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams &params, std::optional<MappedFrameBuffer> *inMapped, std::optional<DmaSyncer> *inDmaSyncer)\n> +{\n> +\teGLImage *eglImageIn;\n> +\teGLImage *eglImageOut;\n> +\n> +\t/* eGL context switch */\n> +\tegl_.makeCurrent();\n> +\n> +\teglImageIn = getCachedInputFrameBuffer(input, inMapped, inDmaSyncer);\n> +\tif (!eglImageIn)\n> +\t\treturn -ENOMEM;\n> +\n> +\teglImageOut = getCachedOutputFrameBuffer(output);\n> +\tif (!eglImageOut)\n> +\t\treturn -ENOMEM;\n> +\n> +\tegl_.attachTextureToFBO(*eglImageOut);\n> +\tsetShaderVariableValues(*eglImageIn, params);\n>   \n> -\tsetShaderVariableValues(*eglImageBayerIn_, params);\n>   \tglViewport(0, 0, width_, height_);\n>   \tglClear(GL_COLOR_BUFFER_BIT);\n>   \tglDrawArrays(GL_TRIANGLE_FAN, 0, DEBAYER_OPENGL_COORDS);\n> @@ -623,19 +701,13 @@ int DebayerEGL::start()\n>   \tif (initBayerShaders(inputPixelFormat_, outputPixelFormat_))\n>   \t\treturn -EINVAL;\n>   \n> -\t/* Raw bayer input as texture */\n> -\teglImageBayerIn_ = std::make_unique<eGLImage>(glFormat_, inputConfig_.stride / bytesPerPixel_, height_, inputConfig_.stride, GL_TEXTURE0, 0);\n> -\n> -\t/* Texture we will render to */\n> -\teglImageBayerOut_ = std::make_unique<eGLImage>(GL_RGBA, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE1, 1);\n> -\n>   \treturn 0;\n>   }\n>   \n>   void DebayerEGL::stop()\n>   {\n> -\teglImageBayerOut_.reset();\n> -\teglImageBayerIn_.reset();\n> +\teglImageBayerOut_.clear();\n> +\teglImageBayerIn_.clear();\n>   \n>   \tif (programId_)\n>   \t\tglDeleteProgram(programId_);\n> diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h\n> index d8509e9f2..238fe7345 100644\n> --- a/src/libcamera/software_isp/debayer_egl.h\n> +++ b/src/libcamera/software_isp/debayer_egl.h\n> @@ -22,6 +22,7 @@\n>   #include \"libcamera/internal/mapped_framebuffer.h\"\n>   #include \"libcamera/internal/software_isp/benchmark.h\"\n>   #include \"libcamera/internal/software_isp/swstats_cpu.h\"\n> +#include \"libcamera/internal/v4l2_videodevice.h\"\n>   \n>   #include <EGL/egl.h>\n>   #include <EGL/eglext.h>\n> @@ -70,14 +71,21 @@ private:\n>   \n>   \tbool use_dmabuf_;\n>   \n> +\tint getBufferCache(V4L2BufferCache &buffercache, FrameBuffer *framebuffer, bool &hit);\n> +\teGLImage *getCachedInputFrameBuffer(FrameBuffer *input, std::optional<MappedFrameBuffer> *inMapped, std::optional<DmaSyncer> *inDmaSyncer);\n> +\teGLImage *getCachedOutputFrameBuffer(FrameBuffer *output);\n> +\n> +\tstd::unique_ptr<V4L2BufferCache> inputBufferCache_;\n> +\tstd::unique_ptr<V4L2BufferCache> outputBufferCache_;\n> +\n>   \t/* Shader program identifiers */\n>   \tGLuint vertexShaderId_ = 0;\n>   \tGLuint fragmentShaderId_ = 0;\n>   \tGLuint programId_ = 0;\n>   \n>   \t/* Pointer to object representing input texture */\n> -\tstd::unique_ptr<eGLImage> eglImageBayerIn_;\n> -\tstd::unique_ptr<eGLImage> eglImageBayerOut_;\n> +\tstd::vector<std::unique_ptr<eGLImage>> eglImageBayerIn_;\n> +\tstd::vector<std::unique_ptr<eGLImage>> eglImageBayerOut_;\n>   \n>   \t/* Shader parameters */\n>   \tfloat firstRed_x_;","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 756FEC3304\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 24 Jun 2026 11:11:06 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 7476F65899;\n\tWed, 24 Jun 2026 13:11:05 +0200 (CEST)","from sender4-op-o12.zoho.com (sender4-op-o12.zoho.com\n\t[136.143.188.12])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 42D4465718\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 24 Jun 2026 13:11:03 +0200 (CEST)","by mx.zohomail.com with SMTPS id 1782299455269317.43847881677016; \n\tWed, 24 Jun 2026 04:10:55 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=collabora.com\n\theader.i=robert.mader@collabora.com header.b=\"kJ78LpCM\"; \n\tdkim-atps=neutral","ARC-Seal":"i=1; a=rsa-sha256; t=1782299458; cv=none; \n\td=zohomail.com; s=zohoarc; \n\tb=erDET75zRfJhvkB0ZZOYrOAVBE+X3cy7tTIn3Zm34JvUnV5wgepfrQAluYA44vtbkb2epTQO/jh/fZS80+U+VA5S3f+uaRCAkiiS/ZciAYZAaqaB+F+5WUGhU5x98dNC65nlwMl/hJcJlZU7kGdTIUhjmi8hjKA4ibkDxQfuu/M=","ARC-Message-Signature":"i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; \n\ts=zohoarc; t=1782299458;\n\th=Content-Type:Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To:Cc;\n\tbh=BCDYcnJsuG81KdDwMWPsLeqfL2wHfZUQY68LTaKpGQQ=; \n\tb=HXRq3nBujRWQN6w0Dht7Zkps4e4BqvL4GfyS1E+yJYFzUfamnZsiVx8NRtki/HUaBIZ+Rn0/DWp/J+89lkQ+8jbF6+xwD6R0dz7cMf+1KqtdIsva96Gi9L/OvvTXV1acUX5Yv0TmMoZaD9mY2SDNDO/2DVkm3c7cpMWRH143XM8=","ARC-Authentication-Results":"i=1; mx.zohomail.com;\n\tdkim=pass  header.i=collabora.com;\n\tspf=pass  smtp.mailfrom=robert.mader@collabora.com;\n\tdmarc=pass header.from=<robert.mader@collabora.com>","DKIM-Signature":"v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1782299458;\n\ts=zohomail; d=collabora.com; i=robert.mader@collabora.com;\n\th=Message-ID:Date:Date:MIME-Version:Subject:Subject:To:To:References:From:From:In-Reply-To:Content-Type:Content-Transfer-Encoding:Message-Id:Reply-To:Cc;\n\tbh=BCDYcnJsuG81KdDwMWPsLeqfL2wHfZUQY68LTaKpGQQ=;\n\tb=kJ78LpCMkbUFnVSOdE0l7Z5mUfkQ484Es39vkTVP6Vh8l7zNzirHGIdTt1rcOcPa\n\t7x2Ip8ixuBLI3XG1nw9aKTdU+xRoc2VfVUOt08HmlxkitRMf2L7ADmsd4uVLhXEWma5\n\tC3U4qi8tNkAXIm20p0GLUTxmckT2/vpQ3xgk6N2k=","Message-ID":"<b35e55c4-1b9e-459c-a48b-9146f5b50dc1@collabora.com>","Date":"Wed, 24 Jun 2026 13:10:52 +0200","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH 10/10] libcamera: software_isp: debayer_egl: Implement\n\tinput/output frame caching mechanism","To":"libcamera-devel@lists.libcamera.org","References":"<20260624085849.873784-1-bryan.odonoghue@linaro.org>\n\t<20260624085849.873784-11-bryan.odonoghue@linaro.org>","Content-Language":"en-US, de-DE, en-GB","From":"Robert Mader <robert.mader@collabora.com>","In-Reply-To":"<20260624085849.873784-11-bryan.odonoghue@linaro.org>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"7bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":39389,"web_url":"https://patchwork.libcamera.org/comment/39389/","msgid":"<fb093756-b0db-4a5a-85ca-2dd282b39476@collabora.com>","date":"2026-06-24T12:35:16","subject":"Re: [PATCH 10/10] libcamera: software_isp: debayer_egl: Implement\n\tinput/output frame caching mechanism","submitter":{"id":140,"url":"https://patchwork.libcamera.org/api/people/140/","name":"Robert Mader","email":"robert.mader@collabora.com"},"content":"On 24.06.26 10:58, Bryan O'Donoghue wrote:\n> Implement a texture caching mechanism for both input and output frames and\n> for both types of input frame.\n>\n> The before/after on a Qualcomm x1e is:\n>\n> 9.737ms per frame\n> 5.691ms per frame\n>\n> The before/after on a Qualcomm sm8250 is:\n>\n> 21.710ms per frame\n> 17.336ms per frame\n>\n> for i in {1..20} do\n> cam -c /base/soc@0/cci@ac16000/i2c-bus@1/camera@10 -s width=1920,height=1080 --capture=60\n>\n> Interestingly there appears to be an absolute ~ 4.x ms per frame uplift as\n> opposed to what intuition might suggest a proportional.\n>\n> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>\n> ---\n>   src/libcamera/software_isp/debayer_egl.cpp | 108 +++++++++++++++++----\n>   src/libcamera/software_isp/debayer_egl.h   |  12 ++-\n>   2 files changed, 100 insertions(+), 20 deletions(-)\n>\n> diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp\n> index 0568c413b..8ac5cb76f 100644\n> --- a/src/libcamera/software_isp/debayer_egl.cpp\n> +++ b/src/libcamera/software_isp/debayer_egl.cpp\n> @@ -355,6 +355,12 @@ int DebayerEGL::configure(const StreamConfiguration &inputCfg,\n>   \t */\n>   \tstats_->setWindow(Rectangle(window_.size()));\n>   \n> +\tinputBufferCache_ = std::make_unique<V4L2BufferCache>(inputCfg.bufferCount);\n> +\toutputBufferCache_ = std::make_unique<V4L2BufferCache>(outputCfg.bufferCount);\n> +\n> +\teglImageBayerIn_.resize(inputCfg.bufferCount);\n> +\teglImageBayerOut_.resize(outputCfg.bufferCount);\n> +\n>   \treturn 0;\n>   }\n>   \n> @@ -514,34 +520,106 @@ void DebayerEGL::setShaderVariableValues(eGLImage &eglImageIn, const DebayerPara\n>   \treturn;\n>   }\n>   \n> -int DebayerEGL::debayerGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams &params, std::optional<MappedFrameBuffer> *inMapped, std::optional<DmaSyncer> *inDmaSyncer)\n> +int DebayerEGL::getBufferCache(V4L2BufferCache &cache, FrameBuffer *framebuffer, bool &cache_hit)\nMaybe something like lookupFramebufferFromBufferCache()? \ngetBufferCache() sounds like it would return a V4L2BufferCache.\n>   {\n> -\t/* eGL context switch */\n> -\tegl_.makeCurrent();\n> +\tint cache_idx;\n> +\n> +\tcache_idx = cache.get(*framebuffer, cache_hit);\n> +\tif (cache_idx < 0) {\n> +\t\tLOG(Debayer, Error) << \"buffer exceeds configured cache size\";\n> +\t\treturn -ENODEV;\n> +\t}\n> +\tcache.put(cache_idx);\n> +\n> +\treturn cache_idx;\n> +}\n> +\n> +eGLImage *DebayerEGL::getCachedInputFrameBuffer(FrameBuffer *input, std::optional<MappedFrameBuffer> *inMapped, std::optional<DmaSyncer> *inDmaSyncer)\n> +{\n> +\teGLImage *eglImageIn;\n> +\tbool cache_hit;\n> +\tint cache_idx;\n> +\n> +\tcache_idx = getBufferCache(*inputBufferCache_, input, cache_hit);\n> +\tif (cache_idx < 0)\n> +\t\treturn nullptr;\n> +\n> +\tif (!cache_hit) {\n> +\t\teglImageBayerIn_[cache_idx] = std::make_unique<eGLImage>(glFormat_, inputConfig_.stride / bytesPerPixel_,\n> +\t\t\t\t\t\t\t\t\t height_, inputConfig_.stride, GL_TEXTURE0, 0);\n> +\t}\n> +\n> +\teglImageIn = eglImageBayerIn_[cache_idx].get();\n>   \n>   \t/* Try to create texture for input buffer via dmabuf import */\n> -\tif (use_dmabuf_) {\n> -\t\tif (egl_.createInputDMABufTexture2D(*eglImageBayerIn_, input->planes()[0].fd.get()) != 0) {\n> +\tif (use_dmabuf_ && !cache_hit) {\n> +\t\tif (egl_.createInputDMABufTexture2D(*eglImageIn, input->planes()[0].fd.get()) != 0) {\n>   \t\t\tuse_dmabuf_ = false;\n>   \t\t\tLOG(Debayer, Info) << \"Importing input buffer with DMABuf import failed, falling back to upload\";\n>   \t\t}\n>   \t}\n>   \n> +\t/* Cache hit using dmabuf activate and bind */\n> +\tif (use_dmabuf_ && cache_hit) {\n> +\t\tegl_.activateBindTexture(*eglImageIn);\n> +\t}\n> +\n>   \t/* Otherwise create texture for input buffer via upload from CPU */\n>   \tif (!use_dmabuf_) {\n>   \t\tinDmaSyncer->emplace(input->planes()[0].fd, DmaSyncer::SyncType::Read);\n>   \t\tinMapped->emplace(input, MappedFrameBuffer::MapFlag::Read);\n>   \t\tif (!inMapped->value().isValid()) {\n>   \t\t\tLOG(Debayer, Error) << \"mmap-ing buffer(s) failed\";\n> -\t\t\treturn -ENODEV;\n> +\t\t\treturn nullptr;\n>   \t\t}\n> -\t\tegl_.createInputTexture2D(*eglImageBayerIn_, inMapped->value().planes()[0].data());\n> +\t\tif (cache_hit)\n> +\t\t\tegl_.updateInputTexture2D(*eglImageIn, inMapped->value().planes()[0].data());\n> +\t\telse\n> +\t\t\tegl_.createInputTexture2D(*eglImageIn, inMapped->value().planes()[0].data());\n>   \t}\n>   \n> -\t/* Generate the output render framebuffer as render to texture */\n> -\tegl_.createOutputDMABufTexture2D(*eglImageBayerOut_, output->planes()[0].fd.get());\n> +\treturn eglImageIn;\n> +}\n> +\n> +eGLImage *DebayerEGL::getCachedOutputFrameBuffer(FrameBuffer *output)\n> +{\n> +\teGLImage *eglImageOut;\n> +\tbool cache_hit;\n> +\tint cache_idx;\n> +\n> +\tcache_idx = getBufferCache(*outputBufferCache_, output, cache_hit);\n> +\tif (cache_idx < 0)\n> +\t\treturn nullptr;\n> +\n> +\tif (!cache_hit) {\n> +\t\teglImageBayerOut_[cache_idx] = std::make_unique<eGLImage>(GL_RGBA, outputSize_.width,\n> +\t\t\t\t\t\t\t\t\t  outputSize_.height, outputConfig_.stride, GL_TEXTURE1, 1);\n> +\t\tegl_.createOutputDMABufTexture2D(*eglImageBayerOut_[cache_idx], output->planes()[0].fd.get());\n> +\t}\n\nDon't we need to call\n\negl_.activateBindTexture(*eglImageOut);\n\nin the else-case here? It's called in createDMABufTexture2D().\n\nIt seems to work for me either way, but I'm confused why. Is it somehow \nimplicit via the attachTextureToFBO() below?\n\n> +\teglImageOut = eglImageBayerOut_[cache_idx].get();\n> +\n> +\treturn eglImageOut;\n> +}\n> +\n> +int DebayerEGL::debayerGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams &params, std::optional<MappedFrameBuffer> *inMapped, std::optional<DmaSyncer> *inDmaSyncer)\n> +{\n> +\teGLImage *eglImageIn;\n> +\teGLImage *eglImageOut;\n> +\n> +\t/* eGL context switch */\n> +\tegl_.makeCurrent();\n> +\n> +\teglImageIn = getCachedInputFrameBuffer(input, inMapped, inDmaSyncer);\n> +\tif (!eglImageIn)\n> +\t\treturn -ENOMEM;\n> +\n> +\teglImageOut = getCachedOutputFrameBuffer(output);\n> +\tif (!eglImageOut)\n> +\t\treturn -ENOMEM;\n> +\n> +\tegl_.attachTextureToFBO(*eglImageOut);\n> +\tsetShaderVariableValues(*eglImageIn, params);\n>   \n> -\tsetShaderVariableValues(*eglImageBayerIn_, params);\n>   \tglViewport(0, 0, width_, height_);\n>   \tglClear(GL_COLOR_BUFFER_BIT);\n>   \tglDrawArrays(GL_TRIANGLE_FAN, 0, DEBAYER_OPENGL_COORDS);\n> @@ -623,19 +701,13 @@ int DebayerEGL::start()\n>   \tif (initBayerShaders(inputPixelFormat_, outputPixelFormat_))\n>   \t\treturn -EINVAL;\n>   \n> -\t/* Raw bayer input as texture */\n> -\teglImageBayerIn_ = std::make_unique<eGLImage>(glFormat_, inputConfig_.stride / bytesPerPixel_, height_, inputConfig_.stride, GL_TEXTURE0, 0);\n> -\n> -\t/* Texture we will render to */\n> -\teglImageBayerOut_ = std::make_unique<eGLImage>(GL_RGBA, outputSize_.width, outputSize_.height, outputConfig_.stride, GL_TEXTURE1, 1);\n> -\n>   \treturn 0;\n>   }\n>   \n>   void DebayerEGL::stop()\n>   {\n> -\teglImageBayerOut_.reset();\n> -\teglImageBayerIn_.reset();\n> +\teglImageBayerOut_.clear();\n> +\teglImageBayerIn_.clear();\n>   \n>   \tif (programId_)\n>   \t\tglDeleteProgram(programId_);\n> diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h\n> index d8509e9f2..238fe7345 100644\n> --- a/src/libcamera/software_isp/debayer_egl.h\n> +++ b/src/libcamera/software_isp/debayer_egl.h\n> @@ -22,6 +22,7 @@\n>   #include \"libcamera/internal/mapped_framebuffer.h\"\n>   #include \"libcamera/internal/software_isp/benchmark.h\"\n>   #include \"libcamera/internal/software_isp/swstats_cpu.h\"\n> +#include \"libcamera/internal/v4l2_videodevice.h\"\n>   \n>   #include <EGL/egl.h>\n>   #include <EGL/eglext.h>\n> @@ -70,14 +71,21 @@ private:\n>   \n>   \tbool use_dmabuf_;\n>   \n> +\tint getBufferCache(V4L2BufferCache &buffercache, FrameBuffer *framebuffer, bool &hit);\n> +\teGLImage *getCachedInputFrameBuffer(FrameBuffer *input, std::optional<MappedFrameBuffer> *inMapped, std::optional<DmaSyncer> *inDmaSyncer);\n> +\teGLImage *getCachedOutputFrameBuffer(FrameBuffer *output);\n> +\n> +\tstd::unique_ptr<V4L2BufferCache> inputBufferCache_;\n> +\tstd::unique_ptr<V4L2BufferCache> outputBufferCache_;\n> +\n>   \t/* Shader program identifiers */\n>   \tGLuint vertexShaderId_ = 0;\n>   \tGLuint fragmentShaderId_ = 0;\n>   \tGLuint programId_ = 0;\n>   \n>   \t/* Pointer to object representing input texture */\n> -\tstd::unique_ptr<eGLImage> eglImageBayerIn_;\n> -\tstd::unique_ptr<eGLImage> eglImageBayerOut_;\n> +\tstd::vector<std::unique_ptr<eGLImage>> eglImageBayerIn_;\n> +\tstd::vector<std::unique_ptr<eGLImage>> eglImageBayerOut_;\n>   \n>   \t/* Shader parameters */\n>   \tfloat firstRed_x_;\n\nTwo small comments, otherwise LGTM - and works great!\n\nReviewed-by: Robert Mader <robert.mader@collabora.com>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id B15CCC3306\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 24 Jun 2026 12:35:27 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id DAF8E658B0;\n\tWed, 24 Jun 2026 14:35:26 +0200 (CEST)","from sender4-op-o12.zoho.com (sender4-op-o12.zoho.com\n\t[136.143.188.12])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id F120465718\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 24 Jun 2026 14:35:24 +0200 (CEST)","by mx.zohomail.com with SMTPS id 1782304519064368.3162564639142;\n\tWed, 24 Jun 2026 05:35:19 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=collabora.com\n\theader.i=robert.mader@collabora.com header.b=\"UDH+s70v\"; \n\tdkim-atps=neutral","ARC-Seal":"i=1; a=rsa-sha256; t=1782304522; cv=none; \n\td=zohomail.com; s=zohoarc; \n\tb=A8M9f9/XahONGZWbFdhwZByDn84p6BbidJynwjKDH2ZckoyUNQfdFlXtE6hxj7rfIXDqv7bZceTJrCQfYiZK9b8hkc/CBEcVuyPdDYxo9cAsQMu+MkBEWW8+tA9b7yQ4BLFH+HZwZxnuq1LhiU98l9GKB9GsKWQm1o2b+KevORc=","ARC-Message-Signature":"i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; \n\ts=zohoarc; t=1782304522;\n\th=Content-Type:Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To:Cc;\n\tbh=+s1vp8yjeIIf05SP2VWi+MTo1d5YMm0id55if/+z/Dw=; \n\tb=OFUobyYIDcEVrWL2Nb9cF72jePYPfNUrUzXqByumMXYMP43qPprCaEbDXTc6ldkSiA4s0RHjBJjF0aG/lihr+FwKpZdruWfB0lrw+2UgOCa+1DLAsvqqLydcHu7LJTeFW5oo7r0QTvPw3SzaDCbRG2IiHazbcaOim5+iGHmmolM=","ARC-Authentication-Results":"i=1; mx.zohomail.com;\n\tdkim=pass  header.i=collabora.com;\n\tspf=pass  smtp.mailfrom=robert.mader@collabora.com;\n\tdmarc=pass header.from=<robert.mader@collabora.com>","DKIM-Signature":"v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1782304522;\n\ts=zohomail; d=collabora.com; i=robert.mader@collabora.com;\n\th=Message-ID:Date:Date:MIME-Version:Subject:Subject:To:To:References:From:From:In-Reply-To:Content-Type:Content-Transfer-Encoding:Message-Id:Reply-To:Cc;\n\tbh=+s1vp8yjeIIf05SP2VWi+MTo1d5YMm0id55if/+z/Dw=;\n\tb=UDH+s70vwoKzXffr4Gpj9UG7veC6wA0qjK5/f+BJq0cCfGelhWKFm2ik+CkS0DTq\n\tToqJqIvxFs7axtLUsFgNs5+fXKTlXQLFKlsN/QTwviypDwRRtOqkiNvhk9x6eNhSiyD\n\t8ASBHO9YNDevazIkAjNZaKxspAZfbosV0nsdgLXI=","Message-ID":"<fb093756-b0db-4a5a-85ca-2dd282b39476@collabora.com>","Date":"Wed, 24 Jun 2026 14:35:16 +0200","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH 10/10] libcamera: software_isp: debayer_egl: Implement\n\tinput/output frame caching mechanism","To":"libcamera-devel@lists.libcamera.org","References":"<20260624085849.873784-1-bryan.odonoghue@linaro.org>\n\t<20260624085849.873784-11-bryan.odonoghue@linaro.org>","Content-Language":"en-US, de-DE, en-GB","From":"Robert Mader <robert.mader@collabora.com>","In-Reply-To":"<20260624085849.873784-11-bryan.odonoghue@linaro.org>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"7bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":39403,"web_url":"https://patchwork.libcamera.org/comment/39403/","msgid":"<6f407acb-f4af-439c-b8b0-60e8ca7738c2@collabora.com>","date":"2026-06-25T07:18:54","subject":"Re: [PATCH 10/10] libcamera: software_isp: debayer_egl: Implement\n\tinput/output frame caching mechanism","submitter":{"id":140,"url":"https://patchwork.libcamera.org/api/people/140/","name":"Robert Mader","email":"robert.mader@collabora.com"},"content":"P.S.:\n\nOn 24.06.26 13:10, Robert Mader wrote:\n> Thanks a lot!\n>\n> I tested this on a FP5 and a Pixel 3a and can not only confirm the \n> improvements on the timings but also observed lower CPU usage. In \n> particular in combination with dmabuf imports the CPU usage seems to \n> essentially collapse when eyeballing htop, see below.\n>\n> So for the whole series I can already give:\n>\n> Tested-by: Robert Mader <robert.mader@collabora.com>\n>\n> Will now go over the individual commits.\n>\n> ---\n>\n> FairPhone 5\n>\n> cam -c 1 -s width=1920,height=1080 --capture=60\n>\n> INFO SoftwareIsp software_isp.cpp:299 Input 2048x1536-RGGB-10-CSI2P \n> stride 2560\n> dmabuf import succeeds\n>\n> before:\n> INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in \n> 365691us, 12189 us/frame\n> ~39% CPU time in Wireplumber/Pipewire when running Snapshot\n>\n> after:\n> INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in \n> 204924us, 6830 us/frame\n> ~13% CPU time in Wireplumber/Pipewire when running Snapshot\n\nI also quickly checked what happens when never processing stats - the \nremaining CPU intense step - and confirmed that this now makes up for \nthe majority of CPU time:\n\nINFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 142502us, 4750 us/frame\n~5% CPU time in Wireplumber/Pipewire when running Snapshot\n\nLibcamera now uses less CPU time than the Wayland compositor, which \nsimilarly just imports a dmabuf from Snapshot and renders it into a \ndisplay output buffer.\n\nIOW: we're pretty good CPU-wise now and once stats-computation is also \ndone on the GPU there's barely anything left to optimize in that regard \n- at least when dmabuf-import works, which depends on the V4L2 drivers.","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 6E6BFC3303\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 25 Jun 2026 07:19:05 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 941C0658B8;\n\tThu, 25 Jun 2026 09:19:04 +0200 (CEST)","from sender4-op-o12.zoho.com (sender4-op-o12.zoho.com\n\t[136.143.188.12])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id C2E3D656DE\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 25 Jun 2026 09:19:02 +0200 (CEST)","by mx.zohomail.com with SMTPS id 178237193709925.095168183397163; \n\tThu, 25 Jun 2026 00:18:57 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=collabora.com\n\theader.i=robert.mader@collabora.com header.b=\"bJepEB4Z\"; \n\tdkim-atps=neutral","ARC-Seal":"i=1; a=rsa-sha256; t=1782371940; cv=none; \n\td=zohomail.com; s=zohoarc; \n\tb=QkWaqgojSDc6wWTEzHkIOT+6MhFr9OlOjVaZKV6i8qmoanpFt6+wqJaS6XPVDYAVHLX/3l9dwvWforFHy1Etul5mWa3opRVVjWfauHdnwO4gfkdHoVaxCxsSOpqdvPNdzKtRc54oezgX82cE/kYX5L9S/aPGSAfsYuQWWeTWhrY=","ARC-Message-Signature":"i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; \n\ts=zohoarc; t=1782371940;\n\th=Content-Type:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To:Cc;\n\tbh=zLVqYF+SUTu+0wQlDCEV98nddTALHfyDL698cvF5eBU=; \n\tb=X80H5WgJrvxbI8Yvz1RxP48dGnT3P9Prppy4ONabe4WA2AR5HPoasgv/8f66hxyqhiuTn4Gtr/PuDc5VuGf6KkgKWPyxnmhtxDj6NDpqptJNEzIuwtLv5kDIhyueYSC7e01iphZtqRChmy/GOB5TZQYWLDzOpTrWDVqcPXpXl2U=","ARC-Authentication-Results":"i=1; mx.zohomail.com;\n\tdkim=pass  header.i=collabora.com;\n\tspf=pass  smtp.mailfrom=robert.mader@collabora.com;\n\tdmarc=pass header.from=<robert.mader@collabora.com>","DKIM-Signature":"v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1782371940;\n\ts=zohomail; d=collabora.com; i=robert.mader@collabora.com;\n\th=Content-Type:Message-ID:Date:Date:MIME-Version:Subject:Subject:To:To:References:From:From:In-Reply-To:Message-Id:Reply-To:Cc;\n\tbh=zLVqYF+SUTu+0wQlDCEV98nddTALHfyDL698cvF5eBU=;\n\tb=bJepEB4ZbvjfNnE0zzokY/AEqYMpWM2gOoeCzCRscTkW50hp6CPV9CnZwoLk0vaR\n\tnkSHu8IvVjm3U0B9CJHmkO1jtnjaCI3r111mUC24nyPs7Sy4PMwOjRDMVQD5JNEBAXL\n\tl6xrwFz7iTWR39rhQeqx5f2Q2G+z0+7Xkjh7ym9g=","Content-Type":"multipart/alternative;\n\tboundary=\"------------uirV0Yi4Tb7JuYyysFyjXH07\"","Message-ID":"<6f407acb-f4af-439c-b8b0-60e8ca7738c2@collabora.com>","Date":"Thu, 25 Jun 2026 09:18:54 +0200","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH 10/10] libcamera: software_isp: debayer_egl: Implement\n\tinput/output frame caching mechanism","To":"libcamera-devel@lists.libcamera.org","References":"<20260624085849.873784-1-bryan.odonoghue@linaro.org>\n\t<20260624085849.873784-11-bryan.odonoghue@linaro.org>\n\t<b35e55c4-1b9e-459c-a48b-9146f5b50dc1@collabora.com>","Content-Language":"en-US, de-DE, en-GB","From":"Robert Mader <robert.mader@collabora.com>","In-Reply-To":"<b35e55c4-1b9e-459c-a48b-9146f5b50dc1@collabora.com>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":39407,"web_url":"https://patchwork.libcamera.org/comment/39407/","msgid":"<95a9f339-1d79-432c-9be2-01da28342fa5@nxsw.ie>","date":"2026-06-25T08:42:43","subject":"Re: [PATCH 10/10] libcamera: software_isp: debayer_egl: Implement\n\tinput/output frame caching mechanism","submitter":{"id":226,"url":"https://patchwork.libcamera.org/api/people/226/","name":"Bryan O'Donoghue","email":"bod.linux@nxsw.ie"},"content":"On 25/06/2026 08:18, Robert Mader wrote:\n> P.S.:\n> \n> On 24.06.26 13:10, Robert Mader wrote:\n>> Thanks a lot!\n>>\n>> I tested this on a FP5 and a Pixel 3a and can not only confirm the \n>> improvements on the timings but also observed lower CPU usage. In \n>> particular in combination with dmabuf imports the CPU usage seems to \n>> essentially collapse when eyeballing htop, see below.\n>>\n>> So for the whole series I can already give:\n>>\n>> Tested-by: Robert Mader <robert.mader@collabora.com>\n>>\n>> Will now go over the individual commits.\n>>\n>> ---\n>>\n>> FairPhone 5\n>>\n>> cam -c 1 -s width=1920,height=1080 --capture=60\n>>\n>> INFO SoftwareIsp software_isp.cpp:299 Input 2048x1536-RGGB-10-CSI2P \n>> stride 2560\n>> dmabuf import succeeds\n>>\n>> before:\n>> INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in \n>> 365691us, 12189 us/frame\n>> ~39% CPU time in Wireplumber/Pipewire when running Snapshot\n>>\n>> after:\n>> INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in \n>> 204924us, 6830 us/frame\n>> ~13% CPU time in Wireplumber/Pipewire when running Snapshot\n> \n> I also quickly checked what happens when never processing stats - the \n> remaining CPU intense step - and confirmed that this now makes up for \n> the majority of CPU time:\n> \n> INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 142502us, 4750 us/frame\n> ~5% CPU time in Wireplumber/Pipewire when running Snapshot\n> \n> Libcamera now uses less CPU time than the Wayland compositor, which \n> similarly just imports a dmabuf from Snapshot and renders it into a \n> display output buffer.\n> \n> IOW: we're pretty good CPU-wise now and once stats-computation is also \n> done on the GPU there's barely anything left to optimize in that regard \n> - at least when dmabuf-import works, which depends on the V4L2 drivers.\n> \n\nThank you for pulling these metrics.\n\nAgreed - stats in GPU. BTW I see about 5ms in the shaders using the \nbenchmarking code in multipass so perhaps after stats there is a way to \nattack the time spent in the shaders themselves.\n\nProbably the best attack vector is making use of UBWC - tiled/compressed \nformats as much as possible since likely the bottleneck is DRAM \nbandwidth to be getting such consistent shader times across different \nplatforms => DRAM3/4 CAS/RAS latency.\n\n---\nbod","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 4EAD5C3306\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 25 Jun 2026 08:42:49 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 4793C658C4;\n\tThu, 25 Jun 2026 10:42:48 +0200 (CEST)","from tor.source.kernel.org (tor.source.kernel.org\n\t[IPv6:2600:3c04:e001:324:0:1991:8:25])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id D3639656DE\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 25 Jun 2026 10:42:46 +0200 (CEST)","from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18])\n\tby tor.source.kernel.org (Postfix) with ESMTP id 79ECA60219;\n\tThu, 25 Jun 2026 08:42:45 +0000 (UTC)","by smtp.kernel.org (Postfix) with ESMTPSA id C2B3F1F00A3D;\n\tThu, 25 Jun 2026 08:42:44 +0000 (UTC)"],"Message-ID":"<95a9f339-1d79-432c-9be2-01da28342fa5@nxsw.ie>","Date":"Thu, 25 Jun 2026 09:42:43 +0100","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH 10/10] libcamera: software_isp: debayer_egl: Implement\n\tinput/output frame caching mechanism","To":"Robert Mader <robert.mader@collabora.com>,\n\tlibcamera-devel@lists.libcamera.org","References":"<20260624085849.873784-1-bryan.odonoghue@linaro.org>\n\t<20260624085849.873784-11-bryan.odonoghue@linaro.org>\n\t<b35e55c4-1b9e-459c-a48b-9146f5b50dc1@collabora.com>\n\t<I9e9ss0L5E8BUegT-Qv9IzsZJJE2_3q_4jbvPol3-eCP2Ti6mCxSySmUCiSuJmB-VAx3DZ6ujbXTxiOd0j2GZg==@protonmail.internalid>\n\t<6f407acb-f4af-439c-b8b0-60e8ca7738c2@collabora.com>","From":"Bryan O'Donoghue <bod.linux@nxsw.ie>","Content-Language":"en-US","In-Reply-To":"<6f407acb-f4af-439c-b8b0-60e8ca7738c2@collabora.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"7bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":39408,"web_url":"https://patchwork.libcamera.org/comment/39408/","msgid":"<fb6c8e8c-aa40-4144-a7cf-6d2d11521bdc@nxsw.ie>","date":"2026-06-25T08:44:24","subject":"Re: [PATCH 10/10] libcamera: software_isp: debayer_egl: Implement\n\tinput/output frame caching mechanism","submitter":{"id":226,"url":"https://patchwork.libcamera.org/api/people/226/","name":"Bryan O'Donoghue","email":"bod.linux@nxsw.ie"},"content":"On 25/06/2026 09:42, Bryan O'Donoghue wrote:\n> DRAM3/4 CAS/RAS latency.\n\nAnd just moving stuff across DRAM interfaces. Compression and layout in \nUBWC is supposed to give something like 40-60% better access times.\n\n---\nbod","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 96177C3304\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 25 Jun 2026 08:44:28 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 4FC0C658C7;\n\tThu, 25 Jun 2026 10:44:28 +0200 (CEST)","from tor.source.kernel.org (tor.source.kernel.org [172.105.4.254])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 9FBF7658BA\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 25 Jun 2026 10:44:26 +0200 (CEST)","from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18])\n\tby tor.source.kernel.org (Postfix) with ESMTP id CB34F6021A;\n\tThu, 25 Jun 2026 08:44:25 +0000 (UTC)","by smtp.kernel.org (Postfix) with ESMTPSA id 1EB8E1F000E9;\n\tThu, 25 Jun 2026 08:44:24 +0000 (UTC)"],"Message-ID":"<fb6c8e8c-aa40-4144-a7cf-6d2d11521bdc@nxsw.ie>","Date":"Thu, 25 Jun 2026 09:44:24 +0100","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH 10/10] libcamera: software_isp: debayer_egl: Implement\n\tinput/output frame caching mechanism","From":"Bryan O'Donoghue <bod.linux@nxsw.ie>","To":"Robert Mader <robert.mader@collabora.com>,\n\tlibcamera-devel@lists.libcamera.org","References":"<20260624085849.873784-1-bryan.odonoghue@linaro.org>\n\t<20260624085849.873784-11-bryan.odonoghue@linaro.org>\n\t<b35e55c4-1b9e-459c-a48b-9146f5b50dc1@collabora.com>\n\t<I9e9ss0L5E8BUegT-Qv9IzsZJJE2_3q_4jbvPol3-eCP2Ti6mCxSySmUCiSuJmB-VAx3DZ6ujbXTxiOd0j2GZg==@protonmail.internalid>\n\t<6f407acb-f4af-439c-b8b0-60e8ca7738c2@collabora.com>\n\t<95a9f339-1d79-432c-9be2-01da28342fa5@nxsw.ie>","Content-Language":"en-US","In-Reply-To":"<95a9f339-1d79-432c-9be2-01da28342fa5@nxsw.ie>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"7bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]