| Message ID | 20260518201508.140849-4-robert.mader@collabora.com |
|---|---|
| State | Superseded |
| Headers | show |
| Series |
|
| Related | show |
On 18/05/2026 21:15, Robert Mader wrote: > + if (egl_.createInputDMABufTexture2D(*eglImageBayerIn_, input->planes()[0].fd.get()) != 0) { > + LOG(Debayer, Debug) << "Importing input buffer with DMABuf import failed, falling back to upload"; > + > + inputBufferDmaSyncer->emplace(input->planes()[0].fd, DmaSyncer::SyncType::Read); > + MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read); > + if (!in.isValid()) { > + LOG(Debayer, Error) << "mmap-ing buffer(s) failed"; > + return -ENODEV; > + } > + egl_.createTexture2D(*eglImageBayerIn_, in.planes()[0].data()); > + } So for this set a flag in the DebayerEGL class to flag the behavior - try once and then keep to the detected behaviour. --- bod
On 19.05.26 17:58, Bryan O'Donoghue wrote: > On 18/05/2026 21:15, Robert Mader wrote: >> + if (egl_.createInputDMABufTexture2D(*eglImageBayerIn_, input->planes()[0].fd.get()) != 0) { >> + LOG(Debayer, Debug) << "Importing input buffer with DMABuf import failed, falling back to upload"; >> + >> + inputBufferDmaSyncer->emplace(input->planes()[0].fd, DmaSyncer::SyncType::Read); >> + MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read); >> + if (!in.isValid()) { >> + LOG(Debayer, Error) << "mmap-ing buffer(s) failed"; >> + return -ENODEV; >> + } >> + egl_.createTexture2D(*eglImageBayerIn_, in.planes()[0].data()); >> + } > So for this set a flag in the DebayerEGL class to flag the behavior - > try once and then keep to the detected behaviour. Did that in v3. FTR.: I *think* the overhead of trying the import every time is negligible - that was the reason I didn't add such a flag in the first place.
2026. 05. 19. 17:58 keltezéssel, Bryan O'Donoghue írta: > On 18/05/2026 21:15, Robert Mader wrote: >> + if (egl_.createInputDMABufTexture2D(*eglImageBayerIn_, input->planes()[0].fd.get()) != 0) { >> + LOG(Debayer, Debug) << "Importing input buffer with DMABuf import failed, falling back to upload"; >> + >> + inputBufferDmaSyncer->emplace(input->planes()[0].fd, DmaSyncer::SyncType::Read); >> + MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read); >> + if (!in.isValid()) { >> + LOG(Debayer, Error) << "mmap-ing buffer(s) failed"; >> + return -ENODEV; >> + } >> + egl_.createTexture2D(*eglImageBayerIn_, in.planes()[0].data()); >> + } > > So for this set a flag in the DebayerEGL class to flag the behavior - > try once and then keep to the detected behaviour. I think that opens an interesting question. At the moment, in libcamera, applications are not constrained in any way what buffers they might use. Meaning that some might be appropriate, some might not. There is no "buffer import" step that would provide information about the set of possible buffers. So disabling it on the first failure might be a pessimization. But of course they will generally cycle through a single set of buffers, so it's most likely fine to have a flag and stop trying after the first failure. > > --- > bod >
diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index a217e3798..e5a661d2c 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -500,16 +500,26 @@ void DebayerEGL::setShaderVariableValues(const DebayerParams ¶ms) return; } -int DebayerEGL::debayerGPU(MappedFrameBuffer &in, int out_fd, const DebayerParams ¶ms) +int DebayerEGL::debayerGPU(FrameBuffer *input, std::optional<DmaSyncer> *inputBufferDmaSyncer, FrameBuffer *output, const DebayerParams ¶ms) { /* eGL context switch */ egl_.makeCurrent(); /* Create a standard texture input */ - egl_.createTexture2D(*eglImageBayerIn_, in.planes()[0].data()); + if (egl_.createInputDMABufTexture2D(*eglImageBayerIn_, input->planes()[0].fd.get()) != 0) { + LOG(Debayer, Debug) << "Importing input buffer with DMABuf import failed, falling back to upload"; + + inputBufferDmaSyncer->emplace(input->planes()[0].fd, DmaSyncer::SyncType::Read); + MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read); + if (!in.isValid()) { + LOG(Debayer, Error) << "mmap-ing buffer(s) failed"; + return -ENODEV; + } + egl_.createTexture2D(*eglImageBayerIn_, in.planes()[0].data()); + } /* Generate the output render framebuffer as render to texture */ - egl_.createOutputDMABufTexture2D(*eglImageBayerOut_, out_fd); + egl_.createOutputDMABufTexture2D(*eglImageBayerOut_, output->planes()[0].fd.get()); setShaderVariableValues(params); glViewport(0, 0, width_, height_); @@ -531,23 +541,15 @@ void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output { bench_.startFrame(); - std::vector<DmaSyncer> dmaSyncers; - - dmaSyncBegin(dmaSyncers, input, nullptr); - /* Copy metadata from the input buffer */ FrameMetadata &metadata = output->_d()->metadata(); metadata.status = input->metadata().status; metadata.sequence = input->metadata().sequence; metadata.timestamp = input->metadata().timestamp; - MappedFrameBuffer in(input, MappedFrameBuffer::MapFlag::Read); - if (!in.isValid()) { - LOG(Debayer, Error) << "mmap-ing buffer(s) failed"; - goto error; - } + std::optional<DmaSyncer> inputBufferDmaSyncer; - if (debayerGPU(in, output->planes()[0].fd.get(), params)) { + if (debayerGPU(input, &inputBufferDmaSyncer, output, params)) { LOG(Debayer, Error) << "debayerGPU failed"; goto error; } @@ -557,8 +559,10 @@ void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output metadata.planes()[0].bytesused = output->planes()[0].length; /* Calculate stats for the whole frame */ + if (!inputBufferDmaSyncer && (frame % SwStatsCpu::kStatPerNumFrames) == 0) + inputBufferDmaSyncer.emplace(input->planes()[0].fd, DmaSyncer::SyncType::Read); stats_->processFrame(frame, 0, input); - dmaSyncers.clear(); + inputBufferDmaSyncer.reset(); outputBufferReady.emit(output); inputBufferReady.emit(input); diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h index 141fb288f..a98a8139a 100644 --- a/src/libcamera/software_isp/debayer_egl.h +++ b/src/libcamera/software_isp/debayer_egl.h @@ -65,7 +65,7 @@ private: int initBayerShaders(PixelFormat inputFormat, PixelFormat outputFormat); int getShaderVariableLocations(); void setShaderVariableValues(const DebayerParams ¶ms); - int debayerGPU(MappedFrameBuffer &in, int out_fd, const DebayerParams ¶ms); + int debayerGPU(FrameBuffer *input, std::optional<DmaSyncer> *inputBufferDmaSyncer, FrameBuffer *output, const DebayerParams ¶ms); /* Shader program identifiers */ GLuint vertexShaderId_ = 0;
In many cases we can import the GPU-ISP input buffers, dmabufs from v4l2, directly into EGL instead of mapping and uploading - i.e. copying - them. Doing so can have positive effects in multiple areas, including reducing memory bandwidth and CPU usage, as well as avoiding expensive dmabuf syncs and syscalls. The main reason direct imports may not work are the more demanding stride alignment requirements many GPUs have - often 128 or 256 bytes - compared to ISPs - apparently often closer to 32 bytes. Thus we first try to import buffers directly and - if that fails - fall back to the previous upload path. Failing imports should come at low cost as drivers know the limitations and can bail out early, without causing additional IO or context switches. In the future we might be able to request buffers with a matching stride from v4l2 drivers in many cases, making direct import the norm instead of a hit-or-miss. An optional kernel API for that exists, but doesn't seem to be implemented by any driver tested so far. While on it, add some minor code adjustments to make it easier to follow. Signed-off-by: Robert Mader <robert.mader@collabora.com> --- src/libcamera/software_isp/debayer_egl.cpp | 32 ++++++++++++---------- src/libcamera/software_isp/debayer_egl.h | 2 +- 2 files changed, 19 insertions(+), 15 deletions(-)