RFC-0205:Vulkan 載入器

RFC-0205:Vulkan 載入器
狀態已接受
領域
  • 圖形
說明

說明應用程式如何載入 Vulkan ICD 和層

問題
毛皮變化
作者
審查人員
提交日期 (年-月-日)2023-01-12
審查日期 (年-月-日)2023-01-12

摘要

此 RFC 說明 Fuchsia 上的軟體如何載入 Vulkan ICD圖層來執行硬體加速轉譯。

本文件中的系統大部分已實作,但 本文件可能包含我們打算在

提振精神

Vulkan API 提供 C 型介面,可供應用程式用於程式設計 搭配採用 Vulkan 的 Vulkan 函式的 Vulkan 應用程式介面 載入器,如以下說明:與 Vulkan 函式

本文件中的「應用程式」用於表示 。

Vulkan 載入器也負責載入可安裝的用戶端驅動程式 (ICD) 和 Vulkan 層,以及委派對 magma 或其他物件的存取權 代表 ICD 執行 GPU 指令所需的 API。

Vulkan ICD 是供應商專屬的共用程式庫,會載入至 能讓您使用 GPU 轉譯應用程式採用 Vulkan 需要特定機制,為 以及系統

Vulkan 層是共用程式庫,可修改或觀察 Vulkan API,透過擴增 Vulkan API 呼叫的調度鏈。可以 用於強化 Vulkan 功能,或代表 Vulkan 偵錯或剖析功能。

相關人員

講師:

rlb@

審查者:

cstout@ costan@ jhowarth@ msandy@ rosasco@ palmer@ wittrock@

諮詢:

社交功能:

設計已通過 Magma 團隊的審查。初期 本文件版本已與元件架構共用 並提供安全團隊諮詢時間

設計

Fuchsia 中的 Vulkan 載入器分為兩個部分: libvulkan.so 共用程式庫 以及由開發人員負責載入的載入程式服務 (vulkan_loader) 載入 ICD VMO 並轉移至 libvulkan.so。他們會透過 fuchsia.vulkan.loader.Loader 通訊協定。

libvulkan.so

Khronos 是 Vulkan API 的標準主體。他們提供了 都適用於 Linux 的載入器共用程式庫實作 Windows、macOS 及其他平台。Google 另外編寫了另一個載入程式 。

Fuchsia 載入器是以 Khronos 實作項目為基礎。程式碼位於 Fuchsia 存放區中的 third_party/Vulkan-Loader,但最終 模型會向上游當應用程式呼叫 vkCreateInstance 或其他列舉函式、載入器 讀取環境變數和 JSON 設定檔,藉此判斷 要使用的 ICD 和層集系統會從元件的 所以通常儲存在 套件中其他可能 從提供給元件的目錄功能載入 載入器設定 來使用這些目錄

正在載入 ICD

Vulkan 載入器啟動
流程

啟動時,libvulkan.so 會連線至 fuchsia.vulkan.loader.Loader 通訊協定。這個管道必須 在應用程式的整個生命週期內仍保持連線狀態。離開這個區域時 載入器呼叫可能會失敗。

這個長效連線會使元件架構無法重新載入,或是 在使用 Vulkan 的用戶端執行期間更新載入器。這是 這項做法能防止 Vulkan ICD 版本意外變更,因此是理想的做法 和載入器介面。只有部分通知 用於列舉擴充功能或其他執行個體屬性的 Vulkan 進入點 不接受任何類型的 context 引數;因此實作時 一些隱含的全域狀態

Vulkan 載入器
流程

系統會使用 fuchsia.vulkan.loader.Loader 通訊協定載入 ICD。載入器 使用 fuchsia.vulkan.loader/Loader.ConnectToManifestFs 方法 其中含有資訊清單檔案來說明所有相關 ICD;這個檔案系統看起來與 /usr/local/share/vulkan/icd.d 檔案系統請參閱「檔案系統提供」一文 該檔案系統的詳細資料

接著,載入器會使用 fuchsia.vulkan.loader/Loader.Get 方法取得 擷取與 ICD 對應的 VMO,dlopen_vmo 可載入至該區域 並從中取得 ICD 進入點這組 Vulkan 進入點 Fuchsia 與 Linux 相同,差別在於 Fuchsia 專用的擴充功能 。

用戶端元件也可封裝至軟體 ICD 實作,例如 SwiftShader.以 SwiftShader 為例,VK_ICD_FILENAMES 環境變數則可用於指定 manifest.json 插入 ICD系統會從 Vulkan 的 /pkg/lib 載入 ICD 共用資料庫 用戶端元件。

由於大部分的 ICD 不會儲存在套件中,因此會分別與 而且只能對 ABI 的 ABI 進行有限的假設 連結的應用程式他們實際可使用的介面是 列在 Fuchsia 系統介面中,但通常只會 允許使用有限的符號清單,這些符號必須來自 libc.solibzircon.so。建構 ICD 時,匯入的符號會 通過 Google Cloud 驗證 許可清單 確保 ICD 可以在多個版本的用戶端上載入 應用程式。日後這個許可清單可能會隨著密封的替換品而縮小

ICD 必須連線至外部通訊協定;尤其必須 連線至與硬體通訊的基礎裝置驅動程式。他們 您可能也想讀取供應商專屬的設定檔 發生錯誤。libc.so 會匯出多個符號來執行 I/O,但在實際運作時 基礎作業 (例如 open) 則是在 libfdio 中實作。此外, 如果沒有問題,就無法使用檔案系統連結 Zircon 管道 直接從 libfdio 匯出的其他符號。

為了讓 ICD 執行有限的 I/O,Vulkan ICD 新增了這些定義 API:

VkResult(VKAPI_PTR* PFN_vkOpenInNamespaceAddr)(const char* pName, uint32_t handle);
VKAPI_ATTR void VKAPI_CALL vk_icdInitializeOpenInNamespaceCallback(PFN_vkOpenInNamespaceAddr
open_in_namespace_addr);

ICD 應公開 vk_icdInitializeOpenInNamespaceCallback。在任一之前 系統會呼叫其他驅動程式函式,此函式將以 open_in_namespace_addr 回呼。ICD 可以傳送檔案名稱和 Zircon 管道用戶端端到這個回呼,即可依名稱連線至檔案系統節點。

這個函式可存取處理程序的傳入命名空間,因此 ICD 可以 讀取設定檔或連結至 fuchsia.logger.LogSinkfuchsia.tracing.provider.Registry。Vulkan ICD 可能包含全球狀態, 程序就是可代管多個子元件的執行元件 (或許是 使用虛擬機器或其他非處理程序機制來隔離元件), 執行元件必須確保提供給 ICD 的服務在 子項元件。舉例來說,如果有多個不受信任的子項元件 居中,執行元件不應轉送 fuchsia.tracing.provider.Registry 透過執行元件的子項元件 的信任感,因為元件可能會窺視所有 ICD 圖形活動。

open_in_namespace_addr 回呼特殊情況會存取 /loader-gpu-devices 路徑。系統會將該路徑的所有存取權轉送至檔案系統 使用 vulkan_loader 提供的 fuchsia.vulkan.loader/Loader.ConnectToDeviceFs 方法;讓 ICD 得以 連線至任何硬體專屬裝置驅動程式庫程式節點。ICD 的 zxio 或原始 FIDL 來掃遍檔案系統;請參閱檔案系統 提供該檔案系統的詳細資訊。

圖層通常會透過 SDK 發布,並從 整合成應用程式,因此可以依賴 SDK 中的軟體透過目錄載入的圖層 來自外部套件的功能應視同 ICD ABI 的縮寫

ICD 卸載/重新載入

目前無法卸載共用資料庫,因此所有 ICD 都會保留 都會產生這些檔案如要避免在建立容器時 新的 Vulkan 例項,載入器會保留所有 ICD 的無到期時間快取 已偵測到 (由共用資料庫的檔案名稱識別)。這個檔案名稱在 中是獨一無二的 前提是 vulkan_loader 連線保持運作。

載入器執行環境

Vulkan API 沒有非同步執行迴圈的概念,因此函式呼叫 必須從應用程式的角度執行同步完成。載入器 不會從應用程式接收 async_dispatcher_t*,也不允許 使用 libasync-default.so 的預設調度工具。它會自行建立 調度器和執行緒的內部。

元件的傳出目錄是由應用程式的程式碼代管,因此 載入器無法放入項目。這會限制與使用者互動的方式 其他元件該應用程式也不是平台規定 載入一次載入器的單一副本,不過目前所有應用程式都使用 「libvulkan.so」的副本,因為因為如此,所以在載入時刪除了重複資料。

根據預設,載入器會在 /vulkan-loader-configuration,降級為 /pkg/data。這些路徑可以是 就會被環境變數或覆寫層覆寫 與 Linux 上一樣

vulkan_loader

vulkan_loader」服務會負責判斷 ICD 的內容 載入這些元件並提供給應用程式託管在 /core/vulkan_loaderfuchsia.vulkan.loader.Loader 系統會將其公開的服務轉送至工作階段、測試架構和 應用程式。這是以 C++ 編寫而成,而程式碼位於 //src/graphics/bin/vulkan_loader,說明文件位於 /src/graphics/bin/vulkan_loader/README.md.

日後可能會從 Rust 重新寫入這項服務,以降低安全性風險,並 運用非同步程式設計功能

辨識新裝置

vulkan_loader 服務必須能辨識可用的 ICD。這個 會由執行中的裝置驅動程式組合所驅動。如果裝置驅動程式庫 並未在硬體上執行,就無法使用相關的 ICD。

vulkan_loader/dev/class/goldfish-pipe 和 /dev/class/gpu 來判斷新的圖形裝置何時顯示。

新的圖形裝置出現時,載入器必須判斷元件 與 ICD 相關的所有資訊確切機制因裝置類型而異:

  • /dev/class/gpu - 呼叫 fuchsia.gpu.magma/Device.GetIcdList 應用程式。
  • /dev/class/goldfish-pipe:ICCD 網址經過硬式編碼 fuchsia-pkg://fuchsia.com/libvulkan_goldfish#meta/vulkan.cm

日後可能會支援更多類型的 GPU 硬體裝置。軟體 ICD 也可能會在某些裝置上透過載入程式通訊協定公開,做為備用 (由 vulkan_loader 設定選擇)。軟體 Vulkan ICD (例如 SwiftShader) 經常使用 JIT,因此需要能夠寫入可執行檔 記憶體;所以可能不可用於正式的生產系統 能力受到嚴密控管

檔案系統提供

vulkan_loader 為客戶提供多個檔案系統,包括 資訊清單 fsdevice fs。建立這些檔案系統時 並透過 devfs 接收多個 ICD 套件與服務。因此 必須由檔案系統供應程式庫建構,且無法反映 磁碟上任何東西。

  • manifest fs:所有說明資訊清單的 JSON 檔案 相關 ICD;這個檔案系統看起來與 /usr/local/share/vulkan/icd.d (適用於 Linux),這樣可以盡量減少載入器 。
  • device fs:包含支援 Vulkan ICD 所需的所有 GPU 裝置。適用對象 /dev/<path>/<node> 裝置,檔案系統會包含 <path>/<node> 項目。

ICDICE 載入器介面

載入器能以 CFv2 元件的形式提供 ICD。ICD 元件必須公開含有任意文字的 contents 目錄 包含共用程式庫的目錄樹狀結構,以及 metadata 目錄 包含單一 metadata.json 檔案

ICD 本身通常包含在獨立的套件中。在此情況下 contents 目錄是套件的根目錄,metadata 則是 應是套件中的 meta/metadata/ 目錄。載入器 但不會強制執行這個版面配置

metadata.jsonmanifest.json 最好儲存在 meta 底下 目錄內的目錄目錄,因為該目錄最有效率 用於儲存小型檔案

ICD 共享程式庫

ICD 共用程式庫應與 Vulkan ICD ABI 相符。ICD 是 可執行的共用程式庫,可放置在大多數的子目錄中 ( /bin)。

元件資訊清單

Vulkan 載入器提供 icd_runner 執行器,可簡化建立作業 從套件中取得 ICD 元件ICD 套件必須包含元件 匯出 contentsmetadata 的資訊清單 .cml 目錄功能

icd_runner 會自動匯出 /pkg/data/pkg/meta/metadata/pkg-data/pkg-metadata 路徑的 ICD 套件中複製對應的目錄。 CML 可使用這些 ID 匯出這兩種目錄功能 (使用 subdir 屬性來公開子目錄完整能力)。

ICD 元件也可以使用 ELF 執行元件,但唯一可用的服務 變更為 fuchsia.logger.LogSink

metadata.json

metadata.json 是一個 JSON 檔案,用來說明載入器的 ICD。 範例:

{
    "file_path": "lib/libvulkan_example.so",
    "version": 1,
    "manifest_path": "meta/icd.d/libvulkan_example.json"
}

其他用戶端

可用的 Vulkan ICD 集會隨著時間變動;系統首次啟動時 在硬體列舉之前,啟動都不會提供 ICD。接著 裝置可能接上電源,然後出現或消失。

這表示 vkEnumeratePhysicalDevices 傳回的裝置清單可以 隨時變更。某些需要 Vulkan 的應用程式可能需要重試 而可用裝置組合變更之後。可以使用檔案系統監控工具 從 fuchsia.vulkan.loader/Loader.ConnectToManifestFs 傳回的檔案系統 來判斷重試的時機。

實作

這項設計代表 Vulkan 載入器目前的架構 Fuchsia 上的資源

成效

Vulkan 載入器最常在程序啟動時使用。一旦 Vulkan ICD 則會在載入時,彈跳至 Vulkan 呼叫進入 ICD,或傳回 ICD 函式實作,以便應用程式呼叫 因此,其效能僅在程序啟動期間至關重要。

我們對載入器效能並未特別考量。它有 來啟動元件並連線至 ICD,以及掃遍多個檔案系統路徑 才能實現 ICD 和層設定目前還不相信 對執行階段效能造成任何重大影響

回溯相容性

libvulkan.so 與 vulkan_loader 之間的通訊會使用檔案系統、JSON 和 FIDL檔案系統和 JSON 已在 Linux 使用多年 不會出現回溯相容性問題有自然的改變方式 (分別新增路徑和金鑰) 以維持回溯相容性。 FIDL 介面較小,可透過 FIDL 版本管理機制發展。

安全性考量

元件會載入 Vulkan 載入器提供的共用程式庫。 系統正常執行驗證過的執行 可執行的共用程式庫來自可信任的位置 (例如 檔案系統)。任何父項元件都可以 fuchsia.vulkan.loader.Loader 通訊協定,因此無法保證載入程式 系統元件的觀察結果將由系統提供。

Magma 系統驅動程式中的路徑參照選擇載入的 ICD (MSD) 並透過解析器載入。根據預設,系統會使用完整解析器 以便載入暫時套件從臨時套件載入 ICD 的方式為 ICD 開發人員參考,但對大多數使用者而言並非必要。 您可以停用完整解析器,停用載入臨時套件的功能 (設定 auto_update_packages=false gn 引數)。您也可以建立多個 產品擁有者可選擇的 Vulkan 載入器核心資料分割;英格蘭 建構可以選擇使用完整解析器的資料分割,而使用者建構作業 搭配基本解析器使用資料分割。

如果特定產品有需要,請同時使用多個 vulkan_loader 例項 服務類型,每個都可存取不同的解析器。他們的 fuchsia.vulkan.loader.Loader 個實作項目可轉送至用戶端 快速部署安全性需求目前否 這類產品都有這項規定

設定載入器可能會導致應用程式發生非預期的行為, 載入新圖層、禁止載入其他圖層或設定選項 在這些層中定義政策元件必須選擇從 (方法是從外部轉送 套件),但還能完全控制載入器設定。

ICD 共用程式庫會在用戶端程序中執行,且可以 將任何程式碼寫入該程序中的任意程式碼建構程序和合規性測試 請確保他們只匯入已加入許可清單的符號,但這並非安全性保證 且很容易被略過,例如著眼於呼叫堆疊 剖析記憶體中的執行檔以尋找有用的小工具。應用程式 驗證 Vulkan 傳回的大部分值,且可能會受到操弄來 您可謹慎操控這些值,藉此任意存取任意記憶體。

如果執行元件載入多個不信任的元件 或許是使用虛擬機器或其他非處理程序機制 這些元件無法直接發出 Vulkan 呼叫 因為沒有已知的方法來驗證 Vulkan API 呼叫,以保證 應用程式不會在 Vulkan ICD 中執行未定義的行為。包括 Vulkan 驗證層的防護效果有限。執行器程式碼可能會使 Vulkan 呼叫本身,例如使用 Skia 或 ANGLE 執行經過驗證的算繪 指令。提供給 ICD 必須來自執行元件信任的特定來源,以防止子項元件 窺視彼此

隱私權注意事項

Vulkan 載入器幾乎不影響隱私保護,唯一會在內部 FIDL 是應用程式是否嘗試使用 Vulkan 及其裝置 嘗試運用不同軟體

測試

vulkan_loader 和 libvulkan.so 執行單元和整合測試。這些測試 不依賴裝置驅動程式或安裝在實體電腦上 有些人會將 Cloud Storage 視為檔案系統 但實際上不是

此外,您也可以透過 CTF 測試,確保將網站導入容器時, fuchsia.vulkan.loader.Loader 通訊協定正確無誤,且 都能與舊版載入器相容

果凍樹中的 Vulkan CTS 和其他 Vulkan 測試可端對端形式運作 測試,檢查 vulkan_loader 是否與 libvulkan.so 相容。 這類軟體只能在搭載 Vulkan 硬體和裝置驅動程式的系統上執行。

說明文件

我們有 vulkan_loader 說明文件: /src/graphics/bin/vulkan_loader/README.md.另有幾位使用者 說明文件說明如何使用 Vulkan 載入器。

上游 Vulkan 載入器提供說明文件。我們應該試試 ,在文件中加入和上游的 Fuchsia 專屬資訊。

既有藝術品和參考資料

Linux/Windows/MacOS 載入器