[英]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.