Trouble creating an XPC service for out-of-process rendering

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.

Answered by DTS Engineer in 877315022
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.

I managed to get it mostly working by changing my approach, now there's a target for the XPC service which will host the game and the editor creates a session per project.

I have an issue with MTLSharedTextureHandle not being Encodable, how am I supposed to send it across?

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.

Trouble creating an XPC service for out-of-process rendering
 
 
Q