ios - 使用 Metal 的旧设备上的内存使用量不断上升

标签 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 检查了内存泄漏,但没有泄漏报告。通过 Allocations 运行应用程序也不会出现任何问题,应用程序也不会被系统关闭。我还发现有趣的是,在较新的设备上,内存使用量是稳定的,但在较旧的设备上,它只会不断增长。

过滤器的复杂性并不重要,因为我尝试了最简单的过滤器,但问题仍然存在。这是我的 Metal 文件中的一个示例:

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 中这是 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
    }

}

最佳答案

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

关于ios - 使用 Metal 的旧设备上的内存使用量不断上升,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56854929/

相关文章:

ios - 无法识别自定义 UITableView 的 UIKeyCommands

macos - 声明 MacOS 应用程序的 Metal 支持要求

swift - Metal:将 MTLRenderCommandEncoder 纹理加载限制为仅部分纹理

opengl-es - 在 SCNShadable 入口点之间传递值

iphone - 如何在 Facebook 登录后返回应用程序?

ios - 强制本地化 UIKit 等内部框架,无需重启应用程序

objective-c - 如何为附加到 UIImageView 的 CALayer 设置动画?

iphone - 如何在 iPhone 上显示 Instagram 用户登录页面

ios - UICollectionView 没有滚动到前几个项目的底部

ios - didselectrowatindexpath 基于登录的导航