共用方式為


硬體翻轉佇列

本文說明從 Windows 11 (WDDM 3.0) 開始支援的硬體翻轉佇列功能。 硬體翻轉佇列允許將多個未來的畫面提交至顯示控制器佇列。 當顯示控制器處理多個佇列畫面時,CPU 和部分 GPU 可以轉換至較低的電源狀態,從而提高功能硬體上視訊播放場景的電源效率。

WDDM 3.0 之前的翻轉佇列模型

許多新式顯示控制器都支援將要依序顯示的多個畫面排入佇列的能力。 從 WDDM 2.1 開始,OS 支援多個未完成的翻轉覆寫要求,這些要求要在下一個 VSync 上呈現。 顯示迷你埠驅動程式 (KMD) 會透過 DXGK_DRIVERCAPS 中的 MaxQueuedMultiPlaneOverlayFlipVSync 值來指出此支援。 這項功能有助於減少高畫面速率遊戲案例中的延遲,其中多個畫面會以間隔 0 循序轉譯,目的是只顯示最新的畫面。

在影片播放場景中,多個將來要顯示的幀的內容是已知的,可以在GPU上排入隊列。 這種高級隊列允許 CPU 在處理排隊幀時進入低功耗狀態,從而節省大量電量。 不過,在 WDDM 3.0 之前,OS 沒有機制可以提交多個畫面,這些畫面需要在螢幕上停留至少一個 VSync 間隔,而不需要進一步的 CPU 介入。 基本硬體翻轉佇列一節介紹了一種解決方案,可讓 CPU 進入低電源狀態,並將佇列幀處理卸載給 GPU。

在 WDDM 3.0 之前的遊戲案例中,GPU 完成將場景轉譯至交換鏈結回回緩衝區之後,會向 CPU 進行往返,以提交要求,將畫面內容呈現至螢幕。 對於接近 VSync 完成的繁重 GPU 工作負載,此來回可能會導致畫面延遲並錯過預期的目標時間,進而造成可觀察到的畫面故障。 進階硬體翻轉佇列區段引進了一種機制,可避免 CPU 的來回操作,並以低延遲將已完成的畫面呈現於螢幕上。 進階硬體翻轉佇列要求必須具備基本硬體翻轉佇列和 GPU 硬體排程階段 2 的功能。

基本硬體翻轉佇列

下圖說明呈現三個畫面的情況,每個畫面都會在畫面上停留一個 VSync 間隔。

圖表說明三個畫面各自停留在螢幕上一個 VSync 間隔。

圖中的填滿模式顯示 Dxgkrnl 軟體翻轉佇列處理和應用程式執行緒必須喚醒並執行 CPU 工作的時間。 在每個 VSync 上,顯示控制器必須向 OS 發出已完成翻轉的 CPU 通知,而且 OS 必須提交下一個翻轉要求。 應用程式也必須在每個 VSync 上喚醒,並查詢目前的統計資料,以最終瞭解何時顯示三個批次中的最後一個畫面。

從 WDDM 3.0 開始,硬體翻轉佇列 DDI 能將多個未來畫面提交至顯示控制器佇列。 如前所述,此機制允許 CPU 和 GPU 的部分在顯示控制器處理多個佇列幀時轉換為較低電源狀態。 此轉換可改善功能硬體上視訊播放案例的電源效率。

下圖說明建議的架構。

示範基本硬體翻轉佇列機制的圖表。

使用硬體翻轉佇列方法時,應用程式和 Dxgkrnl CPU 元件都會在 v2v4 時間之間的兩個 VSync 間隔內完全閒置,讓 CPU 進入低電源狀態。 只有在應用程式要求等待的畫面 N+2 完成時,才會通知 CPU。

進階硬體翻轉佇列

在 WDDM 3.0 之前的遊戲場景中,當 GPU 完成將場景渲染到交換鏈結的背緩衝區後,需要來回切換至 CPU,以提交請求,將幀內容顯示在顯示器上。 下圖顯示此案例。

描述需要 CPU 來回的幀完成的圖表。

此往返過程的成本可能會導致畫面錯過其目標,如果渲染完成時太接近 VSync,如下圖所示。

說明由於所需的 CPU 往返而遺漏的幀的圖表。

某些顯示控制器原生支援等候條件,讓顯示器在 GPU 完成轉譯畫面後提交翻轉要求,而不需要 CPU 來回。 因為硬體翻轉佇列可以將已完成的畫面 N 提交至顯示器,而不需要 CPU 來回,所以可能會避免遺漏畫面,如下圖所示。

顯示框架完成的圖表,無需 CPU 來回過程。

本文的其餘部分將討論基本的硬體翻轉佇列功能。

DDI 支援

已新增下列 DDI 以支援硬體翻轉佇列功能。

檢查功能可用性

硬體翻轉佇列需要作業系統進行啟用或停用的協商。 支援硬體翻轉佇列的 KMD 必須先在裝置啟動期間呼叫 DXGKCB_QUERYFEATURESUPPORT ,且 FeatureIdDXGK_FEATURE_HWFLIPQUEUE ,以判斷 OS 是否允許啟用硬體翻轉佇列。

只有在回呼成功且 Enable 被設為 TRUE 時,才能使用硬體翻轉佇列。

KMD 可以在硬體翻轉佇列的啟動和實驗階段中使用下列範例程式碼。


DXGKARGCB_QUERYFEATURESUPPORT HwFlipQueueEnabledArgs = {};
HwFlipQueueEnabledArgs.DeviceHandle = DeviceHandle;
HwFlipQueueEnabledArgs.FeatureId = DXGK_FEATURE_HWFLIPQUEUE;
HwFlipQueueEnabledArgs.DriverSupportState = DXGK_FEATURE_SUPPORT_EXPERIMENTAL;

if (!NT_SUCCESS(pDxgkInterface->DxgkCbQueryFeatureSupport(&HwFlipQueueEnabledArgs)) ||
    !HwFlipQueueEnabledArgs.Enabled)
{
    // Disable hardware flip queue because the OS didn't allow it.           
}
else
{
    // Enable hardware flip queue because the OS allowed it.
}

在驅動程式啟動期間,即使可以在不啟用 GPU 硬體排程的情況下啟用硬體翻轉佇列,但這種組合沒有獲得正式支援。 Windows 目前需要啟用 GPU 硬體排程,才能在正式發行的驅動程式上啟用基本硬體翻轉佇列。

指出硬體佇列功能

MaxHwQueuedFlips 已新增至 DXGK_DRIVERCAPS ,以指出硬體翻轉佇列支援。 如果 OS 允許硬體翻轉佇列支援,如先前所述,支援硬體翻轉佇列的 KMD 應該將 MaxHwQueuedFlips 設定為大於 1 的值。 當 MaxHwQueuedFlips 大於 1 時,KMD 表示顯示硬體最多支援 MaxHwQueuedFlips 未來畫面,這些畫面可以排入佇列,以針對 GPU 上的指定 VidPnSource 顯示。 OS 遵循驅動程式提供的可預先排入的翻轉類型限制。

HwQueuedFlipCaps 也已新增至 DXGK_DRIVERCAPS。 此成員目前保留供系統使用;驅動程式不應該使用它。

切換目標時間和目標時間戳記格式

當 OS 將翻轉要求提交至硬體翻轉佇列時,它也會傳送目標翻轉時間。 達到目標翻轉時間後,可以讓使用者看到翻轉。

OS 會使用從 KeQueryPerformanceCounter 取得的 CPU 時鐘計數器單位來傳遞目標畫面時間,並解譯實際畫面時間。

提交在排隊的翻轉任務

傳遞給 KMD 的 DxgkDdiSetVidPnSourceAddressWithMultiPlaneOverlay3 回呼函式的 DXGKARG_SETVIDPNSOURCEADDRESSWITHMULTIPLANEOVERLAY3 結構被修改如下,以便啟用佇列化翻轉的提交:

  • 下列三個成員已新增至 OutputFlagsDXGK_SETVIDPNSOURCEADDRESS_OUTPUT_FLAGS 結構。 如需這些成員的詳細數據,請參閱 DxgkDdiSetVidPnSourceAddressWithMultiPlaneOverlay3 重試和失敗案例

    • HwFlipQueueDrainNeeded
    • HwFlipQueueDrainAllPlanes
    • HwFlipQueueDrainAll來源
  • 已新增 TargetFlipTime 成員。 TargetFlipTime 會以 QPC 單位描述目標翻轉時間。 當時鐘達到此值時,使幀能夠在遵循 VSync 和避免撕裂的情況下發送到顯示器。 如果先前排入佇列的擱置翻轉存在,OS 會保證針對翻轉要求所參考的每個 MPO 平面, TargetFlipTime 大於或等於此平面的任何擱置翻轉目標時間。 換句話說,可以有具有相同或增加時間戳記的翻轉序列,但不能有時間回溯的序列。

DxgkDdiSetVidPnSourceAddressWithMultiPlaneOverlay3 重試和失敗案例

由於翻轉程序未完成,無法將請求排入硬體佇列

有幾種特殊情況可能會阻止 KMD 在其他翻頁請求待處理時將翻頁請求排入佇列。 在這種情況下,KMD 應該從 DxgkDdiSetVidPnSourceAddressWithMultiPlaneOverlay3 傳回 STATUS_RETRY,並將 HwFlipQueueDrainNeeded 設定為等於 1。 OS 會在完成受翻轉影響的平面上所有擱置的翻轉之後,以及達到目標時間之後,再次嘗試提交翻轉要求。

在某些情況下,顯示硬體可能需要在所有平面上完成擱置的翻轉,而不只是傳入翻轉要求所參考的平面。 在此情況下, HwFlipQueueDrainNeededHwFlipQueueDrainAllPlanes 旗標都應該設定為 1,而且 KMD 應該傳回 STATUS_RETRY。

同樣地,顯示硬體可能需要完成所有 VidPn 來源上的待處理翻轉,才能重新配置內部資源。在此情況下,必須設定 HwFlipQueueDrainAllSourcesHwFlipQueueDrainNeeded 標誌,而且 KMD 應該傳回 STATUS_RETRY 狀態。

此外,KMD 可以向 OS 指出是否應該在裝置 IRQL 上完成重新提交 (PrePresentNeeded 設定為 0) ,或 OS 是否應該在 PASSIVE_LEVEL 執行此呼叫 (PrePresentNeeded 設定為 1) 。 如果 KMD 仍傳回STATUS_RETRY即使該 VidPnSourceId 上沒有更多擱置翻轉,則此狀況會被視為 無效的參數失敗

請務必確保 MaxHwQueuedFlips 的值仍然能夠反映可排入 MPO 平面佇列的簡單僅限位址變更翻轉的最大數目。 STATUS_RETRY機制應該用於無法深度排入佇列的更複雜的翻轉要求,例如平面設定變更。

無效參數失敗

在硬體翻轉佇列模型中,作業系統對失敗翻轉請求的處理方式已重新設計,以允許更好的偵錯性。 當 KMD 無法處理翻轉要求時,它應該從 DxgkDdiSetVidPnSourceAddressWithMultiPlaneOverlay3 傳回STATUS_INVALID_PARAMETER。 根據作業系統設定,作業系統會執行下列其中一個動作:

  • 核心除錯器中斷與錯誤檢查:此行為通常會在開發/發行前版本上啟用,以便在失敗狀況發生時,提供更好的除錯能力。
  • 即時核心傾印,後面接著 TDR:零售終端使用者行為。

指定 VSync 中斷行為

為了在佇列翻轉案例中實現省電,作業系統通常會暫停常規 VSync 中斷,以使 CPU 保持低功耗狀態。 不過,某些翻轉操作會標示為需要引發中斷,讓應用程式觀察已完成的呈現批次,並將進一步的工作排入等待執行。 在某些情況下,應用程式會要求在每個 VSync 中斷信號時喚醒應用程式,而不論是否有待處理的翻轉請求。 相反地,在完全閒置的系統上,VSync 中斷會暫停,直到出現新的簡報活動或 VSync 接聽程式為止。

為了處理所有這些情況,已引入以下的驅動程式回呼和回呼結構:

KMD 會在 DRIVER_INITIALIZATION_DATA 中提供其 DxgkDdiSetInterruptTargetPresentId 函式的指標

OS 會呼叫 DxgkDdiSetInterruptTargetPresentId 來指定目標 PresentId,以便在對應的頁面翻轉完成時觸發 VSync 中斷。 此函式會在裝置中斷層級(DIRQL)呼叫,以與DxgkDdiSetVidPnSourceAddress和 VSync 中斷同步。

與 DxgkDdiControlInterrupt 的互動

當透過 DxgkDdiControlInterruptDxgkDdiControlInterrupt2//DxgkDdiControlInterrupt3 完全停用 VSync 中斷時,無論中斷目標 PresentId 值為何,它們都會保持停用狀態。 KMD 必須儲存最新的中斷目標目前識別碼,以便在再次啟用 VSync 時遵循。

透過 DxgkDdiControlInterruptXxx 啟用 VSync 中斷時,中斷目標目前識別碼 (pSetInterruptTargetPresentId) 會提供更精細的控制,如下所示:

  • 當目標目前標識碼設定為 UINT64_MAX 時,在目標目前標識碼再次變更之前,不需要 VSync 中斷。 VSync 中斷已停用,但 KMD 必須實作 DXGK_VSYNC_DISABLE_KEEP_PHASE 行為,以重新啟用中斷。

  • 當目標目前識別碼設定為 0 時,每個 VSync 都需要中斷。

  • 對於任何其他當前的 ID 值,如果當前掃描的 PresentId >= InterruptTargetPresentId,則會產生中斷。

當有多個 MPO 平面可用時,如果任何平面需要,則應該引發 VSync 中斷。

使用 DxgkDdiSetInterruptTargetPresentId 停用雙階段 VSync

如果 OS 呼叫 DxgkDdiSetInterruptTargetPresentId 在某個平面上設定了 InterruptTargetPresentId,並因此導致在此 VidPnSource 上完全停用 VSync(也就是說,這個平面是最後一個保持 VSync 啟用的平面,現在該平面也停用了 VSync),KMD 應該停用 VSync 中斷,但在硬體中保留 VSync 階段(DXGK_VSYNC_DISABLE_KEEP_PHASE)。 在特定時間之後(通常相當於兩個 VSync 周期),OS 將會接著呼叫 DxgkDdiControlInterruptXxx 並使用 DXGK_VSYNC_DISABLE_NO_PHASE。 此呼叫可確保 KMD 有機會停用 VSync 階段和 VSync 時鐘,以節省最大電源,並維護與非硬體翻轉佇列系統的效能同位。

排隊翻轉取消

在全螢幕狀態轉換或應用程式結束等情況下,可能需要取消未來的佇列翻轉。 為了處理這些情況,引進了下列驅動程式回調和相關結構:

KMD 提供其 DRIVER_INITIALIZATION_DATADxgkDdiCancelFlips 函式的指標。

OS 會在呼叫 DxgkDdiCancelFlips 時指定要取消的佇列翻轉範圍,而 KMD 會向 OS 報告它能夠同步取消的翻轉範圍。

以下範例說明了單個平面上翻轉取消的機制和同步情況。 (作業系統在 Windows 11 版本 22H2 中不支援非同步取消。)假設下列翻轉正在排入硬體翻轉佇列:

  • PresentId N
  • 時間 t0 PresentId N+1
  • 時間 t1 PresentId N+2
  • 時間 t2 PresentId N+3
  • 時間 t3 PresentId N+4
  • 時間 T4

然後,OS 會決定取消翻轉 N+2N+3N+4,因此會呼叫 DxgkDdiCancelFlips ,並將 PresentIdCancelRequested 設定為 N+2

當 KMD 檢查硬體翻轉佇列狀態時,它會判斷:

  • Flip N+2 已傳送至顯示硬體,且無法在通話時取消。
  • 翻轉 N+3N+4 可以從硬體翻轉佇列中同步刪除,而不會產生副作用。

因此,KMD 會將 PresentIdCancelled 設定為 N+3 ,並照常完成 N+2

作業系統會將 N+3N+4 標記為已取消,並將 NN+1N+2 視為正在進行中。 當引發下一個 VSync 中斷時,翻轉隊列日誌將像往常一樣指示 NN+1N+2 的時間戳記。

同步取消翻轉的範圍必須是連續的,而且當不是零時,會假設包含提交給 KMD 的最後一個目前識別碼。 換句話說,兩個同步取消翻轉範圍內不能有任何間隙。

取消多個平面上的聯鎖翻轉

聯鎖翻轉是藉由呼叫具有多個平面和 PresentIds 的 DxgkDdiSetVidPnSourceAddress 來提交。 作業系統與 KMD 之間的合約如下:

  • 必須讓這組平面在同一個 VSync 上顯示出來。
  • 不允許顯示硬體在一個 VSync 上只顯示部分平面,而在下一個 VSync 上顯示其餘平面。

在硬體翻轉佇列模型中,此類互鎖翻轉會透過在呼叫 DxgkDdiCancelFlips 時傳遞多個平面和 PresentIds 而被取消。 在這類情況下傳遞的平面集必須對應至待處理的互鎖翻轉要求,而 KMD 關於所有互鎖 PresentId 的決定必須相同:

  • 請勿取消,或
  • 同步取消

DxgkDdiCancelFlips 會在裝置中斷層級 (DIRQL) 呼叫,以與 DxgkDdiSetVidPnSourceAddress 和 VSync 中斷同步處理。

取得佇列翻轉的目前統計資料

由於硬體翻轉佇列策略旨在避免每次 VSync 都喚醒 CPU,因此需要一種機制來保存最近幾次佇列翻轉的幀顯示時間。

支援硬體翻轉佇列的圖形驅動程式必須將資訊寫入 OS 提供的翻轉佇列記錄緩衝區,以針對每個作用中 VidPnSource 的指定 MPO 平面,每個已完成或取消的翻轉。

OS 保證在對於每個作用中 VidPnSource,於呼叫第一個指定 MPO 平面的 DxgkDdiSetVidPnSourceAddress 之前,首先於呼叫 DxgkDdiSetFlipQueueLogBuffer 時提供翻轉佇列記錄指標。 當翻轉佇列沒有任何未完成的要求時,允許 OS 終結翻轉佇列記錄緩衝區。 在此情況下,它會在下一個 DxgkDdiSetVidPnSourceAddress 呼叫之前提供新的記錄指標。 翻轉佇列記錄是循環的。 寫入 [NumberOfEntries-1] 專案之後,下一個記錄專案會是 [0]。

完成一批佇列翻轉之後,KMD 必須保證已完成翻轉的翻轉佇列記錄檔會在這兩個時間點中最早更新:

  • VSync 中斷處理常式,用於需要引發中斷的翻轉操作。
  • 回應作業系統發出的明確 DxgkDdiUpdateFlipQueueLog 要求。

翻轉佇列記錄 DDI

已新增下列翻轉佇列記錄相關回呼及相關結構:

KMD 在DRIVER_INITIALIZATION_DATA中提供其函式的指標。

VSync 中斷機制的更新

已對 DXGKARGCB_NOTIFY_INTERRUPT_DATA 結構進行下列變更,以實作硬體翻轉佇列模型的 VSync 中斷:

  • DXGK_INTERRUPT_CRTC_VSYNC_WITH_MULTIPLANE_OVERLAY3枚舉值已新增為 InterruptType
  • CrtcVSyncWithMultiPlaneOverlay3 結構已新增至聯集。 CrtcVSyncWithMultiPlaneOverlay3 的語意類似於現有的 CrtcVSyncWithMultiPlaneOverlay2 結構,不同之處在於 CrtcVSyncWithMultiPlaneOverlay3.pMultiPlaneOverlayVSyncInfo 會指向翻轉佇列記錄中先前未報告的 PresentId 範圍,而不是每個平面的單一最後完成 PresentId。
  • 已針對 CrtcVSyncWithMultiPlaneOverlay3pMultiPlaneOverlayVSyncInfo 成員新增DXGK_MULTIPLANE_OVERLAY_VSYNC_INFO3結構。

再次使用基本硬體翻轉佇列的範例圖表:

示範基本硬體翻轉佇列機制的圖表。

假設在提交翻轉 N 時,FirstFreeFlipQueueLogEntryIndex 已設定為 40,然後完成 NN+1N+2 個呈現。

單一平面配置在 v2、v3、v4 分別完成三個 PresentId NN+1N+2 之後,KMD 已在其紀錄緩衝區中寫入三個新條目,索引為 40、41 和 42。 KMD 會在 CrtcVSyncWithMultiPlaneOverlay3 結構中報告 FirstFreeFlipQueueLogEntryIndex 值 43。 OS 會觀察到 FirstFreeFlipQueueLogEntryIndex 從 40 變更為 43,並從日誌條目 40、41 和 42 讀取。 KMD 需要設定下列翻轉佇列記錄緩衝區值,如下所示:

  • VidPnTargetId:與 CrtcVSyncWithMultiPlaneOverlay2 中的含義相同

  • PhysicalAdapterMask:與 CrtcVSyncWithMultiPlaneOverlay2 中的意義相同

  • MultiPlaneOverlayVSyncInfoCount = 1

  • pMultiPlaneOverlayVSyncInfo[0].LayerIndex = 0

  • pMultiPlaneOverlayVSyncInfo[0] 的FirstFreeFlipQueueLogEntryIndex = 43

  • LogBufferAddressForPlane0[40].PresentId = N

  • LogBufferAddressForPlane0[40]PresentTimestamp = v2

  • LogBufferAddressForPlane0[41].PresentId = N+1

  • LogBufferAddressForPlane0[41].PresentTimestamp = v3

  • LogBufferAddressForPlane0[42].PresentId = N+2

  • LogBufferAddressForPlane0[42].PresentTimestamp = v4

明確翻轉佇列記錄更新要求

在某些情況下,OS 需要取得上次完成翻轉批次的相關資訊,而不需要等候 VSync 中斷。 在這種情況下,OS 會明確呼叫 DxgkDdiUpdateFlipQueueLog ,以要求 KMD 從其專屬顯示硬體資料結構讀取,並將過去的翻轉資訊寫入翻轉佇列記錄。 日誌的語意與先前所述相同;唯一的變更是 FirstFreeFlipQueueLogEntryIndex 會在 VSync 中斷外部傳回 OS。

DxgkDdiUpdateFlipQueueLog 會在裝置中斷層級 (DIRQL) 呼叫,而且它與 DxgkDdiSetVidPnSourceAddressWithMultiPlaneOverlay3 DDI 位於相同的同步處理類別中。

在硬體翻轉佇列中存在佇列翻轉時的顯示模式變更和電源轉換

Dxgkrnl 確保在進行模式變更或關閉監視器電源之前,會完成或取消硬體翻轉佇列中已排入佇列的翻轉作業。

將 Present 要求對應至硬體翻轉佇列時間戳記

在特定介面卡上啟用硬體翻轉佇列時,所有翻轉呼叫都會附帶時間戳記。 換句話說,KMD 不需要處理舊的和新的 DxgkDdiSetVidPnSourceAddress 語意的混合。

OS 會自動將目前的基於間隔的 Present API 要求轉換為使用時間戳記的翻轉呼叫以連接至 KMD。 以下各節討論各種案例,以及如何將它們映射到 KMD 收到的旗標、持續時間和時間戳記的組合。

撕裂和非撕裂翻轉語意

啟用硬體翻轉佇列時,撕裂翻轉的語意在概念上是相同的。 達到TargetFlipTime之後,KMD 應該提交翻轉顯示,同時仍需符合FlipImmediateFlipImmediateNoTearingFlipOnNextVSync等旗標。 換句話說,KMD 的行為應該就像 OS 在 TargetFlipTime 提交翻轉給它時,使用相同的翻轉標誌和參數一樣。

例如,如果 FlipOnNextVSync 設定為 1,且 TargetFlipTime 位於畫面中間,則翻轉應該只會顯示在下一個 VSync 上。

FlipOverwrite 支援和硬體翻轉佇列

硬體翻轉佇列是由 DXGK_DRIVERCAPS 中的 MaxQueuedMultiPlaneOverlayFlipVSync 值所控制的翻轉覆寫功能的一個嚴格超集。

因此,如果驅動程式將 MaxHwQueuedFlips 設定為大於 1 的值,以選擇加入硬體翻轉佇列,OS 會忽略 MaxQueuedMultiPlaneOverlayFlipVSync 值。

TargetFlipTime 已過期的多次翻轉

當指定的 MPO 平面有多個翻轉佇列且 TargetFlipTime 已過期時,硬體顯示佇列必須選擇最近佇列的過期翻轉,並將其送交顯示。 其餘已過期的翻轉應視為已取消,且其相應的翻轉佇列記錄條目應包含 DXGK_HWFLIPQUEUE_TIMESTAMP_CANCELLED 作為 PresentTimestamp 的值。

Duration 和 TargetFlipTime 之間的互動

DXGKARG_SETVIDPNSOURCEADDRESSWITHMULTIPLANEOVERLAY3結構中的 Duration 參數應該在此結構中指定的翻轉顯示在畫面上時生效。 它為VidPnSourceId所指定的輸出,在所有平面上設定新的期望顯示刷新率行為。 在 WDDM 3.1 和 Windows Server 2022 版本中,為了簡化不支援佇列自定義持續 時間 變更之硬體的驅動程式實作,OS 只會在先前的翻轉要求完成之後,提交具有新 Duration 參數的翻轉要求。

將目前間隔對應至 TargetFlipTime

當刷新率固定時的對應區間

若要保留現有的目前間隔語意,OS 必須使用目前間隔和重新整理頻率來計算目標翻轉時間。 不過,將目標翻轉時間完全設定為翻轉應該擊中螢幕的預期 VSync 時間會導致頻繁的故障。 這些故障是因為當實際 VSync 時序輕微漂移時錯過了 VSync。 為了防止故障,OS 會從計算的目標翻轉時間中減去一半的 VSync 間隔。

以下是將當前間隔映射到目標翻轉時間的簡化公式:

TargetFlipTime = PreviousFlipStartVSyncTime + (PreviousFlipPresentInterval * FixedRefreshRate) - (FixedRefreshRate / 2)

WDDM 2.9 功能中當虛擬刷新率存在時的映射間隔

虛擬更新率功能可能會暫時將顯示刷新率提升到當前刷新率的整數倍(也就是說,24 Hz 可以提升到 144 Hz 或 192 Hz)。 對於能夠支援此提升的裝置,會修改上一節中的公式,以使用目前更新率的最快倍數:

TargetFlipTime = PreviousFlipStartVSyncTime + (PreviousFlipPresentInterval * FixedRefreshRate) - (FastestRefreshRate / 2)

重新對應當更新率變更為非倍數時的間隔

當重新整理頻率變更為目前重新整理頻率的非倍數 (例如,從 24 Hz 變更為 60 Hz) 時,OS 必須檢查佇列翻轉,以查看其計算的目標時間是否對新的重新整理速率仍然有效。 如果需要變更目標翻轉時間,OS 會取消佇列的翻轉,並使用新計算的目標翻轉時間重新排入佇列。