Edit

kc3-lang/angle/src/gpu_info_util/SystemInfo_vulkan.cpp

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2020-09-29 19:59:54
    Hash : e1d1b8b3
    Message : Fix info collection on Android without Vulkan. Allows Vulkan info collection even if Vk is not enabled in ANGLE. Also removes the system_utils error message so that the Android test runner can parse the standard output without conflicts. Bug: chromium:1133459 Bug: angleproject:5109 Change-Id: I7d7bff0f1c3e456342f27538812b33ee6cd1054b Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2436657 Reviewed-by: Cody Northrop <cnorthrop@google.com> Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>

  • src/gpu_info_util/SystemInfo_vulkan.cpp
  • //
    // Copyright 2020 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_vulkan.cpp: Generic vulkan implementation of SystemInfo.h
    // TODO: Use VK_KHR_driver_properties. http://anglebug.com/5103
    
    #include <vulkan/vulkan.h>
    #include "gpu_info_util/SystemInfo_internal.h"
    
    #include <cstring>
    #include <fstream>
    
    #include "common/angleutils.h"
    #include "common/debug.h"
    #include "common/system_utils.h"
    
    #if defined(ANGLE_PLATFORM_WINDOWS)
    const char *kLibVulkanNames[] = {"vulkan-1.dll"};
    #else
    const char *kLibVulkanNames[] = {"libvulkan.so", "libvulkan.so.1"};
    #endif
    
    namespace angle
    {
    class VulkanLibrary final : NonCopyable
    {
      public:
        VulkanLibrary() = default;
    
        ~VulkanLibrary()
        {
            if (mInstance != VK_NULL_HANDLE)
            {
                auto pfnDestroyInstance = getProc<PFN_vkDestroyInstance>("vkDestroyInstance");
                if (pfnDestroyInstance)
                {
                    pfnDestroyInstance(mInstance, nullptr);
                }
            }
            SafeDelete(mLibVulkan);
        }
    
        VkInstance getVulkanInstance()
        {
            for (const char *libraryName : kLibVulkanNames)
            {
                mLibVulkan = OpenSharedLibraryWithExtension(libraryName);
                if (mLibVulkan)
                    break;
            }
    
            if (!mLibVulkan)
            {
                // If Vulkan doesn't exist, bail-out early:
                return VK_NULL_HANDLE;
            }
    
            // Determine the available Vulkan instance version:
            uint32_t instanceVersion = VK_API_VERSION_1_0;
    #if defined(VK_VERSION_1_1)
            auto pfnEnumerateInstanceVersion =
                getProc<PFN_vkEnumerateInstanceVersion>("vkEnumerateInstanceVersion");
            if (!pfnEnumerateInstanceVersion ||
                pfnEnumerateInstanceVersion(&instanceVersion) != VK_SUCCESS)
            {
                instanceVersion = VK_API_VERSION_1_0;
            }
    #endif  // VK_VERSION_1_1
    
            // Create a Vulkan instance:
            VkApplicationInfo appInfo;
            appInfo.sType              = VK_STRUCTURE_TYPE_APPLICATION_INFO;
            appInfo.pNext              = nullptr;
            appInfo.pApplicationName   = "";
            appInfo.applicationVersion = 1;
            appInfo.pEngineName        = "";
            appInfo.engineVersion      = 1;
            appInfo.apiVersion         = instanceVersion;
    
            VkInstanceCreateInfo createInstanceInfo;
            createInstanceInfo.sType                   = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
            createInstanceInfo.pNext                   = nullptr;
            createInstanceInfo.flags                   = 0;
            createInstanceInfo.pApplicationInfo        = &appInfo;
            createInstanceInfo.enabledLayerCount       = 0;
            createInstanceInfo.ppEnabledLayerNames     = nullptr;
            createInstanceInfo.enabledExtensionCount   = 0;
            createInstanceInfo.ppEnabledExtensionNames = nullptr;
    
            auto pfnCreateInstance = getProc<PFN_vkCreateInstance>("vkCreateInstance");
            if (!pfnCreateInstance ||
                pfnCreateInstance(&createInstanceInfo, nullptr, &mInstance) != VK_SUCCESS)
            {
                return VK_NULL_HANDLE;
            }
    
            return mInstance;
        }
    
        template <typename Func>
        Func getProc(const char *fn) const
        {
            return reinterpret_cast<Func>(mLibVulkan->getSymbol(fn));
        }
    
      private:
        Library *mLibVulkan  = nullptr;
        VkInstance mInstance = VK_NULL_HANDLE;
    };
    
    ANGLE_FORMAT_PRINTF(1, 2)
    std::string FormatString(const char *fmt, ...)
    {
        va_list vararg;
        va_start(vararg, fmt);
    
        std::vector<char> buffer(512);
        size_t len = FormatStringIntoVector(fmt, vararg, buffer);
        va_end(vararg);
    
        return std::string(&buffer[0], len);
    }
    
    bool GetSystemInfoVulkan(SystemInfo *info)
    {
        // This implementation builds on top of the Vulkan API, but cannot assume the existence of the
        // Vulkan library.  ANGLE can be installed on versions of Android as old as Ice Cream Sandwich.
        // Therefore, we need to use dlopen()/dlsym() in order to see if Vulkan is installed on the
        // system, and if so, to use it:
        VulkanLibrary vkLibrary;
        VkInstance instance = vkLibrary.getVulkanInstance();
        if (instance == VK_NULL_HANDLE)
        {
            // If Vulkan doesn't exist, bail-out early:
            return false;
        }
    
        // Enumerate the Vulkan physical devices, which are ANGLE gpus:
        auto pfnEnumeratePhysicalDevices =
            vkLibrary.getProc<PFN_vkEnumeratePhysicalDevices>("vkEnumeratePhysicalDevices");
        auto pfnGetPhysicalDeviceProperties =
            vkLibrary.getProc<PFN_vkGetPhysicalDeviceProperties>("vkGetPhysicalDeviceProperties");
        uint32_t physicalDeviceCount = 0;
        if (!pfnEnumeratePhysicalDevices ||
            pfnEnumeratePhysicalDevices(instance, &physicalDeviceCount, nullptr) != VK_SUCCESS)
        {
            return false;
        }
        std::vector<VkPhysicalDevice> physicalDevices(physicalDeviceCount);
        if (pfnEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices.data()) !=
            VK_SUCCESS)
        {
            return false;
        }
    
        // If we get to here, we will likely provide a valid answer (unless an unknown vendorID):
        info->gpus.resize(physicalDeviceCount);
    
        for (uint32_t i = 0; i < physicalDeviceCount; i++)
        {
            VkPhysicalDeviceProperties properties;
            pfnGetPhysicalDeviceProperties(physicalDevices[i], &properties);
            // Fill in data for a given physical device (a.k.a. gpu):
            GPUDeviceInfo &gpu = info->gpus[i];
            gpu.vendorId       = properties.vendorID;
            gpu.deviceId       = properties.deviceID;
            // Need to parse/re-format properties.driverVersion.
            //
            // TODO(ianelliott): Determine the formatting used for each vendor
            // (http://anglebug.com/2677)
            switch (properties.vendorID)
            {
                case kVendorID_AMD:
                    gpu.driverVendor                = "Advanced Micro Devices, Inc";
                    gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
                    gpu.detailedDriverVersion.major = properties.driverVersion;
                    break;
                case kVendorID_ARM:
                    gpu.driverVendor                = "Arm Holdings";
                    gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
                    gpu.detailedDriverVersion.major = properties.driverVersion;
                    break;
                case kVendorID_Broadcom:
                    gpu.driverVendor                = "Broadcom";
                    gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
                    gpu.detailedDriverVersion.major = properties.driverVersion;
                    break;
                case kVendorID_ImgTec:
                    gpu.driverVendor                = "Imagination Technologies Limited";
                    gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
                    gpu.detailedDriverVersion.major = properties.driverVersion;
                    break;
                case kVendorID_Intel:
                    gpu.driverVendor                = "Intel Corporation";
                    gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
                    gpu.detailedDriverVersion.major = properties.driverVersion;
                    break;
                case kVendorID_Kazan:
                    gpu.driverVendor                = "Kazan Software";
                    gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
                    gpu.detailedDriverVersion.major = properties.driverVersion;
                    break;
                case kVendorID_NVIDIA:
                    gpu.driverVendor  = "NVIDIA Corporation";
                    gpu.driverVersion = FormatString("%d.%d.%d.%d", properties.driverVersion >> 22,
                                                     (properties.driverVersion >> 14) & 0XFF,
                                                     (properties.driverVersion >> 6) & 0XFF,
                                                     properties.driverVersion & 0x3F);
                    gpu.detailedDriverVersion.major    = properties.driverVersion >> 22;
                    gpu.detailedDriverVersion.minor    = (properties.driverVersion >> 14) & 0xFF;
                    gpu.detailedDriverVersion.subMinor = (properties.driverVersion >> 6) & 0xFF;
                    gpu.detailedDriverVersion.patch    = properties.driverVersion & 0x3F;
                    break;
                case kVendorID_Qualcomm:
                    gpu.driverVendor = "Qualcomm Technologies, Inc";
                    if (properties.driverVersion & 0x80000000)
                    {
                        gpu.driverVersion = FormatString("%d.%d.%d", properties.driverVersion >> 22,
                                                         (properties.driverVersion >> 12) & 0X3FF,
                                                         properties.driverVersion & 0xFFF);
                        gpu.detailedDriverVersion.major    = properties.driverVersion >> 22;
                        gpu.detailedDriverVersion.minor    = (properties.driverVersion >> 12) & 0x3FF;
                        gpu.detailedDriverVersion.subMinor = properties.driverVersion & 0xFFF;
                    }
                    else
                    {
                        gpu.driverVersion = FormatString("0x%x", properties.driverVersion);
                        gpu.detailedDriverVersion.major = properties.driverVersion;
                    }
                    break;
                case kVendorID_VeriSilicon:
                    gpu.driverVendor                = "VeriSilicon";
                    gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
                    gpu.detailedDriverVersion.major = properties.driverVersion;
                    break;
                case kVendorID_Vivante:
                    gpu.driverVendor                = "Vivante";
                    gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
                    gpu.detailedDriverVersion.major = properties.driverVersion;
                    break;
                default:
                    return false;
            }
            gpu.driverDate = "";
        }
    
        return true;
    }
    
    }  // namespace angle