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. cinder migrate基础内容-源码分析

    一.cinder-api服务入口 D:\code-program\cinder-codejuno\api\contrib\admin_actions.py from cinder import vol ...

  2. Logistic回归分析之二元Logistic回归

    在研究X对于Y的影响时,如果Y为定量数据,那么使用多元线性回归分析(SPSSAU通用方法里面的线性回归):如果Y为定类数据,那么使用Logistic回归分析. 结合实际情况,可以将Logistic回归 ...

  3. [FJOI2020]染色图的联通性问题 题解

    FJOI2020 D1T2 题目大意 给出一个由 $n$ 个点 $m$ 条边构成的染色无向图,求删去每一个点及与其相连的边后图中不连通的同色点对数量.$n,m\leq 10^5$. 思路分析 可以想到 ...

  4. 程序员小哥教你秋招拿大厂offer

    快要到秋招了,对于应届生来说,秋招是一个特别重要的机会.对于社招同学来说,金九银十也是一个很好的跳槽窗口. 而我呢,因为是从上海到广州工作,就没有提前先把工作定下来.刚好也趁这个机会出去旅游了两个月. ...

  5. pyinstaller库的简单使用 打包科赫雪花几何图形

    pyinstaller 简单使用 (cmd命令行) pyinstaller -F <文件名.py> Pyinstaller库常用参数 参数 描述 -h 查看帮助 --clean 清理打包过 ...

  6. Python开发的入门教程(六)-函数

    介绍 本文主要介绍Python中函数的基本知识和使用 Python之什么是函数 我们知道圆的面积计算公式为: S = πr² 当我们知道半径r的值时,就可以根据公式计算出面积.假设我们需要计算3个不同 ...

  7. [ASP.NET Core开发实战]基础篇05 服务器

    什么是服务器 服务器指ASP.NET Core应用运行在操作系统上的载体,也叫Web服务器. Web服务器实现侦听HTTP请求,并以构建HttpContext的对象发送给ASP.NET Core应用. ...

  8. URL的字符编码

    摘要: 在通过URL访问HTTP SERVER的时候,通常会产生trace callback的异常,返回505的错误," VERSION IS NOT SUPPORTED ?" , ...

  9. Python 批量下载BiliBili视频 打包成软件

    文章目录 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人,却不知道如何去学习更加高深的知识.那么针对这三类人,我给大家 ...

  10. 2d 骨胳动画

    cocos2d下,优秀骨骼spine的换装思路 https://www.jianshu.com/p/a0019c6cf7ba