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。

  1. 填充计算管线的CommandBuffer,简单来说,就是执行上面的compute pipeline,并把输出纹理layout改成VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL。
  2. 填充呈现渲染里的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下遇到的一些坑。

  1. undefined symbol: ANativeActivity_onCreate 找不到,解决方法在CMake中添加set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")
  2. vkCreateAndroidSurfaceKHR 类似Fatal signal 11 (SIGSEGV)错误。这是前面说的因为需要等到APP_CMD_INIT_WINDOW 消息后,才能初始化surface.
  3. 在WIN平台glsl转的spv文件可以直接在android上使用,而hlsl的不行,这里不知是否有误,测试不行。
  4. 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的更多相关文章

  1. 【原创翻译】初识Unity中的Compute Shader

    一直以来都想试着自己翻译一些东西,现在发现翻译真的很不容易,如果你直接把作者的原文按照英文的思维翻译过来,你会发现中国人读起来很是别扭,但是如果你想完全利用中国人的语言方式来翻译,又怕自己理解的不到位 ...

  2. 使用Compute Shader加速Irradiance Environment Map的计算

    Irradiance Environment Map基本原理 Irradiance Environment Map(也叫Irradiance Map或Diffuse Environment Map), ...

  3. 聊聊如何正确向Compute Shader传递数组

    0x00 前言 前一段时间去英国出差,发现Unity Brighton 办公室的手绘地图墙很漂亮,在这里分享给大家. 在这篇文章中,我们选择了过去几周Unity官方社区交流群以及UUG社区群中比较有代 ...

  4. OpenGL Compute Shader靠谱例子及读取二进制Shader,SPIR-V

    学OpenGL以来一直苦恼没有像DX那样可以读取二进制Shader使用的方法,除去有时不想公开自己写的牛逼Shader的心理(虽然目前还从没写过什么牛逼的Shader), 主要是不用现场编译,加快读取 ...

  5. Compute Shader

    [Compute Shader] 1.Similar to regular shaders, compute shaders are Asset files in your project, with ...

  6. Android渲染器Shader:环状放射渐变渲染器RadialGradient(三)

     Android渲染器Shader:环状放射渐变渲染器RadialGradient(三) Android RadialGradient渲染器提供一种环状.发散.放射形状的渐变渲染器. 写一个例子: ...

  7. Android渲染器Shader:梯度渐变扫描渲染器SweepGradient(二)

     Android渲染器Shader:梯度渐变扫描渲染器SweepGradient(二) 附录文章1介绍了线性渐变渲染器. Android的SweepGradient梯度渐变扫描,重点是在构造Swe ...

  8. Android渲染器Shader:LinearGradient(一)

     Android渲染器Shader:LinearGradient(一) LinearGradient是Android的线性渲染器.我写5个LinearGradient渲染器渲染后的View表现结果 ...

  9. OpenGL 之 Compute Shader(通用计算并行加速)

    平常我们使用的Shader有顶点着色器.几何着色器.片段着色器,这几个都是为光栅化图形渲染服务的,OpenGL 4.3之后新出了一个Compute Shader,用于通用计算并行加速,现在对其进行介绍 ...

随机推荐

  1. [WPF][Rubyer] 写一个自己的 UI 库 (二) - Icon

    前言 制作 WPF 的图标包,主要介绍从 iconfont 下载的图标包导入到 WPF 使用: 1. 添加文件 Ruyber 下添加 自定义控件(WPF) Icon.cs.类 IconType.cs. ...

  2. python基础 Day12

    python Day12 生成器python社区,生成器与迭代器看成一种.生成器的本质就是迭代器. 区别:生成器是我们自己用python代码构建的数据结构.迭代器都是提供的,或者转化得来的. 获取生成 ...

  3. DML语言(数据操纵语言)

    #DML语言/*数据操作语言:插入:insert修改:update删除:delete */ #一.插入语句#方式一:经典的插入/*语法:insert into 表名(列名,...) values(值1 ...

  4. 仿京东BOE官网 css代码

    * { margin: 0; padding: 0; border: 0; list-style: none; } .box { width: 1518px; height: 1300px; marg ...

  5. 迷上我成真恋爱学心理学挽回她PDF文档资料完整版情感技巧脱单教程

    迷上我成真恋爱学心理学挽回她PDF文档资料完整版情感技巧脱单教程 成真迷上我偷听女人心挽回她课程 百度网盘迷上我教程pdf地址 百度网盘挽回她教程pdf+视频的地址 备用地址淘宝百度网盘发货地址 百度 ...

  6. [CSP-S2019]树的重心 题解

    CSP-S2 2019 D2T3 考场上扔了T2来打这题的部分分,然后没看到数据范围是等号,不知道怎么判完全二叉树然后40分滚粗…… ---- 思路分析 很容易想到$O(n^2)$每次暴力找重心,这个 ...

  7. e3mall商城的归纳总结3之后台商品节点、认识nginx

    一  后台商品节点 大家都知道后台创建商品的时候需要选择商品的分类,而这个商品的分类就就像一棵树一样,一层包含一层又包含一层.因此这里用的框架是easyUiTree.该分类前端使用的是异步加载模式(指 ...

  8. vue 中PDF实现在线浏览,禁止下载,打印

    需求:在线浏览pdf文件,并且禁止掉用户下载打印的效果. 分析:普通的iframe.embed标签都只能实现在线浏览pdf的功能,无法禁止掉工具栏的下载打印功能.只能尝试使用插件,pdfobject. ...

  9. Cython编译独立的可执行文件

    cython --embed -o hello.c hello.pygcc hello.c -o hello -I /Library/Frameworks/Python.framework/Versi ...

  10. Web最最基础2

    网页元素HTML 列表 (1)无序列表 <ul> <li>****</li> <li>***</li></ul> 更多样式:&l ...