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,用于通用计算并行加速,现在对其进行介绍 ...
随机推荐
- Hyperledger Fabric【区块链学习一】
Hyperledger Fabric 学习 什么是区块链 什么是区块链在我们没有接触的时候,只知道它是一个去中心化的存储方式.当我们发生交易,或者动作的时候我们会将记录通知给所有参与者共同维护,达到去 ...
- Mybatis入门(三)------日志系统
Mybatis日志系统 简介 Mybatis内置的日志工厂提供日志功能,具体的日志实现有以下几种方式: •SLF4J •Apache Commons Logging •Log4j 2 •Log4j • ...
- Angular 学习思路
近些年前端框架非常多,主流的有 Vue.React.Angular 等.我参与的项目中使用较多的是 Vue.因为 Vue 学习难度不大,上手很快,代码简洁,而且使用 Vue 全家桶(Vue + Vue ...
- 如何利用微博客进行seo赚钱营销
http://www.wocaoseo.com/thread-130-1-1.html 我们知道做SEO就是用人的思维来模仿搜索引擎的习惯,尽量适应seo的规则,并按照搜索引擎的规则和习惯 ...
- fprintfAndFscanf简单操作
C语言fscanf和fprintf函数的用法详解(格式化读写文件)(代码转载) #include<stdio.h> #define N 2 struct stu{ char name[10 ...
- python爬虫-爬取豆瓣电影数据
#!/usr/bin/python# coding=utf-8# 作者 :Y0010026# 创建时间 :2018/12/16 16:27# 文件 :spider_05.py# IDE :PyChar ...
- WPF Devexpress ChartControl CrosshairLabel显示内容居右
源码可加Q群:580749909. 一.解决的问题 ChartControl中希望CrosshairLabel的内容据右 or 自定义 二.实现. 多个显示实例(实例:条形,线形,点等等)下的内容设置 ...
- 滑动窗口(Sliding Window)技巧总结
什么是滑动窗口(Sliding Window) The Sliding Problem contains a sliding window which is a sub – list that run ...
- java最简单的知识之创建一个简单的windows窗口,利用Frame类
作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 微博:http://weibo.com/mcxiaobing 首先给大家看一下 ...
- Lct 动态链接树
通过树链剖分能了解轻重边 Acdreamer 的博客 http://blog.csdn.net/acdreamers/article/details/10591443 然后看杨哲大大的论文,能了解轻重 ...