很多时候不想静态依赖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 }

Vulkan Support Check and Dynamic Loader C++ code sample的更多相关文章

  1. OBJ Loader Source Code

    https://github.com/ChrisJansson/ObjLoader http://www.codeproject.com/Articles/798054/SimpleScene-d-s ...

  2. Java Thread Local – How to use and code sample(转)

    转载自:https://veerasundar.com/blog/2010/11/java-thread-local-how-to-use-and-code-sample/ Thread Local ...

  3. [译]Vulkan教程(03)开发环境

    [译]Vulkan教程(03)开发环境 这是我翻译(https://vulkan-tutorial.com)上的Vulkan教程的第3篇. In this chapter we'll set up y ...

  4. Linux Programe/Dynamic Shared Library Entry/Exit Point && Glibc Entry Point/Function

    目录 . 引言 . C/C++运行库 . 静态Glibc && 可执行文件 入口/终止函数 . 动态Glibc && 可执行文件 入口/终止函数 . 静态Glibc & ...

  5. Linking code for an enhanced application binary interface (ABI) with decode time instruction optimization

    A code sequence made up multiple instructions and specifying an offset from a base address is identi ...

  6. Dynamic Library Design Guidelines

    https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/DynamicLibraries/100 ...

  7. Loader的初步学习笔记

    Loader是一个异步加载数据的类,它和AsyncTask有类似也有不同,今天我们就先来学习下它.由于是对比学习,所以我们先来复习下AsyncTask的使用和特点. 一.AsyncTask 参考自:h ...

  8. Position Independent Code (PIC) in shared libraries

    E原文地址:http://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/下一文: ...

  9. [译]Vulkan教程(07)物理设备和队列家族

    [译]Vulkan教程(07)物理设备和队列家族 Selecting a physical device 选择一个物理设备 After initializing the Vulkan library ...

  10. [译]Vulkan教程(05)Instance

    [译]Vulkan教程(05)Instance Creating an instance 创建一个instance The very first thing you need to do is ini ...

随机推荐

  1. 日志架构演进:从集中式到分布式的Kubernetes日志策略

    当我们没有使用云原生方案部署应用时采用的日志方案往往是 ELK 技术栈. 这套技术方案比较成熟,稳定性也很高,所以几乎成为了当时的标配. 可是随着我们使用 kubernetes 步入云原生的时代后, ...

  2. 使用Docker搭建MongoDB 5.0版本副本集集群

    1.mongodb集群 首先我们需要了解mongodb的集群模式,mongodb安装分为单机安装和集群安装.集群安装分为:主从复制(Master-Slaver)集群.副本集(Replica Set)集 ...

  3. 全链路灰度新功能:MSE上线配置标签推送

    简介: 微服务场景下,全链路灰度作为一种低成本的新功能验证方式,得到了越来越广泛的应用.除了微服务实例和流量的灰度,微服务应用中的配置项也应该具备相应的灰度能力,以应对灰度应用对特殊配置的诉求. 为什 ...

  4. 云原生事件驱动引擎(RocketMQ-EventBridge)应用场景与技术解析

    简介: RocketMQ 给人最大的印象一直是一个消息引擎.那什么是事件驱动引擎?为什么我们这次要推出事件驱动引擎这个产品?他有哪些应用场景,以及对应的技术方案是什么?本文我们就一起来看下. 作者:罗 ...

  5. Quick BI产品核心功能大图(五)移动端:让数据在更多业务场景中流通

    ​简介:将数据更好的融入日常工作中,一个重要的前提条件就是多端多渠道的数据触达和办公协同能力. Quick BI凭借移动端交互体验,帮助用户随时随地便捷查看报表,并通过在线协同方式,追踪策略的执行落地 ...

  6. C++ 多态与虚拟:Class 语法语义

    1.object与class:在object-oriented programming编程领域,对象(object)有更严格的定义.对象是由数据结构和用于处理该结构的过程(称为methods)组成的实 ...

  7. [MySQL] 导入数据库和表的两种方式

    如果是导入 mysqldump 导出的 sql 文件,使用 mysql 命令再导入就可以了. 下面是另一种可选方式: use xxdb source /var/lib/mysql/xxtable.sq ...

  8. 学习 Avalonia 框架笔记 如何创建一个全屏置顶的 X11 应用窗口

    本文记录我从 Avalonia 框架里面学到如何创建一个全屏置顶的 X11 应用窗口的方法 开始之前,先从 Avalonia 或 CPF 里面拷贝足够的代码,这部分代码可以从本文末尾找到下载方法 设置 ...

  9. 如何参与 .NET 的开发和设计

    现在 dotnet 属于 dotnet 基金会,所有开发者都可以向 dotnet 贡献代码和参与 .NET 的设计,参与路线决策.本文来告诉大家一些基本玩法,带着小伙伴们入坑 注意哦,参与 dotne ...

  10. 2019-8-31-dotnet-使用-Environment.FailFast-结束程序

    title author date CreateTime categories dotnet 使用 Environment.FailFast 结束程序 lindexi 2019-08-31 16:55 ...