天天看點

Linux Graphics 周刊(第 4 期)

(2020.08.31 ~ 2020.09.06)

導讀
  • LPC2020: Linux kernel 添加 Rust 支援
  • LPC2020: 隻需要一筆 Patch,Android AOSP 就可以在 kernel-5.9 主線上運作
  • drm/prime: sg_table nents 漏洞修複
  • drm/vc4: 為樹莓派4添加 Display 驅動
  • RenderEngine: bugfix for alpha blending func
  • MESA 釋出 20.2.0-rc4
  • ACO:為 AMD ACO Back-End 添加詳細的說明文檔
  • Weston 9.0.0 釋出
  • Collabora: 使用 Perfetto 抓取 Panfrost performance counters 資訊
  • GPU 壓縮紋理格式詳解

一、Linux

1. LPC2020: Linux kernel 添加 Rust 支援

之前曾在我的星球中報道過關于《Linux kernel 是否要支援 Rust 語言?》 以及《Linus Torvalds 首次回應對 kernel 添加 Rust 的看法》的消息,而上周線上上舉辦的 Linux Plumbers Conference 2020 則更進一步的讨論了這一話題。

回顧之前關于 kernel 支援 rust 的消息,Rust 語言由 Mozilla 開發,最早釋出于 2014 年 9 月。該語言最大的特點沒有垃圾回收,能夠確定記憶體安全和線程安全,它的長遠目标是取代 C 語言。Google 工程師 Nick Desaulniers (因向核心添加 LLVM Clang 支援而聞名)曾在7月份向核心社群發送郵件讨論過該話題,并一度引起社群開發者的高度關注。而且很快,Linus 也回應了針對該話題的個人看法,首先他并沒有直接否定該想法,反而是提倡在預設情況下應該開啟該 feature,以確定該 feature 能被更充分的測試。當然該 feature 最好做成自适應的,如果在系統上檢測到了 Rust 編譯器,那麼 Kconfig 就可以啟用 Rust 支援,并建構用 Rust 編寫的核心代碼。

而本次 LPC 2020 大會上,Nick 則更進一步讨論了該話題的實作方案。首先他聲明添加 Rust 的目的不是為了重寫那 2500 萬行 kernel 代碼,C 語言仍然是核心代碼的第一實作語言,而 Rust 隻是用于後續新功能添加的代碼,尤其是那些特變關注記憶體安全、多并發性問題的代碼,以及那些更适合使用 Rust 來實作的技術領域。除此之外,他們還讨論了是否應該使用 Rust’s Cargo 來作為 Kbuild/Kconfig 中的建構工具,以及如何使用 Cargo 的離線模式來確定所有的 Rust 代碼都在 kernel in-tree 中維護(因為 Cargo 預設是從外部倉庫來拉取代碼的)。該話題最終并沒有給出一個明确的結論,而這僅僅隻是一個開放式的線上讨論會,而且讨論并沒有結束,該話題會在核心郵件清單中持續讨論下去。

如下 Github 為一個 Rust 版的 kernel module 實作,感興趣的同學可以參考一下:

https://rust-for-linux.github.io/

LPC 2020 大會關于 Rust 讨論的 PPT 文檔:

Barriers to in-tree Rust

更多詳細内容:

  1. Supporting Linux kernel development in Rust
  2. Linux Developers Continue Evaluating The Path To Adding Rust Code To The Kernel

2. drm/prime: sg_table nents 漏洞修複

Marek Szyprowski (Samsung) 早前在重構 Exynos DRM GEM 代碼時,就發現了 DRM Framework 中普遍存在的一個高風險漏洞,無論是 drm prime API 還是 Vendor 廠商自己實作的 prime 代碼,都錯誤的使用了 sg_table 中的 nents 變量,這可能會引起 DMA 記憶體通路異常。

首先,DMA-Mapping 文檔中有明确說明,dma_map_sg() 函數傳回的 nents 值有可能會比傳進去的 origin_nents 參數值小,而後續使用 dma_sync_sg_for_() 以及 dma_unmap_sg() 時,應該使用 origin_nents 作為參數。因為某些情況下,實體連續的 page 會被聚合成一個 nents,這樣新生成的 nents 值就會比原始的 nents 值小。但 Marek 發現,在 DRM 驅動代碼中,大家都清一色的使用 sg_table->nents 來作為 dma_sync_sg_for_() 和 dma_unmap_sg() 參數使用,而且最關鍵的是,這種錯誤的用法在大多數情況下都沒有發生什麼異常!正确的使用方法應該是使用 sg_table->origin_nents 作為參數來調用 dma_sync_sg_for_*() 和 dma_unmap_sg() 函數。

為此,它送出了一組長達32筆 patch 的送出,用于修改 drm prime 架構和 Vendor 廠商對 sg_table->nents 引用的代碼,以確定程式的健壯性。該 patch 目前已經進行到第9輪 review 階段,看起來已經很有希望在9月底合入 drm-misc next 分支。

詳情:[PATCH v9 00/32] DRM: fix struct sg_table nents vs. orig_nents misuse

3. drm/vkms: 一個 gamma_set 接口引發的讨論

Sidong.Yang 向社群送出了一筆 patch,用于在 vkms 驅動的 vkms_crtc_funcs 中添加 gamma_set 回調接口,并且采用 drm_atomic_helper_legacy_gamma_set() 函數來實作。他送出該 patch 的理由是:現有的 vkms 驅動不支援 gamma 操作,這會導緻 IGT 測試中的 kms_plane (pixel-format-pipe-A-plan) 測試項 fail,因為該測試 case 中調用了 drmModeCrtcSetGamma() 函數。

而 Simon Ser 則認為這樣的 patch 顯然不合理:首先,這應該是 IGT 測試 case 的問題,而不應該是 vkms 驅動的問題,因為 vkms 驅動本身不支援 gamma 操作,那麼上層測試程式就不應對該驅動發起 gamma 調用的操作。其次,該 patch 給 vkms 添加了支援 gamma 的能力,但是卻沒有在任何地方使用上層傳下來的 gamma 參數,這就沒什麼意義。

經過一番讨論後,最終的結論是:IGT 測試 case 添加 gamma 操作的目的其實并非真正想要執行 gamma 相關操作,而是為了友善 C8 格式的 CRC 校驗處理位元組序的問題而使用了 gamma LUT 這段記憶體。是以應該針對 C8 格式的 plane 單獨設定一個 test case,這樣就可以将多餘的 gamma LUT 删掉了。

詳情:[PATCH] drm/vkms: add support for gamma_set interface

4. drm/i915: 優化 DisplayPort DFP 的處理

Ville Syrjala (Intel) 正在為 Intel 915 DisplayPort 驅動優化 DFP (Downstream Facing Port) 的處理流程。為了讓 DFP 的處理過程更加順暢,Ville 為 drm/dp 架構新增了如下 feature:

  • 添加 DP 1.3 & 1.4 新增寄存器的宏定義
  • 完善 DPCD DFP capabilities
  • 添加 helper 函數用于判斷目前 downstream facing port 的類型
  • 添加 helper 函數用于擷取 TMDS clock 的能力限制
  • 添加

    drm_dp_downstream_mode()

    函數用于根據 DPCD 來擷取目前 sink 所支援的 display mode
  • 添加 helper 函數用于處理 DFP YCbCr 4:2:0 格式

詳情:[PATCH v2 00/18] drm/i915: Pimp DP DFP handling

5. drm/vc4: 為樹莓派4添加 Display 驅動

  • 樹莓派4:開源開發闆,采用博通BCM2711 SoC,CPU 4核64bit Cotex-A72,GPU 采用博通自研 VideoCore VI,支援 OpenGLES 3.x。
  • VC4: 博通 GPU VideoCore IV 驅動在 drm 和 mesa 中的名字(羅馬數字 IV 是 4 的意思)
  • V3D: 博通 GPU VideoCore VI 驅動在 drm 和 mesa 中的名字(羅馬數字 VI 是 6 的意思)

目前 broadcom 在 drm 目錄下存放着 vc4 和 v3d 兩個目錄,vc4 既包含 Display 驅動也包含 GPU 驅動,主要用于樹莓派3及之前的 SoC;而 v3d 則隻包含 gpu 驅動,專用于樹莓派4。由于 vc4 和 v3d 的 Display 硬體差異不大,為了讓樹莓派4最大化利用 vc4 現有的 Display 驅動,Maxime Ripard (DRM-Misc Maintainer) 半年前就向社群送出了一組長達 80 筆 patch 的 VC4 KMS 送出,而上周已經更新到第5輪 review 了。這組 patch 除了對原來 VC4 KMS 相關代碼的重構外,還新增了 HDMI 的支援,因為樹莓派4 SoC 内部有2個 HDMI 控制器。同時 Maxime 還修複了一些 4K 顯示以及雙屏輸出的 bug,如果沒有什麼大的問題,該 patch 有望合入 linux-5.10 主線。

詳情:[PATCH v5 00/80] drm/vc4: Support BCM2711 Display Pipeline

二、AOSP

1. LPC2020: 隻需要一筆 Patch,Android AOSP 就可以在 kernel-5.9 主線上運作

Satya Tangirala(Google)和 Sumit Semwal(kernel ION/DMA-BUF/Heap/dma-fence Maintainer,Linaro)在上周的 Linux Plumbers Conference 2020 線上大會上為大家介紹了 Android 在最新的 Linux Kernel 主線上的開發進展。他們宣稱,隻需要借助一筆 patch,Android AOSP master 分支就可以直接在 Linux-5.9 mainline 上運作了,當然前提是你的 SoC 驅動都已經 upstreaming 到 kernel-5.9 主線中了。而需要額外打上的那筆 patch 則其實是 Android kernel 由來已久的 “anonymous VMA naming support” patch,該 patch 的曆史可以追溯到 2013 年,是 AOSP 啟動所必須的 patch,一直都隻在 Android 自己的 kernel 倉庫中維護,從未進入過社群。

雖然 Google 聲稱隻需要一筆 patch,但由于大部分的移動手機廠商(或晶片廠商)并沒有将自己完整的 SoC 驅動都 Upstream 到核心主線中,實際上對于大多數的移動平台來說,它們需要的其實不隻一筆 anonymous VMA patch。

更多詳細内容:

  1. Android AOSP Can Boot Off Mainline Linux 5.9 With Just One Patch
  2. LPC2020 PPT:State of Android on Mainline kernels

2. RenderEngine: bugfix for alpha blending func

預設情況下,GPU 合成輸出的 Alpha 為 Premultiplied,且為 Coverage blending mode。如果這時候再和其它 Device 的 layer 做合成,使用現有的 RenderEngine blend 函數,GPU 的 layer 将會直接覆寫 Device 的 layer,這是不正确的。

修改前的代碼,當 alpha 為 premultiplied 時,GLES 後端使用的 blending 函數為 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA),該函數對應的公式如下:

out.rgba = src.rgba * src.rgba + dst.rgba * (1 - src.rgba)

當 alpha 不為 premultiplied 時,則使用 glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA),對應的公式如下:

out.rgba = dst.rgba * (1 - src.rgba)

這是不正确的,正确的 alpha blending 公式應該如下:

out.a = src.a + dst.a * (1 - src.a)

out.rgb = ((src.rgb * src.a + dst.rgb * dst.a * (1 - src.a)) / out.a

  • 當使用 coverage blend mode:

out.a = src.a + dst.a * (1 - src.a)

out.rgb * out.a = (src.rgb * src.a + dst.rgb * dst.a * (1 - src.a)

  • 當使用 premultiplied blend mode:

out.a = src.a + dst.a * (1 - src.a)

out.rgb = src.rgb + dst.rgb * (1 - src.a)

詳情:aosp/native[master]: [RenderEngine] correct alpha blending func

3. ashmem: 為 ASharedMemory_create() 添加 CLOEXEC flag

熟悉 fork() 的同學都知道,當父程序 fork() 子程序後,子程序就繼承了父程序所有的堆&棧資料,包括已 open 的 fd 資源。如果後續子程序通過調用 exec() 來執行新的可執行程式的話,新的可執行程式将會徹底覆寫原子程序的所有代碼段和資料段,那麼原來子程序中被打開的 fd 就無法被 close,于是出現 fd 洩露。為了防止這類問題的發生,可以事先在 open() 某個檔案時傳入

O_CLOEXEC

flag 來告訴該程序在執行 exec() 後就自動關閉之前已打開的 fd。

Android share memory 就存在這樣的 fd 洩露風險,為此需要在執行 memfd_create() 時傳入 MFD_CLOEXEC flag 來避免此類問題的發生。

詳情:

  1. aosp/core[master]: ashmem: ensure ashmem fds are CLOEXEC.
  2. aosp/native[master]: Document that ASharedMemory_create fds may or may not be CLOEXEC

三、Mesa

1. MESA 釋出 20.2.0-rc4

上周 Mesa 釋出了 20.2.0-rc4 版本,同時也将是 20.2.0 的最後一個候選版本,Dylan Baker(Mesa 版本維護者,Intel)使用“pretty tame”來形容此次版本的釋出。如果不出意外,下周應該可以正式 release Mesa-20.2.0 版本。

此次釋出的 20.2.0-rc4 主要包含如下修改(Vendor修改不計算在内):

  • egl/x11_dri3: 實作了 EGL_KHR_swap_buffers_with_damage 接口
  • bugfix for OpenBSD
  • gallium/dri2: 修複了 YUYV & UYVY plane count 誤報的問題
  • vulkan/wsi/x11: 添加 sent image counter
  • vulkan/wsi/x11: wait for acquirable images in FIFO mode
  • vulkan: 記憶體洩露 bugfix

詳情:[ANNOUNCE] mesa 20.2.0-rc4

2. ACO:為 AMD ACO Back-End 添加詳細的說明文檔

ACO (AMD Compiler) 是 Valve 公司為 AMD GPU 的 Mesa 開源 Vulkan 驅動 “RADV” 專門開發的 Shader 編譯器,旨在提供更快的編譯速度,以及生成更适合遊戲運作的優化代碼。目前 RADV 使用 LLVM 作為 Shader 編譯器後端,而在即将到來的 Mesa-20.2 中,ACO 将作為 RADV 的預設編譯器後端而被使能。

9月1日,Mesa 社群合入了一份關于 ACO 的 README 文檔,該文檔較長的描述了:

  • ACO 是什麼?
  • 為什麼要開發這個編譯器?
  • 它的控制流程是怎樣的?
  • 它的編譯過程是如何工作的?
  • 它都支援哪些 Shader Stage?
  • 如何 debug?

該文檔寫的非常詳細,可以作為 ACO 使用的參考手冊。

詳情:aco: Add README which explains about what ACO is and how it works

四、Wayland

Weston 9.0.0 釋出

9月4日,Wayland 社群釋出了 Weston 9.0.0 版本。Weston 作為 Wayland Compositor 的官方參考實作,旨在提供一個高效、邏輯清晰、功能簡單的 Linux 參考桌面。此次版本釋出主要包括如下内容:

  • 新增 Kiosk Shell,适用于隻有單個 UI 程序的全屏顯示需求
  • 優化了測試架構,新增 DRM 和 OpenGL 測試用例
  • 添加對 DRM panel orientation property 的支援
  • 其他 bugfix

詳情:[ANNOUNCE] weston 9.0.0

五、其它

1. Collabora: 使用 Perfetto 抓取 Panfrost performance counters 資訊

Perfetto 是 Google 去年新推出的一個開源性能分析工具,用于取代 systrace。它的功能遠比 systrace 強大,抓取 trace 的時間更長,抓取的資訊量更大,且提供了靈活的擴充接口,友善開發人員抓取自定義的資料資訊。

目前的 Perfetto 雖然也可以抓取 GPU 的資訊,但也隻限于 GPU 的頻率資訊,如果想要抓取更多 GPU 相關資訊,則隻能通過 Perfetto 的擴充功能進行抓取。

gfx-pps (Graphics Performance Producers) 是由 Collabora 公司開發的一款專門搜集 Graphics 性能資料的 Perfetto 擴充插件,它作為 client 程序将搜集到的 Graphics 性能資料發送給 Perfetto trace service。它是開源的,遵循 MIT license,源碼放在 freedesktop GitLab 上托管。目前 gfx-pps 主要搜集兩種 data source:一種是 Mali GPU 的 Performance Counters 資訊,另一種則是 Weston timeline 的 track events。

Collabora 官方專門發表了一篇關于 gfx-pps 的部落格,并描述了如何使用 gfx-pps 以及如何分析抓取的 graphics 性能資料,感興趣的同學請通路如下連結:

Panfrost performance counters with Perfetto

2. GPU 壓縮紋理格式詳解

如下兩篇文章詳細介紹了 GPU Compressed Texture Format 壓縮原理及其解壓方式,值得一看。

  1. Compressed GPU texture formats – a review and compute shader decoders – part 1
  2. Compressed GPU texture formats – a review and compute shader decoders – part 2