结合多个MTKView / CAMetalLayer显示

时间:2018-06-02 10:19:48

标签: ios metal metalkit

我使用多个MTKViews在屏幕上显示不同的内容以及普通的UIView(用于显示UI)。我想将这些MTKViews的显示与同一时钟同步。有没有办法同步这些MTKViews的演示?原则上,我可以将这些视图的布局组合到单个MTKView中,但这会破坏代码的模块性,并且不确定我是否会因为过多的工作而在性能上取得任何成果。

2 个答案:

答案 0 :(得分:2)

在大多数情况下应该使用的简单方法是计算您希望绘制框架的时间并使用present(_:atTime:) MTLCommandBuffer方法而不是present(_:)方法方法。

为了更好地控制,有助于理解命令缓冲区的present...方法做什么和不做什么。它们将任何命令编码到缓冲区中。如文档所述,它们基本上只是为自己添加一个调度处理程序,在drawable上调用present

如果你对它很小心,你可以安排以一种不太涉及命令缓冲区的方式呈现drawable。

但是,使用预定处理程序的命令缓冲区是否有意义?它不应该使用完成的处理程序吗?毕竟,你想要显示完成的渲染,对吗?

嗯,drawables很聪明地展示自己。 present方法不会立即出现。计划命令的可绘制轨道可以渲染或写入其纹理。当present被调用时,在所有这些命令完成之后会安排drawable在屏幕上尽快绘制。 (请注意,这并不意味着命令缓冲区本身已经完成。可能还有其他命令不涉及尚未完成的drawable纹理。)

这为同步多个drawable的呈现提供了挑战和机会。挑战在于,虽然您可以控制何时在每个drawable上调用present,但这不一定会同步它们的实际显示,因为每个都会在调用present之后尽快显示所有命令完成涉及其纹理,并且最后一部分可以在不同的时间出现在不同的绘图中。

解决此问题的一种可能方法是向主drawable添加一个呈现的处理程序。处理程序将在其他3个drawable上调用present。在调度所有命令缓冲区后,在主drawable上调用present。您可以使用调度组来确定何时调度所有命令缓冲区。为每个命令缓冲区输入一次组,并为每个离开组的计数器添加一个计划的处理程序。然后在执行主服务器的组上设置通知块。这种技术可能无法实现完美的同步,因为主绘图实际呈现的时间与调用呈现的处理程序之间存在延迟,然后呈现其他绘图的延迟。

另一种可能的方法是将所有presentsWithTransaction s的CAMetalLayer属性设置为true。然后,当它出现时,在每个命令缓冲区上调用waitUntilScheduled,然后在每个drawable上调用present。 (不要使用命令缓冲区的present...方法。)这将保证所有drawable将在同一个Core Animation事务中出现 - 即同步。

答案 1 :(得分:0)

您可以使用presentsWithTransaction

  1. 在 MTKView 中设置presentWithTransaction = true

  2. 更改 commandBuffer 提交样式

     public func draw(in view: MTKView) {
    
     ...
    
     commandBuffer?.commit()
     commandBuffer?.waitUntilScheduled()
     view.currentDrawable?.present() }
    

现在所有金属视图将同步显示。 它对我有用。