代码之家  ›  专栏  ›  技术社区  ›  kennyc

如何跨进程同步MTLTexture和iSurface?

  •  3
  • kennyc  · 技术社区  · 6 年前

    我需要使用哪些API,以及在向应用程序写入时需要采取哪些预防措施 IOSurface 在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服务能够定期向 表面 使用核心图像,然后在应用程序端使用Metal呈现新内容。

    需要什么样的同步来确保正确完成?双缓冲或三缓冲策略是一种,但这对我来说并不适用,因为我可能没有足够的内存来分配2倍或3倍数量的曲面。 (为了清晰起见,上面的例子使用了一个曲面,但实际上我可能有几十个正在绘制的曲面。每个曲面代表一个图像的一个平铺。一个图像可以是JPG/TIFF/etc允许的最大值。)

    WWDC 2010-442谈论 表面 并简要地提到,这一切“只是工作”,但这是在OpenGL的背景下,没有提到核心图像或金属。

    我最初以为核心图像和/或金属将调用 IOSurfaceLock() IOSurfaceUnlock() 保护读/写访问,但事实似乎并非如此。 (以及标题文件中的注释) IOSurfaceRef.h 建议锁定仅用于CPU访问。)

    我真的可以让Core Image CIRenderDestination 随意写信给 表面 当我阅读相应的 MTLTexture 在我的应用程序的更新循环中?如果是这样,那么,如果像WWDC视频中所说的那样,所有纹理都绑定到 表面 共享相同的视频内存?如果阅读和写作发生在同一个过程中,我肯定会被表面的内容撕裂。

    1 回复  |  直到 6 年前
        1
  •  4
  •   user1118321    6 年前

    您需要做的事情是确保CoreImage绘图在 IOSurface 用于在应用程序中绘制。如果两边都使用OpenGL或Metal,则可以调用 glFlush() [-MTLRenderCommandEncoder waitUntilScheduled] .我假设CoreImage中有人在打这些电话。

    我可以说,如果不发生这种情况,这很可能是显而易见的,因为如果事情没有正确同步,你会得到半新半旧的图像。我见过在使用 表面 它跨越了XPC。

    你可以做的一件事就是在屏幕上设置一些符号断点 -waitUntilScheduled -waitUntilCompleted 并查看CI是否在XPC中调用它们(假设 documentation 没有明确告诉你)。金属中还有其他同步原语,但我对它们不太熟悉。它们也可能有用。(据我所知,CI现在在引擎盖下是全金属的。)

    还有 表面 对象有方法 -incrementUseCount , -decrementUseCount -localUseCount .可能值得检查一下,看看CI是否正确设置了它们。(见 <IOSurface/IOSurfaceObjC.h> 详细信息。)