Article

Getting the GPU that Drives a View's Display

Keep up to date with the optimal device for your display.

Overview

A user can have multiple external displays connected directly to a Mac or to an external GPU. Each view in your app is shown on a single display, and each display is driven by a single GPU. The display in which your view appears and the GPU that drives the display can change dynamically; therefore, you need to prepare your app to handle these changes. Register for display change notifications, get the device that drives your view's display, and decide if your app should use that device to present rendered graphics.

Handle Display Change Notifications

Register for the following notifications so the system can notify your app about specific display changes:

  • didChangeScreenNotification. The system posts this notification when any window, including the window containing your view, moves to a different display.

  • didChangeScreenParametersNotification. The system posts this notification when the Mac's display configuration changes; for example, when the user connects or disconnects an external display from the system. Another example is when the GPU driving the display changes, such as when automatic graphics switching is enabled and the system switches between discrete and integrated GPUs to drive the display.

When the system posts a display change notification, you can decide if you should get and use a new device.

@objc func handleDisplayChanges(notification: NSNotification) {
    // Handle display changes
}

func registerForDisplayChangeNotifications() {
    NotificationCenter.default.addObserver(self,
                                           selector: #selector(handleDisplayChanges(notification:)),
                                           name: NSNotification.Name(rawValue: "NSWindowDidChangeScreenNotification"),
                                           object: nil)
    
    NotificationCenter.default.addObserver(self,
                                           selector: #selector(handleDisplayChanges(notification:)),
                                           name: NSNotification.Name(rawValue: "NSApplicationDidChangeScreenParametersNotification"),
                                           object: nil)
}

To deregister from the previous notifications, call the removeObserver(_:name:object:) method.

Identify the Device that Drives Your View's Display

Get the CGDirectDisplayID value for the display in which your view currently appears. Then call the CGDirectDisplayCopyCurrentMetalDevice function to get the device that drives that display.

guard let viewDisplayID = mtkView.window?.screen?.deviceDescription[NSDeviceDescriptionKey("NSScreenNumber")] as? CGDirectDisplayID else { return }
let displayDevice = CGDirectDisplayCopyCurrentMetalDevice(viewDisplayID)

See Also

Selecting GPUs on Mac

Device Selection and Fallback for Graphics Rendering

Demonstrates how to work with multiple GPUs and efficiently render to a display.

Device Selection and Fallback for Compute Processing

Demonstrates how to work with multiple GPUs and efficiently execute a compute-intensive simulation.

About External GPUs

Learn how to support external GPUs in your macOS apps and games.

About Multi-GPU and Multi-Display Setups

Learn about the different ways that a user can connect external GPUs and external displays to a Mac computer.

About GPU Bandwidth

Learn about some of the main factors that affect bandwidth between a GPU and a system on a Mac.

Handling External GPU Additions and Removals

Register and respond to external GPU notifications initiated by a user.

Getting Different Types of GPUs

Obtain, identify, and choose suitable GPUs for your app.