本人使用樹莓派 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 適配,從代碼量來說,適配代碼真的很少,但是又異常困難,在此記錄一下我走過的坑,希望我走過的坑,后來者不用再掉下去。
編輯:黃飛
?
評論
查看更多