#创作者激励#OpenHarmony富设备移植指南(6.3)GPU调试经验分享 原创 精华
【本文正在参加2023年第一期优质创作者激励计划】
本人使用树莓派4和小米6进行OpenHarmony适配GPU时产生过许多问题,这里回顾一下我移植GPU的过程,同时也做一些总结和经验分享,希望大家看过之后能少走一些弯路。
1.树莓派4GPU移植
树莓派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,同时修改foundation/graphic/graphic_2d/rosen/modules/render_service/core/pipeline/rs_base_render_engine.cpp中的NeedForceCPU函数,强制使用cpu合成
//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适配的思路如下:
1.不启用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",
2.启用部分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",
3.启用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移植也可以参考安卓方面的移植。
2.小米6GPU移植
小米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适配,从代码量来说,适配代码真的很少,但是又异常困难,在此记录一下我走过的坑,希望我走过的坑,后来者不用再掉下去。
可以看出适配之路困难重重。
适配可真不容易
大佬这个厉害
未知领域感觉很多时候就只能凭经验来猜了
多读官方公告还是有用的
能够正常触摸嘛?
感觉会有用,哪里有下载地址呢。