ios - 跨多个 MTKViews 共享一个 MTLCommandBuffer

标签 ios swift xcode graphics metal

我在我的 UIKit 应用程序中使用 MTKViews 来选择 UI 元素。我有一个中央 Metal Controller ,它做的事情有点像这样:

public class MetalView: MTKView                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   {

    var id:Int? = nil
    func getBuffer() -> MTLCommandBuffer {
        if (id == nil) {
            id = MetalView.idCounter
            MetalView.idCounter += 1
            MetalView.frameRegistry.append(id!)
            setNeedsDisplay()
        }

        if MetalView.frameRegistry.contains(id!) {
            MetalView.frameRegistry.removeAll()
            if let buffer = MetalView.savedBuffer {
                buffer.commit()
                buffer.waitUntilCompleted()
            }
            MetalView.savedBuffer = MetalView.queue.makeCommandBuffer()
        }
        MetalView.frameRegistry.append(id!)
        return MetalView.savedBuffer!
    }

    static private var savedBuffer:MTLCommandBuffer? = nil
    static private var frameRegistry:[Int] = []
    static private var idCounter:Int = 0

}

每个 Metal UI 元素的子类都有自己的 ID,允许它在其绘制函数中调用 getBuffer 以获取框架的命令缓冲区。

这段代码基于两个假设

  1. 每个 MTKView 都有自己的 drawable
  2. 你应该每帧只制作一个 MTLCommandBuffer

这就是我理解事物运作的方式。

不幸的是,这与纹理产生了相当明显的同步错误

enter image description here

这应该是一个均匀色调的渐变,但色调被快速切换,结果留下了撕裂,其中一部分绘制了与另一部分不同的色调。

所以我想我的问题是:

  1. 我的假设是否正确
  2. 当并非所有对象都需要绘制每一帧时,跨 Metal 绘图对象共享 MTLCommandBuffer 的正确方法是什么。
  3. 我该如何解决这个问题?

最佳答案

Apple 明确指出 MTLCommandBuffer 只能使用一次,一旦提交就不应重复使用。来自 Metal 编程指南:

Command buffers are transient single-use objects and do not support reuse. Once a command buffer has been committed for execution, the only valid operations are to wait for the command buffer to be scheduled or completed.

因此,不支持您正在做的事情。唯一允许重用的对象是:

  • 命令队列
  • 数据缓冲区
  • 纹理
  • 采样器状态
  • 图书馆
  • 计算状态
  • 渲染管线状态
  • 深度/模板状态

来源:Metal Programming Guide .

您的问题的一个可能解决方案是通过相同的命令队列为每个可绘制对象排队一个 MTLCommandBuffer。要了解如何对两个不同的命令缓冲区进行排队并确保它们的执行顺序,您应该查看 Apple 的 ObjectExample 示例代码。您可以从here下载。 .

关于ios - 跨多个 MTKViews 共享一个 MTLCommandBuffer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51475080/

相关文章:

ios - 无法将 iSpeech 导入我的 iOS Swift 项目

ios - 如何通过 Swift 从 Google 搜索结果页面 URL 中提取搜索关键字?

c - 允许在 Swift 中使用 C 函数的桥接 header 失败

iphone - 根据设备大小 xcode 缩放图像

ios - 如何将 UIButton 标识符更改为相机图标?

iphone - iOS Bluetooth LE peripheralManager didReceiveWriteRequests 的例子在哪里

objective-c - 无法在低于IOS6的设备上测试社交框架

如果在 JSON 中通知 "aps",iOS 推送通知将不起作用

ios - 间歇性 Swift 框架编译器错误

ios - 使用配置文件从终端问题构建 .ipa