我正在将MTKViews用于UIKit应用程序内的选定UI元素。我有一个中央金属控制器,其功能类似于以下内容:
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
}
每个金属UI元素子类都有自己的ID,允许其在其draw函数中调用getBuffer来获取框架的命令缓冲区。
此代码基于两个假设
这就是我理解工作原理的方式。
不幸的是,这会导致纹理出现明显的同步错误
这应该是均匀色调的梯度,但是色调被快速切换,结果,这种撕裂留下了一部分,而另一部分的色调不同。
所以我想我的问题是:
答案 0 :(得分:0)
Apple明确声明MTLCommandBuffer只能使用一次,并且一旦提交就不应重复使用。来自《金属编程指南》:
命令缓冲区是临时的一次性对象,不支持重用。提交命令缓冲区以供执行后,唯一有效的操作是等待命令缓冲区被调度或完成。
因此,不支持您在做什么。唯一允许重用的对象是:
一种可能的解决方案是通过同一Command Queue在每个可绘制对象中排队一个MTLCommandBuffer。要了解如何使两个不同的命令缓冲区入队并确保它们执行的顺序,您应该检查Apple的ObjectExample示例代码。您可以从here下载它。