tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SystemInfo_vulkan.cpp (12058B)


      1 //
      2 // Copyright 2020 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 // SystemInfo_vulkan.cpp: Generic vulkan implementation of SystemInfo.h
      8 // TODO: Use VK_KHR_driver_properties. http://anglebug.com/5103
      9 
     10 #include "gpu_info_util/SystemInfo_vulkan.h"
     11 
     12 #include <vulkan/vulkan.h>
     13 #include "gpu_info_util/SystemInfo_internal.h"
     14 
     15 #include <cstring>
     16 #include <fstream>
     17 
     18 #include "common/angleutils.h"
     19 #include "common/debug.h"
     20 #include "common/system_utils.h"
     21 #include "common/vulkan/libvulkan_loader.h"
     22 
     23 namespace angle
     24 {
     25 class VulkanLibrary final : NonCopyable
     26 {
     27  public:
     28    VulkanLibrary() = default;
     29 
     30    ~VulkanLibrary()
     31    {
     32        if (mInstance != VK_NULL_HANDLE)
     33        {
     34            auto pfnDestroyInstance = getProc<PFN_vkDestroyInstance>("vkDestroyInstance");
     35            if (pfnDestroyInstance)
     36            {
     37                pfnDestroyInstance(mInstance, nullptr);
     38            }
     39        }
     40 
     41        CloseSystemLibrary(mLibVulkan);
     42    }
     43 
     44    VkInstance getVulkanInstance()
     45    {
     46        mLibVulkan = vk::OpenLibVulkan();
     47        if (!mLibVulkan)
     48        {
     49            // If Vulkan doesn't exist, bail-out early:
     50            return VK_NULL_HANDLE;
     51        }
     52 
     53        // Determine the available Vulkan instance version:
     54        uint32_t instanceVersion = VK_API_VERSION_1_0;
     55 #if defined(VK_VERSION_1_1)
     56        auto pfnEnumerateInstanceVersion =
     57            getProc<PFN_vkEnumerateInstanceVersion>("vkEnumerateInstanceVersion");
     58        if (!pfnEnumerateInstanceVersion ||
     59            pfnEnumerateInstanceVersion(&instanceVersion) != VK_SUCCESS)
     60        {
     61            instanceVersion = VK_API_VERSION_1_0;
     62        }
     63 #endif  // VK_VERSION_1_1
     64 
     65        // Create a Vulkan instance:
     66        VkApplicationInfo appInfo;
     67        appInfo.sType              = VK_STRUCTURE_TYPE_APPLICATION_INFO;
     68        appInfo.pNext              = nullptr;
     69        appInfo.pApplicationName   = "";
     70        appInfo.applicationVersion = 1;
     71        appInfo.pEngineName        = "";
     72        appInfo.engineVersion      = 1;
     73        appInfo.apiVersion         = instanceVersion;
     74 
     75        VkInstanceCreateInfo createInstanceInfo;
     76        createInstanceInfo.sType                   = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
     77        createInstanceInfo.pNext                   = nullptr;
     78        createInstanceInfo.flags                   = 0;
     79        createInstanceInfo.pApplicationInfo        = &appInfo;
     80        createInstanceInfo.enabledLayerCount       = 0;
     81        createInstanceInfo.ppEnabledLayerNames     = nullptr;
     82        createInstanceInfo.enabledExtensionCount   = 0;
     83        createInstanceInfo.ppEnabledExtensionNames = nullptr;
     84 
     85        auto pfnCreateInstance = getProc<PFN_vkCreateInstance>("vkCreateInstance");
     86        if (!pfnCreateInstance ||
     87            pfnCreateInstance(&createInstanceInfo, nullptr, &mInstance) != VK_SUCCESS)
     88        {
     89            return VK_NULL_HANDLE;
     90        }
     91 
     92        return mInstance;
     93    }
     94 
     95    template <typename Func>
     96    Func getProc(const char *fn) const
     97    {
     98        return reinterpret_cast<Func>(angle::GetLibrarySymbol(mLibVulkan, fn));
     99    }
    100 
    101  private:
    102    void *mLibVulkan     = nullptr;
    103    VkInstance mInstance = VK_NULL_HANDLE;
    104 };
    105 
    106 ANGLE_FORMAT_PRINTF(1, 2)
    107 std::string FormatString(const char *fmt, ...)
    108 {
    109    va_list vararg;
    110    va_start(vararg, fmt);
    111 
    112    std::vector<char> buffer;
    113    size_t len = FormatStringIntoVector(fmt, vararg, buffer);
    114    va_end(vararg);
    115 
    116    return std::string(&buffer[0], len);
    117 }
    118 
    119 bool GetSystemInfoVulkan(SystemInfo *info)
    120 {
    121    return GetSystemInfoVulkanWithICD(info, vk::ICD::Default);
    122 }
    123 
    124 bool GetSystemInfoVulkanWithICD(SystemInfo *info, vk::ICD preferredICD)
    125 {
    126    const bool enableValidationLayers = false;
    127    vk::ScopedVkLoaderEnvironment scopedEnvironment(enableValidationLayers, preferredICD);
    128 
    129    // This implementation builds on top of the Vulkan API, but cannot assume the existence of the
    130    // Vulkan library.  ANGLE can be installed on versions of Android as old as Ice Cream Sandwich.
    131    // Therefore, we need to use dlopen()/dlsym() in order to see if Vulkan is installed on the
    132    // system, and if so, to use it:
    133    VulkanLibrary vkLibrary;
    134    VkInstance instance = vkLibrary.getVulkanInstance();
    135    if (instance == VK_NULL_HANDLE)
    136    {
    137        // If Vulkan doesn't exist, bail-out early:
    138        return false;
    139    }
    140 
    141    // Enumerate the Vulkan physical devices, which are ANGLE gpus:
    142    auto pfnEnumeratePhysicalDevices =
    143        vkLibrary.getProc<PFN_vkEnumeratePhysicalDevices>("vkEnumeratePhysicalDevices");
    144    auto pfnGetPhysicalDeviceProperties =
    145        vkLibrary.getProc<PFN_vkGetPhysicalDeviceProperties>("vkGetPhysicalDeviceProperties");
    146    auto pfnGetPhysicalDeviceProperties2 =
    147        vkLibrary.getProc<PFN_vkGetPhysicalDeviceProperties2>("vkGetPhysicalDeviceProperties2");
    148    uint32_t physicalDeviceCount = 0;
    149    if (!pfnEnumeratePhysicalDevices || !pfnGetPhysicalDeviceProperties ||
    150        pfnEnumeratePhysicalDevices(instance, &physicalDeviceCount, nullptr) != VK_SUCCESS)
    151    {
    152        return false;
    153    }
    154    std::vector<VkPhysicalDevice> physicalDevices(physicalDeviceCount);
    155    if (pfnEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices.data()) !=
    156        VK_SUCCESS)
    157    {
    158        return false;
    159    }
    160 
    161    // If we get to here, we will likely provide a valid answer (unless an unknown vendorID):
    162    info->gpus.resize(physicalDeviceCount);
    163 
    164    for (uint32_t i = 0; i < physicalDeviceCount; i++)
    165    {
    166        VkPhysicalDeviceDriverProperties driverProperties = {};
    167        driverProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
    168 
    169        VkPhysicalDeviceProperties2 properties2 = {};
    170        properties2.sType                       = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
    171        properties2.pNext                       = &driverProperties;
    172 
    173        VkPhysicalDeviceProperties &properties = properties2.properties;
    174        pfnGetPhysicalDeviceProperties(physicalDevices[i], &properties);
    175 
    176        // vkGetPhysicalDeviceProperties2() is supported since 1.1
    177        // Use vkGetPhysicalDeviceProperties2() to get driver information.
    178        if (properties.apiVersion >= VK_API_VERSION_1_1)
    179        {
    180            pfnGetPhysicalDeviceProperties2(physicalDevices[i], &properties2);
    181        }
    182 
    183        // Fill in data for a given physical device (a.k.a. gpu):
    184        GPUDeviceInfo &gpu = info->gpus[i];
    185        gpu.vendorId       = properties.vendorID;
    186        gpu.deviceId       = properties.deviceID;
    187        // Need to parse/re-format properties.driverVersion.
    188        //
    189        // TODO(ianelliott): Determine the formatting used for each vendor
    190        // (http://anglebug.com/2677)
    191        // TODO(http://anglebug.com/7677): Use driverID instead of the hardware vendorID to detect
    192        // driveVendor, etc.
    193        switch (properties.vendorID)
    194        {
    195            case kVendorID_AMD:
    196                gpu.driverVendor                = "Advanced Micro Devices, Inc";
    197                gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
    198                gpu.detailedDriverVersion.major = properties.driverVersion;
    199                break;
    200            case kVendorID_ARM:
    201                gpu.driverVendor                = "Arm Holdings";
    202                gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
    203                gpu.detailedDriverVersion.major = properties.driverVersion;
    204                break;
    205            case kVendorID_Broadcom:
    206                gpu.driverVendor                = "Broadcom";
    207                gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
    208                gpu.detailedDriverVersion.major = properties.driverVersion;
    209                break;
    210            case kVendorID_GOOGLE:
    211                gpu.driverVendor                = "Google";
    212                gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
    213                gpu.detailedDriverVersion.major = properties.driverVersion;
    214                break;
    215            case kVendorID_ImgTec:
    216                gpu.driverVendor                = "Imagination Technologies Limited";
    217                gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
    218                gpu.detailedDriverVersion.major = properties.driverVersion;
    219                break;
    220            case kVendorID_Intel:
    221                gpu.driverVendor                = "Intel Corporation";
    222                gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
    223                gpu.detailedDriverVersion.major = properties.driverVersion;
    224                break;
    225            case kVendorID_Kazan:
    226                gpu.driverVendor                = "Kazan Software";
    227                gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
    228                gpu.detailedDriverVersion.major = properties.driverVersion;
    229                break;
    230            case kVendorID_NVIDIA:
    231                gpu.driverVendor  = "NVIDIA Corporation";
    232                gpu.driverVersion = FormatString("%d.%d.%d.%d", properties.driverVersion >> 22,
    233                                                 (properties.driverVersion >> 14) & 0XFF,
    234                                                 (properties.driverVersion >> 6) & 0XFF,
    235                                                 properties.driverVersion & 0x3F);
    236                gpu.detailedDriverVersion.major    = properties.driverVersion >> 22;
    237                gpu.detailedDriverVersion.minor    = (properties.driverVersion >> 14) & 0xFF;
    238                gpu.detailedDriverVersion.subMinor = (properties.driverVersion >> 6) & 0xFF;
    239                gpu.detailedDriverVersion.patch    = properties.driverVersion & 0x3F;
    240                break;
    241            case kVendorID_Qualcomm:
    242                gpu.driverVendor = "Qualcomm Technologies, Inc";
    243                if (properties.driverVersion & 0x80000000)
    244                {
    245                    gpu.driverVersion = FormatString("%d.%d.%d", properties.driverVersion >> 22,
    246                                                     (properties.driverVersion >> 12) & 0X3FF,
    247                                                     properties.driverVersion & 0xFFF);
    248                    gpu.detailedDriverVersion.major    = properties.driverVersion >> 22;
    249                    gpu.detailedDriverVersion.minor    = (properties.driverVersion >> 12) & 0x3FF;
    250                    gpu.detailedDriverVersion.subMinor = properties.driverVersion & 0xFFF;
    251                }
    252                else
    253                {
    254                    gpu.driverVersion = FormatString("0x%x", properties.driverVersion);
    255                    gpu.detailedDriverVersion.major = properties.driverVersion;
    256                }
    257                break;
    258            case kVendorID_VeriSilicon:
    259                gpu.driverVendor                = "VeriSilicon";
    260                gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
    261                gpu.detailedDriverVersion.major = properties.driverVersion;
    262                break;
    263            case kVendorID_Vivante:
    264                gpu.driverVendor                = "Vivante";
    265                gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
    266                gpu.detailedDriverVersion.major = properties.driverVersion;
    267                break;
    268            case kVendorID_Mesa:
    269                gpu.driverVendor                = "Mesa";
    270                gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
    271                gpu.detailedDriverVersion.major = properties.driverVersion;
    272                break;
    273            default:
    274                return false;
    275        }
    276        gpu.driverId         = static_cast<DriverID>(driverProperties.driverID);
    277        gpu.driverApiVersion = properties.apiVersion;
    278        gpu.driverDate       = "";
    279    }
    280 
    281    return true;
    282 }
    283 
    284 }  // namespace angle