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_;
 
