[英]Memory usage keeps rising on older devices using Metal
我使用Metal
和CADisplayLink
实时过滤CIImage
并将其渲染到MTKView
。
// Starting display link
displayLink = CADisplayLink(target: self, selector: #selector(applyAnimatedFilter))
displayLink.preferredFramesPerSecond = 30
displayLink.add(to: .current, forMode: .default)
@objc func applyAnimatedFilter() {
...
metalView.image = filter.applyFilter(image: ciImage)
}
根据Xcode中的内存监视器,iPhone X上的内存使用率稳定且永远不会超过100mb,在iPhone 6或iPhone 6s等设备上,内存使用量不断增长,直到最终系统杀死应用程序。
我使用Instruments
检查了内存泄漏,但没有报告泄漏。 通过分配运行应用程序也不会显示任何问题,系统不会关闭应用程序。 我还发现有趣的是,在较新的设备上,内存使用率是稳定的,但在较旧的设备上,它只是不断增长和增长。
过滤器的复杂性并不重要,因为我尝试了最简单的过滤器,问题仍然存在。 这是我的金属文件中的一个示例:
extern "C" { namespace coreimage {
float4 applyColorFilter(sample_t s, float red, float green, float blue) {
float4 newPixel = s.rgba;
newPixel[0] = newPixel[0] + red;
newPixel[1] = newPixel[1] + green;
newPixel[2] = newPixel[2] + blue;
return newPixel;
}
}
我想知道什么可能导致旧设备上的问题以及我应该注意的方向。
更新1:这里有两个1分钟的图表,一个来自Xcode
,一个来自Allocations
都使用相同的过滤器。 Allocations
图是稳定的,而Xcode
图总是在增长:
更新2:附加按大小排序的分配列表的屏幕截图,应用程序运行16分钟,应用过滤器不停止:
更新3:有关applyAnimatedFilter()
发生的事情的更多信息:
我将过滤后的图像渲染到一个metalView
的MTKView
。 我从filter.applyFilter(image: ciImage)
接收过滤后的图像,其中Filter
类接下来发生:
func applyFilter(image: ciImage) -> CIImage {
...
var colorMix = ColorMix()
return colorMix.use(image: ciImage, time: filterTime)
}
其中filterTime
只是一个Double变量。 最后,这是整个ColorMix类:
import UIKit
class ColorMix: CIFilter {
private let kernel: CIKernel
@objc dynamic var inputImage: CIImage?
@objc dynamic var inputTime: CGFloat = 0
override init() {
let url = Bundle.main.url(forResource: "default", withExtension: "metallib")!
let data = try! Data(contentsOf: url)
kernel = try! CIKernel(functionName: "colorMix", fromMetalLibraryData: data)
super.init()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func outputImage() -> CIImage? {
guard let inputImage = inputImage else {return nil}
return kernel.apply(extent: inputImage.extent, roiCallback: {
(index, rect) in
return rect.insetBy(dx: -1, dy: -1)
}, arguments: [inputImage, CIVector(x: inputImage.extent.width, y: inputImage.extent.height), inputTime])
}
func use(image: CIImage, time: Double) -> CIImage {
var resultImage = image
// 1. Apply filter
let filter = ColorMix()
filter.setValue(resultImage, forKey: "inputImage")
filter.setValue(NSNumber(floatLiteral: time), forKey: "inputTime")
resultImage = filter.outputImage()!
return resultImage
}
}
以下是一些观察,但我不确定其中一个是否真正导致您看到的内存使用情况:
applyFilter
您每帧都要创建一个新的ColorMix
过滤器。 另外,在实例方法中use(image:, time:)
你在每次调用时都会创建另一个 。 这是一个很大的开销,特别是因为过滤器每次都在init
上加载它的内核。 建议在安装过程中创建一个ColorMix
过滤器,并在每一帧上更新其inputImage
和inputTime
。 outputImage
不是一个func
,而是一个从CIFilter
超类重写的var
:
override var outputImage: CIImage? { /* your code here */ }
你的colorMix
内核是否colorMix
执行任何类型的卷积? 如果没有,它可能是CIColorKernel
而不是。
sampler
上调用.size()
。 这是Xcode诊断功能(金属验证和/或GPU帧捕获)中的一个错误。 如果关闭它们,内存使用量应与在Xcode外部运行时类似。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.