| RFC-0162:Flatland API | |
|---|---|
| 狀態 | 已接受 |
| 區域 |
|
| 說明 | 說明 Flatland,這是 Fuchsia 的 2D 合成 API。 |
| Gerrit 變更 | |
| 作者 | |
| 審查人員 | |
| 提交日期 (年-月-日) | 2021-05-24 |
| 審查日期 (年-月-日) | 2021-05-30 |
舊版 API 設計文件
這份 RFC 先前以 API 設計文件形式提交,API 設計文件範本淘汰後,才轉換為 RFC。
摘要
本文建議為 Fuchsia 圖形用戶端提供 2D API。Flatland 為用戶端提供類似顯示控制器的功能,可在 2D 世界中定義資源。
目標和用途
Scenic 目前在 fuchsia.ui.gfx 命名空間下提供 3D API 給圖形用戶端 (即「gfx api」)。這個 3D API 會為用戶端提供類似於電玩遊戲引擎或其他 3D 繪圖程式的場景模型。繪圖順序由 Z 深度處理,不透明度則由以深度為準的 Alpha 混合處理。很抱歉,無論從產品或效能角度來看,gfx API 都已無法滿足 Scenic 的需求。由於不清楚如何處理一組半透明內容的陰影,因此無法使用群組不透明度等功能。
從產品角度來看,我們目前的顧客是 2D 產品。沒有深度和繪製順序的概念。這些只是提交不同批次繪圖幾何的順序。由於沒有深度,透明效果也取決於繪製順序。「2D」用戶端 (透過 Flutter、Chromium 和工作階段架構) 必須額外處理 Scenic 的 3D 場景表示法與使用者體驗的 2D 表示法不符的問題。
就效能而言,新式視訊螢幕控制器 (VDC) 硬體提供多個螢幕平面和硬體疊加等加速功能,Scenic 未來可善用這些功能,降低耗電量和 GPU 使用率。不過,硬體是以嚴格的 2D 範例運作,且只會解讀可放置在 X/Y 的矩形圖層。Scenic 目前的 3D API 允許並鼓勵用戶端提交不符合此範例的內容,導致最佳化嘗試受挫。
我們希望透過公開真正的 2D API,提升 2D 用戶的體驗:
- 2D API 更符合 2D 用戶端的期望。
- 盡可能將工作委派給 VDC,減少 GPU 用量。
- 更輕巧的 Scenic,僅針對 2D 矩形圖層進行最佳化。
設計
建議您從頭編寫 2D 通訊協定,不要重複使用 fuchsia.ui.gfx 的部分。
建議的 2D API 目前狀態為 fuchsia.ui.scenic.internal.flatland 程式庫,將做為本次審查的一部分提交。歡迎查看並留下評論。
以下說明針對 Flatland API 做出的一些高層決策:
- Flatland 密切追蹤並提供類似於
fuchsia.hardware.display/Controller上定義的顯示控制器 API 功能。- 在 Scenic 中實作 Flatland 時,如果資源直接傳遞至螢幕,不經過合成,成效最佳。因此,顯示控制器 API 的常見資源是以相同方式定義。也就是說,zx.handle:EVENT 會做為柵欄,在可安全存取資源時發出信號,並透過這些通訊協定傳輸,且具有相同的意義和用途。
- Flatland 的目標是為用戶提供確定性的 CPU 成本。有一個排定截止時間的算繪執行緒。每個 Flatland 工作階段都會在自己的調度器上執行,而調度器位於目前設定中的專屬執行緒。
- 可能有多個 Flatland 工作階段,每個工作階段都是與 Flatland 對話的管道,目的是在螢幕上算繪矩形圖層。這些工作階段可能不會互相影響簡報或表演流程。
- 系統會強制透過 Scenic 的 Allocator 通訊協定 (定義於
fuchsia.ui.composition/Allocator) 進行圖片分配。- 由於用戶端和 Scenic 會先就分配和格式達成共識,再使用 Sysmem 進行分配,因此所有圖像用量都是零複製。
- 分配器可讓圖片用於多個 Flatland 工作階段。
- Flatland 不提供指令聯集模式。Present() 呼叫是處理已加入佇列指令 (即個別方法) 的標記。
- Flatland 會嚴格限制用戶端呼叫 Present() 的次數,並透過 OnPresentProcessed() 回應傳達這項資訊,做為節流機制。
- Flatland 可能會在 OnPresentProcessed() 回呼中傳回錯誤,向用戶端回報非法作業。因此 Flatland 管道已關閉。
- Flatland 預期用戶端會定義並追蹤專屬資源 ID。系統會透過這些 ID 周圍定義的結構 (例如 TransformId 和 ContentId) 強制執行型別安全。
- Flatland 會使用暫止式 GET 要求,通知用戶連結結構或屬性的變更。這些事件是透過其他通訊協定發出。
不明
在某些領域,Flatland 設計可能會演變,以更符合客戶需求。
- 用戶可能會預期合成器處理顯示器硬體未處理的某些 2D 效果,例如模糊效果。這些作業的費用較高。我們計畫將這兩類作業分開,以明確區分兩者。Flatland 目前的狀態僅支援可由螢幕處理的作業。
- 簡報和意見回饋流程會根據客戶的意見回饋進行調整。在定義目前的 Flatland 流程之前,gfx API 的呈現流程經過三次疊代。因此,PresentArgs 定義為表格,以便日後進行變更。
- 我們在設計和簡報意見回饋中,著重於低延遲用戶端和高輸送量用戶端。OnPresentProcessed() 會在適合開始處理下一個影格時通知用戶端。OnFramePresented() 會通知進階用戶端,顯示的影格何時出現在畫面上。
可用性
請參閱 flatland_unittest 中的樹狀結構內測試,瞭解 Flatland API 的大量使用範例。
下圖說明連結多個 Flatland 工作階段的連線圖表運作方式。這是較為複雜但常見的用途。
圖 1 - 平面國
測試
Flatland 目前定義為內部 API,測試則由樹狀結構內的單元測試提供。由於除了測試之外,沒有其他方式可以執行 Flatland 程式碼,因此我們已透過自動化測試,全面涵蓋每段程式碼。我們計畫維持這項測試涵蓋範圍和品質。
我們計畫最終將所有圖像範例轉換為 Flatland。我們沒有任何客戶必須嚴格遵守 3D 世界的規範。我們目前正以 Flatland 簡報者為基礎,新增及遷移樹狀結構內整合測試 https://fxbug.dev/42156206。這項作業是為了日後遷移部分重要外部用戶端 (例如 Flutter 和 Chromium) 做準備。
Flatland 的設計宗旨是允許執行業務邏輯,而不必依附於 Vulkan 和螢幕等硬體功能。Vulkan 可以替換為空值轉譯器實作,這會略過組合。顯示器可以取代現有的虛假顯示器實作方式。
其他 Flatland API 整合測試將在 Compatibility Test Suite 中提供。
效能注意事項
Flatland 的設計宗旨是讓多個用戶端同時運作,且不會互相影響。
- 每個方法都是單向 FIDL 方法,代表用戶端在螢幕矩形部分中轉譯的指令。Present() 會發出信號,表示來自用戶端的指令序列已結束,Scenic 則開始處理下一次的螢幕更新。
- 大多數用戶端在主動更新內容時,每個 VSync 至少會發出一次呼叫。也就是說,在每秒 60 影格的顯示情況下,大約是 16 毫秒。在每個 VSync 間隔中:
- 用戶端可能會進行 N 次呼叫來修改場景圖,然後進行一次 Present() 呼叫。
- Flatland 會發出 OnPresentProcessed(),通知用戶端作業已排入佇列,且用戶端應開始產生下一個影格。目前,客戶不知道何時是開始工作的理想時間,而且依賴硬式編碼的偏移來避免重疊和 OnPresentProcessed() 修正。這項意見回饋也會提供提示,說明理想的未來 Present() 呼叫應傳送給用戶端,並告知用戶端 Present() 配額。
- 用戶端可能會忽略 OnPresentProcessed() 中提供的時間和提示,並根據內部時鐘繼續呈現內容。這仍有效,但無法保證避免資源爭用。
- Flatland 會發出 OnFramePresented(),通知用戶端內容已實際顯示在畫面上。進階用戶端需要這項意見回饋,才能進行音訊/視訊等同步作業。
- Flatland 會明確定義
num_presents_returned,防止惡意用戶端將過多 Present() 呼叫排入佇列。用戶端呼叫 Present() 的次數不得超過 OnPresentProcessed() 允許的次數。每個用戶端一開始都有一項呈現許可。 - 請注意,Flatland 會在各自的調度器上執行每個管道連線。這些意見回饋機制為非同步。
安全性考量
Flatland 使用者彼此之間不會互相影響。他們各自透過專屬管道與 Scenic 連結。專屬資源 ID僅在管道範圍內定義。只能以父項 Flatland 工作階段定義的螢幕部分為目標。
每種錯誤情況都會導致 Flatland 管道關閉。在這些錯誤狀態下,系統無法清楚判斷應在畫面上繪製的內容,因此我們認為不應允許用戶端繼續呈現內容。
隱私權注意事項
Flatland 不會公開任何裝置 ID 或隱私權敏感資訊。用戶端不會直接與硬體互動。
用戶端可透過 Flatland 的 SetDebugName() 設定可識別的偵錯字串。列印錯誤的詳細系統記錄時,這個字串會做為前置字串,協助用戶端區分自己的內容。用戶可完全控管要在此處設定的內容,如果未設定任何內容,系統記錄中就不會有前置字元。
缺點和替代方案
我們從現有 3D API (位於 fuchsia.ui.gfx 下方) 獲得的經驗,是決定 Flatland 2D API 的依據。我們在做出設計決策時,已將所有使用者意見回饋、錯誤和經驗教訓納入考量。
- 我們可以在現有的 3D API 下選擇 2D API 的演進。不過,兩者之間存在一些基本差異,這會導致用戶端和實作程序變得不必要地複雜。
- Flatland 可以使用指令聯集模式,例如
fuchsia.ui.gfx。目前每個 Flatland 指令都會對應為 FIDL 方法。做出這項決定的原因,是我們在 3D API 中觀察到現有指令模式的負面影響。我們必須為用戶端提供並維護不同語言的包裝函式。不過,將每則註解對應為方法,也有一些缺點。在單一寫入作業支援多則訊息之前,這項設計會防止批次處理。不過,我們預期用戶不會經常操控場景圖,因此不認為這會造成高昂的費用。
之後的作業
我們計畫在以下幾個方面著手,改善 Flatland API:
- 每個 Flatland 執行個體都會有相關聯的 ViewRef,以及用於擷取自己和子項 ViewRef 的方法。請參閱 https://fxbug.dev/42159888。
- 「工廠函式」可將輸入通訊協定繫結至特定 Flatland 執行個體,因此將範圍限制在執行個體的檢視畫面子樹狀結構。請參閱 https://fxbug.dev/42159922。
- 大小和指標會從父項流向子項,但父項 (和中介伺服器) 不知道這些大小和指標會影響哪個影格,只有第一個影格除外。這會產生連鎖效應:使用者可能會看到不完美的影格,而其他 API 也會受到用戶端邏輯延遲的影響。請參閱 https://fxbug.dev/42156345。
- 我們正在考慮跨多個執行個體同步處理 Present(),但尚未解決這個問題。請參閱 https://fxbug.dev/42159935。
- Flatland 會與其依附元件一起位於 fuchsia.ui.composition 命名空間下。fuchsia.scenic.allocation 和 fuchsia.scenic.scheduling 也會移至該處。請參閱 https://fxbug.dev/42158797。