绘制到 MTKView 或 CAMetalLayer 是否需要在主线程上进行?

ken*_*nyc 8 macos uikit appkit metal metalkit

众所周知,更新用户界面AppKit需要UIKit在主线程中进行。Metal 在呈现时是否有相同的要求drawable

在我一直在使用的层托管中NSView,我注意到我可以[CAMetalLayer nextDrawable]dispatch_queue不是main_queue. 然后我可以像往常一样更新该可绘制的纹理并呈现它。

似乎工作正常,但我发现这很可疑。除非我忽略了文档中的某些内容,否则我找不到任何提及 Metal 的主线程要求的内容(无论是支持还是反对)。

(我正在 macOS 10.13 上进行测试,但我假设 iOS 的主线程要求也是相同的......?)

Ken*_*ses 6

在后台线程上绘图是安全的。文档-nextDrawable

调用此方法会阻塞当前 CPU 线程,直到有新的可绘制对象可用。

(强调。)如果它只能在主线程上调用,那可能就不会那么普遍了。另外,Apple 的一般建议是避免阻塞主线程,因此您可能会认为他们会在这里以某种方式指出这一事实,例如建议您不要调用它,除非您非常确定它不会阻塞。

对于如何使用可绘制对象(而不是获取),请注意,典型的用例是调用命令缓冲区的-presentDrawable:方法。该方法可以方便地添加计划处理程序块(如 via -addScheduledHandler:),然后该处理程序块将调用可绘制-present对象。未指定处理程序块将在哪个线程或队列上调用,这表明不能保证对-present可绘制对象的调用将在主线程上发生。

即使在那之后,可绘制对象在屏幕上的实际呈现在对 的调用中也不是同步的-present。可绘制对象会等待任何渲染或写入其纹理的命令完成,然后才会呈现在屏幕上。它没有指定如何实现异步性,但它进一步表明-present调用哪个线程并不重要。

Metal 编程指南中有一些关于多线程的讨论,尽管它并不像人们希望的那么直接。请特别参阅有关多线程、命令缓冲区和命令编码器的部分。请注意,这里讨论了后台线程填充的命令缓冲区,并且没有关于使用可绘制对象的具体警告。再说一遍,这是缺乏证据的争论,但我认为这是明确的。他们确实指出,一次只能有一个线程对给定的命令缓冲区执行操作,因此他们正在考虑线程安全问题。