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. Hyperledger Fabric【区块链学习一】

    Hyperledger Fabric 学习 什么是区块链 什么是区块链在我们没有接触的时候,只知道它是一个去中心化的存储方式.当我们发生交易,或者动作的时候我们会将记录通知给所有参与者共同维护,达到去 ...

  2. Mybatis入门(三)------日志系统

    Mybatis日志系统 简介 Mybatis内置的日志工厂提供日志功能,具体的日志实现有以下几种方式: •SLF4J •Apache Commons Logging •Log4j 2 •Log4j • ...

  3. Angular 学习思路

    近些年前端框架非常多,主流的有 Vue.React.Angular 等.我参与的项目中使用较多的是 Vue.因为 Vue 学习难度不大,上手很快,代码简洁,而且使用 Vue 全家桶(Vue + Vue ...

  4. 如何利用微博客进行seo赚钱营销

    http://www.wocaoseo.com/thread-130-1-1.html       我们知道做SEO就是用人的思维来模仿搜索引擎的习惯,尽量适应seo的规则,并按照搜索引擎的规则和习惯 ...

  5. fprintfAndFscanf简单操作

    C语言fscanf和fprintf函数的用法详解(格式化读写文件)(代码转载) #include<stdio.h> #define N 2 struct stu{ char name[10 ...

  6. python爬虫-爬取豆瓣电影数据

    #!/usr/bin/python# coding=utf-8# 作者 :Y0010026# 创建时间 :2018/12/16 16:27# 文件 :spider_05.py# IDE :PyChar ...

  7. WPF Devexpress ChartControl CrosshairLabel显示内容居右

    源码可加Q群:580749909. 一.解决的问题 ChartControl中希望CrosshairLabel的内容据右 or 自定义 二.实现. 多个显示实例(实例:条形,线形,点等等)下的内容设置 ...

  8. 滑动窗口(Sliding Window)技巧总结

    什么是滑动窗口(Sliding Window) The Sliding Problem contains a sliding window which is a sub – list that run ...

  9. java最简单的知识之创建一个简单的windows窗口,利用Frame类

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 微博:http://weibo.com/mcxiaobing 首先给大家看一下 ...

  10. Lct 动态链接树

    通过树链剖分能了解轻重边 Acdreamer 的博客 http://blog.csdn.net/acdreamers/article/details/10591443 然后看杨哲大大的论文,能了解轻重 ...