Share via


DXGI 翻轉模型

Windows 8新增在 DXGI 1.2 中翻轉簡報模型及其相關簡報統計資料的支援。 Windows 8的 DXGI 翻轉簡報模型類似于 Windows 7 的Direct3D 9EX 翻轉模式簡報。 視訊或畫面播放速率型簡報應用程式,例如遊戲,可以使用翻轉簡報模型來獲益最多。 使用 DXGI 翻轉簡報模型的應用程式可減少系統資源負載並提升效能。 應用程式也可以透過翻轉簡報模型使用簡報統計資料增強功能,藉由提供即時意見反應和更正機制,以更妥善地控制簡報的速率。

比較 DXGI 翻轉模型和 BitBlt 模型

執行時間會使用位區塊傳輸 (bitblt) 和翻轉簡報模型,在顯示器監視器上呈現圖形內容。 bitblt 和翻轉呈現模型之間的最大差異在於,後端緩衝區內容如何取得組合的Windows 8 DWM。 在 bitblt 模型中,後端緩衝區的內容會在每次呼叫 IDXGISwapChain1::P resent1時複製到重新導向介面中。 在翻轉模型中,所有背景緩衝區都會與桌面視窗管理員共用, (DWM) 。 因此,DWM 可以直接從這些背景緩衝區撰寫,而不需要執行任何其他複製作業。 一般而言,翻轉模型更有效率。 翻轉模型也提供更多功能,例如增強的目前統計資料。

如果您有使用 Windows Graphics Device Interface (GDI) 直接寫入 HWND 的舊版元件,請使用 bitblt 模型。

當應用程式處於視窗模式時,DXGI 翻轉模型的效能改善相當重要。 此表格中的順序和圖例會比較記憶體頻寬使用量,以及選擇翻轉模型與 bitblt 模型的視窗式應用程式讀取和寫入。

步驟 提供給 DWM 的 BitBlt 模型 DXGI 翻轉模型呈現至 DWM
1. 應用程式會更新其框架 (寫入)
應用程式會更新其框架 (寫入)
2. Direct3D 執行時間會將表面內容複寫到 DWM 重新導向介面, (讀取、寫入)
Direct3D 執行時間會將應用程式介面傳遞至 DWM
3. 共用表面複製完成之後,DWM 會將應用程式介面轉譯到畫面上, (讀取、寫入)
DWM 會將應用程式介面轉譯到螢幕上, (讀取、寫入)

 

blt 模型和翻轉模型的比較圖例

翻轉模型可藉由減少 Direct3D 執行時間的讀取和寫入數目,藉此減少 DWM 的視窗式框架組合的系統記憶體使用量。

如何使用 DXGI 翻轉模型

以 Windows 8 為目標的 Direct3D 11.1 應用程式會建立交換鏈結,並使用DXGI_SWAP_CHAIN_DESC1結構之 SwapEffect成員中設定的 DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL列舉值來建立翻轉模型。 當您將 SwapEffect 設定為 DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL時,也請將 DXGI_SWAP_CHAIN_DESC1 的這些成員設定為指定的值:

  • BufferCount 的值介於 2 到 16 之間,以防止效能降低,因為等候 DWM 釋放先前的簡報緩衝區。
  • 格式 為 DXGI_FORMAT_R16G16B16A16_FLOAT、DXGI_FORMAT_B8G8R8A8_UNORM 或 DXGI_FORMAT_R8G8B8A8_UNORM
  • SampleDesc成員指定的DXGI_SAMPLE_DESC結構計數成員,並將DXGI_SAMPLE_DESCQuality成員指定為零,因為不支援多個範例反鋸齒 (MSAA)

如果您在 Windows 7 或舊版作業系統上使用 DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL ,裝置建立會失敗。 當您使用翻轉模型時,可以在視窗模式中使用全螢幕呈現統計資料。 全螢幕行為不會受到影響。 如果您將Null傳遞給視窗交換鏈結的IDXGIFactory2::CreateSwapChainForHwnd的 pFullscreenDesc參數,並將SwapEffect設定為DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL,執行時間會建立一個額外的背景緩衝區,並輪替每一個控制碼屬於呈現時間成為前端緩衝區的緩衝區。

當您使用翻轉模型時,請考慮下列秘訣:

  • 每個 HWND使用一個翻轉模型交換鏈結。 請勿將多個翻轉模型交換鏈結的目標設為相同的 HWND
  • 請勿搭配 GDI 的 ScrollWindowScrollWindowEx 函 式使用翻轉模型交換鏈結。 某些 Direct3D 應用程式會使用 GDI 的 ScrollWindowScrollWindowEx 函式,在發生使用者捲動事件之後更新視窗內容。 ScrollWindowScrollWindowEx 會在使用者捲動視窗時,在螢幕上執行視窗內容的位。 這些函式也需要 GDI 和 Direct3D 內容的 bitblt 模型更新。 當應用程式處於視窗模式時,使用任一函式的應用程式不一定會顯示幕幕上捲動的可見視窗內容。 我們建議您不要使用 GDI 的ScrollWindow 和 ScrollWindowEx函式,而是改為在畫面上重新繪製 GDI 和 Direct3D 內容,以回應捲動。
  • 在其他 API 未以其他 API 為目標的 HWND 中使用翻轉模型,包括 DXGI bitblt 簡報模型、Direct3D 的其他版本或 GDI。 因為 bitblt 模型會維護額外的表面複本,所以您可以透過 Direct3D 和 GDI 的分次更新,將 GDI 和其他 Direct3D 內容新增至相同的 HWND 。 當您使用翻轉模型時,只會顯示執行時間傳遞至 DWM 之翻轉模型交換鏈結中的 Direct3D 內容。 執行時間會忽略所有其他 bitblt 模型 Direct3D 或 GDI 內容更新。

DXGI 翻轉模型應用程式的畫面同步處理

目前統計資料是媒體應用程式用來同步處理視訊和音訊串流的畫面時間資訊,並從視訊播放問題中復原。 App 可以使用目前統計資料中的畫面時間資訊來調整其視訊畫面的呈現速率,以取得更順暢的簡報。 若要取得目前的統計資料資訊,請呼叫 IDXGISwapChain::GetFrameStatistics 方法來取得 DXGI_FRAME_STATISTICS 結構。 DXGI_FRAME_STATISTICS 包含 IDXGISwapChain1::P resent1 呼叫的相關統計資料。 翻轉模型交換鏈結可在視窗和全螢幕模式中提供統計資料資訊。 對於視窗模式中的 bitblt 模型交換鏈結,所有 DXGI_FRAME_STATISTICS 值都是零。

針對翻轉模型呈現統計資料,在這些情況下, IDXGISwapChain::GetFrameStatistics 會傳回 DXGI_ERROR_FRAME_STATISTICS_DISJOINT

  • 第一次呼叫 GetFrameStatistics,指出序列的開頭
  • 模式變更:將視窗模式切換為全螢幕或全螢幕或全螢幕轉換

PresentRefreshCountSyncRefreshCountSyncQPCTime成員DXGI_FRAME_STATISTICS中的值具有下列特性:

  • 當應用程式在每個 vsync 上出現時,PresentRefreshCount等於SyncRefreshCount
  • 提交目前時,SyncRefreshCount會在 vsync 間隔上取得,SyncQPCTime大約是與 vsync 間隔相關聯的時間。

IDXGISwapChain::GetLastPresentCount方法會傳回最後一個存在計數,也就是與交換鏈結相關聯之顯示裝置所發出之最後一次成功IDXGISwapChain1::P resent1呼叫的目前識別碼。 這個現用識別碼是DXGI_FRAME_STATISTICS結構的PresentCount成員值。 對於 bitblt 模型交換鏈結,在視窗模式中,所有 DXGI_FRAME_STATISTICS 值都是零。

避免、偵測及從問題中復原

執行下列步驟,以避免、偵測及從畫面簡報中的問題復原:

  1. 佇列 IDXGISwapChain1::P resent1 呼叫 (,也就是呼叫 IDXGISwapChain1::P resent1 多次,這會導致它們收集在佇列) 中。

  2. 建立現成佇列結構,以儲存 IDXGISwapChain1::P resent1的目前識別碼 (由 IDXGISwapChain::GetLastPresentCount 傳回的所有成功提交 IDXGISwapChain1::GetLastPresentCount) 和相關聯的匯出/預期 PresentRefreshCount 值。

  3. 若要偵測問題:

    • 呼叫 IDXGISwapChain::GetFrameStatistics
    • 在此畫面中,取得目前識別碼 (PresentCount) 和 vsync 計數,其中作業系統會將最後一個映射呈現給監視器 (PresentRefreshCount) 。
    • 擷取與目前識別碼相關聯的預期 PresentRefreshCount ,而且您先前儲存在目前佇列結構中。
    • 如果實際的 PresentRefreshCount 晚于預期的 PresentRefreshCount,則發生問題。
  4. 若要從問題中復原:

    • 計算要略過以從問題中復原的畫面數。 例如,如果步驟 3 顯示目前識別碼的預期 vsync 計數 (PresentRefreshCount) (PresentCount) 為 5,而目前識別碼的實際 vsync 計數為 8,則要從問題中復原的畫面數是 3 個畫面格。

    • 在此對IDXGISwapChain1::P resent1的呼叫中,將 0 傳遞給SyncInterval參數,以捨棄並略過此數目的畫面格。

      注意

      如果問題是由大量的畫面格所組成,請呼叫 IDXGISwapChain1::P resent1 ,並將 Flags 參數設定為 DXGI_PRESENT_RESTART 以捨棄並略過所有未處理的佇列簡報。

       

以下是從畫面簡報中的問題中復原的範例案例:

從畫面簡報中的問題中復原的範例案例圖例

在範例案例中,您預期畫面 A 會在 1 的 vsync 計數上顯示畫面。 但您實際上偵測到畫面上顯示 A 的 vsync 計數為 4。 因此,您會判斷發生問題。 接著,您可以捨棄 3 個畫面格,也就是說,您可以在 3 次對IDXGISwapChain1::P resent1的呼叫中傳遞 0 至SyncInterval參數。 在上述範例案例中,若要從問題中復原,您需要總共 8 個 IDXGISwapChain1::P resent1 呼叫。 然後,第 9 個畫面格會根據您預期的 vsync 計數來顯示。

以下是簡報事件的時間表。 每個垂直線都代表 vsync。 水準方向是時間,這會向右增加。 您可以使用此圖來想像如何發生問題。

簡報事件的時間表圖例

此圖說明此順序:

  1. 應用程式會在 vsync 上喚醒、轉譯藍色、呼叫 IDXGISwapChain1::P resent1,然後返回睡眠。

  2. 圖形處理單位 (GPU) 從閒置喚醒、執行轉譯為藍色,然後回到睡眠狀態。

  3. DWM 會在下一個 vsync 喚醒、將藍色組成其返回緩衝區、呼叫 IDXGISwapChain1::P resent1,然後返回睡眠狀態。

  4. 應用程式喚醒、轉譯綠色、呼叫 IDXGISwapChain1::P resent1,然後返回睡眠。

    注意

    當 GPU 執行藍色的組成時,應用程式會同時執行。

     

  5. 接下來,GPU 會呈現應用程式的綠色。

  6. 最後,數位到類比轉換器 (DAC) 在下一個 vsync 上顯示監視器上的 DWM 組合結果。

從時間表,您可以想像目前統計資料的延遲,以及可能發生問題的方式。 例如,若要顯示出現在螢幕上綠色的 DWM 問題,請想像擴大綠色/紅色方塊,讓綠色/紅色方塊的右側符合紫色/紅色方塊的右邊。 在此案例中,DAC 會顯示兩個藍色框架,然後顯示綠色框架。 您可以看到此問題發生于讀取目前統計資料。

使用翻轉模型、已變更的矩形和捲動區域來增強簡報