在MetalKit中创建呈现传递时,等待完成或添加完成处理程序的性能会更好吗?如果我使用完成处理程序,那么我将得到许多嵌套的闭包,但我认为waitForCompletion可能会阻塞一个线程。如果首选完成处理程序,那么Swift中是否有更好的方法可以做到这一点而不必使用如此多的嵌套闭包?
例如,
buffer.addCompletionHandler { _ in
... next task
buffer2.addCompletionHandler { _ in
... etc etc
}
}发布于 2022-03-06 21:45:46
其他人告诉你这可能不是你想要做的,你应该去教育自己别人是如何在金属中创建渲染循环的。
也就是说,如果你真的有非阻塞版本的waitUntilCompleted或waitUntilScheduled的用例,你可以创建和使用你自己的,直到苹果有时间提供同样的。
public extension MTLCommandBuffer {
/// Wait until this command buffer is scheduled for execution on the GPU.
var schedulingCompletion: Void {
get async {
await withUnsafeContinuation { continuation in
addScheduledHandler { _ in
continuation.resume()
}
}
}
}
/// Wait until the GPU has finished executing the commands in this buffer.
var completion: Void {
get async {
await withUnsafeContinuation { continuation in
addCompletedHandler { _ in
continuation.resume()
}
}
}
}
}但我怀疑这些属性是否会改进任何代码,因为所有任务排序代码(确保在调用commit之前添加了“处理程序”)都比回调更糟糕。
let string: String = await withTaskGroup(of: String.self) { group in
let buffer = MTLCreateSystemDefaultDevice()!.makeCommandQueue()!.makeCommandBuffer()!
group.addTask {
await buffer.schedulingCompletion
return "2"
}
group.addTask {
await buffer.completion
return "3"
}
group.addTask {
buffer.commit()
return "1"
}
return await .init(group)
}
XCTAssertEqual(string, "123")public extension String {
init<Strings: AsyncSequence>(_ strings: Strings) async rethrows
where Strings.Element == String {
self = try await strings.reduce(into: .init()) { $0.append($1) }
}
}然而,虽然我不相信addScheduledHandler是可改进的,但我认为addCompletedHandler和commit配对具有更大的潜力。
public extension MTLCommandBuffer {
/// Commit this buffer and wait for the GPU to finish executing its commands.
func complete() async {
await withUnsafeContinuation { continuation in
self.addCompletedHandler { _ in
continuation.resume()
}
commit()
} as Void
}
}发布于 2022-03-06 20:09:18
您应该使用MTLCommandQueue和MTLEvent来序列化您的GPU工作,而不是完成处理程序。完成处理程序只能在需要CPU-GPU同步的情况下使用。例如,当您需要在CPU上读取GPU计算结果时,或者需要增加背压,例如,当您只想同时绘制一定数量的帧时。
https://stackoverflow.com/questions/71372088
复制相似问题