| RFC-0198:Magma API | |
|---|---|
| 狀態 | 已接受 |
| 區域 |
|
| 說明 | GPU 和其他運算加速器的驅動程式 API 設計。 |
| Gerrit 變更 | |
| 作者 | |
| 審查人員 | |
| 提交日期 (年-月-日) | 2022-09-19 |
| 審查日期 (年-月-日) | 2022-11-01 |
摘要
Magma 是 Fuchsia 的 GPU 驅動程式庫程式設計。還可用於支援其他硬體運算加速器。本 RFC 是 Magma FIDL 通訊協定的 API 設計文件。
Magma 有兩個驅動程式庫元件:載入每個應用程式位址空間的硬體專屬程式庫 (「用戶端驅動程式庫程式」,有時稱為「可安裝的用戶端驅動程式庫」或「ICD」),以及與硬體介接的 Magma 系統驅動程式庫。兩個「驅動程式」之間的通訊是由 Magma 通訊協定定義。
本文中的「應用程式」是指使用用戶端驅動程式庫程式公開 API 的軟體元件。
提振精神
Magma API 解決了在 Fuchsia 系統上支援硬體加速圖形和運算 API (主要是 Vulkan) 的問題。其 API 概念並非專為 Vulkan 設計,因此可減少支援其他用戶端 API (例如 VA-API for video、OpenVX 和 OpenCL) 時的摩擦。
Magma 的設計用途是供 Vulkan API 的實作項目使用。Vulkan 是 Fuchsia SDK 中提供的 C 樣式 ABI。這些實作 (「ICD」) 通常由硬體供應商開發,因為加速器硬體龐大而複雜,且建構實作需要詳細的硬體程式設計知識。
由於應用程式可能會直接使用 Vulkan,ICD 是系統提供的程式庫,但無法存取硬體。ICD 可透過 Magma 與加速器硬體介接,滿足 Vulkan API 的需求,主要包括執行用戶端定義的程式。
Magma 系統驅動程式 (「MSD」) 會排定及執行硬體上的用戶端要求,藉此實作這個通訊協定的伺服器端。因此,Magma 的用途是連結 ICD 和 MSD,扮演類似於 Linux 上 DRM (直接算繪管理工具) 的角色。
Magma 的目標是盡可能減少 API 中供應商專屬的層面。這樣比較容易推斷 API 安全性,並方便稽核驅動程式的安全性。
Magma 提供一組核心 API 功能和方法,通常是必要項目,而且在必要時,Magma 允許廠商專屬的查詢和指令結構,因此 GPU 廠商不必設計自己的 ICD-MSD 介面 (Linux 上常見的情況)。Magma 定義中不包含供應商規格,但驅動程式庫專屬說明文件會說明這些規格。
不支援螢幕硬體。
目前有三個正式版驅動程式使用 Magma API。由於 Fuchsia SDK 不提供 API,因此這些用戶端驅動程式的建構和發布程序相當複雜。
在所有目前案例中,使用的用戶端程式庫可簡化與 C 程式碼庫的整合 (C 是 Mesa 的偏好語言,提供許多開放原始碼的圖形驅動程式),並為虛擬化提供便利的抽象層。我們會在日後審查用戶端程式庫,並可能將其納入 SDK。
利害關係人
協助人員:
不適用
審查者:
jbauman@, rlb@:硬體圖形
已諮詢:
API 委員會
社交:
不適用
設計
Magma 有三種通訊協定,定義於:
https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/sdk/fidl/fuchsia.gpu.magma/magma.fidl
部分名稱會加上數字後置字元 (例如 BufferRangeOp2),這些數字代表通訊協定的演進細節,可以忽略。
- 裝置
在 Fuchsia 開機順序期間,系統會為每個可加速圖形和/或運算的實體裝置,例項化 Magma 系統驅動程式庫。只要具備適當的應用程式權限,用戶端就能掃描一或多個「gpu」類別裝置是否存在,並開啟這些裝置。您可以透過裝置通訊協定執行同步查詢,取得有助於應用程式判斷要使用哪個實體裝置和設定的參數。查詢參數也用於判斷哪些類型的 ICD 與各個 GPU 裝置相容。驅動程式庫和裝置專屬通訊協定的確切行為,取決於這些查詢參數。
應用程式宣告要與特定實體裝置搭配運作時,系統會建立與 Magma 系統驅動程式庫的連線。舉例來說,在 Vulkan 中,如要使用實體裝置,請呼叫 vkCreateDevice()。這個連線會成為用戶端驅動程式庫和系統驅動程式庫之間所有後續通訊的基礎。
連線包含兩個管道。主要管道用於主要通訊協定,大多是從用戶端到伺服器,另一個管道則用於從伺服器到用戶端的通知。
- Primary
主要通訊協定包含少量核心功能,並採用前饋設計。發生錯誤時,系統會觸發墓誌銘訊息,然後關閉連線管道。
a) 匯入共用資源、緩衝區和事件 (ImportObject、ReleaseObject)
緩衝區是由 Zircon VMO 支援的共用記憶體物件。Zircon 事件可用於 API 預期有信號燈的同步作業。
物件由用戶端分配,並以 KOID (核心物件 ID) 參照。用戶端分配是前饋設計的選擇。這項假設的前提是所有緩衝區都來自系統記憶體,這在行動裝置類別的硬體中通常是事實。
未來支援具備專用記憶體的桌機級 GPU 時,可能需要變更 API。
日後支援外部 Vulkan 時間軸信號時,可能需要匯入新型核心物件。
b) 對應緩衝區 (MapBufferGpu、UnmapBufferGpu、BufferRangeOp)
緩衝區必須對應至裝置位址空間,硬體才能存取。每個用戶端連線都會獲得私人 GPU 位址空間 (請參閱「安全性與隱私權」),因此 Magma 會預期由用戶端執行裝置位址空間管理作業。
對部分驅動程式而言,MapBufferGpu 可能表示裝置 MMU 中的頁面表格填入作業,而對部分驅動程式而言,則可透過緩衝區範圍作業明確控制頁面表格填入作業。
頁面表填入的資料會隱含緩衝區頁面的提交。任何用戶端頁面取消認可作業都應透過適當的取消填入作業,與系統驅動程式協調。
c) 建立執行作業結構定義 (CreateContext、DestroyContext)
如要在硬體上執行工作,需要有內容。內容包含所有必要的硬體狀態,可讓多個內容切換至硬體,並由 Magma 系統驅動程式庫程式排定執行時間。Magma 支援每個連線的多個內容,因此多個內容可以共用單一位址空間。
d) 執行指令 (ExecuteCommand、ExecuteImmediateCommands)
命令包含供應商專屬資料,可修改硬體狀態,並在加速器的運算核心上觸發程式碼執行作業。應用程式會將程式碼提供給用戶端驅動程式庫,通常採用與機器無關的格式,例如 SPIR-V。用戶端驅動程式庫必須將程式碼轉譯為加速器硬體可解讀的機器層級指令。
Magma 提供兩種介面來執行指令:
ExecuteCommand 會假設程式碼和相關聯的資源都包含在共用緩衝區中。同步處理作業會提供等待信號燈清單,這些信號燈必須在排定工作前發出信號,以及在指令完成時發出信號的信號燈。
ExecuteImmediateCommands 會內嵌傳送指令。如果驅動程式庫定義了分割指令的方式,單一管道訊息中可能會包含多個指令。目前每則訊息的指令位元組數上限為 2,000,這個任意設定的限制至今運作良好,但無法有效運用完整管道訊息大小。系統會提供信號燈,可視相關聯的指令資料用於等待或發出信號。
未來提交指令時,可考慮使用具有暫時 VMO 的 fuchsia.mem.Data,或 Linux「io_uring」等模型:https://en.wikipedia.org/wiki/Io_uring
e) 流量控制
為避免用戶端將過多訊息推送至主要管道,以及避免主要管道中待匯入的緩衝區物件過度使用記憶體,裝置通訊協定會發布最大值,而主要通訊協定會規定用戶端保留計數,並延遲傳送訊息,以確保計數低於發布的最大值。伺服器會提供事件訊息,在計數可能遞減時通知用戶端。
f) 效能計數器
主要通訊協定會公開多項 API,專門用於與硬體計數器互動,這對應用程式深入瞭解行為和效能特徵至關重要,有助於在加速器硬體上執行程式。
- 通知
通知管道用於僅以反向 (伺服器到用戶端) 傳送的訊息,通常是為了回應指令完成。通知訊息的內容通常會因供應商而異,因此我們定義了空白通訊協定。
與主要管道分開的通知管道可讓用戶端更輕鬆地處理通知事件,例如用戶端可以使用專屬執行緒。在主要管道上,用戶端呼叫可來自多個執行緒,其中沒有任何迴圈在非同步調度器中輪詢,且基於效能考量,我們不希望將這些呼叫 Proxy 到主要管道。這使得讀取非同步事件變得困難 (除了只需要在傳送訊息期間讀取的流程控制事件)。
不明
目前支援四個 Magma 驅動程式 (三個已投入生產),另外兩個則已完成原型設計。每項額外 Magma 驅動程式庫的啟動作業,都能提供額外洞察資訊,瞭解 Magma 通訊協定是否適合取代各種現有的 Linux 型用戶端驅動程式庫程式核心驅動程式庫程式介面。新增對桌機級 GPU 的支援,可確保核心 API 與各種硬體相容。
可改善的 API 領域主要有:指令執行和通知處理。
API 委員會的意見回饋對下列主題特別有幫助:
a) 這些 API 與其他 Fuchsia API 相似或相異之處為何? b) 是否有機會讓這些 API 更能因應未來變化? c) 您認為 io_uring 模型對 Fuchsia 是否實用?
Google 的網域專家已簡要審查過這項 API,但如果能進行更詳盡的審查 (包括其他專家/Google 其他相關團隊),應該會很有幫助。
效能
裝置通訊協定包含同步方法,但這些方法只能在應用程式的設定階段使用。主要通訊協定包含非同步方法,且指令完成作業會透過通知管道以非同步方式傳回。
大部分資料都是在 VMO 中共用,因此可盡量減少資料複製作業。建立及對應緩衝區可能很慢,但假設應用程式設計良好 (例如執行記憶體子配置),這些作業應該很少發生。
在大多數情況下,我們測得 Fuchsia 上的 Magma 驅動程式效能,與在相同硬體上執行的 Linux 相同用戶端驅動程式庫程式碼庫效能相當。
人體工學、可用性
API 設計與現有的 Linux 型用戶端驅動程式庫 - 核心驅動程式介面類似,但分配作業會盡可能在用戶端執行。
我們認為 API 的語意相當直覺,因為 API 已使用兩年,期間經過修訂,目前正在為不同供應商的三個驅動程式提供服務。
日後,Vulkan 時間軸信號可能需要新的核心物件;如果需要,可能會新增至 ObjectType,且在執行 API 中以 KOID 指定信號時,可能會參照「時間軸」物件,而非事件。
回溯相容性
在預期未來可擴充的各種位置,都已使用 FIDL 表格。
安全性
應用程式可透過 Magma API 在重要的共用系統資源上執行未驗證的程式,因此安全性是重要的主題。安全性審查已於 2021 年 6 月完成:請參閱 https://fxbug.dev/42146613。
用戶端可能會提交長時間執行的程式,導致其他用戶端無法存取硬體。Magma 系統驅動程式可確保長時間執行的程式會以可接受的系統中斷程度終止,與其他系統的行為類似。
圖像記憶體可能包含密碼等機密資訊,因此用戶端記憶體存取權必須受到隔離。用戶端連線會透過獨立的硬體位址空間彼此隔離,也就是說,用戶端的程式只能存取已匯入連線的記憶體緩衝區 (由用戶端建立,或從外部明確接收)。這種方法可能會受到硬體安全漏洞影響。
用戶端數量可能超過硬體提供的位址空間數量。MSD 應排定這些資源的存取時間,或完全拒絕用戶端存取。
基於效能考量,驗證用戶端指令和程式並不實際,因此硬體應具備復原能力。
隱私權
查詢 DEVICE_ID 取得的裝置 ID 通常不會是專屬 ID。
效能計數器事件可用於判斷系統上其他工作負載的詳細統計資料,進而指紋識別其他程序正在執行的作業。因此,這些 API 比大多數 Magma API 受到更多限制,且僅限於可存取 /dev/class/gpu-performance-counters 裝置的程序集。
測試
以下提供 API 的簡易功能測試:
https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/src/graphics/lib/magma/tests/integration/test_magma_fidl.cc
如果不納入硬體規格,就難以編寫更精密的測試來運用 Magma API。用戶端驅動程式庫程式碼包含這些硬體程式設計詳細資料,因此測試套件會運用用戶端驅動程式公開的 API,這點至關重要。
系統會在持續整合中測試兩個正式版 Magma 驅動程式的 Vulkan 一致性測試。OpenVX 一致性測試會在 ML 的 Magma 驅動程式上執行。
請注意,建構 Magma 驅動程式庫時,開發人員必須先建構實作 Magma 通訊協定伺服器端的 Magma 系統驅動程式庫,才能測試使用 Magma API 的用戶端驅動程式庫程式碼。
說明文件
文件與 FIDL 定義內嵌。
缺點、替代方案和未知事項
這項設計與 Vulkan 同步,目的在於盡量減少驅動程式庫負擔,並盡可能提升系統的圖形效能。這項設計的缺點是安全性在很大程度上取決於硬體,而替代設計可能會嘗試驗證用戶端指令。不過,驗證程序複雜、不完美,而且可能需要付出高昂的效能代價。
既有技術和參考資料
Linux GPU 驅動程式開發人員指南:https://www.kernel.org/doc/html/v4.18/gpu/index.html