Vulkan Support Check and Dynamic Loader C++ code sample

很多时候不想静态依赖VulkanSDK所提供的静态库,因为会遇到一些过早的电脑不支持vulkan,

那么就需要使用动态加载vulkan-1.dll(for Windows)或libMoltenVK.dylib(for MacOS)的方式进行判断了。

VulkanSDK提供了相关头文件实现可以做到相关功能,仅需要include一下头文件 `vulkan/vulkan.hpp`,不需要再额外链接它的vulkan-1.lib文件

本段代码包含三个部分:

1. 判断是否支持vulkan(简单判断)

2. 从系统动态链接库(显卡厂商提供的dll)动态加载Vulkan,然后初始化。

3. 实际使用导出的函数,去遍历此电脑所有支持vulkan的设备。

那么直接贴代码:

  1 #include "vulkan/vulkan.hpp"
  2 
  3 struct GpuInfo
  4 {
  5     uint32_t api_version = 0;
  6     uint32_t driver_version = 0;
  7     uint32_t vendor_id = 0;
  8     uint32_t device_id = 0;
  9     char device_name[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE] = {0};
 10     // 0 = discrete gpu
 11     // 1 = integrated gpu
 12     // 2 = virtual gpu
 13     // 3 = cpu
 14     int type = 0;
 15 };
 16 
 17 std::vector<GpuInfo> gpuInfos;
 18 
 19 bool isSupportVulkan = false;
 20 std::unique_ptr<vk::DynamicLoader> vulkanDynamicLoader;
 21 std::unique_ptr<vk::DispatchLoaderDynamic> vulkanDispatchLoaderDynamic;
 22 
 23 try
 24 {
 25 #ifdef WIN32
 26     std::string vulkanLibraryFilePath = "vulkan-1.dll";
 27 #else //APPLE
 28     std::string vulkanLibraryFilePath = diropt::CurrentPath() + "/Contents/Frameworks/libMoltenVK.dylib";
 29 #endif
 30     vulkanDynamicLoader = std::make_unique<vk::DynamicLoader>(vulkanLibraryFilePath);
 31 }
 32 catch(std::runtime_error& ex)
 33 {
 34     isSupportVulkan = false;
 35     return -1;
 36 }
 37 if(!vulkanDynamicLoader)
 38 {
 39     isSupportVulkan = false;
 40     return -1;
 41 }
 42 isSupportVulkan = vulkanDynamicLoader->success();
 43 if(!isSupportVulkan)
 44 {
 45     isSupportVulkan = false;
 46     return -1;
 47 }
 48 PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = vulkanDynamicLoader->getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
 49 if(!vkGetInstanceProcAddr)
 50 {
 51     isSupportVulkan = false;
 52     return -1;
 53 }
 54 
 55 // 用vkGetInstanceProcAddr指针去创建默认的分发器对象并初始化
 56 vulkanDispatchLoaderDynamic = std::make_unique<vk::DispatchLoaderDynamic>(vkGetInstanceProcAddr);
 57 
 58 VkResult ret;
 59 VkInstance g_instance;
 60 uint32_t instance_api_version = VK_MAKE_VERSION(1, 0, 0);
 61 typedef VkResult(VKAPI_PTR * PFN_vkEnumerateInstanceVersion)(uint32_t * pApiVersion);
 62 PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion =
 63         (PFN_vkEnumerateInstanceVersion)vulkanDispatchLoaderDynamic->vkGetInstanceProcAddr(0, "vkEnumerateInstanceVersion");
 64 if (vkEnumerateInstanceVersion)
 65 {
 66     //列举vulkan实例的版本
 67     ret = vkEnumerateInstanceVersion(&instance_api_version);
 68     if (ret != VK_SUCCESS)
 69     {
 70         return -1;
 71     }
 72 }
 73 
 74 VkApplicationInfo applicationInfo;
 75 applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
 76 applicationInfo.pNext = 0;
 77 applicationInfo.pApplicationName = "vulkan-check";
 78 applicationInfo.applicationVersion = 0;
 79 applicationInfo.pEngineName = "vulkan-check";
 80 applicationInfo.engineVersion = 20230447;
 81 applicationInfo.apiVersion = instance_api_version;
 82 
 83 VkInstanceCreateInfo instanceCreateInfo;
 84 instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
 85 instanceCreateInfo.pNext = 0;
 86 instanceCreateInfo.flags = 0;
 87 instanceCreateInfo.pApplicationInfo = &applicationInfo;
 88 instanceCreateInfo.enabledLayerCount = 0;
 89 instanceCreateInfo.ppEnabledLayerNames = 0;
 90 instanceCreateInfo.enabledExtensionCount = 0;
 91 instanceCreateInfo.ppEnabledExtensionNames = 0;
 92 
 93 VkInstance instance = 0;
 94 //创建Vulkan实例
 95 ret = vulkanDispatchLoaderDynamic->vkCreateInstance(&instanceCreateInfo, 0, &instance);
 96 if (ret != VK_SUCCESS)
 97 {
 98     return -1;
 99 }
100 g_instance = instance;
101 
102 //再用已经创建好的Vulkan实例去进一步初始化vulkanDispatchLoaderDynamic
103 vulkanDispatchLoaderDynamic->init(instance, vkGetInstanceProcAddr);
104 
105 //获取所有支持vulkan的设备列表
106 uint32_t physicalDeviceCount = 0;
107 ret = vulkanDispatchLoaderDynamic->vkEnumeratePhysicalDevices(g_instance, &physicalDeviceCount, 0);
108 if (ret != VK_SUCCESS)
109 {
110     return -1;
111 }
112 #define NCNN_MAX_GPU_COUNT 8
113 if (physicalDeviceCount > NCNN_MAX_GPU_COUNT)
114     physicalDeviceCount = NCNN_MAX_GPU_COUNT;
115 
116 std::vector<VkPhysicalDevice> physicalDevices(physicalDeviceCount);
117 //列举所有支持Vulkan的物理设备
118 ret = vulkanDispatchLoaderDynamic->vkEnumeratePhysicalDevices(g_instance, &physicalDeviceCount, physicalDevices.data());
119 if (ret != VK_SUCCESS)
120 {
121     return -1;
122 }
123 
124 int gpu_info_index = 0;
125 for (uint32_t i = 0; i < physicalDeviceCount; i++)
126 {
127     const VkPhysicalDevice& physicalDevice = physicalDevices[i];
128 
129     // device type
130     VkPhysicalDeviceProperties physicalDeviceProperties;
131     vulkanDispatchLoaderDynamic->vkGetPhysicalDeviceProperties(physicalDevice, &physicalDeviceProperties);
132 
133     // info
134     GpuInfo gpu_info;
135     gpu_info.api_version = physicalDeviceProperties.apiVersion;
136     gpu_info.driver_version = physicalDeviceProperties.driverVersion;
137     gpu_info.vendor_id = physicalDeviceProperties.vendorID;
138     gpu_info.device_id = physicalDeviceProperties.deviceID;
139     memset(gpu_info.device_name, 0, VK_MAX_PHYSICAL_DEVICE_NAME_SIZE);
140     memcpy(gpu_info.device_name, physicalDeviceProperties.deviceName, strlen(physicalDeviceProperties.deviceName));
141 
142     if (physicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_OTHER)
143         gpu_info.type = 0;
144     else if (physicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU)
145         gpu_info.type = 1;
146     else if (physicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
147         gpu_info.type = 2;
148     else if (physicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU)
149         gpu_info.type = 3;
150     else if (physicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU)
151         gpu_info.type = 4;
152     else
153         gpu_info.type = -1;
154 
155     gpu_info_index++;
156     gpuInfos.emplace_back(gpu_info);
157 }

 

posted @ 2023-04-28 12:21  重庆Debug  阅读(220)  评论(0编辑  收藏  举报