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

时间:2018-08-12 21:21:58

标签: macos uikit metal appkit metalkit

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

在我一直在使用的图层托管NSView中,我注意到可以从[CAMetalLayer nextDrawable]而非{{1} }。然后,我可以照常更新该drawable的纹理并将其呈现。

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

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

1 个答案:

答案 0 :(得分:2)

可以安全地使用后台线程。 docs for -nextDrawable说:

  

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

(添加了强调。)如果只能在主线程上调用它,则可能无法这么概括。另外,Apple的一般建议是避免阻塞主线程,因此您认为他们会在这里以某种方式指出这一事实,例如建议您不要调用它,除非您确定它不会阻塞。 / p>

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

即使在此之后,在向-present的调用中,可绘制对象在屏幕上的实际显示也不同步。可绘制对象等待,直到渲染或写入其纹理的所有命令完成,然后才显示在屏幕上。尚未说明如何实现异步性,但它进一步表明调用哪个线程-present并不重要。

Metal Programming Guide中有一些关于多线程的讨论,尽管它并不像人们希望的那样直接。尤其参见the section on Multiple Threads, Command Buffers, and Command Encoders。请注意,这里讨论了由后台线程填充命令缓冲区的问题,并且没有关于使用drawable的特定警告。同样,这是缺乏证据的论点,但我认为这很清楚。他们确实指出一次只能有一个线程作用在给定的命令缓冲区上,因此他们正在考虑线程安全性问题。