复杂的 CoreImage CIFilter 管道递归地消耗 GB 的内存
Complex CoreImage CIFilter pipeline recursively eats GBs of memory
我正在编写一个 macOS 应用程序,它对图像执行一系列复杂的 CIFilter
操作,以极大地改变高分辨率照片的外观,通常是 24 兆像素或更大。
其中一些效果包括高斯模糊、反锐化蒙版、泛光、暗淡,以及我使用自定义 CIKernel
在 Metal 中编写的自定义“颗粒”片段着色器。 CIContext
正在使用 Metal 设备渲染它。本质上,它是 initialImage -> CIFilter -> outputImage -> CIFilter -> outputImage -> CIFilter -> ...
的长链
不仅所有这些 CIFilters 必须按顺序 运行 用于最终输出,它们还必须在全分辨率上 运行 才能正确缩放效果。
我面临的问题是执行整个过程会导致大量使用内存。对于 6000x4000 输入图像,渲染时内存使用量跃升至 6.6GiB。
我使用 Xcode 中的 Metal 检测来诊断问题,似乎 CoreImage 正在为每个过滤器递归分配内存,因此内存不断堆积,直到它最终可以释放所有的内存资源在最后。
我希望这是顺序的,在下一个操作之前释放每个源缓冲区。我不确定如何帮助这种情况。有什么方法可以将每个输出图像传递给下一个过滤器,首先强制清理每个输入 CIImage
渲染?
if let device = self.device,
let texture = device.makeTexture(descriptor: descriptor),
let queue = device.makeCommandQueue(),
let buffer = queue.makeCommandBuffer() {
let destination = CIRenderDestination(
width: descriptor.width,
height: descriptor.height,
pixelFormat: self.colorPixelFormat,
commandBuffer: buffer) {
return texture
}
try! metalImage.context.context.startTask(toRender: metalImage.image, to: destination)
self.renderedImage = texture
buffer.commit()
}
在没有任何 CIContext 的情况下向 NSImageView
显示 24 兆像素 CIImage
时,这似乎只使用了几百 MB 的内存。
let image = // Create CIImage from complex CIFilter pipeline
let rep = NSBitmapImageRep(ciImage: image)
let previewImage = NSImage(size: rep.size)
previewImage.addRepresentation(rep)
previewImageView?.image = previewImage
在 5K iMac 上,它会非常高效地进行预览渲染(更新时间不到半秒)。在使用 CGImageDestination
.
导出图像之前不需要 CIContexts
我正在编写一个 macOS 应用程序,它对图像执行一系列复杂的 CIFilter
操作,以极大地改变高分辨率照片的外观,通常是 24 兆像素或更大。
其中一些效果包括高斯模糊、反锐化蒙版、泛光、暗淡,以及我使用自定义 CIKernel
在 Metal 中编写的自定义“颗粒”片段着色器。 CIContext
正在使用 Metal 设备渲染它。本质上,它是 initialImage -> CIFilter -> outputImage -> CIFilter -> outputImage -> CIFilter -> ...
不仅所有这些 CIFilters 必须按顺序 运行 用于最终输出,它们还必须在全分辨率上 运行 才能正确缩放效果。
我面临的问题是执行整个过程会导致大量使用内存。对于 6000x4000 输入图像,渲染时内存使用量跃升至 6.6GiB。
我使用 Xcode 中的 Metal 检测来诊断问题,似乎 CoreImage 正在为每个过滤器递归分配内存,因此内存不断堆积,直到它最终可以释放所有的内存资源在最后。
我希望这是顺序的,在下一个操作之前释放每个源缓冲区。我不确定如何帮助这种情况。有什么方法可以将每个输出图像传递给下一个过滤器,首先强制清理每个输入 CIImage
渲染?
if let device = self.device,
let texture = device.makeTexture(descriptor: descriptor),
let queue = device.makeCommandQueue(),
let buffer = queue.makeCommandBuffer() {
let destination = CIRenderDestination(
width: descriptor.width,
height: descriptor.height,
pixelFormat: self.colorPixelFormat,
commandBuffer: buffer) {
return texture
}
try! metalImage.context.context.startTask(toRender: metalImage.image, to: destination)
self.renderedImage = texture
buffer.commit()
}
在没有任何 CIContext 的情况下向 NSImageView
显示 24 兆像素 CIImage
时,这似乎只使用了几百 MB 的内存。
let image = // Create CIImage from complex CIFilter pipeline
let rep = NSBitmapImageRep(ciImage: image)
let previewImage = NSImage(size: rep.size)
previewImage.addRepresentation(rep)
previewImageView?.image = previewImage
在 5K iMac 上,它会非常高效地进行预览渲染(更新时间不到半秒)。在使用 CGImageDestination
.
CIContexts