如需 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-mali 和 aml-gpu。
如果 GPU IP 廠商允許對 SoC 中的 IP 區塊進行許多自訂,請為每個 SoC 建立個別的 MSD。如果 GPU IP 廠商允許對 SoC 中的 IP 區塊進行許多自訂調整,可能就需要使用個別的 MSD。不同 SoC 的 MSD 實作可能會共用一個單獨的 SoC 程式碼程式庫,但會編譯為獨立驅動程式。
要拆分責任嗎?(PCI 版本)
PCI GPU 通常包含顯示控制器硬體。 顯示控制器應公開硬體專屬的 banjo 介面,且 MSD 可繫結至顯示驅動程式庫。
請參閱 msd-intel-gen 和 intel-i915,瞭解 PCI 驅動程式庫的分割範例 (分成兩個部分)。
正在開啟電源
建構 MSD 後,下一步就是編寫程式碼來重設裝置,並進入運作模式。這類資訊可能包括:
- 啟動裝置電源 (可能使用 fuchsia.hardware.power.Device banjo 介面)。
- 啟用時鐘 (可能使用 fuchsia.hardware.clock.Clock FIDL 介面)。
- 啟用匯流排主要或記憶體存取功能。
- 正在載入韌體。
驅動程式也應視需要存取 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 可使用的依附元件。以下列舉一些不允許的程式庫和可能的取代項目:
- HLCPP:可以替換為新的 C++ 繫結。
- 「syslog」:可替換為 syslog/structured_backend。
- async-default:一律必須明確指定非同步調度器。
- libtrace-engine:目前還沒有替換。
- libsvc:可替換為
fuchsia.io
呼叫和vk_icdInitializeOpenInNamespaceCallback
(請見下方說明)。
在這個階段,您可以視需要移除所有其他參照。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.so
和libzircon.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_query
與 MAGMA_QUERY_VENDOR_ID
搭配使用,才能判斷要使用哪部裝置。
在此階段後,magma_*
函式將正常運作,因此 ioctl()
呼叫可逐漸轉換為對等的 Magma 呼叫。
在這個階段進行測試:
- vkreadback (繪製顏色),然後讀取 framebuffer 值。這是 Magma L0 的一部分。
- Vulkan 合規性測試。理想情況下,這個階段完成後會顯示 100% 的通過率。詳情請參閱 Magma 測試策略。
移除不允許使用的符號
在連結 ICD 時使用版本指令碼,確保隻公開 Fuchsia 系統 ABI 允許的符號。
只有符號許可清單中列出的符號才能用於 ICD。如要確認,請將許可清單與在 ICD 共用資料庫上執行 llvm-nm -gD
取得的清單進行比對。
針對提供給 vk_icdInitializeOpenInNamespaceCallback
的 OpenInNamespace
回呼,系統可能會將部分不支援的檔案作業替換為呼叫。
在這個階段進行測試:
- icd_conformance 測試成功。
實作 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 標頭中找到。
在這個階段進行測試:
vkext
(Magma L0 的一部分)。- vkcube-on-fb (使用 VK_KHR_swapchain 的動畫 - 屬於 Magma L1 的一部分)。
驗證
上述每個子章節中列出的所有測試都必須通過。如需更多詳細資料與測試案例的完整清單,請參閱測試策略說明文件。
長期支援
MSD 和 ICD 必須隨著硬體廠商提供新的程式碼推送更新,在理想情況下,程式碼為上游,GPU 供應商將使用 Zircon DDK 提供及維護系統驅動程式。