Magma:移植指南

如需 Magma 總覽,包括背景、硬體需求和架構說明,請參閱「Magma:總覽」。

本文件提供驅動程式庫開發人員可遵循的流程,將 Vulkan 驅動程式移植至 Fuchsia。

相關規定

將 Vulkan 驅動程式庫移植至 Fuchsia 需要下列項目:

  • 硬體說明文件 (登記規格、作業論)。
  • Vulkan 參考資料實作 (Linux)。
  • 用戶端程式庫 (ICD) 應提供符合規定的 Vulkan 1.1/1.2 實作。

硬體必須通過啟動,才能使用網路存取、磁碟儲存空間和 fx pave 函式。

Magma 目前只支援 UMA 裝置,但如果您有意願,不妨嘗試轉移至具有獨立記憶體的 GPU。

建立虛設常式系統驅動程式庫

Magma 系統驅動程式庫 (MSD) 與其他作業系統上的核心驅動程式庫相似。此時,請考慮是否要從其他作業系統移植現有核心驅動程式庫,或從頭開始編寫。

此時,您應參閱駕駛概念一節,瞭解 Fuchsia 驅動程式庫模型。

這項選擇取決於現有核心驅動程式庫程式碼的許多方面。請考量以下事項:

  • 驅動程式庫是否有平台抽象層,還是依附於 Linux 核心介面?
  • 授權。
  • 其 ioctl 介面和 Magma 進入點的相似程度如何?

第一步是建立建構的基本 MSD。MSD 位於驅動程式庫目錄。而是使用 GN 建構系統建構為 fuchsia_drivers。Magma 系統驅動程式庫必須是開放原始碼,而非 GPL,並且由 fuchsia.googlesource.com 代管。

Fuchsia 驅動程式是一般的使用者空間程序。這表示他們可以存取大部分的 c 程式庫,以及部分 POSIX API。與大多數程序不同,不允許任何檔案系統存取。

Magma 目前支援兩種不同的裝置類型:平台裝置和 PCI 裝置。

  • SoC 通常都有平台裝置。這些方法並非立即可用,但需要主面板驅動程式,將適當的資源委派給他們。
  • PCI 裝置在 PCI 匯流排上,且是由 PCI 匯流排驅動程式所委派的資源。

兩者皆由 Fuchsia 驅動程式庫程式架構支援,因此可以建立並繫結至一般 Fuchsia 驅動程式。

要拆分責任嗎?(SoC 版本)

在 SoC 上,GPU 硬體通常會以獨立 IP 區塊的形式呈現,可以由 SoC 廠商自訂。視廠商的自訂層級而定,處理方法有以下幾種。

  • 經過統合的 MSD,但先前已載入 SoC 專屬驅動程式庫。
  • 為每個 SoC 或 SoC 廠商建立個別的 MSD。

如果 SoC 的自訂空間很小,則建議使用統一的 MSD。廠商專用驅動程式庫會先繫結,並匯出 MSD 的 banjo 介面,以開啟/關閉 GPU、變更時鐘等。這麼做的好處是,您可以更輕鬆地將 MSD 移植到新硬體,而無需修改供應商專屬的新驅動程式庫。如需這種方法的範例,請參閱 msd-arm-maliaml-gpu

如果 GPU IP 廠商允許對 SoC 中的 IP 區塊進行許多自訂,請為每個 SoC 建立個別的 MSD。如果 GPU IP 廠商允許對 SoC 中的 IP 區塊進行許多自訂調整,可能就需要使用個別的 MSD。不同 SoC 的 MSD 實作可能會共用一個單獨的 SoC 程式碼程式庫,但會編譯為獨立驅動程式。

要拆分責任嗎?(PCI 版本)

PCI GPU 通常包含顯示控制器硬體。 顯示控制器應公開硬體專屬的 banjo 介面,且 MSD 可繫結至顯示驅動程式庫。

請參閱 msd-intel-genintel-i915,瞭解 PCI 驅動程式庫的分割範例 (分成兩個部分)。

正在開啟電源

建構 MSD 後,下一步就是編寫程式碼來重設裝置,並進入運作模式。這類資訊可能包括:

驅動程式也應視需要存取 MMIO 範圍,且應開始處理中斷情形。針對 SoC,您必須修改主面板驅動程式,才能將這些資源傳送給 MSD 或 SoC 專用驅動程式庫,且必須新增要繫結 MSD 的裝置。

在這個階段進行測試:

  • 在驅動程式庫啟動時記錄 MMIO。

實作 MSD

以下是驅動程式庫可實作的主要函式彙整清單:

  • 初始化硬體
    • msd_driver_create
    • msd_driver_configure
    • msd_driver_destroy
    • msd_driver_create_device
    • msd_device_destroy
  • 支援參數查詢
    • msd_device_query
  • 支援狀態傾印功能
    • msd_device_dump_status
  • 建立連線
    • msd_device_open
    • msd_connection_close
  • 建立緩衝區
    • msd_buffer_import
    • msd_buffer_destroy
  • 設定記憶體空間和緩衝區對應
    • msd_connection_map_buffer_gpu
    • msd_connection_unmap_buffer_gpu
    • msd_connection_commit_buffer
    • msd_connection_release_buffer
  • 設定硬體情境
    • msd_connection_create_context
    • msd_context_destroy
  • 指令緩衝區排程
    • msd_context_execute_command_buffer
    • msd_context_execute_immediate_commands
    • msd_connection_set_notification_callback
  • 建立區隔
    • msd_semaphore_import
    • msd_semaphore_destroy
  • 錯誤處理
  • 電源管理

硬體成功啟動後,下一步是決定如何將現有的指標對應至 MSD 進入點。

在大多數情況下,linux DRI ioctls 和 MSD 函式之間的對應相當簡單。有一個例外情況是記憶體管理:在 Magma 中,ICD 是會分配和對應記憶體的 ICD,而不是 MSD (或核心驅動程式庫)。這麼做可能會改變某些分配 VMO 的指令流程,因為 MSD 必須將現有的緩衝區匯入 GPU 硬體。

如果這個方法不適用於某些類型的記憶體,驅動程式庫可能會使用 Sysmem 堆積來處理該記憶體的配置。用戶端會使用 Sysmem 分配記憶體,並使用一般 Magma 介面匯入控點。之後,MSD 就可以與 sysmem 通訊,取得記憶體的詳細資訊。

驅動程式可能不需要實作所有功能。建議您根據 ICD 的需求,逐步實作 MSD 函式。這在實作 MSD 函式時可提供背景資訊,並有助於避免對非必要函式造成浪費。

在這個階段進行測試:

  • 驅動程式庫專屬單元測試 (非特定硬體)
  • 硬體專屬驅動程式庫測試 (請參閱範例)。這些測試應以最少的方式執行 GPU,例如寫入暫存器或造成 GPU 修改記憶體位置。
  • 使用 Magma 介面的驅動程式庫專屬整合測試。
  • magma-conformance-tests (屬於 Magma L0 的一部分)。
  • magma-info-test (屬於 Magma L0 的一部分)。

打造 ICD

IHV ICD 必須移植至 Fuchsia。ICD 應使用 Bazel SDK 建構。ICD 建構作業可能會轉移至 Bazel,或包含在 Bazel 建構作業中。rules_foreign_cc 是如何包裝現有建構的好範例。

因為 ICD abi 限制,ICD 必須對其所有依附元件以靜態方式連結。而且只能參照以下共用資料庫:

  • libc.so
  • libzircon.so

這會限制 ICD 可使用的依附元件。以下列舉一些不允許的程式庫和可能的取代項目:

在這個階段,您可以視需要移除所有其他參照。ICD 也必須以 @fuchsia_pkg//pkg/magma_client 連結 SDK 提供的 Magma 執行階段程式庫。

Vulkan 載入器服務會從套件擷取 ICD,並向 Vulkan 用戶端通告。ICD 必須納入內含中繼資料和資訊清單 JSON 檔案的 Fuchsia 套件中,如載入器服務說明文件所述。您可以使用 Bazel SDK 存放區指令將套件提供給裝置。

如果 ICD 套件已涵蓋在「宇宙」中,則可執行 fx shell killall vulkan_loader.cm 重新載入。之後啟動的元件會取得新的 ICD 套件,而較舊的元件在建立 Vulkan 執行個體時會失敗。

ICD 必須匯出一組特定符號,請參閱 Vulkan ABI 定義。此時,您應該實作這些方法。

在這個階段進行測試:

  • 共用資料庫的 readelf -d,確保除了 libc.solibzircon.so 以外沒有依附元件。
  • 使用 fx shell cat /svc/fuchsia.vulkan.loader.Loader 啟動 vulkan 載入器,並檢查 ffx inspect show core/vulkan_loader,確認是否已載入。錯誤會移至系統記錄檔。
  • 執行 vulkan_icd_load 測試。這項測試會檢查系統上是否有任何 ICD 正常運作,因此在執行之前,請確保系統上沒有其他 ICD。

將 ICD 連線至 Magma

此時,ICD 應使用提供給 vk_icdInitializeOpenInNamespaceCallback 的回呼,連線至 /loader-gpu-devices/class/gpu 目錄。ICD 可使用 fuchsia.io.Directory FIDL 通訊協定列出目錄內容。此目錄包含系統中所有 MSD 的裝置節點,每個節點都以不重複的三位數號碼命名。數字在啟動作業中會保持穩定,但每次重新載入 MSD 時 (例如裝置重新啟動) 可能會變更。

每個 Magma 裝置路徑都可以使用 vk_icdInitializeOpenInNamespaceCallback 開啟,還可使用 magma_device_import 將產生的 zircon 管道提供給 libmagma。如果系統中有多個放大鏡裝置,驅動程式庫必須將 magma_queryMAGMA_QUERY_VENDOR_ID 搭配使用,才能判斷要使用哪部裝置。

在此階段後,magma_* 函式將正常運作,因此 ioctl() 呼叫可逐漸轉換為對等的 Magma 呼叫。

在這個階段進行測試:

  • vkreadback (繪製顏色),然後讀取 framebuffer 值。這是 Magma L0 的一部分。
  • Vulkan 合規性測試。理想情況下,這個階段完成後會顯示 100% 的通過率。詳情請參閱 Magma 測試策略

移除不允許使用的符號

在連結 ICD 時使用版本指令碼,確保隻公開 Fuchsia 系統 ABI 允許的符號。

只有符號許可清單中列出的符號才能用於 ICD。如要確認,請將許可清單與在 ICD 共用資料庫上執行 llvm-nm -gD 取得的清單進行比對。

針對提供給 vk_icdInitializeOpenInNamespaceCallbackOpenInNamespace 回呼,系統可能會將部分不支援的檔案作業替換為呼叫。

在這個階段進行測試:

實作 Fuchsia 擴充功能

ICD 目前無法與 scenic 搭配使用,且尚未整合視窗系統。驅動程式必須實作 Fuchsia 專用的 Vulkan 擴充功能。用戶端程式庫應提供符合規定的 Vulkan 1.0/1.1/1.2 實作。

VK_FUCHSIA_external_memory

這項擴充功能與 VK_KHR_external_memory_fd 類似,可讓您從 VMO 匯入/匯出 VkDeviceMemory。這項擴充功能已上游 Vulkan 規格

在這個階段進行測試:

  • vkext --gtest_filter=VulkanExtension.* (Magma L0 的一部分)。

VK_FUCHSIA_external_semaphore

這項擴充功能與 VK_KHR_external_semaphore_fd 類似,可允許匯入/匯出二進位分段至 zircon 事件。這項擴充功能已上游 Vulkan 規格

在這個階段進行測試:

  • vkext --gtest_filter=VulkanExtension.* (Magma L0 的一部分)。
  • vulkan-cts-zircon (Vulkan CTS 的一部分)。

VK_FUCHSIA_buffer_collection

這項擴充功能會與 sysmem 互動,可讓用戶端協商圖片格式並分配記憶體。詳情請參閱 sysmem 說明文件。

這項擴充功能目前為 WIP,可能會有變動,但您可以在 Fuchsia 內部 Vulkan 標頭中找到。

在這個階段進行測試:

驗證

上述每個子章節中列出的所有測試都必須通過。如需更多詳細資料與測試案例的完整清單,請參閱測試策略說明文件

長期支援

MSD 和 ICD 必須隨著硬體廠商提供新的程式碼推送更新,在理想情況下,程式碼為上游,GPU 供應商將使用 Zircon DDK 提供及維護系統驅動程式。