Swift 为什么这个Xcode项目使用金属来显示相机输出对电池有这么大的影响,我怎样才能使它更好?

Swift 为什么这个Xcode项目使用金属来显示相机输出对电池有这么大的影响,我怎样才能使它更好?,swift,performance,camera,metal,battery,Swift,Performance,Camera,Metal,Battery,我使用金属作为基础,通过摄像头显示实时过滤输出。问题是,我意外地得到了高电池的影响,当我期望金属性能比更新UIImageView甚至OpenGL好得多 更新:使用或测试 在测试原始项目之前,一定要更新一些内容: -在ImageView.swift中,必须在commandBuffer.commit()之后调用draw() -在captureOutput中围绕connection.videoOrientation包装DispatchQueue.main.async: DispatchQueu

我使用金属作为基础,通过摄像头显示实时过滤输出。问题是,我意外地得到了高电池的影响,当我期望金属性能比更新UIImageView甚至OpenGL好得多

更新:使用或测试

在测试原始项目之前,一定要更新一些内容:

-在ImageView.swift中,必须在commandBuffer.commit()之后调用draw()

-在captureOutput中围绕connection.videoOrientation包装DispatchQueue.main.async:

    DispatchQueue.main.async{
        connection.videoOrientation = AVCaptureVideoOrientation(rawValue: UIApplication.shared.statusBarOrientation.rawValue)!

    }
我正在iPhone 6s Plus上进行测试,在调试导航器中查看时,CICMYKHalftone效应会将电池的影响提升到较高水平

我认为使用这种金属视图将极大地提高性能,但它似乎没有,即使在以25-30 fps的较低帧速率运行时也是如此

有没有什么重要的东西会像其他实时相机特效应用一样,让电池的使用变得更好

更新


我添加的另一个性能更新是MTKView对preferredFramesPerSecond的设置,我将其设置为30,因为默认情况下每秒最多调用60次。我将其与较低的设备帧速率相结合,以实现更好的性能和更少的电池影响

首先,由于是手动驱动图形(通过调用
draw()
),因此应将视图的
isPaused
属性设置为true。如果不这样做,则在调用时以及在内部计时器上,视图都在绘制自身

其次,
renderImage()
draw()
之间的关系是反向的。
image
didSet
观察者不应调用
renderImage()
。它应该调用
draw()
。您应该有一个对
draw(rect:CGRect)
的重写,它执行
renderImage()
(减去对
draw()
的调用)。(您可以使用
draw(\rect:CGRect)
调用
renderImage()
,也可以将
renderImage()
重命名为
draw(\rect:CGRect)


根据具体需要,您还可以将
enableSetNeedsDisplay
设置为true,并将
image
didSet
更改为调用
setNeedsDisplay()
而不是
draw()
。这将有一点延迟,但将避免尝试太频繁地画画。

谢谢Ken-我想除了第一个建议,我什么都懂。您的意思是我应该将MetalImageView的暂停属性设置为true吗?我没有看到该属性。
paused
MTKView
的属性
MetalImageView
继承了它。很抱歉,
isPaused
。在Objective-C中,它被称为“暂停”,因此您限制了视图的显示频率。AVCapture多久向您发送一次帧?它这样做的频率可能超过了需要。另外,在
cameracaptureheloper.captureOutput
中,您误用了dispatch。首先,只将实际需要在主线程上完成的事情分流到主队列。查询
UIApplication.shared.statusBarOrientation
may,设置
connection.videoOrientation
不会。此外,该块必须是同步的,而不是异步的。调用
newCameraImage
可能只是主线程,但创建
CIImage
不是。我认为应该从调用
captureautput
的线程上的像素缓冲区创建
CIImage
,然后在主线程上调用
newCameraImage
。所以,您可以将当前的一条语句拆分为两条。为什么您希望Metal比更新UIImageView或使用OpenGL更快?CPU和GPU上的工作负载对于所有这些都是相同的。Metal的开销比OpenGL小,但如果使用Metal,GPU的计算能力和内存带宽不会发生神奇的变化。(如果Metal的性能比UIImageView或OpenGL差得多,那么肯定是出了问题。)因为我使用CIFilters过滤图像,所以有必要在从像素缓冲区获得图像后立即创建CIImage。通过实现Metal,我可以更快地将图像渲染到视图上,而无需首先转换为CGImage。Metal比OpenGL更优化,我比较了它的影响。这并不是关于性能,更多的是关于电池的影响。