众所周知,需要在主线程上进行AppKit
或UIKit
中的用户界面更新。在呈现drawable
时,Metal是否有相同的要求?
在我一直在使用的图层托管NSView
中,我注意到可以从[CAMetalLayer nextDrawable]
而非{{1} }。然后,我可以照常更新该drawable的纹理并将其呈现。
此似乎可以正常工作,但是我觉得这有点可疑。除非我忽略了文档中的某些内容,否则我不会提及Metal的主线程要求(支持或反对)。
(我正在macOS 10.13上进行测试,但我认为iOS的主线程要求也相同...?)
答案 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的特定警告。同样,这是缺乏证据的论点,但我认为这很清楚。他们确实指出一次只能有一个线程作用在给定的命令缓冲区上,因此他们正在考虑线程安全性问题。