首页 > 解决方案 > 是否需要在主线程上绘制到 MTKView 或 CAMetalLayer?

问题描述

众所周知,更新用户界面AppKitUIKit需要在主线程上进行。Metal 在展示 时是否有相同的要求drawable

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

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

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

标签: macosuikitmetalappkitmetalkit

解决方案


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

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

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

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

甚至在那之后,drawable 在屏幕上的实际呈现在对-present. 可绘制对象等待直到渲染或写入其纹理的任何命令完成,然后才呈现到屏幕上。没有具体说明如何实现这种异步性,但它进一步表明-present调用哪个线程并不重要。

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


推荐阅读