本人使用樹莓派 4 和小米 6 進(jìn)行 OpenHarmony 適配 GPU 時產(chǎn)生過挺多問題,這里回顧以下我移植 GPU 的過程,同時也做一些總結(jié)和經(jīng)驗分享,希望大家看過之后能少走一些彎路。
樹莓派?4 的?GPU?移植
樹莓派 4 的 GPU 驅(qū)動組成比較復(fù)雜,在 Linux 的 GPU 驅(qū)動目錄中 drm 目錄下存放著 vc4 和 v3d 兩個目錄。
vc4 既包含 Display 驅(qū)動也包含 GPU 驅(qū)動,主要用于樹莓派 3 及之前的 SoC;而 v3d 則只包含 GPU 驅(qū)動,專用于樹莓派 4。
由于 vc4 和 v3d 的 Display 硬件差異不大,為了讓樹莓派 4 最大化利用 vc4 現(xiàn)有的 Display 驅(qū)動,樹莓派驅(qū)動的開發(fā)者并沒有分離代碼,所以樹莓派的 GPU 驅(qū)動需要同時啟用 vc4 和 v3d。
同時,我在查閱 mesa3d 的文檔中有關(guān) 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 驅(qū)動還需要 kmsro,當(dāng)時我不太理解,經(jīng)過好幾天的網(wǎng)上搜索,最終抱著不確定的心態(tài),使用了以下的參數(shù)編譯 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
在復(fù)制編譯好的 lib 文件加入編譯框架,并在 config.json 中設(shè)置啟用 GPU:
"graphic_standard_feature_ace_enable_gpu?=?true",
編譯燒錄之后運(yùn)行黑屏,受到 SIG-OpenGfxDrv 群里的大神指導(dǎo),調(diào)試 GPU 可以先設(shè)置 CPU 合成,GPU 渲染的模式,即保持 config.json 中設(shè)置啟用 GPU,同時修改下面函數(shù),強(qiáng)制使用 CPU 合成:
foundation/graphic/graphic_2d/rosen/modules/render_service/core/pipeline/rs_base_render_engine.cpp中的NeedForceCPU
//bool?forceCPU?=?false; bool?forceCPU?=?true;
再次編譯,燒錄運(yùn)行,發(fā)現(xiàn)屏幕能點亮,但是顯示異常,經(jīng)過各種探索,仍然無法解決,第一次移植失敗。
經(jīng)過斷斷續(xù)續(xù)的查找資料,對比驗證,找到了驗證 gpu 工作的方法,就是通過 opengl 的 api 調(diào)用一個簡單的 gpu 繪圖程序,結(jié)果仍然撕裂。
接口能調(diào)用成功,但是顯示異常,這種 bug 不會報錯,沒有圖形相關(guān)經(jīng)驗的我根本定位不到原因。 最終我想到樹莓派 4 有安卓的移植項目,查到安卓也是用 mesa3d,然后我找到了兩個樹莓派 4 移植項目:【lineage-rpi】和【android-rpi】。 對比了兩個倉中的 mesa3d 代碼之后,終于給我在【android-rpi】中發(fā)現(xiàn)了關(guān)鍵代碼,樹莓派 4 適配安卓僅僅修改了下面這些地方:
然后再看 OpenHarmony 的 mesa3d 的代碼,之前我對比過 platform_ohos.c 跟 platform_android.c 的區(qū)別,差異是有,但是總體比較類似。 同時我也發(fā)現(xiàn)了注釋中有說明 platform_ohos 是基于 platform_android 修改。
經(jīng)過對比,我把 android-rpi 對 mesa 的修改手動同步到了 OpenHarmony 的 mesa 中。 修改如下:
經(jīng)過重新編譯,燒錄,測試?yán)咏K于能夠正常顯示,前后歷時四個多月,從 3.2beta3 跨到了 3.2beta4。 cpu 合成+cpu 渲染組合下,調(diào)用 OpenGLApi 進(jìn)行三角形的繪制:
啟用 GPU 渲染后,能夠感知到幀率有提升,打個比方,cpu 合成+cpu 渲染在豎屏旋轉(zhuǎn)下只有 7 幀/秒,cpu 合成+gpu 渲染下能達(dá)到 14 幀/秒,有提升但是仍然卡頓嚴(yán)重,經(jīng)過多方求教仍未解決問題。 在初步打通 gpu 調(diào)用之后,夜里腦子仍在思考著問題的解決辦法,不斷排列組合,最終想到了 3.2beta4 的一個公告內(nèi)容,RS 側(cè)支持 GPU 合成。 然后又聯(lián)系到了幾個月前我看到過的一個關(guān)于 gpu 的 issue,描述到了【graphic_standard_feature_rs_enable_eglimage】這個參數(shù)。 最后爬起來把這個參數(shù)設(shè)置成了 true,編譯燒錄一套走起,最后居然給干成了,流暢度可感知的達(dá)到了 60fps 那種流暢。
通過樹莓派 4 適配 GPU 的經(jīng)歷,我總結(jié)出 GPU 適配的思路如下:
①不啟用 GPU 功能,在 CPU 合成+CPU 渲染的環(huán)境下,確認(rèn) GPU 驅(qū)動正常工作。
foundation/graphic/graphic_2d/rosen/modules/render_service/core/pipeline/rs_base_render_engine.cpp中的NeedForceCPU 中修改強(qiáng)制cpu合成 //bool?forceCPU?=?false; bool?forceCPU?=?true; vendor/raspberrypi/rpi4/config.json 中設(shè)置不啟用gpu "graphic_standard_feature_ace_enable_gpu?=?false",? ?②啟用部分 GPU 功能,在 CPU 合成+GPU 渲染的環(huán)境下,確認(rèn) GPU 能正確渲染。
foundation/graphic/graphic_2d/rosen/modules/render_service/core/pipeline/rs_base_render_engine.cpp中的NeedForceCPU 中修改關(guān)閉cpu合成 //bool?forceCPU?=?false; bool?forceCPU?=?true; vendor/raspberrypi/rpi4/config.json 中設(shè)置啟用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 中還原關(guān)閉cpu合成 bool?forceCPU?=?false; vendor/raspberrypi/rpi4/config.json 中設(shè)置啟用gpu,同時啟用gpu合成 "graphic_standard_feature_ace_enable_gpu?=?true", "graphic_standard_feature_rs_enable_eglimage?=?true"? ? 同時 OpenHarmony 開源的 GPU 移植也可以參考安卓方面的移植。 ?
小米 6 的 GPU?移植
小米 6 的 GPU 是 Adreno 540,經(jīng)過網(wǎng)上搜索資料 mesa 驅(qū)動對應(yīng)的名字是 freedreno。
所以編譯參數(shù)對應(yīng)為:
-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? ?但是編譯燒錄之后運(yùn)行簡單的測試 gpu 程序始終無法運(yùn)行,signal 11 程序崩潰了。
通過 /data/log/faultlog/temp 下崩潰日志確認(rèn) build_id_find_nhdr_callback 存在問題。
通過在函數(shù)內(nèi)部加 print 打印的方式,對比分析之后確認(rèn)是 offset 計算不正確,最后我意外發(fā)現(xiàn)了 OpenHarmony 的【third_party_libunwind】有修改過 build-id。 經(jīng)過查看 pr 提交發(fā)現(xiàn)了以下關(guān)鍵代碼,原來是 oh 的編譯框架在編譯出的 elf 文件頭增加了一個非標(biāo)準(zhǔn)的 note 段,mesa 使用標(biāo)準(zhǔn)的方式去解析 note 內(nèi)容導(dǎo)致偏移量計算出錯,需要處理一下偏移量問題。 然而 mesa3d 這個開源 gpu 驅(qū)動常年沒人維護(hù),這個問題一直沒有暴露出來,這給我碰到了。。。同步修改之后解決調(diào)用崩潰問題。
同時接口調(diào)用也能正常顯示了:
但是當(dāng)我進(jìn)行移植第二步,CPU 合成+GPU 渲染時黑屏,無法顯示內(nèi)容,又是一番加打印然后調(diào)試,最后發(fā)現(xiàn)關(guān)鍵代碼,freedreno 中有強(qiáng)制設(shè)置對齊。
在 hilog 中發(fā)現(xiàn) Assertion failed:
查看源碼發(fā)現(xiàn) a5xx 系的頭文件中有 pitch 的驗證,【&0x3f】相當(dāng)于判斷能否被 64 整除。
然后我往前找到 buffer 設(shè)置的某個地方嘗試著把 pich 強(qiáng)制 64 對齊,終于能顯示出圖像。
不黑屏了,但是仍然顯示不正常,很明顯能感知到是長度沒有對齊導(dǎo)致錯位了。
最終在 SIG-OpenGfxDrv 群里的 lhl 大神指導(dǎo)下,修改 display 適配層中的 WIDTH_ALIGN 參數(shù)為 64,成功解決顯示問題。
確認(rèn) CPU 合成+GPU 渲染顯示能正常工作之后,啟用 GPU 合成+GPU 渲染,成功運(yùn)行,小米 6 終于適配 GPU 成功。 樹莓派 4 和小米 6 的 GPU 適配,從代碼量來說,適配代碼真的很少,但是又異常困難,在此記錄一下我走過的坑,希望我走過的坑,后來者不用再掉下去。
編輯:黃飛
?
評論