使用 Metal 进行屏幕撕裂和相机拍摄

Screen tearing and camera capture with Metal

提问人:Gary 提问时间:8/11/2016 更新时间:8/2/2017 访问量:1051

问:

为了避免同时从 gpu 和 cpu 写入常量缓冲区,Apple 建议在信号量的帮助下使用三重缓冲区系统,以防止 cpu 领先 gpu 太远(这很好,现阶段至少有三个 Metal 视频)。

但是,当常量资源是 MTLTexture 并且 AVCaptureVideoDataOutput 委托与呈现循环 (CADisplaylink) 分开运行时,类似的三重缓冲系统(如 Apple 的示例代码 MetalVideoCapture 中使用的)如何保证同步?如果采用 MetalVideoCapture 代码并简单地渲染全屏四边形并将预设更改为 AVCaptureSessionPresetHigh(此时撕裂被旋转四边形和低质量预设遮挡),则可以观察到屏幕撕裂(纹理撕裂)。

我意识到渲染循环和 captureOutput 委托方法(在本例中)都在主线程上,并且信号量(在渲染循环中)会检查_constantDataBufferIndex整数(它索引到 MTLTexture 中以进行创建和编码),但仍然可以观察到屏幕撕裂,这让我感到困惑(如果纹理的 gpu 写入不是编码后的下一帧而是 2 帧,那将是有道理的或 3 帧后,但我不相信是这样)。另外,还有一点:渲染循环和 captureOutput 对于缓冲纹理系统来说不应该具有相同的帧速率,这样旧帧就不会与最近的帧交错渲染。

对此事的任何想法或澄清将不胜感激;McZonk 还有另一个例子,它不使用三重缓冲系统,但我也观察到这种方法撕裂(但较少)。显然,如果我使用 waitUntilCompleted(相当于 Open GL 的 glfinish),就不会观察到撕裂,但这就像一只胳膊绑在背后弹手风琴一样!

iOS Objective-C 视频 OpenGL-ES Metal

评论

0赞 Rocket Garden 7/9/2017
我是 Metal 的新手,所以在遇到类似的问题时有点挣扎,就我而言,您使用 waitUntilCompleted 的建议解决了我的具体问题,所以感谢您提出这个问题!
0赞 Jeshua Lacock 7/31/2022
如果不看到你实际在做什么,我就无法提供帮助。
0赞 Gary 10/7/2022
这是一个非常古老的线程,我几年前通过对 Y 和 CbCr 的 CVMetalTextureRef 使用三重缓冲实例变量来解决它。在所有旧的示例代码(发布的第一个东西)中,只有 MTLTexture 是一个实例变量。
0赞 tenuki 12/12/2023
@Gary 您是否碰巧知道您提到的 MetalVideoCapture 示例代码是否仍然可以在任何地方访问?
0赞 Gary 12/14/2023
@tenuki我不确定,我在那里看了一下,似乎找不到它,如果你愿意,我可能会从我的旧电脑中挖出一份副本,它的目标 C。我不知道你是否可以在这个网站上私信,我可以通过电子邮件发送给你。我有很多不同的示例代码,如果我找不到那个特定的代码,它是我几年前做的许多代码的基础,同样都是客观的 C。

答: 暂无答案