作者:Diemit 本人使用树莓派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的描述中也有类似的说明,原文如下: TheV3DMesadriverscommunicatedirectlywiththeV3DkernelDRMdriverforschedulingGPUcommands。Additionally,ontheRaspberryPi4,thekernelusestheVC4DRMdriverfordisplaysupport,soMesaexposesavc4dri。sousingthekmsrohelperstodobehindthescenesbuffermanagementbetweenthetwokerneldrivers,whileexecutingrenderingontheV3Dkernelmodule。 这时我看到树莓派的mesa3d驱动还需要kmsro,当时我不太理解,经过好几天的网上搜索,最终抱着不确定的心态,使用了以下的参数编译mesa:DplatformsohosDeglnativeplatformohosDdridriversDgalliumdriversv3d,vc4,kmsroDvulkandriversDgbmenabledDeglenabledDcpprttifalseDglxdisabledDtoolsDdrisearchpathvendorlibchipsetsdk 在复制编译好的lib文件加入编译框架,并在config。json中设置启用GPU:graphicstandardfeatureaceenablegputrue, 编译烧录之后运行黑屏,受到SIGOpenGfxDrv群里的大神指导,调试GPU可以先设置CPU合成,GPU渲染的模式,即保持config。json中设置启用GPU,同时修改下面函数,强制使用CPU合成:foundationgraphicgraphic2drosenmodulesrenderservicecorepipelinersbaserenderengine。cpp中的NeedForceCPUboolforceCPUfalse;boolforceCPUtrue; 再次编译,烧录运行,发现屏幕能点亮,但是显示异常,经过各种探索,仍然无法解决,第一次移植失败。 经过断断续续的查找资料,对比验证,找到了验证gpu工作的方法,就是通过opengl的api调用一个简单的gpu绘图程序,结果仍然撕裂。 接口能调用成功,但是显示异常,这种bug不会报错,没有图形相关经验的我根本定位不到原因。 最终我想到树莓派4有安卓的移植项目,查到安卓也是用mesa3d,然后我找到了两个树莓派4移植项目:【lineagerpi】和【androidrpi】。 对比了两个仓中的mesa3d代码之后,终于给我在【androidrpi】中发现了关键代码,树莓派4适配安卓仅仅修改了下面这些地方: 然后再看OpenHarmony的mesa3d的代码,之前我对比过platformohos。c跟platformandroid。c的区别,差异是有,但是总体比较类似。 同时我也发现了注释中有说明platformohos是基于platformandroid修改。 经过对比,我把androidrpi对mesa的修改手动同步到了OpenHarmony的mesa中。 修改如下: 经过重新编译,烧录,测试例子终于能够正常显示,前后历时四个多月,从3。2beta3跨到了3。2beta4。 cpu合成cpu渲染组合下,调用OpenGLApi进行三角形的绘制: 启用GPU渲染后,能够感知到帧率有提升,打个比方,cpu合成cpu渲染在竖屏旋转下只有7帧秒,cpu合成gpu渲染下能达到14帧秒,有提升但是仍然卡顿严重,经过多方求教仍未解决问题。 在初步打通gpu调用之后,夜里脑子仍在思考着问题的解决办法,不断排列组合,最终想到了3。2beta4的一个公告内容,RS侧支持GPU合成。 然后又联系到了几个月前我看到过的一个关于gpu的issue,描述到了【graphicstandardfeaturersenableeglimage】这个参数。 最后爬起来把这个参数设置成了true,编译烧录一套走起,最后居然给干成了,流畅度可感知的达到了60fps那种流畅。 通过树莓派4适配GPU的经历,我总结出GPU适配的思路如下: 不启用GPU功能,在CPU合成CPU渲染的环境下,确认GPU驱动正常工作。foundationgraphicgraphic2drosenmodulesrenderservicecorepipelinersbaserenderengine。cpp中的NeedForceCPU中修改强制cpu合成boolforceCPUfalse;boolforceCPUtrue;vendorraspberrypirpi4config。json中设置不启用gpugraphicstandardfeatureaceenablegpufalse, 启用部分GPU功能,在CPU合成GPU渲染的环境下,确认GPU能正确渲染。foundationgraphicgraphic2drosenmodulesrenderservicecorepipelinersbaserenderengine。cpp中的NeedForceCPU中修改关闭cpu合成boolforceCPUfalse;boolforceCPUtrue;vendorraspberrypirpi4config。json中设置启用gpugraphicstandardfeatureaceenablegputrue, 启用GPU合成GPU渲染,加速OpenHarmony图形显示。foundationgraphicgraphic2drosenmodulesrenderservicecorepipelinersbaserenderengine。cpp中的NeedForceCPU中还原关闭cpu合成boolforceCPUfalse;vendorraspberrypirpi4config。json中设置启用gpu,同时启用gpu合成graphicstandardfeatureaceenablegputrue,graphicstandardfeaturersenableeglimagetrue 同时OpenHarmony开源的GPU移植也可以参考安卓方面的移植。 小米6的GPU移植 小米6的GPU是Adreno540,经过网上搜索资料mesa驱动对应的名字是freedreno。 所以编译参数对应为:DplatformsohosDeglnativeplatformohosDdridriversDgalliumdriversfreedrenoDvulkandriversDgbmenabledDeglenabledDcpprttifalseDglxdisabledDtoolsDdrisearchpathvendorlib64chipsetsdk 但是编译烧录之后运行简单的测试gpu程序始终无法运行,signal11程序崩溃了。 通过datalogfaultlogtemp下崩溃日志确认buildidfindnhdrcallback存在问题。 通过在函数内部加print打印的方式,对比分析之后确认是offset计算不正确,最后我意外发现了OpenHarmony的【thirdpartylibunwind】有修改过buildid。 经过查看pr提交发现了以下关键代码,原来是oh的编译框架在编译出的elf文件头增加了一个非标准的note段,mesa使用标准的方式去解析note内容导致偏移量计算出错,需要处理一下偏移量问题。 然而mesa3d这个开源gpu驱动常年没人维护,这个问题一直没有暴露出来,这给我碰到了同步修改之后解决调用崩溃问题。 同时接口调用也能正常显示了: 但是当我进行移植第二步,CPU合成GPU渲染时黑屏,无法显示内容,又是一番加打印然后调试,最后发现关键代码,freedreno中有强制设置对齐。 在hilog中发现Assertionfailed: 查看源码发现a5xx系的头文件中有pitch的验证,【0x3f】相当于判断能否被64整除。 然后我往前找到buffer设置的某个地方尝试着把pich强制64对齐,终于能显示出图像。 不黑屏了,但是仍然显示不正常,很明显能感知到是长度没有对齐导致错位了。 最终在SIGOpenGfxDrv群里的lhl大神指导下,修改display适配层中的WIDTHALIGN参数为64,成功解决显示问题。 确认CPU合成GPU渲染显示能正常工作之后,启用GPU合成GPU渲染,成功运行,小米6终于适配GPU成功。 树莓派4和小米6的GPU适配,从代码量来说,适配代码真的很少,但是又异常困难,在此记录一下我走过的坑,希望我走过的坑,后来者不用再掉下去。