diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp
index d08634640..e83a68a97 100644
--- a/src/libcamera/software_isp/debayer_egl.cpp
+++ b/src/libcamera/software_isp/debayer_egl.cpp
@@ -10,6 +10,7 @@
 #include "debayer_egl.h"
 
 #include <algorithm>
+#include <assert.h>
 #include <memory>
 #include <stdlib.h>
 #include <string>
@@ -500,16 +501,34 @@ void DebayerEGL::setShaderVariableValues(const DebayerParams &params)
 	return;
 }
 
-int DebayerEGL::debayerGPU(MappedFrameBuffer &in, int out_fd, const DebayerParams &params)
+int DebayerEGL::debayerGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams &params, std::optional<MappedFrameBuffer> *inMapped, std::optional<DmaSyncer> *inDmaSyncer)
 {
+	bool dmabuf_import_succeeded = false;
+
 	/* eGL context switch */
 	egl_.makeCurrent();
 
-	/* Create a standard texture input */
-	egl_.createTexture2D(*eglImageBayerIn_, in.planes()[0].data());
+	/* Try to create texture for input buffer via dmabuf import */
+	if (!eglImageBayerIn_->dmabuf_import_failed_) {
+		if (egl_.createInputDMABufTexture2D(*eglImageBayerIn_, input->planes()[0].fd.get()) == 0)
+			dmabuf_import_succeeded = true;
+		else
+			LOG(Debayer, Info) << "Importing input buffer with DMABuf import failed, falling back to upload";
+	}
+
+	/* Otherwise create texture for input buffer via upload from CPU */
+	if (!dmabuf_import_succeeded) {
+		inDmaSyncer->emplace(input->planes()[0].fd, DmaSyncer::SyncType::Read);
+		inMapped->emplace(input, MappedFrameBuffer::MapFlag::Read);
+		if (!inMapped->value().isValid()) {
+			LOG(Debayer, Error) << "mmap-ing buffer(s) failed";
+			return -ENODEV;
+		}
+		egl_.createTexture2D(*eglImageBayerIn_, inMapped->value().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 +550,16 @@ 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<MappedFrameBuffer> inMapped;
+	std::optional<DmaSyncer> inDmaSyncer;
 
-	if (debayerGPU(in, output->planes()[0].fd.get(), params)) {
+	if (debayerGPU(input, output, params, &inMapped, &inDmaSyncer)) {
 		LOG(Debayer, Error) << "debayerGPU failed";
 		goto error;
 	}
@@ -555,8 +567,22 @@ void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output
 	metadata.planes()[0].bytesused = output->planes()[0].length;
 
 	/* Calculate stats for the whole frame */
-	stats_->processFrame(frame, 0, in);
-	dmaSyncers.clear();
+	if (frame % SwStatsCpu::kStatPerNumFrames) {
+		stats_->finishFrame(frame, 0);
+	} else {
+		if (!inMapped) {
+			/*
+			 * The buffer was directly imported into EGL and thus
+			 * not mapped for texture upload. Do it now for the
+			 * CPU-based stats calculation.
+			 */
+			assert(!inDmaSyncer);
+			inDmaSyncer.emplace(input->planes()[0].fd, DmaSyncer::SyncType::Read);
+			inMapped.emplace(input, MappedFrameBuffer::MapFlag::Read);
+		}
+		stats_->processFrame(frame, 0, inMapped.value());
+	}
+	inDmaSyncer.reset();
 
 	egl_.syncOutput();
 	bench_.finishFrame();
diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h
index 141fb288f..875e7cfc5 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 &params);
-	int debayerGPU(MappedFrameBuffer &in, int out_fd, const DebayerParams &params);
+	int debayerGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams &params, std::optional<MappedFrameBuffer> *mappedInputBuffer, std::optional<DmaSyncer> *inputBufferDmaSyncer);
 
 	/* Shader program identifiers */
 	GLuint vertexShaderId_ = 0;
