Skip to content

Commit

Permalink
macOS/ARM: Allow populating GPU based on AGXAccelerator
Browse files Browse the repository at this point in the history
The existing scheme for populating GPU vendor and device IDs fails
on macOS/ARM. If we find no PCI registry entries, look for a
AGXAccelerator entry, and (partially) populate that.

This is sufficient for Chrome to initialize hardware acceleration.
It is unknown how this will interact with multiple GPUs, and this
will likely need to be revisited.

Bug: chromium:1110421
Change-Id: I08069d7aecf45c83a1d2827cfccc4733c1835994
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2324939
Reviewed-by: Corentin Wallez <[email protected]>
Reviewed-by: Geoff Lang <[email protected]>
Reviewed-by: Lingfeng Yang <[email protected]>
Commit-Queue: ccameron <[email protected]>
  • Loading branch information
ccameron-chromium authored and kakashidinho committed May 8, 2021
1 parent 4ccacad commit 5dcbac4
Showing 1 changed file with 50 additions and 30 deletions.
80 changes: 50 additions & 30 deletions src/gpu_info_util/SystemInfo_mac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -118,40 +118,64 @@ bool GetEntryProperty(io_registry_entry_t entry, CFStringRef name, uint32_t *val
return true;
}

// Gathers the vendor and device IDs for the PCI GPUs
bool GetPCIDevices(std::vector<GPUDeviceInfo> *devices)
// Gathers the vendor and device IDs for GPUs listed in the IORegistry.
void GetIORegistryDevices(std::vector<GPUDeviceInfo> *devices)
{
// matchDictionary will be consumed by IOServiceGetMatchingServices, no need to release it.
CFMutableDictionaryRef matchDictionary = IOServiceMatching("IOPCIDevice");

io_iterator_t entryIterator;
if (IOServiceGetMatchingServices(kIOMasterPortDefault, matchDictionary, &entryIterator) !=
kIOReturnSuccess)
constexpr uint32_t kNumServices = 2;
const char *kServiceNames[kNumServices] = {"IOPCIDevice", "AGXAccelerator"};
const bool kServiceIsVGA[kNumServices] = {true, false};
for (uint32_t i = 0; i < kNumServices; ++i)
{
return false;
}
// matchDictionary will be consumed by IOServiceGetMatchingServices, no need to release it.
CFMutableDictionaryRef matchDictionary = IOServiceMatching(kServiceNames[i]);

io_registry_entry_t entry = IO_OBJECT_NULL;
io_iterator_t entryIterator;
if (IOServiceGetMatchingServices(kIOMasterPortDefault, matchDictionary, &entryIterator) !=
kIOReturnSuccess)
{
continue;
}

while ((entry = IOIteratorNext(entryIterator)) != IO_OBJECT_NULL)
{
constexpr uint32_t kClassCodeDisplayVGA = 0x30000;
uint32_t classCode;
GPUDeviceInfo info;

if (GetEntryProperty(entry, CFSTR("class-code"), &classCode) &&
classCode == kClassCodeDisplayVGA &&
GetEntryProperty(entry, CFSTR("vendor-id"), &info.vendorId) &&
GetEntryProperty(entry, CFSTR("device-id"), &info.deviceId))
io_registry_entry_t entry = IO_OBJECT_NULL;
while ((entry = IOIteratorNext(entryIterator)) != IO_OBJECT_NULL)
{
constexpr uint32_t kClassCodeDisplayVGA = 0x30000;
uint32_t classCode;
GPUDeviceInfo info;

// AGXAccelerator entries only provide a vendor ID.
if (!GetEntryProperty(entry, CFSTR("vendor-id"), &info.vendorId))
{
continue;
}

if (kServiceIsVGA[i])
{
if (!GetEntryProperty(entry, CFSTR("class-code"), &classCode))
{
continue;
}
if (classCode != kClassCodeDisplayVGA)
{
continue;
}
if (!GetEntryProperty(entry, CFSTR("device-id"), &info.deviceId))
{
continue;
}
}

devices->push_back(info);
IOObjectRelease(entry);
}
IOObjectRelease(entryIterator);

IOObjectRelease(entry);
// If any devices have been populated by IOPCIDevice, do not continue to AGXAccelerator.
if (!devices->empty())
{
break;
}
}
IOObjectRelease(entryIterator);

return true;
}

void SetActiveGPUIndex(SystemInfo *info)
Expand Down Expand Up @@ -203,11 +227,7 @@ bool GetSystemInfo(SystemInfo *info)
info->machineModelVersion = std::to_string(major) + "." + std::to_string(minor);
}

if (!GetPCIDevices(&(info->gpus)))
{
return false;
}

GetIORegistryDevices(&info->gpus);
if (info->gpus.empty())
{
return false;
Expand Down

0 comments on commit 5dcbac4

Please sign in to comment.