是否需要在主线程上绘制MTKView或CAMetalLayer? [英] Is drawing to an MTKView or CAMetalLayer required to take place on the main thread?
问题描述
众所周知,需要在主线程上更新 AppKit
或 UIKit
中的用户界面.在呈现 drawable
时,Metal是否有相同的要求?
在我一直在玩的图层托管的 NSView
中,我注意到可以从 dispatch_queue调用
[CAMetalLayer nextDrawable]
而不是 main_queue
.然后,我可以照常更新该drawable的纹理并将其呈现.
此似乎可以正常工作,但是我觉得这有点可疑.除非我忽略了文档中的某些内容,否则我不会提及Metal的主线程要求(支持或反对).
(我正在macOS 10.13上进行测试,但我认为iOS的主线程要求也相同...?)
在后台线程上绘制是安全的.用于 -nextDrawable
的文档说:
调用此方法将阻塞当前CPU线程,直到有新的可绘制对象可用为止.
(添加了强调.)如果只能在主线程上调用它,则可能不会如此概括.此外,Apple的一般建议是避免阻塞主线程,因此您认为他们会在这里以某种方式指出这一事实,例如建议您不要调用它,除非您确定它不会阻塞./p>
关于使用drawable的方式(而不是获取方式),请注意,典型的用例是调用命令缓冲区的 -presentDrawable:
方法.该方法很方便添加计划的处理程序块(例如通过 -addScheduledHandler:
),该块随后将在可绘制对象上调用 -present
.未指定处理程序块将在哪个线程或队列上调用,这表明无法保证对drawable的 -present
调用将在主线程上发生.
即使在此之后,在 -present
的调用中,可绘制对象在屏幕上的实际显示也不同步.可绘制对象等待,直到渲染或写入其纹理的所有命令完成,然后才呈现到屏幕.尚未说明如何实现异步性,但它进一步表明调用 -present
线程是无关紧要的.
有关多线程,命令缓冲区和命令编码器的部分.请注意,这里讨论的是由后台线程填充命令缓冲区,而没有关于使用可绘制对象的特定警告.同样,这是缺乏证据的论点,但我认为这很清楚.他们确实指出,一次只有一个线程可以同时作用于给定的命令缓冲区,因此他们正在考虑线程安全性问题.
It's well known that updating the user interface in AppKit
or UIKit
is required to take place on the main thread. Does Metal have the same requirement when it comes to presenting a drawable
?
In a layer-hosted NSView
that I've been playing around with, I've noticed that I can call [CAMetalLayer nextDrawable]
from a dispatch_queue
that is not the main_queue
. I can then update that drawable's texture as usual and present it.
This appears to work properly, but I find that rather suspicious. Unless I've overlooked something in the documentation, I can find no mention of Metal's main thread requirements (either for, or against).
(I'm testing on macOS 10.13, but I would assume the main thread requirements would be the same for iOS as well...?)
It is safe to draw on background threads. The docs for -nextDrawable
say:
Calling this method blocks the current CPU thread until a new drawable is available.
(Emphasis added.) If it could only be called on the main thread, that would probably not be so generalized. Also, Apple's general advice is to avoid blocking the main thread, so you'd think they would call out that fact in some way here, such as advising you not to call it unless you're pretty sure it won't block.
For how the drawable is used (rather than obtained), note that a typical use case is to call the command buffer's -presentDrawable:
method. That method is a convenience for adding a scheduled handler block (as via -addScheduledHandler:
) which will then call -present
on the drawable. It is unspecified what thread or queue the handler blocks will be called on, which suggests that there's no promise that the -present
call on the drawable will happen on the main thread.
And even after that, the actual presentation of the drawable to the screen is not synchronous within the call to -present
. The drawable waits until any commands that render or write to its texture are completed and only then presents to the screen. It's not specified how that asynchronicity is achieved, but it further suggests that it doesn't matter what thread -present
is called on.
There's a bit of discussion about multi-threading in the Metal Programming Guide, although it's not quite as direct as one might hope. See especially the section on Multiple Threads, Command Buffers, and Command Encoders. Note that there's a discussion of command buffers being filled by background threads and no specific warning about working with drawables. Again, it's sort of argument by lack of evidence, but I think it's clear. They do call out that only a single thread may act on a given command buffer at a time, so they are considering thread safety questions.
这篇关于是否需要在主线程上绘制MTKView或CAMetalLayer?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!