本人使用树莓派 4 和小米 6 进行 OpenHarmony 适配 GPU 时产生过挺多问题,这里回顾以下我移植 GPU 的过程,同时也做一些总结和经验分享,希望大家看过之后能少走一些弯路。
树莓派 4 的 GPU 移植
树莓派 4 的 GPU 驱动组成比较复杂,在 Linux 的 GPU 驱动目录中 drm 目录下存放着 vc4 和 v3d 两个目录。
vc4 既包含 Display 驱动也包含 GPU 驱动,主要用于树莓派 3 及之前的 SoC;而 v3d 则只包含 GPU 驱动,专用于树莓派 4。
由于 vc4 和 v3d 的 Display 硬件差异不大,为了让树莓派 4 最大化利用 vc4 现有的 Display 驱动,树莓派驱动的开发者并没有分离代码,所以树莓派的 GPU 驱动需要同时启用 vc4 和 v3d。
同时,我在查阅 mesa3d 的文档中有关 v3d 的描述中也有类似的说明,原文如下:
The V3D Mesa drivers communicate directly with the V3D kernel DRM driver for scheduling GPU commands. Additionally, on the Raspberry Pi 4, the kernel uses the VC4 DRM driver for display support, so Mesa exposes a vc4_dri.so using the kmsro helpers to do behind-the-scenes buffer management between the two kernel drivers, while executing rendering on the V3D kernel module.
这时我看到树莓派的 mesa3d 驱动还需要 kmsro,当时我不太理解,经过好几天的网上搜索,最终抱着不确定的心态,使用了以下的参数编译 mesa:
-Dplatforms=ohos -Degl-native-platform=ohos -Ddri-drivers= -Dgallium-drivers=v3d,vc4,kmsro
-Dvulkan-drivers= -Dgbm=enabled -Degl=enabled -Dcpp_rtti=false -Dglx=disabled -Dtools= -Ddri-search-path=/vendor/lib/chipsetsdk
在复制编译好的 lib 文件加入编译框架,并在 config.json 中设置启用 GPU:
"graphic_standard_feature_ace_enable_gpu = true",
编译烧录之后运行黑屏,受到 SIG-OpenGfxDrv 群里的大神指导,调试 GPU 可以先设置 CPU 合成,GPU 渲染的模式,即保持 config.json 中设置启用 GPU,同时修改下面函数,强制使用 CPU 合成:
foundation/graphic/graphic_2d/rosen/modules/render_service/core/pipeline/rs_base_render_engine.cpp中的NeedForceCPU
//bool forceCPU = false; bool forceCPU = true;
再次编译,烧录运行,发现屏幕能点亮,但是显示异常,经过各种探索,仍然无法解决,第一次移植失败。
经过断断续续的查找资料,对比验证,找到了验证 gpu 工作的方法,就是通过 opengl 的 api 调用一个简单的 gpu 绘图程序,结果仍然撕裂。
接口能调用成功,但是显示异常,这种 bug 不会报错,没有图形相关经验的我根本定位不到原因。 最终我想到树莓派 4 有安卓的移植项目,查到安卓也是用 mesa3d,然后我找到了两个树莓派 4 移植项目:【lineage-rpi】和【android-rpi】。 对比了两个仓中的 mesa3d 代码之后,终于给我在【android-rpi】中发现了关键代码,树莓派 4 适配安卓仅仅修改了下面这些地方:
然后再看 OpenHarmony 的 mesa3d 的代码,之前我对比过 platform_ohos.c 跟 platform_android.c 的区别,差异是有,但是总体比较类似。 同时我也发现了注释中有说明 platform_ohos 是基于 platform_android 修改。
经过对比,我把 android-rpi 对 mesa 的修改手动同步到了 OpenHarmony 的 mesa 中。 修改如下:
经过重新编译,烧录,测试例子终于能够正常显示,前后历时四个多月,从 3.2beta3 跨到了 3.2beta4。 cpu 合成+cpu 渲染组合下,调用 OpenGLApi 进行三角形的绘制:
启用 GPU 渲染后,能够感知到帧率有提升,打个比方,cpu 合成+cpu 渲染在竖屏旋转下只有 7 帧/秒,cpu 合成+gpu 渲染下能达到 14 帧/秒,有提升但是仍然卡顿严重,经过多方求教仍未解决问题。 在初步打通 gpu 调用之后,夜里脑子仍在思考着问题的解决办法,不断排列组合,最终想到了 3.2beta4 的一个公告内容,RS 侧支持 GPU 合成。 然后又联系到了几个月前我看到过的一个关于 gpu 的 issue,描述到了【graphic_standard_feature_rs_enable_eglimage】这个参数。 最后爬起来把这个参数设置成了 true,编译烧录一套走起,最后居然给干成了,流畅度可感知的达到了 60fps 那种流畅。
通过树莓派 4 适配 GPU 的经历,我总结出 GPU 适配的思路如下:
①不启用 GPU 功能,在 CPU 合成+CPU 渲染的环境下,确认 GPU 驱动正常工作。
foundation/graphic/graphic_2d/rosen/modules/render_service/core/pipeline/rs_base_render_engine.cpp中的NeedForceCPU 中修改强制cpu合成 //bool forceCPU = false; bool forceCPU = true; vendor/raspberrypi/rpi4/config.json 中设置不启用gpu "graphic_standard_feature_ace_enable_gpu = false",②启用部分 GPU 功能,在 CPU 合成+GPU 渲染的环境下,确认 GPU 能正确渲染。
foundation/graphic/graphic_2d/rosen/modules/render_service/core/pipeline/rs_base_render_engine.cpp中的NeedForceCPU 中修改关闭cpu合成 //bool forceCPU = false; bool forceCPU = true; vendor/raspberrypi/rpi4/config.json 中设置启用gpu "graphic_standard_feature_ace_enable_gpu = true",③启用 GPU 合成+GPU 渲染,加速 OpenHarmony 图形显示。
foundation/graphic/graphic_2d/rosen/modules/render_service/core/pipeline/rs_base_render_engine.cpp中的NeedForceCPU 中还原关闭cpu合成 bool forceCPU = false; vendor/raspberrypi/rpi4/config.json 中设置启用gpu,同时启用gpu合成 "graphic_standard_feature_ace_enable_gpu = true", "graphic_standard_feature_rs_enable_eglimage = true"同时 OpenHarmony 开源的 GPU 移植也可以参考安卓方面的移植。
小米 6 的 GPU 移植
小米 6 的 GPU 是 Adreno 540,经过网上搜索资料 mesa 驱动对应的名字是 freedreno。
所以编译参数对应为:
-Dplatforms=ohos -Degl-native-platform=ohos -Ddri-drivers= -Dgallium-drivers=freedreno -Dvulkan-drivers= -Dgbm=enabled -Degl=enabled -Dcpp_rtti=false -Dglx=disabled -Dtools= -Ddri-search-path=/vendor/lib64/chipsetsdk但是编译烧录之后运行简单的测试 gpu 程序始终无法运行,signal 11 程序崩溃了。
通过 /data/log/faultlog/temp 下崩溃日志确认 build_id_find_nhdr_callback 存在问题。
通过在函数内部加 print 打印的方式,对比分析之后确认是 offset 计算不正确,最后我意外发现了 OpenHarmony 的【third_party_libunwind】有修改过 build-id。 经过查看 pr 提交发现了以下关键代码,原来是 oh 的编译框架在编译出的 elf 文件头增加了一个非标准的 note 段,mesa 使用标准的方式去解析 note 内容导致偏移量计算出错,需要处理一下偏移量问题。 然而 mesa3d 这个开源 gpu 驱动常年没人维护,这个问题一直没有暴露出来,这给我碰到了。。。同步修改之后解决调用崩溃问题。
同时接口调用也能正常显示了:
但是当我进行移植第二步,CPU 合成+GPU 渲染时黑屏,无法显示内容,又是一番加打印然后调试,最后发现关键代码,freedreno 中有强制设置对齐。
在 hilog 中发现 Assertion failed:
查看源码发现 a5xx 系的头文件中有 pitch 的验证,【&0x3f】相当于判断能否被 64 整除。
然后我往前找到 buffer 设置的某个地方尝试着把 pich 强制 64 对齐,终于能显示出图像。
不黑屏了,但是仍然显示不正常,很明显能感知到是长度没有对齐导致错位了。
最终在 SIG-OpenGfxDrv 群里的 lhl 大神指导下,修改 display 适配层中的 WIDTH_ALIGN 参数为 64,成功解决显示问题。
确认 CPU 合成+GPU 渲染显示能正常工作之后,启用 GPU 合成+GPU 渲染,成功运行,小米 6 终于适配 GPU 成功。 树莓派 4 和小米 6 的 GPU 适配,从代码量来说,适配代码真的很少,但是又异常困难,在此记录一下我走过的坑,希望我走过的坑,后来者不用再掉下去。
编辑:黄飞
评论
查看更多