天天看點

小米6成功适配GPU經驗分享!

作者:漫威電影情報局

作者:Diemit

本人使用樹莓派 4 和小米 6 進行 OpenHarmony 适配 GPU 時産生過挺多問題,這裡回顧以下我移植 GPU 的過程,同時也做一些總結和經驗分享,希望大家看過之後能少走一些彎路。

小米6成功适配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;           

再次編譯,燒錄運作,發現螢幕能點亮,但是顯示異常,經過各種探索,仍然無法解決,第一次移植失敗。

小米6成功适配GPU經驗分享!

經過斷斷續續的查找資料,對比驗證,找到了驗證 gpu 工作的方法,就是通過 opengl 的 api 調用一個簡單的 gpu 繪圖程式,結果仍然撕裂。

小米6成功适配GPU經驗分享!

接口能調用成功,但是顯示異常,這種 bug 不會報錯,沒有圖形相關經驗的我根本定位不到原因。

最終我想到樹莓派 4 有安卓的移植項目,查到安卓也是用 mesa3d,然後我找到了兩個樹莓派 4 移植項目:【lineage-rpi】和【android-rpi】。

對比了兩個倉中的 mesa3d 代碼之後,終于給我在【android-rpi】中發現了關鍵代碼,樹莓派 4 适配安卓僅僅修改了下面這些地方:

小米6成功适配GPU經驗分享!

然後再看 OpenHarmony 的 mesa3d 的代碼,之前我對比過 platform_ohos.c 跟 platform_android.c 的差別,差異是有,但是總體比較類似。

同時我也發現了注釋中有說明 platform_ohos 是基于 platform_android 修改。

小米6成功适配GPU經驗分享!

經過對比,我把 android-rpi 對 mesa 的修改手動同步到了 OpenHarmony 的 mesa 中。

修改如下:

小米6成功适配GPU經驗分享!

經過重新編譯,燒錄,測試例子終于能夠正常顯示,前後曆時四個多月,從 3.2beta3 跨到了 3.2beta4。

cpu 合成+cpu 渲染組合下,調用 OpenGLApi 進行三角形的繪制:

小米6成功适配GPU經驗分享!

啟用 GPU 渲染後,能夠感覺到幀率有提升,打個比方,cpu 合成+cpu 渲染在豎屏旋轉下隻有 7 幀/秒,cpu 合成+gpu 渲染下能達到 14 幀/秒,有提升但是仍然卡頓嚴重,經過多方求教仍未解決問題。

在初步打通 gpu 調用之後,夜裡腦子仍在思考着問題的解決辦法,不斷排列組合,最終想到了 3.2beta4 的一個公告内容,RS 側支援 GPU 合成。

然後又聯系到了幾個月前我看到過的一個關于 gpu 的 issue,描述到了【graphic_standard_feature_rs_enable_eglimage】這個參數。

最後爬起來把這個參數設定成了 true,編譯燒錄一套走起,最後居然給幹成了,流暢度可感覺的達到了 60fps 那種流暢。

小米6成功适配GPU經驗分享!

通過樹莓派 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 程式崩潰了。

小米6成功适配GPU經驗分享!

通過 /data/log/faultlog/temp 下崩潰日志确認 build_id_find_nhdr_callback 存在問題。

小米6成功适配GPU經驗分享!

通過在函數内部加 print 列印的方式,對比分析之後确認是 offset 計算不正确,最後我意外發現了 OpenHarmony 的【third_party_libunwind】有修改過 build-id。

經過檢視 pr 送出發現了以下關鍵代碼,原來是 oh 的編譯架構在編譯出的 elf 檔案頭增加了一個非标準的 note 段,mesa 使用标準的方式去解析 note 内容導緻偏移量計算出錯,需要處理一下偏移量問題。

然而 mesa3d 這個開源 gpu 驅動常年沒人維護,這個問題一直沒有暴露出來,這給我碰到了。。。同步修改之後解決調用崩潰問題。

小米6成功适配GPU經驗分享!

同時接口調用也能正常顯示了:

小米6成功适配GPU經驗分享!

但是當我進行移植第二步,CPU 合成+GPU 渲染時黑屏,無法顯示内容,又是一番加列印然後調試,最後發現關鍵代碼,freedreno 中有強制設定對齊。

小米6成功适配GPU經驗分享!

在 hilog 中發現 Assertion failed:

小米6成功适配GPU經驗分享!

檢視源碼發現 a5xx 系的頭檔案中有 pitch 的驗證,【&0x3f】相當于判斷能否被 64 整除。

小米6成功适配GPU經驗分享!

然後我往前找到 buffer 設定的某個地方嘗試着把 pich 強制 64 對齊,終于能顯示出圖像。

小米6成功适配GPU經驗分享!

不黑屏了,但是仍然顯示不正常,很明顯能感覺到是長度沒有對齊導緻錯位了。

小米6成功适配GPU經驗分享!

最終在 SIG-OpenGfxDrv 群裡的 lhl 大神指導下,修改 display 适配層中的 WIDTH_ALIGN 參數為 64,成功解決顯示問題。

小米6成功适配GPU經驗分享!
小米6成功适配GPU經驗分享!

确認 CPU 合成+GPU 渲染顯示能正常工作之後,啟用 GPU 合成+GPU 渲染,成功運作,小米 6 終于适配 GPU 成功。

樹莓派 4 和小米 6 的 GPU 适配,從代碼量來說,适配代碼真的很少,但是又異常困難,在此記錄一下我走過的坑,希望我走過的坑,後來者不用再掉下去。