Edit

kc3-lang/angle/src/gpu_info_util/SystemInfo_mac.mm

Branch :

  • Show log

    Commit

  • Author : Corentin Wallez
    Date : 2017-02-16 10:58:46
    Hash : d83f64f5
    Message : gpu_info_util: Implement GetSystemInfo on OSX Also adds a test that prints the gathered information for manual checking and to help know what the system is when looking at the logs. BUG=angleproject:1874 Change-Id: Icb0cc390c9808fd8db0f966d667b94dde4b94e62 Reviewed-on: https://chromium-review.googlesource.com/443845 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Geoff Lang <geofflang@chromium.org> Reviewed-by: Zhenyao Mo <zmo@chromium.org>

  • src/gpu_info_util/SystemInfo_mac.mm
  • //
    // Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    
    // SystemInfo_mac.cpp: implementation of the Mac-specific parts of SystemInfo.h
    
    #include "gpu_info_util/SystemInfo_internal.h"
    
    #import <Cocoa/Cocoa.h>
    #import <IOKit/IOKitLib.h>
    
    namespace angle
    {
    
    namespace
    {
    
    std::string GetMachineModel()
    {
        io_service_t platformExpert = IOServiceGetMatchingService(
            kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"));
    
        if (platformExpert == IO_OBJECT_NULL)
        {
            return "";
        }
    
        CFDataRef modelData = static_cast<CFDataRef>(
            IORegistryEntryCreateCFProperty(platformExpert, CFSTR("model"), kCFAllocatorDefault, 0));
        if (modelData == nullptr)
        {
            IOObjectRelease(platformExpert);
            return "";
        }
    
        std::string result = reinterpret_cast<const char *>(CFDataGetBytePtr(modelData));
    
        IOObjectRelease(platformExpert);
        CFRelease(modelData);
    
        return result;
    }
    
    // Extracts one integer property from a registry entry.
    bool GetEntryProperty(io_registry_entry_t entry, CFStringRef name, uint32_t *value)
    {
        *value = 0;
    
        CFDataRef data = static_cast<CFDataRef>(
            IORegistryEntrySearchCFProperty(entry, kIOServicePlane, name, kCFAllocatorDefault,
                                            kIORegistryIterateRecursively | kIORegistryIterateParents));
    
        if (data == nullptr)
        {
            return false;
        }
    
        const uint32_t *valuePtr = reinterpret_cast<const uint32_t *>(CFDataGetBytePtr(data));
    
        if (valuePtr == nullptr)
        {
            CFRelease(data);
            return false;
        }
    
        *value = *valuePtr;
        CFRelease(data);
        return true;
    }
    
    // CGDisplayIOServicePort is deprecated as of macOS 10.9, but has no replacement, see
    // https://crbug.com/650837
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wdeprecated-declarations"
    
    // Find the info of the current GPU.
    bool GetActiveGPU(VendorID *vendorId, DeviceID *deviceId)
    {
        io_registry_entry_t port = CGDisplayIOServicePort(kCGDirectMainDisplay);
    
        return GetEntryProperty(port, CFSTR("vendor-id"), vendorId) &&
               GetEntryProperty(port, CFSTR("device-id"), deviceId);
    }
    
    #pragma clang diagnostic pop
    
    // Gathers the vendor and device IDs for the PCI GPUs
    bool GetPCIDevices(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)
        {
            return false;
        }
    
        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;
    
            if (GetEntryProperty(entry, CFSTR("class-code"), &classCode) &&
                classCode == kClassCodeDisplayVGA &&
                GetEntryProperty(entry, CFSTR("vendor-id"), &info.vendorId) &&
                GetEntryProperty(entry, CFSTR("device-id"), &info.deviceId))
            {
                devices->push_back(info);
            }
    
            IOObjectRelease(entry);
        }
        IOObjectRelease(entryIterator);
    
        return true;
    }
    
    }  // anonymous namespace
    
    bool GetSystemInfo(SystemInfo *info)
    {
        {
            int32_t major = 0;
            int32_t minor = 0;
            ParseMacMachineModel(GetMachineModel(), &info->machineModelName, &major, &minor);
            info->machineModelVersion = std::to_string(major) + "." + std::to_string(minor);
        }
    
        if (!GetPCIDevices(&(info->gpus)))
        {
            return false;
        }
    
        if (info->gpus.empty())
        {
            return false;
        }
    
        // Find the active GPU
        {
            VendorID activeVendor;
            DeviceID activeDevice;
            if (!GetActiveGPU(&activeVendor, &activeDevice))
            {
                return false;
            }
    
            for (size_t i = 0; i < info->gpus.size(); ++i)
            {
                if (info->gpus[i].vendorId == activeVendor && info->gpus[i].deviceId == activeDevice)
                {
                    info->activeGPUIndex = i;
                    break;
                }
            }
        }
    
        FindPrimaryGPU(info);
    
        return true;
    }
    
    }  // namespace angle