How do I detect External GPU (eGPU) connection and disconnection on macOS?

alf*_*att 2 macos gpu iokit metal

I'd like to write a macOS app which detects when you disconnect an external GPU via the Disconnect "GPU Name" Menu Extra and then takes some action.

  • What API do I use to detect the presence of the GPU?

  • Can I get notifications when the GPU is disconnected and subsequently plugged in?

Ken*_*ses 7

来自Apple的Metal 文档

注册获取外部GPU通知

调用该MTLCopyAllDevicesWithObserver函数以获取系统可用的所有Metal设备的列表,并注册一个在此列表更改(或由于安全断开请求而更改)时调用的观察者。

id <NSObject> deviceObserver  = nil;
NSArray<id<MTLDevice>> *deviceList = nil;
deviceList = MTLCopyAllDevicesWithObserver(&deviceObserver,
                                           ^(id<MTLDevice> device, MTLDeviceNotificationName name) {
                                               [self handleExternalGPUEventsForDevice:device notification:name];
                                           });
_deviceObserver = deviceObserver;
_deviceList = deviceList;
Run Code Online (Sandbox Code Playgroud)

要注销观察者,请调用该MTLRemoveDeviceObserver 函数。

响应外部GPU通知

Metal将这些外部GPU事件通知您的应用程序:

  • MTLDeviceWasAddedNotification。当将外部GPU添加到系统时,Metal将发布此通知。评估更新后的设备列表,并考虑使用新添加的设备。

  • MTLDeviceRemovalRequestedNotification。当用户启动外部GPU的安全断开请求时,Metal将发布此通知。您的应用大约需要一秒钟的时间才能从设备上迁移工作并删除对该设备的所有引用。如果您的应用程序失败,macOS会通知用户您的应用程序阻止了安全断开连接请求。

  • MTLDeviceWasRemovedNotification。当系统中移除了外部GPU且您的应用仍具有对该设备的引用时,Metal会发布此通知。如果用户安全地断开了外部GPU的连接,Metal将在发布通知后发布此MTLDeviceRemovalRequestedNotification通知。如果用户意外断开了外部GPU的连接,Metal将发布此通知,而无需先发布 MTLDeviceRemovalRequestedNotification通知。卸下外部GPU后,为该设备排队的所有命令缓冲区都将完成,并出现错误,而引用该设备的任何新API调用均将失败,并出现错误。

设置一种方法来响应通知,并将该方法传递给函数的handler参数MTLCopyAllDevicesWithObserver

- (void)handleExternalGPUEventsForDevice:(id<MTLDevice>)device notification:(MTLDeviceNotificationName)notification
{
    if (notification == MTLDeviceWasAddedNotification) {  }
    else if (notification == MTLDeviceRemovalRequestedNotification) {  }
    else if (notification == MTLDeviceWasRemovedNotification) {  }
}
Run Code Online (Sandbox Code Playgroud)