Vulkan在Android使用Compute shader
oeip 相关功能只能运行在window平台,想移植到android平台,暂时选择vulkan做为图像处理,主要一是里面有单独的计算管线且支持好,二是熟悉下最新的渲染技术思路。
这个 demo(git地址) 的功能很简单,在android下,,利用vulkan的compute shader对输入图进行1-x的运行后,把计算结果复制到当前交换链里正在渲染的图像上显示出来。

本文主要记录其中一些过程,因为第一次尝试类似开发,所以有误的地方欢迎大家指出。
前期准备工作主要如下,VSCode C++环境配置,熟悉CMake。
为什么选择vscode,而不是visual studio/android studio,主要是基于如下考虑,首先在win平台方便调试与测试,在win平台完成demo后再移植到android下就方便了,而visual studio/android studio分别在开发原生win/android下方便,而vscode+cmake的组合很方便在win平台调试测试,然后平稳生成相应的android studio项目方案,然后在android studio里进行调试封装,并且最新android studio首选cmake构建,更方便集成。VSCode必需的C++插件主要是如下几个 C/C++ for Visual Studio Code/Cmake/Cmake tools.
然后我花了一些时间在vscode里编译了ogre-next,并把它的cmake文件跟了一遍,大致了解了cmake的用法,总结了下 CMake常用命令 。
vulkan结合github上二个vulkan 的demo方案,初步了解vulkan API与渲染流程。vulkan网上说的二千多行代码画个三角形确实一点也不夸张,Vulkan API粒度细,控制度高,以及为多线程渲染设计的渲染队列,渲染命令及同步,所以代码量看着就上去了,但是你根据你的需求简单封装下,如交换链,渲染管线,UBO,buffer等,再写也就大部分业务逻辑代码。简单来说,先根据demo熟悉流程与API,再手动写个2K多行的简单demo,在这过程,通过比较以前opengl/dx的API流程熟悉与加深思路,然后根据你的需求确定一些参数,封装一些类,最后开始你的需求并反向不断完善更新你的封装库。
知乎上各位大佬已经把Vulkan API/Demo讲解的非常清晰,这里就说下这个DEMO的流程,供大家参考,欢迎大家指出理解有误的部分。
首先窗口初始化相关,这部分也是android/window平台区别最大的部分,注意这里有个大坑,不同win32下,在创建窗口的线程下可以直接创建surface,在android下需要等到窗口的消息APP_CMD_INIT_WINDOW里才能创建surface,android里的native activity初始化过程可以参考 Android——NativeActivity - C/C++ Apk开发,创建surface过程,选择呈现/渲染通道以及同步呈现与渲染的对象,创建renderpass,然后根据surface创建交换链,根据交换链得到呈现image列表,根据image列表得到fbo列表用于附着到RenderPass上用于渲染,这里选择一种比较简单的CommandBuffer记录方式,就是有交换链有几个image,就创建几个对应的CommandBuffer记录.
然后创建逻辑设备,加载需要参与计算的输入图像资源,一般来说,图像资源要使用compute shader,usage肯定要有VK_IMAGE_USAGE_STORAGE_BIT,而现在大部分硬件来说,线性 features不支持VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT,用于CPU 可以访问的资源需要linera_tiling.简单来说,compute shader要求的纹理,现在硬件上,CPU大部分不能直接访问,这就要求一个中转,先创建一个CPU可以访问的资源如vkbuffer,然后把数据导入这个资源中,然后通过设备资源间vkCmdCopyBufferToImage复制到原CPU不能访问的GPU纹理上。然后创建一个compute shader要求的输出纹理,对应一个UBO结构,这个UBO对应compute shader输入输出。加载转化的spv文件,生成对应的compute pipeline.
在这个需求里,渲染命令不会每桢修改,所以我们完成可以在开始桢渲染前就填充CommandBuffer。
- 填充计算管线的CommandBuffer,简单来说,就是执行上面的compute pipeline,并把输出纹理layout改成VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL。
- 填充呈现渲染里的CommandBuffer,根据交换链里的image数据填充对应的每个CommandBuffer,简单来说,就是把上面计算完成的纹理通过vkCmdBlitImage复制到当前呈现的那张vkimage中。
注意,这里只是保存了动作,相当于把action放入队列中,并没执行队列,在这里,所有在每桢运行前的逻辑已经处理完。
然后到每桢渲染,如上先等计算管线的fences来信号,这表明GPU队列中已经执行完成CommandBuffer,如下代码的computerCmd又变成可执行状态。注意创建fences时需要先给信号,不然第一次进入就会一起等待,并且fences需要手动reset.然后根据vkAcquireNextImageKHR得到的索引拿到呈现渲染的CommandBuffer,执行完成呈现出来,呈现与渲染的同步都在设备GPU内,一般用VkSemaphore来同步,不同于vkFence,他用于gpu-gpu间的同步,自动reset.
void onPreDraw() {
auto device = context->logicalDevice.device;
vkWaitForFences(device, 1, &computerFence, VK_TRUE, UINT64_MAX);
vkResetFences(device, 1, &computerFence);
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &context->computerCmd;
VK_CHECK_RESULT(
vkQueueSubmit(context->computeQueue, 1, &submitInfo, computerFence));
}
在window平台测试完,参照vulkan的demo,新建一个android文件夹,设置其中的setings.gragle.

主build.gradle就和一般的一样,在vkcs1目录下的build.gradle添加externalNativeBuild的cmake路径,设置好AndroidManifest.xml,如下图。

然后就可以用android studio打开这个文件夹,然后Sync Project with Gradle Files,就会补起成余下内容,最后应该是如下结构。

正常来说,应该就可以在android studio安装及调试了。
最后说下在移植到android下遇到的一些坑。
- undefined symbol: ANativeActivity_onCreate 找不到,解决方法在CMake中添加set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")
- vkCreateAndroidSurfaceKHR 类似Fatal signal 11 (SIGSEGV)错误。这是前面说的因为需要等到APP_CMD_INIT_WINDOW 消息后,才能初始化surface.
- 在WIN平台glsl转的spv文件可以直接在android上使用,而hlsl的不行,这里不知是否有误,测试不行。
- 1080P下16/16的结果不对,二种解决方案,一是使用32/8,满足整除,但是需要图像满足对应的长宽条件,二是divup,然后在shader里传入width/hight,检查ThreadID.xy在width/hight范围了,需要做if检查,但是不限制图像长宽大小。
参考:
https://github.com/LunarG/VulkanSamples vulkan基本API用法实例
https://github.com/SaschaWillems/Vulkan vulkan进阶demo.
https://www.zhihu.com/people/xiao-peng-you-38-21/posts 上面vulkan demo的讲解。
Android——NativeActivity - C/C++ Apk开发
Vulkan在Android使用Compute shader的更多相关文章
- 【原创翻译】初识Unity中的Compute Shader
一直以来都想试着自己翻译一些东西,现在发现翻译真的很不容易,如果你直接把作者的原文按照英文的思维翻译过来,你会发现中国人读起来很是别扭,但是如果你想完全利用中国人的语言方式来翻译,又怕自己理解的不到位 ...
- 使用Compute Shader加速Irradiance Environment Map的计算
Irradiance Environment Map基本原理 Irradiance Environment Map(也叫Irradiance Map或Diffuse Environment Map), ...
- 聊聊如何正确向Compute Shader传递数组
0x00 前言 前一段时间去英国出差,发现Unity Brighton 办公室的手绘地图墙很漂亮,在这里分享给大家. 在这篇文章中,我们选择了过去几周Unity官方社区交流群以及UUG社区群中比较有代 ...
- OpenGL Compute Shader靠谱例子及读取二进制Shader,SPIR-V
学OpenGL以来一直苦恼没有像DX那样可以读取二进制Shader使用的方法,除去有时不想公开自己写的牛逼Shader的心理(虽然目前还从没写过什么牛逼的Shader), 主要是不用现场编译,加快读取 ...
- Compute Shader
[Compute Shader] 1.Similar to regular shaders, compute shaders are Asset files in your project, with ...
- Android渲染器Shader:环状放射渐变渲染器RadialGradient(三)
Android渲染器Shader:环状放射渐变渲染器RadialGradient(三) Android RadialGradient渲染器提供一种环状.发散.放射形状的渐变渲染器. 写一个例子: ...
- Android渲染器Shader:梯度渐变扫描渲染器SweepGradient(二)
Android渲染器Shader:梯度渐变扫描渲染器SweepGradient(二) 附录文章1介绍了线性渐变渲染器. Android的SweepGradient梯度渐变扫描,重点是在构造Swe ...
- Android渲染器Shader:LinearGradient(一)
Android渲染器Shader:LinearGradient(一) LinearGradient是Android的线性渲染器.我写5个LinearGradient渲染器渲染后的View表现结果 ...
- OpenGL 之 Compute Shader(通用计算并行加速)
平常我们使用的Shader有顶点着色器.几何着色器.片段着色器,这几个都是为光栅化图形渲染服务的,OpenGL 4.3之后新出了一个Compute Shader,用于通用计算并行加速,现在对其进行介绍 ...
随机推荐
- cinder migrate基础内容-源码分析
一.cinder-api服务入口 D:\code-program\cinder-codejuno\api\contrib\admin_actions.py from cinder import vol ...
- Logistic回归分析之二元Logistic回归
在研究X对于Y的影响时,如果Y为定量数据,那么使用多元线性回归分析(SPSSAU通用方法里面的线性回归):如果Y为定类数据,那么使用Logistic回归分析. 结合实际情况,可以将Logistic回归 ...
- [FJOI2020]染色图的联通性问题 题解
FJOI2020 D1T2 题目大意 给出一个由 $n$ 个点 $m$ 条边构成的染色无向图,求删去每一个点及与其相连的边后图中不连通的同色点对数量.$n,m\leq 10^5$. 思路分析 可以想到 ...
- 程序员小哥教你秋招拿大厂offer
快要到秋招了,对于应届生来说,秋招是一个特别重要的机会.对于社招同学来说,金九银十也是一个很好的跳槽窗口. 而我呢,因为是从上海到广州工作,就没有提前先把工作定下来.刚好也趁这个机会出去旅游了两个月. ...
- pyinstaller库的简单使用 打包科赫雪花几何图形
pyinstaller 简单使用 (cmd命令行) pyinstaller -F <文件名.py> Pyinstaller库常用参数 参数 描述 -h 查看帮助 --clean 清理打包过 ...
- Python开发的入门教程(六)-函数
介绍 本文主要介绍Python中函数的基本知识和使用 Python之什么是函数 我们知道圆的面积计算公式为: S = πr² 当我们知道半径r的值时,就可以根据公式计算出面积.假设我们需要计算3个不同 ...
- [ASP.NET Core开发实战]基础篇05 服务器
什么是服务器 服务器指ASP.NET Core应用运行在操作系统上的载体,也叫Web服务器. Web服务器实现侦听HTTP请求,并以构建HttpContext的对象发送给ASP.NET Core应用. ...
- URL的字符编码
摘要: 在通过URL访问HTTP SERVER的时候,通常会产生trace callback的异常,返回505的错误," VERSION IS NOT SUPPORTED ?" , ...
- Python 批量下载BiliBili视频 打包成软件
文章目录 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人,却不知道如何去学习更加高深的知识.那么针对这三类人,我给大家 ...
- 2d 骨胳动画
cocos2d下,优秀骨骼spine的换装思路 https://www.jianshu.com/p/a0019c6cf7ba