TL;DR: How do you encode and decode an MTLSharedTextureHandle
and MTLSharedEventHandler
such that it can be transported across an XPC connection inside an xpc_dictionary
?
A macOS application I'm working on makes extensive use of XPC services and was implemented using the C-based API. (i.e.: xpc_main, xpc_connection, xpc_dictionary...
) This made sense at the time because certain objects, like IOSurfaces
, did not support NSCoding/NSSecureCoding
and had to be passed using IOSurfaceCreateXPCObject
.
In macOS 10.14, Apple introduced new classes for sharing Metal textures and events between processes: MTLSharedTextureHandle
and MTLSharedEventHandle
. These classes support NSSecureCoding
but they don't appear to have a counter-part in the C-XPC interface for encoding/decoding them.
I thought I could use something like [NSKeyedArchiver archivedDataWithRootObject:requiringSecureCoding:error]
to just convert them to NSData
objects, which can then be stored in an xpc_dictionary
, but when I try and do that, I get the following exception:
Caught exception during archival:
This object may only be encoded by an NSXPCCoder.
(NSXPCCoder is a private class.)
This happens for both MTLSharedTextureHandle
and MTLSharedEventHandle
. I could switch over to using the new NSXPCConnection
API but I've already got an extensive amount of code built on the C-interface, so I'd rather not have to make the switch.
Is there any way to archive either of those two classes into a payload that can be stored in an xpc_dictionary
for transfer between the service and the client?
MTLSharedTextureHandle
only works withNSXPCConnection
. If you're creating the texture from an IOSurface you can share the surface instead which is effectively the same thing. Make sure you are using the same GPU (sameid<MTLDevice>
) in both processes.There is no workaround for
MTLSharedEventHandle
using public API.I recommend switching to
NSXPCConnection
if you can. Unfortunately there isn't a good story for partially changing over using public API, you'll have to do it all at once or split your XPC service into two separate services.