共用方式為


組合交換鏈程序設計指南

組合交換鏈 API 是 DXGI 交換鏈的精神後續專案,可讓應用程式將內容轉譯並呈現至畫面。 透過 DXGI 交換鏈使用此 API 有幾個優點。 更精細的控制會提供給您的應用程式有關交換鏈的狀態,而且在使用交換鏈的方式時會提供更多自由度。 此外,API 會為精確的目前計時提供更佳的故事。

什麼是簡報?

簡報 是在螢幕上顯示繪圖作業結果的概念。 簡報是簡報的單一實例,要求在螢幕上將繪圖作業的結果顯示在單一緩衝區上。 簡報可以包含描述如何在畫面上顯示的其他屬性。 在此 API 中,簡報也可以有 目標時間,也就是系統相對時間戳(插斷時間),其描述應該顯示目前的理想時間。 您的應用程式可以使用此功能,更精確地控制畫面上出現內容的速率,以及同步處理系統中其他事件,例如音訊播放軌。

簡報的核心是同步處理。 也就是說,繪圖作業通常是由 GPU 執行,而不是 CPU,因此,它們會從最初發出作業的 CPU 的異步時間軸上執行。 簡報是提交至 GPU 的作業,可確保先前發出的繪圖作業會在畫面上顯示緩衝區之前完成。

您的應用程式通常會在一段時間內發出許多簡報,並在發出簡報時選取多個紋理。 您的應用程式必須使用此 API 提供的同步處理機制,以確保一旦您繪製至緩衝區並呈現緩衝區,您就不會再次繪製該緩衝區,直到顯示該存在,並隨後以後續存在的新緩衝區取代。 否則,應用程式最初要呈現的緩衝區內容可以覆寫,因為畫面上會顯示該內容。

簡報模式-組合、多平面重迭和獨立翻轉

應用程式所呈現的緩衝區可以透過幾種不同的方式來顯示。

最簡單的方式是,目前會傳送至 DWM,而 DWM 會根據顯示的緩衝區轉譯框架。 也就是說,將簡報緩衝區的複本(或更準確地說是 3D 轉譯)複製到 DWM 傳送給顯示器的後緩衝器。 這個顯示簡報的方法稱為 Composition。

更高效能的顯示簡報模式是直接將簡報緩衝區掃描到硬體,並消除所發生的複本。 這個顯示簡報的方法稱為直接掃描。 處理簡報時,DWM 可以決定將緩衝區指派給多平面重疊平面(或 MPO 平面,簡稱),或直接將緩衝區翻轉至硬體(稱為直接翻轉),以決定將硬體直接掃描出簡報緩衝區。

顯示簡報的效能更高的方式是讓圖形核心直接顯示簡報,並完全略過 DWM。 這種簡報方法稱為 獨立翻轉 (iflip)。 多平面重疊和 iflip 都說明為 獲得最佳效能,請使用 DXGI 翻轉模型

組合是最容易支援的,但也最不有效率。 表面必須特別配置,才能符合直接掃描或 iflip 的資格,而這種類型的特殊配置比組合交換鏈更嚴格的系統需求。 它僅適用於 WDDM 3.0 和更高的硬體。 因此,您的應用程式可以查詢僅撰寫簡報的 API 支援,以及符合直接掃描或 iflip 資格的簡報。

注意

為了讓表面能夠自動利用這些更優化的呈現模式,介面必須配置為 GPU 可直接顯示。 針對 Direct3D 11 表面,您必須將表面配置為 顯示。 未配置為可顯示的介面仍可由螢幕上的系統組合器所複合,但永遠不會獲得獨立翻轉模式的優點。

簡報處理站、檢查功能和簡報管理員

您的應用程式將使用組合交換鏈 API 的第一個對象是 簡報處理站。 簡報處理站是由您的應用程式所建立,並系結至應用程式傳遞給建立呼叫的 Direct3D 裝置,因此,具有與該裝置相關聯的視訊配接器親和性。

簡報處理站會公開方法來檢查目前的系統和圖形裝置是否能夠使用組合交換鏈 API。 您可以使用 IPresentationFactory::IsPresentationSupported功能方法來檢查系統支援。 如果功能方法指出 API 的系統支援,您可以使用簡報處理站來建立 簡報管理員。 此簡報管理員是您用來執行簡報功能的物件,而且會系結至與用來建立簡報處理站相同的 Direct3D 裝置和視訊配接器。

目前,使用組合交換鏈 API 的系統需求全都是支援 WDDM (Windows 設備驅動器模型) 2.0 和 Windows 11 (組建 10.0.22000.194) 或更新版本的 GPU 驅動程式。 若要以最高效能的方式使用組合交換鏈 API(直接掃描和獨立翻轉或 iflip),系統將需要支援 WDDM 3.0 的 GPU 驅動程式。

如果系統無法使用組合交換鏈 API,則您的應用程式必須有個別的程式代碼路徑,才能使用舊版方法來處理簡報,例如 DXGI 交換鏈。

註冊要呈現的簡報緩衝區

簡報管理員會追蹤可以呈現的緩衝區。 若要呈現 Direct3D 紋理,您的應用程式必須先使用 Direct3D 建立該紋理,然後向簡報管理員註冊該紋理。 當紋理向簡報管理員註冊時,它稱為 簡報緩衝區,而且可以從該點開始由該簡報管理員呈現到畫面。 您的應用程式可以視需要新增和移除簡報緩衝區,不過可以新增至單一簡報管理員的簡報緩衝區數目上限(目前為31個)。 這些簡報緩衝區的大小和格式也不同,當個別的簡報緩衝區呈現時,這些大小和格式都會生效。

紋理可以向任意數目的簡報管理員註冊;不過,在大部分情況下,這不會被視為正常使用,而且會顯示應用程式負責管理的複雜同步處理案例。

定義要呈現的內容

一般而言,我們呈現的緩衝區必須與可視化樹狀結構的內容相關聯。 因此,我們需要定義一種系 ,以便在應用程式問題出現時,清楚顯示緩衝區的可視化樹狀結構中要呈現的緩衝區。 我們稱之為系結 簡報內容

呈現的內容可能採用許多形式。 您的應用程式可能想要顯示單一緩衝區,或者它可能想要呈現立體內容,以及左右眼的緩衝區等等。 此 API 的初始版本支援將單一緩衝區呈現至畫面。

我們將簡報介面定義為一次呈現單一緩衝區的簡報內容形式。 簡報介面可以設定為可視化樹狀結構中的內容,而且可以一次在螢幕上顯示單一簡報緩衝區。 簡報管理員會以不可部分完成的方式更新一或多個簡報介面所顯示的緩衝區。

簡報管理員可用來為指定的 組合介面控點建立一或多個簡報介面。 每個組合介面句柄都可以系結至可視化樹狀結構中的一或多個視覺效果(透過 Windows.UI.Composition DirectComposition API 檔中概述的策略),以定義相關聯呈現介面與其出現在可視化樹狀結構中的關聯性。 您的應用程式可以更新一或多個呈現介面,這些介面會提交至系統,並在下一個目前作業上進行。

請注意,簡報管理員可以將任何簡報緩衝區呈現給任何想要的任何簡報介面。 沒有任何限制。 不過,您的應用程式會追蹤您發出的緩衝區,以及何處,以確保您不會嘗試在簡報介面顯示時,向該緩衝區發出新的繪圖。

將屬性套用至簡報介面

除了指定要在簡報介面中顯示的緩衝區之外,簡報也可以指定該簡報介面的各種其他屬性。 這些包括定義如何取樣來源紋理的屬性,包括 Alpha 模式和色彩空間、來源紋理如何轉換和配置,以及受保護內容的任何顯示或回寫限制。 所有這些方法都會在應用程式可以變更的簡報介面上公開為屬性 setter 方法,就像緩衝區更新一樣,在應用程式存在時生效。

呈現至呈現介面

在應用程式建立簡報介面、註冊簡報緩衝區,並指定在簡報期間發出的更新之後,您可以藉由呈現來套用這些屬性。 您的應用程式會透過簡報管理員發出簡報。 當存在由系統處理時,所有更新都會以不可部分完成的方式套用。 此外,您的應用程式也可以指定目前的其他屬性,例如它應該進行的理想時間( 目前的目標時間 時間)和其他罕見的屬性,例如預定的內容速率,可用來啟用系統上的自定義重新整理模式。 由於簡報可以在指定時間排程,因此您的應用程式可以事先發出多個簡報。 當到達排程的時間時,這些簡報會逐一處理。

同步處理簡報

您的應用程式必須確定,當它轉譯為緩衝區,併發出問題時,它會選取一個緩衝區,以轉譯目前尚未由任何其他未處理的上一個存在所參考的緩衝區,因為這樣做可能會覆寫那些呈現的緩衝區內容。 此外,如果您的應用程式在掃描硬體中顯示簡報介面目前顯示的緩衝區時發生問題,則其轉譯可能會無限期停止,因為 Direct3D 不允許 前端緩衝區轉譯。

組合交換鏈 API 提供一些不同的機制,可讓您的應用程式練習它所呈現之緩衝區的適當同步處理。

如果沒有參考緩衝區的未完成簡報,則表示緩衝區可供 使用 ,而且系統目前不會顯示緩衝區。 否則,無法使用。 API 會為每個表示緩衝區提供事件,指出緩衝區是否可用。 這是應用程式使用的最簡單同步處理方法。 在繪製至緩衝區並呈現它之前,您的應用程式可以確定其 可用的 事件已發出訊號。 特定緩衝區的可用事件在 API 中系結至簡報介面的那一刻會變成未對齊,並一直保持未對齊狀態,直到目前變成淘汰為止。

其次,簡報管理員會追蹤單 一簡報淘汰的柵欄 ,以與已完成簡報的應用程式通訊。 圍欄的值會對應到上一個開始 其生命週期淘汰 階段之目前標識碼,如下的 生命週期 一節所述。 一旦存在進入這個階段,可以放心地假設任何已由後續簡報取代的緩衝區都可以重複使用。

這個同步處理方法更進階,但可讓您更進一步控制工作流程的節流,而且對於目前目前佇列深度的系統狀態有更詳細的資訊。 如需目前生命週期的概觀,請參閱下一節。

簡報的生命週期

簡報管理員會將簡報排入系統,作為其 目前佇列的一部分。 系統進程會依佇列順序呈現。 此外,每個簡報都有唯一的 (簡報管理員) 相關聯的 簡報標識符,這是指派給簡報的遞增值,從第一個簡報的 1 開始,然後針對每個後續的簡報遞增 1。 此現成標識碼用於 API 的各個部分,例如同步處理基本類型與呈現統計數據,以參考該特定存在。

每個應用程式問題都遵循特定生命週期,如下所述。

一旦您的應用程式將變更設定為簡報的一部分,它就會使用簡報管理員實際發出簡報。 此時,據說現在正在 等待

一旦擱置,簡報就會坐在簡報管理員的目前佇列中,直到發生兩件事之一為止。

  • 現在會 變成取消。 簡報管理員可讓您的應用程式取消先前發行的簡報。 如果發生這種情況,那麼現在據說被取消,然後它立即退休。 在此轉換中,將會更新已取消簡報的相關緩衝區 可用 事件,不過目前的已淘汰圍欄將不會發出訊號,因為先前顯示的存在(在取消簡報之前)仍會顯示。 基於這個理由,您的應用程式無法使用目前的淘汰柵欄來判斷哪些簡報已取消。 您必須改為從每個已取消的目前狀態統計數據中瞭解這一點。 我們建議您的應用程式使用緩衝區 可用的 事件,在取消之後尋找可用的緩衝區。 顯示該簡報之後,上一個簡報將會開始淘汰程式,並更新目前的淘汰柵欄。
  • 如果未取消,則目前最終會準備好進行處理。 若要做好準備,必須符合兩個主要條件。
    • 呼叫目前之前,所有發出至 Direct3D 內容的繪圖工作都必須完成。 這可確保應用程式繪圖完成之前不會顯示緩衝區。
    • 如果指定了目前的目標時間,則我們預期能夠顯示目前的系統相對時間符合應用程式套用至目前的要求目標時間。

當系統決定要在螢幕上找到要顯示的簡報時,它會挑選已準備好要顯示的最後一個簡報。 如果有多個 就緒 簡報,則除了最新狀態之外,也會 略過所有已淘汰的簡報,並立即進入 已淘汰 狀態,此時會發出其緩衝區 可用 事件的訊號,但目前的淘汰圍欄將不會發出訊號,因為略過的目前不會從 顯示 的狀態轉換。

選擇顯示就緒簡報時,系統會開始執行工作以在畫面上顯示它。 這可能表示將緩衝區轉譯為 DWM 框架的一部分,然後要求硬體顯示畫面上的畫面,或表示在 iflip 的情況下,將緩衝區直接傳送到掃描硬體。 事件發生后,據說現在被 排入佇列。 概括而言,這表示它是在顯示的方式。

當硬體四處顯示目前時,據說會顯示該禮物。 它會在畫面上保持可見,直到後續的簡報出現並取代它。

當後續的簡報變成已排入佇列時,我們知道硬體最終會停止顯示目前的目前簡報。 此時,據說現在即將 退休

當隨後的簡報顯示時,即表示目前的簡報即將 淘汰

簡報管理員會 公開目前的淘汰柵欄,當簡報進入 淘汰 狀態時,會向每個簡報的目前標識碼發出訊號。 此訊號會向您的應用程式指出,將轉譯工作發行至與存在之緩衝區相關聯的緩衝區變得安全,而不會損毀先前的目前。 如果您的應用程式在目前 淘汰 狀態期間發出轉譯工作,則轉譯工作會排入佇列,直到目前進入 已淘汰 狀態,此時會執行轉譯工作。 如果呈現工作在目前淘汰之後發出,則會立即執行。

以下是此狀態變更的圖表。

簡報的生命週期

緩衝區、表面和呈現的圖表

下圖與簡報管理員、簡報緩衝區、簡報介面、簡報和更新有關。

緩衝區、表面和呈現的圖表

此圖表顯示簡報管理員,其中兩個簡報介面和三個簡報緩衝區,到目前為止已發出兩個已發行的簡報,第一個顯示緩衝區 1 在表面 1,而緩衝區 2 則為 surface 2。 第二個目前更新的介面 2 以顯示簡報緩衝區 3,而且沒有變更 surface 1 的系結。 顯示目前 2 之後,表面 1 會顯示緩衝區 1,而 surface 2 會顯示緩衝區 3,這可以在簡報管理員中物件的目前狀態中看到。 佇列中的每個存在都會在系統中處理時生效。

注意

因為 Present 2 未變更 surface 1 的緩衝區,因此 surface 1 會從上一個目前保留至緩衝區 1。 從這個意義上說,目前 2 中緩衝區 1 上有「隱含」參考,因為顯示目前 2 之後,surface 1 會維持系結至緩衝區 1。

將簡報介面新增至可視化樹狀結構

簡報介面是構成可視化樹狀結構一部分的內容。 每個簡報介面都會系結至 組合介面控點。 在 Windows.UI.Composition 中,您可以為預先存在的組合介面控點建立表面筆刷,並系結至 Sprite 視覺效果。 在 DirectComposition 中,可以從預先存在的組合介面句柄建立組合介面,並系結為內容至視覺效果。 如需詳細資訊,請參閱每個 API 的個別檔。

建置為使用此 API 的 Windows Media Foundation 之類的 API,會公開將預先系結至簡報介面的組合介面控點。 應用程式也可以建立自己的組合介面句柄,以後續系結至簡報介面,並藉由呼叫 DCompositionCreateSurfaceHandle 新增至可視化樹狀結構。

閱讀簡報統計數據

組合交換鏈 API 會 公開簡報統計數據,其中描述處理特定呈現方式的各種資訊。 資訊通常可能描述如何在 DWM 框架中使用簡報介面、顯示時間點、是否全部顯示,依此說明。

有不同類型的簡報統計數據,其設計目的是在未來版本的API中可擴充。 應用程式會使用簡報管理員來註冊以接收其感興趣的統計數據類型。 然後,這些統計數據會推送至簡報管理員的 統計數據佇列。 簡報管理員會將 統計數據可用事件 公開給應用程式,這是事件句柄,指出統計數據佇列何時有可供讀取的統計數據專案。 這樣做時,您的應用程式可以將第一個統計數據專案從佇列中清除佇列、讀取並處理它。 當您的應用程式已讀取佇列中目前的所有統計數據時,簡報管理員將會重設可用的統計數據事件。 應用程式通常會在迴圈中讀取和處理統計數據,直到統計數據可用事件重設為止。 您的應用程式通常會在用來發出問題的相同工作循環中處理此統計數據佇列。 建議的使用模式是將處理統計數據優先於發出新簡報,以確保佇列不會溢位。

佇列有將追蹤的統計數據數目上限,其順序為 512-1024 統計數據。 佇列深度上限應該足以在正常情況下儲存大約 5 秒的統計數據。 如果統計數據佇列已滿,而且會報告更多統計數據,則原則是最舊的統計數據將會淘汰以騰出空間。