I'm working on an editor for Bevy games and wanted the following workflow:
- Launch the game process
- Host a Metal view for the game's render target
- Use an XPC service to transfer an
MTLSharedTextureHandle - Keep the connection for editor/game communication and hot reload
As such I created the following editor service:
public let XPCEditorServiceName = "org.bevy.editor"
public enum XPCEditorMessage: Codable {
case ping
}
public enum XPCEditorReply: Codable {
case pong
}
extension XPCListener {
static let bevy = try! XPCListener(service: XPCEditorServiceName) { request in
request.accept(XPCEditorService.init)
}
}
struct XPCEditorService: XPCPeerHandler {
let session: XPCSession
private func handle(_ message: XPCEditorMessage) -> XPCEditorReply? {
switch message {
case .ping:
return .pong
}
}
func handleIncomingRequest(_ message: XPCReceivedMessage) -> (any Encodable)? {
do {
return handle(try message.decode())
} catch {
return nil
}
}
func handleCancellation(error: XPCRichError) {
print(error)
}
}
and I initialize it in my app's App initializer:
// Launch the XPC service
print(XPCListener.bevy)
I wanted to test this using an executable target with the following main.swift:
let session = try XPCSession(xpcService: XPCEditorServiceName)
let response: XPCEditorReply = try session.sendSync(XPCEditorMessage.ping)
print("Connected to editor!")
The editor prints Listener<org.bevy.editor>(Active) but the game fails with Underlying connection was invalidated. Reason: Connection init failed at lookup with error 3 - No such process
What am I doing wrong?
PS. Would also appreciate an example of sending & rendering the MTLSharedTextureHandle both in editor & game.
now there's a target for the XPC service
Right. XPC doesn’t let you establish a connection between arbitrary processes. Rather, the process advertising the named XPC endpoint must be known to the system. I talk about this a bunch in XPC and App-to-App Communication; see XPC Resources for a link to that.
Note that this only affects the connection direction. XPC connections are bidirectional, so the communication direction can go the other way, or in fact go both ways. XPC Resources has a link to another post that discusses that.
I have an issue with MTLSharedTextureHandle not being Encodable
It conforms to NSSecureCoding, indicating that it’s intended to be sent across an NSXPCConnection rather than the newer XPCSession. AFAICT there’s no generic way to transfer such an object via XPCSession [1]. If you’d like to see that added in the future, I encourage you to file an enhancement request for it. And if you file an ER, please post your bug number, just for the record.
XPC Resources has an overview of the various XPC APIs with links documentation and so on.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] You can do it with an IOSurface but — and, to be clear, I’m in no way a Metal expert — my understanding is that there’s a strong preference for MTLSharedTextureHandle.