原本你写的程序是静态链接的系统的vulkan-1.dll,如果系统不存在vulkan-1.dll,则会直接崩溃。

关于将ncnn静态链接vulkan改成动态加载vulkan的形式,然后提供这两个函数

bool ncnn::has_vulkan();
void ncnn::use_vulkan(bool);

请教过ncnn的作者nihui,她对此issue表示不以为意,没有必要,优先级不高。

那就只有自己动手丰衣足食了。

本文的目标是将其改为动态加载的方式,用到了KhronosGroup组织下的Vulkan-SDK里面的CPP部分,即vulkan.hpp

本人的上一篇文章(https://www.cnblogs.com/hyb1/p/17361775.html)说的是如何动态判断是否存在vulkan-1.dll并且再加载的过程,

但是没提到如何针对现有的项目改动,比如说现在的ncnn含有的大量C Style的vulkan函数符号直接调用的代码,如果直接修改,需要将每一个vulkan函数的地方都加一个前缀,类似这样:

mVulkanDispatchLoaderDynamic->vkCreateInstance(&instanceCreateInfo, 0, &instance);

mVulkanDispatchLoaderDynamic->vkEnumeratePhysicalDevices(g_instance, &physicalDeviceCount, 0);

跨越了很多.cpp和.h文件,修改起来相当麻烦,而且还会遇到全局变量是否有效等等问题。

废话不多说,直接说总结:

Vulkan Loader提供了多个宏定义:VULKAN_HPP_STORAGE_API和VULKAN_HPP_STORAGE_SHARED和VULKAN_HPP_STORAGE_SHARED_EXPORT
它们是vulkan.hpp中用来控制vulkan函数的存储类别的宏。
VULKAN_HPP_STORAGE_API:

这个宏用来指定vulkan函数的存储类别,比如__declspec(dllexport)或者__declspec(dllimport)。
这个宏可以在编译时由外部定义,以便于将vulkan函数导出或者导入。

VULKAN_HPP_STORAGE_SHARED:

这个宏用来启用动态链接库的模式,即将vulkan函数作为dll的导出或者导入。
如果定义了这个宏,那么VULKAN_HPP_STORAGE_API会根据VULKAN_HPP_STORAGE_SHARED_EXPORT是否定义来自动设置为__declspec(dllexport)或者__declspec(dllimport)。
如果没有定义这个宏,那么VULKAN_HPP_STORAGE_API会被设置为空。

VULKAN_HPP_STORAGE_SHARED_EXPORT:

这个宏用来控制动态链接库的模式下,vulkan函数是作为dll的导出还是导入。
如果定义了这个宏,那么VULKAN_HPP_STORAGE_API会被设置为__declspec(dllexport),表示vulkan函数是dll的导出。

如果没有定义这个宏,那么VULKAN_HPP_STORAGE_API会被设置为__declspec(dllimport),表示vulkan函数是dll的导入。

如果你是希望通过vk::DispatchLoaderDynamic加载到defaultDispatchLoaderDynamic之后,仍旧按照静态链接的模式来编写代码,但是不是链接到真正的vulkan-1.dll上,而是由vulkan-loader生成的符号,应该这样做(重点来了):

1. 定义VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL和VULKAN_HPP_DISPATCH_LOADER_DYNAMIC两个宏,以启用动态加载vulkan库和函数的功能。
2. 不要定义VULKAN_HPP_STORAGE_SHARED和VULKAN_HPP_STORAGE_SHARED_EXPORT两个宏,以避免使用dll的模式。
3. 使用vk::DynamicLoader类来动态加载vulkan-loader生成的符号,并且获取vkGetInstanceProcAddr函数的地址。
4. 调用VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr)来初始化默认的函数指针封装对象。
5. 使用默认的函数指针封装对象或者自定义的vk::DispatchLoaderDynamic对象来调用其他vulkan函数。

#define VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL 1
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
//#define VULKAN_HPP_STORAGE_API 0
#undef VULKAN_HPP_STORAGE_SHARED
#undef VULKAN_HPP_STORAGE_SHARED_EXPORT #include <vulkan/vulkan.hpp> //定义一个全局的vk::DispatchLoaderDynamic对象defaultDispatchLoaderDynamic
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE //初始化的时候这样写
try
{
#ifdef WIN32
std::string vulkanLibraryFilePath = "vulkan-1.dll";
#else //APPLE
std::string vulkanLibraryFilePath = diropt::CurrentPath() + "/Contents/Frameworks/libMoltenVK.dylib";
#endif
mVulkanDynamicLoader = std::make_unique<vk::DynamicLoader>(vulkanLibraryFilePath);
}
catch(std::runtime_error ex)
{
mSupportVulkan = false;
printf("vk::DynamicLoader is null\n");
return;
}
if(!mVulkanDynamicLoader)
{
mSupportVulkan = false;
printf("mVulkanDynamicLoader is null\n");
return;
}
mSupportVulkan = mVulkanDynamicLoader->success();
if(!mSupportVulkan)
{
mSupportVulkan = false;
printf("mSupportVulkan is false\n");
return;
}
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = mVulkanDynamicLoader->getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr");
if(!vkGetInstanceProcAddr)
{
mSupportVulkan = false;
printf("vkGetInstanceProcAddr is null\n");
return;
} mVulkanDispatchLoaderDynamic = std::make_unique<vk::DispatchLoaderDynamic>(vkGetInstanceProcAddr);
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);

只要这样按照这上面的5点来修改ncnn的话,就可以编译出动态加载vulkan版本的ncnn了,如果你看到了这里觉得对你有帮助的话,就分享到qq群里的各位小伙伴吧~

使用Vulkan-Loader将ncnn代码改成Dynamic Loader Vulkan的形式的更多相关文章

  1. 使用chatgt(GPT-4)将过程式(的java代码)改成函数式(的elixir代码)

    天啦噜太可怕了,之前我还嘲笑chatgpt不会小众语言来着. chatgt(GPT-4)在接收2次prompt后,把过程式(的java代码)改成了函数式(的elixir代码),给出的Elixir代码可 ...

  2. 把JavaScript代码改成ES6语法不完全指南

    目录 * 核心例子 * 修改成静态变量(const)或块级变量(let) * 开始修改 * 疑问解释(重复定义会发生什么) * 疑问解释(let的块级作用域是怎样的) * 疑问解释(const定义的变 ...

  3. python学习——将while循环改成函数

    笨办法学python第33节 这一节主要学习内容是while循环,记录内容为将while改成函数,首先源代码如下: i = 0 numbers = [] while i < 6: print & ...

  4. 把纯C的动态库代码改造成C++版的

    近期想把一份纯C的跨Win/Linux的动态库工程代码改成支持C++编译器,这样用C++写起代码来比较顺手.要点是保证动态库的ABI一致性,既导出接口不能改变. 主要的改动有: 1.把.c后缀名换成. ...

  5. 【Android端】代码打包成jar包/aar形式

    Android端代码打包成jar包和aar形式: 首先,jar包的形式和aar形式有什么区别? 1.打包之后生成的文件地址: *.jar:库/build/intermediates/bundles/d ...

  6. 取消开机logo,改成代码刷屏

    将开机logo改成开始时代码刷屏,这样就能很方便看到开始时的一些问题 首先 sudo chmod 666 /etc/default/grub 然后将 GRUB_CMDLINE_LINUX_DEFAUL ...

  7. zepto插件 countdown 倒计时插件 从jquery 改成 zepto

    插件特色:支持zepto库  支持时间戳格式 支持年月日时分秒格式 countdown 由jquery依赖库改成zepto zepto的event机制与jquery不同,所以更换之后代码不能正常运行 ...

  8. 将html页改成jsp的两种方式

    将html页改成jsp的两种方式 作者: 字体:[增加 减小] 类型:转载 时间:2013-08-13 将html页改成jsp有两种方法,第一种是直接修改html文件,另一种是新建jsp文件.下面为大 ...

  9. Java-马士兵设计模式学习笔记-观察者模式-读取properties文件改成单例模式

    一.概述 1.目标:读取properties文件改成单例模式 二.代码 1.Test.java class WakenUpEvent{ private long time; private Strin ...

  10. 维护没有源代码,float改成double

    float f= 931340.31f; Console.WriteLine(f.ToString("#,###,##0.00")); 返回 931,340.30 ,float 1 ...

随机推荐

  1. (二)asyncio的简单使用,python异步高效处理数据,asyncio.get_event_loop(),loop.run_until_complete(main()),loop.close()

    Asyncio 是一个基于事件循环的异步I/O框架,它提供了高效的协程实现,能够轻松地编写高并发的Python程序.Asyncio 在 Python 3.4 中首次引入,它的核心是事件循环(Event ...

  2. 【Oracle】使用exit,return,continue跳出循环

    [Oracle]使用exit,return,continue跳出循环 exit是结束循环,但还会继续执行程序包中其他的内容 return则是直接中断整个程序 continue的作用是终止本次循环,开始 ...

  3. 讲座回顾丨基于 OpenYurt 和 EdgeX 的云边端协同新可能

    简介: 为帮助参赛选手更好地了解并运用相关技术,本次大赛将在 7 月至 9 月持续开展 3 轮技术培训,涵盖初.中.高不同层级,帮助开发者系统学习智能边缘系统知识.我们邀请到来自英特尔.VMware. ...

  4. 基于阿里云 ASK 的 Istio 微服务应用部署初探

    简介: 本文会通过在 ASK 上试用 Istio 部署微服务应用的方式,来验证 ASK 对标准 Kubernetes 的兼容性.Istio 作为 Service Mesh(服务网格)的领导解决方案,一 ...

  5. Hexo博客框架—轻量、一令部署

    ​简介:Hexo 是一个快速.简洁且高效的博客框架.Hexo 使用 Markdown(或其他渲染引擎)解析文章,在几秒内,即可利用靓丽的主题生成静态网页.Hexo支持Github Flavored M ...

  6. 一看即会:Serverless 应用开发的 7 个实战小技巧

    ​简介:干货满满,马住收藏! ​ Serverless 应用开发的 7 个经验心得 作者说:Serverless 架构下的应用开发,与传统架构的应用开发还是有比较大的区别点的,例如天然分布式架构会让很 ...

  7. 最佳实践丨三种典型场景下的云上虚拟IDC(私有池)选购指南

    ​简介:业务上云常态化,业务在云上资源的选购.弹性交付.自助化成为大趋势.不同行业的不同客户,业务发展阶段不一样,云上资源的成本投入在业务整体成本占比也不一样,最小化成本投入.最大化业务收益始终是不同 ...

  8. 庖丁解InnoDB之REDO LOG

    ​简介: 数据库故障恢复机制的前世今生一文中提到,今生磁盘数据库为了在保证数据库的原子性(A, Atomic) 和持久性(D, Durability)的同时,还能以灵活的刷盘策略来充分利用磁盘顺序写的 ...

  9. 一文详解Redis中BigKey、HotKey的发现与处理

    简介: 在Redis的使用过程中,我们经常会遇到BigKey(下文将其称为"大key")及HotKey(下文将其称为"热key").大Key与热Key如果未能及 ...

  10. [FAQ] Mac Mini 怎么让主机不休眠

    Mac Mini 的防止休眠设置,在首选项,显示器里. 显示器里找到高级按钮. 然后有个开关是:显示器关闭时,防止自动进入睡眠.打开这个开关即可防止自动睡眠. Link:https://www.cnb ...