[30/30] libcamera: software_isp: gpu: Cache input framebuffers, only do texture creation when required
diff mbox series

Message ID 20260618122245.946138-31-bryan.odonoghue@linaro.org
State New
Headers show
Series
  • RFC/RFT: gpuisp: Multipass with speed optimisations on top
Related show

Commit Message

Bryan O'Donoghue June 18, 2026, 12:22 p.m. UTC
Implement a cache of input textures - making one texture for each input
FrameBuffer we see.

➜  libcamera git:(0.7.0-multipass-v4) ✗ grep Bench after.log
[26:30:50.382000193] [1232323]  INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 594603us, 19820 us/frame
[26:30:57.401535061] [1232356]  INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 573922us, 19130 us/frame
[26:31:00.693007555] [1232386]  INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 619533us, 20651 us/frame
[26:31:04.943431215] [1232415]  INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 595097us, 19836 us/frame
[26:31:08.495371222] [1232444]  INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 596719us, 19890 us/frame
[26:31:14.057239566] [1232479]  INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 586299us, 19543 us/frame
[26:31:18.201198235] [1232509]  INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 639572us, 21319 us/frame
[26:31:21.971954439] [1232539]  INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 610732us, 20357 us/frame
[26:31:25.391881496] [1232574]  INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 596533us, 19884 us/frame
[26:31:29.887852761] [1232603]  INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 552319us, 18410 us/frame

➜  libcamera git:(0.7.0-multipass-v4) ✗ grep Bench before.log
[26:32:12.443884778] [1232907]  INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 591871us, 19729 us/frame
[26:32:21.394113992] [1232943]  INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 634355us, 21145 us/frame
[26:32:24.923236983] [1232983]  INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 601128us, 20037 us/frame
[26:32:28.173610317] [1233017]  INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 578252us, 19275 us/frame
[26:32:33.265933583] [1233050]  INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 598317us, 19943 us/frame
[26:32:36.590115049] [1233091]  INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 586617us, 19553 us/frame
[26:32:40.014877516] [1233127]  INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 594843us, 19828 us/frame
[26:33:03.293347156] [1233182]  INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 586804us, 19560 us/frame
[26:33:07.471525107] [1233221]  INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 615955us, 20531 us/frame
[26:33:13.015977863] [1233262]  INFO Benchmark benchmark.cpp:89 Debayer processed 30 frames in 576757us, 19225 us/frame

Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
 .../software_isp_pipeline_gpu.cpp             | 25 ++++++++++++-------
 .../software_isp/software_isp_pipeline_gpu.h  |  2 +-
 2 files changed, 17 insertions(+), 10 deletions(-)

Patch
diff mbox series

diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp
index bc5d59575..0bcd4df58 100644
--- a/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp
+++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.cpp
@@ -244,9 +244,18 @@  int SoftwareIspPipelineGpu::processGPU(FrameBuffer *input, FrameBuffer *output,
 	/* eGL context switch */
 	egl_.makeCurrent();
 
+	auto [input_cache, input_miss] = eglImageBayerIn_.try_emplace(input);
+	if (input_miss) {
+		/* Raw bayer input as texture */
+		input_cache->second = std::make_unique<eGLImage>(gpuIspShaderPassBlcNormalise_.glFormat_,
+								 inputConfig_.stride / gpuIspShaderPassBlcNormalise_.getBytesPerPixel(),
+								 height_, inputConfig_.stride, GL_TEXTURE0, 0);
+	}
+	eGLImage &eglImageBayerIn = *input_cache->second;
+
 	/* 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)
+	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";
@@ -260,7 +269,9 @@  int SoftwareIspPipelineGpu::processGPU(FrameBuffer *input, FrameBuffer *output,
 			LOG(Debayer, Error) << "mmap-ing buffer(s) failed";
 			return -ENODEV;
 		}
-		egl_.updateInputTexture2D(*eglImageBayerIn_, inMapped->value().planes()[0].data());
+		if (input_miss)
+			egl_.createInputTexture2D(eglImageBayerIn, NULL);
+		egl_.updateInputTexture2D(eglImageBayerIn, inMapped->value().planes()[0].data());
 	}
 
 	/* Find an existing eglImage in the cache */
@@ -272,7 +283,7 @@  int SoftwareIspPipelineGpu::processGPU(FrameBuffer *input, FrameBuffer *output,
 	}
 	eGLImage &eglImageRGBAOut = *output_cache->second;
 
-	pipelineResult = gpuIspShaderPassBlcNormalise_.process(*eglImageBayerIn_, *eglImagePingPong_[0], width_, height_, params);
+	pipelineResult = gpuIspShaderPassBlcNormalise_.process(eglImageBayerIn, *eglImagePingPong_[0], width_, height_, params);
 	if (pipelineResult) {
 		LOG(Debayer, Error) << "BlcNormalise fail";
 		return pipelineResult;
@@ -370,14 +381,10 @@  int SoftwareIspPipelineGpu::start()
 
 	initShaderBenchMarks();
 
-	/* Raw bayer input as texture */
-	eglImageBayerIn_ = std::make_unique<eGLImage>(gpuIspShaderPassBlcNormalise_.glFormat_, inputConfig_.stride / gpuIspShaderPassBlcNormalise_.getBytesPerPixel(), height_, inputConfig_.stride, GL_TEXTURE0, 0);
-
 	/* Intermediary ping/pong textures */
 	eglImagePingPong_[0] = std::make_unique<eGLImage>(gpuIspShaderPassDemosiac_.glFormat_, width_, height_, outputConfig_.stride, GL_TEXTURE1, 1);
 	eglImagePingPong_[1] = std::make_unique<eGLImage>(gpuIspShaderPassDemosiac_.glFormat_, width_, height_, outputConfig_.stride, GL_TEXTURE2, 2);
 
-	egl_.createInputTexture2D(*eglImageBayerIn_, NULL);
 	egl_.createOutputTexture2D(*eglImagePingPong_[0]);
 	egl_.createOutputTexture2D(*eglImagePingPong_[1]);
 
@@ -389,7 +396,7 @@  void SoftwareIspPipelineGpu::stop()
 	eglImageRGBAOut_.clear();
 	eglImagePingPong_[1].reset();
 	eglImagePingPong_[0].reset();
-	eglImageBayerIn_.reset();
+	eglImageBayerIn_.clear();
 
 	gpuIspShaderPassDemosiac_.stop();
 }
diff --git a/src/libcamera/software_isp/software_isp_pipeline_gpu.h b/src/libcamera/software_isp/software_isp_pipeline_gpu.h
index 995e84295..e2aceefdc 100644
--- a/src/libcamera/software_isp/software_isp_pipeline_gpu.h
+++ b/src/libcamera/software_isp/software_isp_pipeline_gpu.h
@@ -67,7 +67,7 @@  private:
 	void printShaderBenchMarks(void);
 
 	/* Pointer to object representing input texture */
-	std::unique_ptr<eGLImage> eglImageBayerIn_;
+	std::unordered_map<FrameBuffer *, std::unique_ptr<eGLImage>> eglImageBayerIn_;
 	std::unique_ptr<eGLImage> eglImagePingPong_[2];
 	std::unordered_map<FrameBuffer *, std::unique_ptr<eGLImage>> eglImageRGBAOut_;