如何在进程之间同步MTLTexture和IOSurface



在XPC进程中写入IOSurface时,我需要使用哪些API,以及需要采取哪些预防措施,XPC进程也用作主应用程序中MTLTexture的后备存储?

在我的XPC服务中,我有以下内容:

IOSurface *surface = ...;
CIRenderDestination *renderDestination = [... initWithIOSurface:surface];
// Send the IOSurface to the client using an NSXPCConnection.
// In the service, periodically write to the IOSurface.

在我的应用程序中,我有以下内容:

IOSurface *surface = // ... fetch IOSurface from NSXPConnection.
id<MTLTexture> texture = [device newTextureWithDescriptor:... iosurface:surface];
// The texture is used in a fragment shader (Read-only)

我有一个MTKView正在运行它的正常更新循环。我希望我的XPC服务能够使用Core Image定期写入IOSurface,然后让Metal在应用程序端呈现新内容。

需要什么样的同步才能确保正确执行?两次或三次缓冲策略是其中之一,但这对我来说并不奏效,因为我可能没有足够的内存来分配2倍或3倍的表面数量(为了清晰起见,上面的例子使用了一个表面,但实际上我可能要绘制几十个表面。每个表面代表一个图像的瓦片。图像可以是JPG/TIFF等允许的大小。)

WWDC 2010-442谈到了IOSurface,并简要提到它"只是起作用",但这是在OpenGL的背景下,没有提到Core Image或Metal。

我最初认为Core Image和/或Metal将调用IOSurfaceLock()IOSurfaceUnlock()来保护读/写访问,但事实并非如此(IOSurfaceRef.h的头文件中的注释表明锁定仅用于CPU访问。)

当我在应用程序的更新循环中读取相应的MTLTexture时,我真的可以让Core Image的CIRenderDestination随意写入IOSurface吗?如果是这样,那么,正如WWDC视频所说,如果绑定到IOSurface的所有纹理共享相同的视频内存,这怎么可能呢?如果阅读和写作同时进行,我肯定会对表面内容产生一些撕裂

您需要做的是确保在应用程序中使用IOSurface绘制之前,CoreImage绘制已在XPC中完成。如果在两侧都使用OpenGL或Metal,则可以调用glFlush()[-MTLRenderCommandEncoder waitUntilScheduled]。我认为CoreImage中的某个东西正在打这些电话。

我可以说,如果没有发生这种情况,这可能是显而易见的,因为如果事情没有正确同步,你会得到撕裂或一半是新渲染一半是旧渲染的图像。我在跨XPC使用IOSurface时看到过这种情况。

您可以做的一件事是在-waitUntilScheduled-waitUntilCompleted上放置一些符号断点,看看CI是否在XPC中调用它们(假设文档没有明确告诉您)。Metal中还有其他同步原语,但我对它们不是很熟悉。它们也可能有用。(据我所知,CI现在全是金属。)

此外,IOSurface对象具有方法-incrementUseCount-decrementUseCount-localUseCount。也许值得检查一下,看看CI是否对它们进行了适当的设置。(详见<IOSurface/IOSurfaceObjC.h>。)

相关内容

  • 没有找到相关文章

最新更新