RFC-0161:風景式 Allocator API

RFC-0161:Scenic Allocator API
狀態已接受
區域
  • 圖形
說明

Scenic Allocator 的舊版 API 設計文件,用於 API 校正。

Gerrit 變更
作者
審查人員
提交日期 (年-月-日)2021-03-19
審查日期 (年-月-日)2021-04-05

舊版 API 設計文件

這份 RFC 先前以 API 設計文件形式提交,API 設計文件範本淘汰後,才轉換為 RFC。

摘要

本文件提出一項計畫,將 Scenic 的圖片資源分配作業擷取至獨立的通訊協定。

目標和用途

Allocator API 的目標是改善現有的圖像分配流程,並與即將推出的變更相容。

  • 從 Scenic::Session 擴充所分配 BufferCollection 資源的範圍。一個 BufferCollection 可用於在多個 Scenic::Session 中建立 Image 資源,以及即將推出的 2D API Flatland 的工作階段。

  • 將緩衝區分配作業與 Scenic::Session 分開,可明確瞭解通訊協定的用途。 分配器只會處理緩衝區分配作業,而 Scenic::Sessions 則用於呈現和繪圖。

  • 我們的 3D API 和即將推出的 2D API 都能使用分配器。因此可使用更複雜的圖像。

使用這個 API,更複雜的使用者可以在獨立的 Scenic::Sessions 之間共用 Image 資源。目前無法這麼做,因此通常需要重新分配。

設計

我們的建議主要是將緩衝區註冊和取消註冊功能從 Scenic::Session 移至新通訊協定。請參閱下方的建議通訊協定。

library fuchsia.ui.composition;

/// A typed wrapper for an eventpair, representing the registry endpoint of a buffer collection.
resource struct BufferCollectionExportToken {
    zx.handle:EVENTPAIR value;
};

/// A typed wrapper for an eventpair, representing the Image import endpoint of a buffer
/// collection.
resource struct BufferCollectionImportToken {
    zx.handle:EVENTPAIR value;
};

protocol Allocator {
    /// A BufferCollection is a set of VMOs created by Sysmem and shared by a number of
    /// participants, one of which is the Flatland Renderer. Some content, such as Images, use a
    /// BufferCollection as their backing memory.
    ///
    /// Clients can send `export_token` to register buffer collections with Allocator to be used
    /// later in [`fuchsia.ui.composition/Flatland`] instances or other Scenic APIs. For
    /// example, by passing a [`BufferCollectionImportToken`] containing the matching peer of
    /// [`BufferCollectionExportToken`], they can create image resources via
    /// [`fuchsia.ui.composition/Flatland.CreateImage`]. Clients should wait for the response
    /// before using `import_token`.
    ///
    /// Flatland participates in the allocation of buffers by setting constraints on the
    /// BufferCollection referenced by `buffer_collection_token`. It will not block on buffers
    /// being allocated until the client creates content using the BufferCollection.
    ///
    /// The buffer collection registered with `export_token` is available and kept alive as long
    /// as the client holds a valid [`BufferCollectionImportToken`]. They will be garbage collected
    /// when all [`BufferCollectionImportToken`]s are closed and all the associated Image resources
    /// are released.
    RegisterBufferCollection(BufferCollectionExportToken export_token,
                             fuchsia.sysmem.BufferCollectionToken buffer_collection_token)
        -> () error RegisterBufferCollectionError;
};

圖 1 - 圖片建立流程 這張圖顯示用戶端、分配器和呈現 API 之間的關係。

請注意,現在已不需要取消緩衝區註冊。您可以在用戶端捨棄所有 BufferCollectionImportToken 執行個體,即可隱含地完成這項作業。考量到許多用戶端在意外關機時,無法執行取消註冊流程,這項做法可更有效地防範記憶體洩漏。

現有的緩衝區註冊功能需要用戶端定義專屬 ID,才能參照 BufferCollection。這會由 EVENTPAIR 取代,用戶端可輕鬆重複任意次數,以供參照。請參閱下方的現有流程。

protocol Session {
    RegisterBufferCollection(uint32 buffer_id, fuchsia.sysmem.BufferCollectionToken token);

    DeregisterBufferCollection(uint32 buffer_id);
};

建議設計的實作工作持續進行中,必要的重構也已完成。 如需實際變更,請參閱 fxr/498558 和 fxr/499479。

可用性

分配器 API 提供另一種方式來達成現有功能,從用戶端角度來看更簡單。

  • 用戶端會建立 EVENTPAIR,而不是找出專屬 ID。
  • 用戶端可以捨棄事件配對的另一端,而不需使用相同的專屬 ID 明確呼叫 DeregisterBufferCollection。
  • 用戶端可以複製並使用事件配對的另一端,在多個 Scenic::Session 中建立 Image 資源。

如需 Scenic::Session 的使用模式範例,請參閱下文。

fuchsia::ui::composition::AllocatorPtr scenic_allocator;
fuchsia::sysmem::BufferCollectionTokenSyncPtr token;
auto ref_pair = allocation::BufferCollectionImportExportTokens::New();
scenic::SessionPtr session;
scenic_allocator->RegisterBufferCollection(std::move(ref_pair.export_token), std::move(token),
                                             [&]() {
                                               session->Enqueue(scenic::NewCreateImage3Cmd(
                                                 image_id, width, height,
                                                 std::move(ref_pair.import_token), vmo_index));
                                             });

測試

我們計畫針對 API 新增大量單元測試。如要執行需要搭配 Scenic::Session 使用分配器的整合測試,可以轉換樹狀結構內的像素測試。

效能注意事項

Allocator API 不會新增任何其他 API 呼叫。這樣一來,用戶端就不必呼叫 DeregisterBufferCollection。

安全性考量

Allocator API 依賴 EVENTPAIR 功能解決安全問題。EVENTPAIR 的獨特性和建立時與其他端點的緊密連結,可確保惡意用戶端無法盜用及存取基礎緩衝區。如果他們以某種方式取得 EVENTPAIR,就只能顯示這張圖片,但無法修改或讀取。

缺點和替代方案

分配器 API 提案有兩個主要改善重點,其中任一項都可以取代現有的通訊協定和流程。

  • 我們可以繼續使用專屬 ID 參照緩衝區集合,而不是事件配對。我們可以預期用戶端會選取專屬集合 ID,也可以從註冊呼叫傳回專屬集合 ID。
    • 挑選專屬 ID 需要同步處理,包括用戶端尋找可用的 ID,以及等待 Allocator 確認後再使用。
    • 惡意用戶端可能會輕易盜用專屬 ID。
    • 我們需要明確的 DeregisterBufferCollection() 呼叫。
  • 我們可以將 Allocator 保留在 Scenic::Session 和 Flatland 執行個體中,而不是公開新的通訊協定。
    • 如果複雜的用戶端使用多個工作階段,仍會受到限制,無法使用註冊工作階段以外的緩衝區集合。