使用Metal的较旧设备的内存使用率不断上升

Sma*_*ree 5 core-image ios cadisplaylink swift metal

我使用MetalCADisplayLink实时过滤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)
}
Run Code Online (Sandbox Code Playgroud)

根据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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我想知道是什么原因会导致较旧的设备出现问题,我应该朝哪个方向看。

更新1:这是两个1分钟的图表,一个来自Xcode一个,另一个来自Allocations两个,都使用相同的过滤器。AllocationsXcode图总是增长时,图是稳定的:

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)
 }
Run Code Online (Sandbox Code Playgroud)

在哪里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
    }

}
Run Code Online (Sandbox Code Playgroud)

Ken*_*ses 6

这是 Xcode 诊断功能(金属验证和/或 GPU 帧捕获)中的一个错误。如果关闭它们,内存使用量应该与在 Xcode 之外运行时类似。