Edit

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

Branch :

  • Show log

    Commit

  • Author : Xiaoxuan Liu
    Date : 2021-03-03 17:56:07
    Hash : ed4f7cb6
    Message : Reland "Reland "Add support for Linux GPU info with Vulkan backend"" This is a reland of 9a8397327f9aac278f4bd1f5ab9094eec7e7798b Chrome Linux crash issue could be fixed in 0615bbde39ca42e27eb764b2b4986b21ab602ce9, let's reland this now. Original change's description: > Reland "Add support for Linux GPU info with Vulkan backend" > > This is a reland of 5c09c1f882f15e1a77577f1a62d861355aac90a4 > > Extra change: Add new ANGLE_HAS_VULKAN_SYSTEM_INFO compile > variable for GetSystemInfoVulkan() in linux platform. > > Original change's description: > > Add support for Linux GPU info with Vulkan backend > > > > 1. Add support for Linux GPU info with vulkan backend: for > > dev board without PCI support, try vulkan backend to get > > GPU info. > > 2. Fix getVulkanInstance() issue when loading non-exist lib: > > return NULL instance if open lib failed. > > > > Bug: angleproject:5717 > > Change-Id: I03c11da25a8787496d098f6c9d6b4c53701383e4 > > Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2734375 > > Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> > > Reviewed-by: Jamie Madill <jmadill@chromium.org> > > Commit-Queue: Jamie Madill <jmadill@chromium.org> > > Bug: angleproject:5717 > Change-Id: Iaaab8f512b6ec1d524d7ebb3b4252fec3cfe7dc3 > Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2739097 > Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> > Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> > Reviewed-by: Jamie Madill <jmadill@chromium.org> Bug: angleproject:5717 Change-Id: Iad6736f9137b7e9640c97fa2b9eded3fd37ac88f Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2821410 Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Commit-Queue: Shahbaz Youssefi <syoussefi@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)
                {
                    if (mLibVulkan->getNative())
                    {
                        break;
                    }
                    else
                    {
                        SafeDelete(mLibVulkan);
                    }
                }
            }
    
            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;
        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