首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >快速的MetalKit缓冲区完成处理程序与waitForCompletion?

快速的MetalKit缓冲区完成处理程序与waitForCompletion?
EN

Stack Overflow用户
提问于 2022-03-06 16:23:20
回答 2查看 169关注 0票数 -2

在MetalKit中创建呈现传递时,等待完成或添加完成处理程序的性能会更好吗?如果我使用完成处理程序,那么我将得到许多嵌套的闭包,但我认为waitForCompletion可能会阻塞一个线程。如果首选完成处理程序,那么Swift中是否有更好的方法可以做到这一点而不必使用如此多的嵌套闭包?

例如,

代码语言:javascript
复制
buffer.addCompletionHandler { _ in
    ... next task
    buffer2.addCompletionHandler { _ in
        ... etc etc
    }
}
EN

回答 2

Stack Overflow用户

发布于 2022-03-06 21:45:46

其他人告诉你这可能不是你想要做的,你应该去教育自己别人是如何在金属中创建渲染循环的。

也就是说,如果你真的有非阻塞版本的waitUntilCompletedwaitUntilScheduled的用例,你可以创建和使用你自己的,直到苹果有时间提供同样的。

代码语言:javascript
复制
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之前添加了“处理程序”)都比回调更糟糕。

代码语言:javascript
复制
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")
代码语言:javascript
复制
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是可改进的,但我认为addCompletedHandlercommit配对具有更大的潜力。

代码语言:javascript
复制
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
  }
}
票数 0
EN

Stack Overflow用户

发布于 2022-03-06 20:09:18

您应该使用MTLCommandQueueMTLEvent来序列化您的GPU工作,而不是完成处理程序。完成处理程序只能在需要CPU-GPU同步的情况下使用。例如,当您需要在CPU上读取GPU计算结果时,或者需要增加背压,例如,当您只想同时绘制一定数量的帧时。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71372088

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档