你如何在 macOS 上将 MTLSharedTextureHandle 或 MTLSharedEventHandle 与 C XPC 接口一起使用?

How do you use MTLSharedTextureHandle or MTLSharedEventHandle with the C XPC interface on macOS?

TL;DR: 如何对 MTLSharedTextureHandleMTLSharedEventHandler 进行编码和解码,以便它可以在 xpc_dictionary?


我正在开发的一个 macOS 应用程序广泛使用了 XPC 服务,并且是使用基于 C 的 API 实现的。 (即:xpc_main, xpc_connection, xpc_dictionary...)这在当时是有道理的,因为某些对象,如 IOSurfaces,不支持 NSCoding/NSSecureCoding,必须使用 IOSurfaceCreateXPCObject 传递。

在 macOS 10.14 中,Apple 引入了新的 classes 用于在进程之间共享 Metal 纹理和事件:MTLSharedTextureHandleMTLSharedEventHandle。这些 classes 支持 NSSecureCoding 但它们在 C-XPC 接口中似乎没有 encoding/decoding 它们的对应部分。

我想我可以使用 [NSKeyedArchiver archivedDataWithRootObject:requiringSecureCoding:error] 之类的东西将它们转换为 NSData 对象,然后可以将其存储在 xpc_dictionary 中,但是当我尝试这样做时,我收到以下异常:

Caught exception during archival: 
This object may only be encoded by an NSXPCCoder.

(NSXPCCoder 是私有的class。)

MTLSharedTextureHandleMTLSharedEventHandle 都会出现这种情况。我可以切换到使用新的 NSXPCConnection API 但我已经在 C 接口上构建了大量代码,所以我宁愿不必进行切换。

有什么方法可以将这两个 class 中的任何一个存档到可以存储在 xpc_dictionary 中的有效载荷中,以便在服务和客户端之间传输?

MTLSharedTextureHandle 仅适用于 NSXPCConnection。如果您从 IOSurface 创建纹理,则可以共享表面,这实际上是同一件事。确保您在两个进程中使用相同的 GPU(相同 id<MTLDevice>)。

MTLSharedEventHandle 没有使用 public API 的解决方法。

如果可以,我建议切换到 NSXPCConnection。不幸的是,使用 public API 进行部分更改并不是一个好故事,您必须一次完成所有操作,或者将您的 XPC 服务拆分为两个单独的服务。