RFC-0198:Mamama API

RFC-0198:Magma API
狀態已接受
區域
  • 圖形
說明

針對 GPU 和其他運算加速器設計的驅動程式 API。

Gerrit 變更
作者
審查人員
提交日期 (年-月-日)2022-09-19
審查日期 (年-月-日)2022-11-01

摘要

Magma 是 Fuchsia 的 GPU 驅動程式庫程式設計。也可以用來支援其他硬體運算加速器。本 RFC 是 Magma FIDL 通訊協定的 API 設計文件。

Magma 有兩個驅動程式庫元件:硬體專屬程式庫 (載入至每個應用程式的位址空間) 和 Magma 系統驅動程式庫程式 (與硬體介面)。兩個「驅動程式」之間的通訊是由 Magma 通訊協定定義。

在本文件中,「應用程式」一詞用來表示使用用戶端驅動程式庫程式公開的 API 的軟體元件。

提振精神

Magma API 可解決在 Fuchsia 系統上支援硬體加速圖形和運算 API (主要是 Vulkan) 的問題。其 API 概念並非專屬於 Vulkan,可減少支援其他用戶端 API 的摩擦,例如影片的 VA-API、OpenVX 和 OpenCL。

Magma 的設計目的,是供 Vulkan API 實作項目使用。Vulkan 是 Fuchsia SDK 中提供的 C 樣式 ABI。這些實作項目 (「ICD」) 通常由硬體供應商開發,因為加速器硬體龐大且複雜,建構實作項目需要具備硬體程式設計的詳細知識。

由於應用程式可能會直接使用 Vulkan,ICD 是系統提供的程式庫,但無法存取硬體。使用 Magma 時,ICD 可能會與加速器硬體介接,以滿足 Vulkan API 的要求,而這項要求主要包括執行用戶端定義的程式。

Magma 系統驅動程式 (「MSD」) 會在硬體上排程及執行用戶端要求,實作此通訊協定的伺服器端。因此,Magma 旨在連結 ICD 和 MSD,扮演與 Linux 上的 DRM (Direct Rendering Manager) 類似的角色。

Magma 的目標是務實地盡量減少 API 中供應商專屬層面的程度。這樣一來,您就能更輕鬆地推論 API 安全性,並便於對驅動程式進行安全性稽核。

與 Linux 常見的情況不同,Magma 並未讓每個 GPU 供應商設計自己的 ICD-MSD 介面,而是提供一組核心 API 功能和方法,以滿足常見需求。此外,Magma 還可在必要時允許供應商專屬的查詢和指令結構。Magma 定義中不包含供應商專屬資訊,但在驅動程式庫專屬說明文件中會加以說明。

不支援顯示器硬體。

目前有三個正式版驅動程式使用 Magma API。由於 API 無法在 Fuchsia SDK 中使用,因此這些用戶端驅動程式的建構和發布程序相當複雜。

針對目前所有情況,我們都會使用用戶端程式庫,方便整合 C 程式碼基礎 (C 是 Mesa 中提供許多開放原始碼圖形驅動程式的首選語言),並提供虛擬化的方便抽象層。我們日後會審查用戶端程式庫,並考慮是否納入 SDK。

相關人員

協助人員:

審查者:

jbauman@, rlb@:硬體圖形

諮詢:

API 委員會

社會化:

設計

Magma 有三個通訊協定,定義如下:

https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/sdk/fidl/fuchsia.gpu.magma/magma.fidl

部分名稱會附有數字字尾 (例如 BufferRangeOp2);這個數字是協定演進過程的詳細資料,可以忽略。

  1. 裝置

在 Fuchsia 啟動序列期間,系統會為每個可加速圖形和/或運算的實體裝置,例項化 Magma 系統驅動程式庫。有了適當的應用程式權限,用戶端就能掃描是否有一個或多個「gpu」類別裝置,並開啟這些裝置。您可以透過裝置通訊協定執行同步查詢,取得有助於應用程式決定要與哪些實體裝置搭配使用,以及搭配哪些設定的參數。查詢參數也可用於決定哪些類型的 ICD 與各 GPU 裝置相容。特定驅動程式庫和裝置通訊協定的確切行為取決於這些查詢參數。

當應用程式宣告其意圖要與特定實體裝置搭配使用時,就會建立與 Magma 系統驅動程式庫的連線。舉例來說,在 Vulkan 中,使用實體裝置的意圖會透過呼叫 vkCreateDevice() 表示。此連線可建立用戶端驅動程式庫和系統驅動程式庫之間所有後續通訊的基礎。

連線包含兩個管道。主要管道用於主要通訊協定,主要用於用戶端-伺服器方向,而其他管道則用於伺服器傳送至用戶端的通知。

  1. Primary

主要通訊協定包含少數核心功能,這些功能是透過前饋設計實作。錯誤會觸發「Epitaph」訊息,接著關閉連線管道。

a) 匯入共用資源、緩衝區和事件 (ImportObject、ReleaseObject)

緩衝區是 Zircon VMOs 支援的共用記憶體物件。在 API 預期使用信號量時,可使用 Zircon 事件進行同步處理。

物件是由用戶端分配,並由其 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 會傳送內嵌指令。如果驅動程式庫定義了分割指令的方式,單一管道訊息中可能會包含多個指令。目前每則訊息的命令位元組數量上限為 2k,這項任意限制至今運作良好,但無法有效運用完整的管道訊息大小。系統會提供信號量,可用於等待或傳送信號,具體取決於相關聯的指令資料。

日後提交指令時,請考量以下事項:使用 fuchsia.mem.Data 搭配暫時性 VMOs,或 Linux 的「io_uring」等模型:https://en.wikipedia.org/wiki/Io_uring

e) 流量控制

為避免用戶端將過多訊息推送至主要管道,並避免緩衝區物件在主要管道中待匯入時過度使用記憶體,裝置通訊協定會發布最大值,而主要通訊協定則會要求用戶端保留計數,並延遲傳送訊息,以便將這些計數保持在低於發布最大值的情況。伺服器會提供事件訊息,通知用戶端何時可能減少計數。

f) 效能計數器

主要通訊協定會公開多個 API,專門用於與硬體計數器互動,這對應用程式而言至關重要,因為應用程式必須深入瞭解在加速器硬體上執行的程式行為和效能特徵。

  1. 通知

通知管道用於只在反向 (伺服器-用戶端) 方向傳送的訊息,通常是回應指令完成的情況。通知訊息的內容通常因供應商而異,因此已定義空白通訊協定。

與主要管道分開的通知管道可讓用戶端更輕鬆地處理通知事件,例如用戶端可能會使用專用執行緒。在主要管道上,用戶端呼叫可以來自多個執行緒,其中沒有任何迴圈會在非同步調度器中進行輪詢,而且我們不想將這些呼叫代理至主要管道,以免影響效能。這會導致讀取非同步事件的難度提高 (除了流程控制事件,因為這類事件只需要在傳送訊息時讀取)。

未知

目前有四個支援的 Magma 驅動程式 (其中三個已投入生產),另外兩個則已完成原型設計。每個額外 Magma 驅動程式庫都會提供額外洞察資料,說明 Magma 通訊協定是否適合取代各種現有的 Linux 用戶端驅動程式庫程式-核心驅動程式介面。新增對電腦級 GPU 的支援,可確保核心 API 與各種硬體相容。

需要改善的 API 領域大多是指令執行和通知處理。

我們非常歡迎 API 委員會提供意見回饋,特別是下列主題:

a) 這些 API 與其他 Fuchsia API 有何相似之處或不同之處? b) 有沒有機會讓 API 更能因應未來需求? c) 您對 Fuchsia 的 io_uring 模型有何看法?

Google 的領域專家已簡要審查這個 API,但如果能由 Google 的其他專家/其他相關團隊進行更徹底的審查,或許會更有幫助。

成效

裝置通訊協定包含同步方法,但這些方法應僅用於應用程式的設定階段。主要通訊協定包含非同步方法,且指令完成狀態會透過通知管道以非同步方式傳回。

大部分資料都會在 VMOs 中共用,因此資料複製作業會降到最低。建立和對應緩衝區的速度可能較慢,但如果應用程式設計良好 (例如執行記憶體子分配),則這些作業應很少發生。

在大多數情況下,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 通常不會重複。

效能計數器事件可用於判斷系統上其他工作負載的詳細統計資料,這些資料可用於記錄其他程序的運作情形。因此,這些 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 相容性測試。在 Magma 機器學習驅動程式庫程式上執行 OpenVX 相容性測試。

請注意,在建構 Magma 驅動程式庫時,開發人員必須先建構功能性 Magma 系統驅動程式庫,實作 Magma 通訊協定的伺服器端,才能測試使用 Magma API 的用戶端驅動程式庫程式碼。

說明文件

文件會與 FIDL 定義內嵌。

缺點、替代方案和未知事項

這項設計與 Vulkan 同步,旨在盡量減少驅動程式庫額外負擔,並盡量提升系統圖形效能。此設計的缺點是,在安全性方面,它在很大程度上依賴硬體,而其他設計可能會嘗試提供用戶端指令的驗證。不過,驗證作業相當複雜且不完美,而且可能會導致效能大幅降低。

既有技術與參考資料

Linux GPU 驅動程式開發人員指南:https://www.kernel.org/doc/html/v4.18/gpu/index.html