The ROI callback that is passed to a CIKernel
’s apply(…)
method seems to be referenced beyond the render call and is not released properly. That also means that any captured state is retained longer than expected.
I noticed this in a camera capture scenario because the capture session stopped delivering new frames after the initial batch. The output ran out of buffers because they were not properly returned to the pool. I was capturing the filter’s input image in the ROI callback like in this simplified case:
override var outputImage: CIImage? {
guard let inputImage = inputImage else { return nil }
let roiCallback: CIKernelROICallback = { _, _ in
return inputImage.extent
}
return Self.kernel.apply(extent: inputImage.extent, roiCallback: roiCallback, arguments: [inputImage])
}
While it is avoidable in this case, it is also very unexpected that the ROI callback is retained longer than needed for rendering the output image. Even when not capturing a lot of state, this would still unnecessarily accumulate over time.
Note that calling ciContext.clearCaches()
does actually seem to release the captured ROI callbacks. But I don’t want to do that after every frame since there are also resources worth caching.
Is there a reason why Core Image caches the ROI callbacks beyond the rendering calls they are involved in?