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
命名空間 (「gfx api」) 下的 3D 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 對話的管道,目的是將內容算繪至螢幕上的矩形圖層。這些工作階段可能不會影響彼此的呈現或執行流程。
- 系統會強制執行圖片分配作業,透過
fuchsia.ui.composition/Allocator
下定義的 Scenic Allocator 通訊協定完成。- 由於用戶端和 Scenic 會在使用 Sysmem 進行配置前就同意分配和格式,因此所有圖像用途都會採用零複製方式。
- Allocator 可讓圖片在多個 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 可透過空值轉譯器實作來交換,這樣可略過合成作業。可將螢幕切換為現有的假設螢幕實作。
我們會在 Compatibility Test Suite 中提供其他 Flatland API 整合測試。
效能考量
Flatland 的設計可讓多個用戶端同時運作,且不會影響彼此的工作。
- 每個方法都是單向 FIDL 方法,代表用戶端的命令,用於將畫面轉譯至顯示畫面的矩形部分。Present() 會標示用戶端傳來的指令序列結束,以及 Scenic 開始處理下一次顯示更新的時間。
- 大多數用戶端在主動更新內容時,至少會在每個 vsync 中發出一個呼叫。也就是說,在 60 fps 顯示情境下,大約為 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() 設定可識別的偵錯字串。在列印有關錯誤的詳細系統記錄時,系統會使用前置字串,協助用戶端區分哪些是自己的錯誤。用戶端可完全控制此處的設定內容,如果未設定任何內容,系統記錄中就不會顯示任何前置字串。
缺點和替代方案
我們從 fuchsia.ui.gfx
下方的現有 3D API 中學到,這也是 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。