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

时间:2019-07-02 14:41:16

标签: ios swift metal core-image cadisplaylink

我使用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)
}

根据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图始终在增长:

Xcode

Allocations

更新2:附加了按大小排序的分配列表的屏幕快照,该应用运行了16分钟,并应用了过滤器不间断:

enter image description here

更新3:有关applyAnimatedFilter()中发生的事情的更多信息:

我将过滤后的图像渲染到metalView的{​​{1}}中。我收到了来自MTKView的经过过滤的图像,其中发生在filter.applyFilter(image: ciImage)类中的下一个是

Filter

其中 func applyFilter(image: ciImage) -> CIImage { ... var colorMix = ColorMix() return colorMix.use(image: ciImage, time: filterTime) } 只是一个Double变量。最后,这是整个ColorMix类:

filterTime

2 个答案:

答案 0 :(得分:2)

以下是一些观察结果,但是我不确定其中之一是否真正导致您看到的内存使用情况:

  • applyFilter中,您将创建一个新的ColorMix过滤器每一帧。此外,在实例方法use(image:, time:)中,您将在每次调用时创建另一个。这会产生很多开销,特别是因为过滤器每次都会在init上加载其内核。建议在设置过程中仅创建一个ColorMix过滤器,并在每帧上更新其inputImageinputTime
  • outputImage不是func,而是您从var超类中覆盖的CIFilter

    override var outputImage: CIImage? { /* your code here */ }

  • 您的colorMix内核是否进行任何卷积运算?如果不是,则可能是CIColorKernel

  • 如果您需要内核内部输入的大小,则无需将其作为额外的参数传递。您只需在输入.size()上调用sampler

答案 1 :(得分:2)

这是Xcode的诊断功能(金属验证和/或GPU帧捕获)中的错误。如果您将其关闭,则内存使用情况应与在Xcode外部运行时类似。