Skip to main content
本主題說明 Microsoft Game Development Kit with XBOX Extensions (GDKX) 中用於畫面排程的畫面步調 API,涵蓋這些 API 的目標、功能與陷阱。您將了解如何使用這些 API 在遊戲穩定性與延遲之間取得平衡。
此資訊截至 2022 年 4 月為最新。此後部分功能可能已變更或更新。

畫面步調 API

新的畫面步調 API 全面翻新了圖形呈現的流程,其目標如下。
  • 對可顯示資源的建立與管理提供更直接的控制
  • 降低從輸入裝置取樣到呈現的畫面資源掃描輸出之間的端對端延遲
  • 擴充動態設定顯示平面與參數的彈性
  • 提高選擇用於提交呈現之命令佇列的自由度
  • 建立明確的 CPU 節流機制,以精細控制模擬與轉譯管線的執行
  • 強化畫面管線統計資料的維護與報告
這些 API 已推出數年,但在 GDKX 文件中著墨不多。 圖 1. 包含重大變更的畫面步調 API。 畫面步調 API 在圖 1 中,程式碼範例有黑色文字與洋紅色文字。過去曾有一項重大變更,自 2019 年 4 月起成為強制性要求。左側黑色的 API 是標準 Direct3D 或 XDK 擴充功能。如果您使用 Present API,就會呼叫左側黑色的 API。左側另外兩個是在 ERA 時期新增的擴充功能。右側洋紅色的 API 是新的 API,例如 PresentX。 這是一項重大變更,因此移轉至 GDKX 時需要修改程式碼。三年前移轉就已是強制性要求。如果您在過去三年內建立過遊戲,您就已經在使用這些 API。

舊方式 - 初始化

圖 2. 舊方式 - 初始化。 舊方式 - 初始化 圖 2 呈現您先前的 Present API 用法。 以往在遊戲開始時的初始化期間,您會建立所謂的「交換鏈」。現在已不再以相同的意義使用交換鏈。請注意,交換鏈緩衝區是由系統配置的。

舊方式 - 畫面迴圈

圖 3. 舊方式 - 畫面迴圈。 舊方式 - 畫面迴圈 以往對於每個畫面,您會使用下列流程。
  1. 向交換鏈要求緩衝區。
  2. 將畫面影像轉譯至交換鏈提供的緩衝區。
  3. 呼叫 Present。
Present 是只有少數參數的簡單 API。圖 3 顯示 Present 與 frameInterval 參數。其值為 1 時代表 60 赫茲 (Hz)。 請注意,這裡沒有時間控制。只要正確,系統就會盡可能地推進。不過,在某些情況下 Present 可能會停滯。

新方式 - 初始化

圖 4. 新方式 - 初始化。 新方式 - 初始化 圖 4 顯示呈現的初始化。啟動遊戲時,您必須呼叫更多程式碼,因為您的遊戲比以前擁有更多控制權。遊戲會建立自己的交換鏈緩衝區、事先指定畫面播放速率,然後建立畫面原點事件。 如圖 4 所示,您不是建立交換鏈介面,而是像一般資源一樣,一次建立一個自己的交換鏈緩衝區。HEAP_ALLOW_DISPLAY 旗標表示您打算將這些緩衝區用於顯示。接著您會呼叫數個新 API。 新的 API SetFrameIntervalX 會事先指定您的目標畫面播放速率,而不是等到畫面呈現時才指定。在此案例中,目標畫面播放速率為 60 Hz。若要完成初始化,請排程 ORIGIN 事件。此事件有許多用途,包括指定您希望畫面開始的時間。 以上就是初始化時要做的事。至於畫面迴圈,您現在每個畫面要執行下列動作一次。

新方式 - 畫面迴圈

圖 5. 新方式 - 畫面迴圈。 新方式 - 畫面迴圈 如圖 5 所示,您不是只呼叫 Present,而是先呼叫 WaitFrameEventX。它會等待您如圖 4 所示排程的 ORIGIN 事件。畫面不再能隨時開始,您必須等待。 接著,將畫面轉譯至您自己建立的交換鏈緩衝區。最後,呼叫新版的 Present,也就是 PresentX。PresentX 有許多參數,已不再是簡單的 API。

新 API 的動機

本節列出舊版 API 遇到的一系列問題,以及新 API 如何解決這些問題。文中提供程式碼範例,圖中以洋紅色文字表示解決方案程式碼。

主要主題:延遲

新 API 的主要主題是控制延遲,這是一個重要的概念。如果您常看 Digital Foundry,就會發現他們的評測會試圖精確測量延遲。 透過 XBOX Game Streaming,玩家可以在雲端玩遊戲。延遲對雲端遊戲也很重要。先前的 Present API 在延遲方面表現不佳。例如,當您呼叫 Present 時,驅動程式會視需要停滯,而且可能停滯很久,您無法控制。 當時的延遲往往是畫面間隔的整數倍。如果您受限於 GPU,即使不需要,通常也會得到最高的延遲。 新 API 具有明確的延遲。遊戲可以要求以微秒為單位的精確延遲,而不是整數個畫面。您可以視需要增加或減少延遲。在高負載期間,您可以使用較高的延遲以避免掉格。在低負載期間,您可以降低延遲,讓遊戲反應更靈敏。

問題 1/10:多個顯示平面缺乏擴充性

XBOX One 首次引進第二個顯示平面。它有公開給遊戲使用,但不具擴充性。

解決方案:多個顯示平面的擴充性

圖 6. 多個顯示平面的擴充性。 多個顯示平面的擴充性 圖 6 以洋紅色顯示部分硬式編碼,但並非針對兩個顯示平面。現在呼叫 Present 時,您可以傳入任意數量的平面,每個平面中可以有任意數量的檢視。此程式碼可處理具有兩個以上平面或每個平面多個顯示的任何硬體。 您可以有一個顯示平面,其中一個檢視是共用指數的 RGBE,第二個檢視則包含 Alpha 通道。也可能有其他情境,例如使用兩個檢視進行分割畫面,或使用兩個檢視進行觀戰模式。這些情境目前不受支援,但 API 已隱含支援它們。

問題 2/10:無法分離顯示平面的轉譯速率

此問題與顯示平面擴充性有關。過去無法分離顯示平面的轉譯速率。例如,一個顯示平面以每秒 60 個畫面 (FPS) 轉譯,另一個以 30 FPS 轉譯。硬體支援這種做法,但 API 不支援。 如今對於越來越普遍的 120 Hz 遊戲而言,顯示平面擴充性很重要。UI 不需要以 120 Hz 轉譯。如果您以 120 Hz 執行,每個畫面只有很短的時間。

解決方案:分離顯示平面轉譯速率的方法

圖 7. 分離顯示平面的轉譯速率。 分離顯示平面的轉譯速率 如圖 7 所示,新 API 隱含支援分離轉譯速率,因為您會傳入要顯示的資源。因此,您可以連續兩次為 UI 平面傳入相同的資源。

問題 3/10:沒有 PresentationThreshold 來支援有限度的撕裂

下一個問題是 XBOX 360 時代的 PresentationThreshold。這是一種在畫面撕裂與掉格之間取捨的方法。 PresentationThreshold 是透過 XBOX 360 上的擴充功能公開的。它是 0 到 100 的撕裂百分比。0% 是預設值,表示永不撕裂。50% 表示如果錯過畫面預算,而畫面完成時只掃描了畫面上方 50%,就會立即使用 Present 並產生撕裂。 如果已使用超過 50%,就不需要撕裂,您會等待下一個 Vblank。另一個極端是 100%,表示只要達到畫面播放速率就不撕裂。不過,若錯過畫面目標,就可能發生撕裂。

解決方案:使用 PresentationThreshold 支援有限度的撕裂

圖 8. 使用 PresentationThreshold 支援有限度的撕裂。 解決方案:使用 PresentationThreshold 支援有限度的撕裂 圖 8 顯示新 API 中 ImmediateThresholdPercent 的用法。 PresentationThreshold 支援有限度的撕裂。您現在就可以使用。許多遊戲使用 100% 模式,這可能是最常見的用法。

問題 4/10:不支援高於 60 FPS 的畫面播放速率

先前的 API 不支援高於 60 FPS 的畫面播放速率。由於畫面間隔是 UINT,因此無法表達。1 代表 60 FPS。您無法使用 1 的一半,因為一半不是整數。 先前的 API 無法表示您想要 120 Hz,因此需要新的 API。 新 API 支援 120 Hz,並隱含支援該畫面時間的任何倍數。藉此您可以得到 40 FPS,或最近新增的過場動畫用 24 FPS。

解決方案:支援高於 60 FPS 的畫面播放速率

圖 9. 支援高於 60 FPS 的畫面播放速率。 支援高於 60 FPS 的畫面播放速率 如圖 9 所示,解決方案是使用 LengthInMicroseconds 參數。 它仍是不帶正負號的整數,但現在以微秒為單位。任何畫面播放速率都可以在此表達。傳入您想要的微秒長度,如果該長度受支援,API 就會成功。 如果未來某個時候需要支援 240 FPS,API 不需要變更。最近新增 24 FPS 支援時,API 也沒有變更。
偵測 120 FPS 支援的正確方式是使用 GetDisplayModeListX。它不會呼叫 SetFrameIntervalX 或檢查傳回碼。

問題 5/10:無法在計算佇列上完成畫面

先前的 API 呼叫 Present,它是交換鏈介面的成員。交換鏈隱含屬於圖形佇列。 畫面的最後工作完全以計算為主是很常見的。如果能執行該工作、呼叫 Present,然後已經開始下一個畫面的圖形工作,會很有幫助。圖形與計算會稍微重疊,管線化不足。 先前曾有範例示範如何使用舊 API 在計算佇列上完成畫面。不過,由於這項缺漏,做法相當複雜。

解決方案:在計算佇列上完成畫面的方法

圖 10. 在計算佇列上完成畫面的方法。 在計算佇列上完成畫面的方法 圖 10 顯示新 API 中已不再有交換鏈介面。Present 已移至命令佇列,因此 API 可以表示畫面可在任何命令佇列上完成。PresentX 是 ID3D12CommandQueue (基底類別) 的方法,而不是已不存在的 IDXGISwapChain 的方法。 目前圖形與非同步計算都支援此功能。如果未來有理由在新類型的佇列或現有佇列 (例如直接記憶體存取 (DMA)) 上支援它,也可以在不變更 API 的情況下完成。

問題 6/10:節流缺乏精細控制

先前的 API 無法精細控制節流。節流是刻意的停滯,用來防止延遲無限制地增加。這是轉譯延遲,預設通常是畫面間隔的整數倍。 遊戲的變通方式是新增第三個交換鏈緩衝區、在畫面中途某處發出柵欄訊號,然後在 CPU 上等待該柵欄。基本上,遊戲會在驅動程式自動節流之前手動節流。不過,這並不精確。您可以節流一個畫面加上一次深度預先處理,但無法節流一個畫面加 4 毫秒。

解決方案:精細控制節流

圖 11. 精細控制節流。 精細控制節流 圖 11 顯示新 API 的控制方式。此控制是透過洋紅色文字中的兩個參數完成 (本主題稍後會更詳細說明)。第一個參數是 PeriodInIntervals,表示從開始到結束完成一個畫面需要多少個畫面播放速率間隔。 例如,如果畫面播放速率為 60 FPS,畫面播放速率間隔就是 16.7 毫秒。從畫面開始到結束可能需要多個間隔。 第二個參數是 IntervalOffsetInMicroseconds。請將其用於小數畫面的延遲。也許以間隔計的週期是 2,但實際上需要介於 1 與 2 之間。可以找到適當的間隔位移值來達成此目的。

問題 7/10:控制器輸入沒有明確同步

先前的 API 不允許您與控制器同步。這是造成延遲的重要因素,對無線控制器而言尤其如此。按下按鈕時,遊戲不會立即反應。 為了節省電池壽命,無線控制器只會每隔一段時間傳送更新。玩家可能在更新前一刻按下按鈕,並立即得到該更新。不過,如果玩家在更新後一刻按下按鈕,就必須等待下一次更新,按鈕按下才會被辨識。這就是延遲。從某種角度來說,這是最糟的延遲,因為每個畫面的延遲都不同。 如果玩家知道延遲會是多少,而且延遲總是相同,他們就能稍微補償。否則,在講求反應速度的遊戲中,就很難在需要的那一刻精準按下按鈕。

解決方案:與控制器輸入明確同步

圖 12. 與控制器輸入明確同步。 與控制器輸入明確同步 圖 12 顯示如果您以可預測的方式排程 ORIGIN 事件,它能發揮的用途之一。無線控制器可以及時傳送更新,也許在遊戲需要之前 1 毫秒。這會降低延遲,而且每個畫面的延遲都相同。

問題 8/10:重要事件沒有通知

除了 Vblank 之外,先前的 API 不允許重要事件的通知。 遊戲知道 Vblank 中斷何時發生很重要。部分此功能已被移除。不過,仍有方法可以取得重要事件的通知。

解決方案:重要事件的通知

圖 13. 重要事件的通知。 重要事件的通知 如圖 13 所示,新 API 預設支援兩個事件:Vblank 通知與 Flip 通知。Flip 事件會在新的交換鏈緩衝區變為可見時發生,而且具擴充性。Flip 通知是得知何時可以安全地再次循環使用交換緩衝區的便利方式。 可以在不變更 API 的情況下為 Flip 新增更多內容。

問題 9/10:PIX 無法顯示畫面

過去,PIX 計時擷取無法顯示 (追蹤) 整個畫面。PIX 對畫面僅有的資訊,是您使用舊 API 呼叫 Present 的時間。沒有任何關於哪些工作促成該 Present 呼叫,或該畫面何時開始的資訊。

解決方案:讓 PIX 顯示畫面的方法

圖 14. 讓 PIX 顯示畫面的方法。 讓 PIX 顯示畫面的方法 圖 14 顯示畫面管線權杖。當您等待 ORIGIN 事件時,會收到畫面管線權杖作為傳回值。請儲存它,因為稍後會用到。呼叫 Present 時,您會傳入相同的權杖。PIX 現在可以辨識:
  • 畫面的開始,以及該畫面對應的結束。
  • 當您傳入相同權杖時,其他事件屬於同一個畫面。

問題 10/10:遊戲無法擷取詳細的計時資料

先前的 API 無法擷取詳細的計時資料。對您的遊戲而言,您可能想知道某些作業花了多久或何時發生。例如:
  • GPU 在一個畫面中忙碌了多少時間?
  • 畫面何時開始?
  • ORIGIN 事件何時發生?
  • 畫面何時呈現?
  • Present 呼叫何時抵達 GPU?
遊戲可以使用查詢自行解決部分問題。不過,如果驅動程式能在同一處提供所有這些資訊會更好。

解決方案:讓遊戲擷取詳細計時資料的方法

圖 15. 讓遊戲擷取詳細計時資料的方法。 讓遊戲擷取詳細計時資料的方法 圖 15 顯示新 API 使用 GetFrameStatisticsX 擷取詳細的計時資料。它提供許多統計資料,且與其他 API 一樣具擴充性。可以在不變更 API 簽章的情況下新增新類型的統計資料。

畫面步調 API 的建議用法

本節說明如何調節延遲:找出您目前的延遲、決定您想要的延遲,然後使用畫面步調 API 進行變更。

調節延遲

圖 16. 調節延遲:三個簡單步驟。 調節延遲:三個簡單步驟 圖 16 顯示調節延遲的三個建議步驟。
  1. 使用畫面統計資料測量遊戲中的理想延遲。
  2. 為變動性加上一些餘裕。
  3. 計算參數。
在第一個步驟中,有兩個重要的統計資料:發出畫面開始訊號的 ORIGIN SignalTime,以及在呼叫 `Present’ 並抵達 GPU 時發出畫面結束訊號的 GPUProcessTime。此時您要顯示的畫面緩衝區已完成,兩個統計資料之間的差值就是遊戲的理想延遲。 在第二個步驟中,最好保留餘裕,以應對理想延遲不完全準確的情況。如果您的餘裕估計過低,而下一次延遲較高,就會掉格。如果估計過高,延遲就會高於所需。 第三個步驟是使用所有這些資訊計算兩個參數:PeriodInIntervals 與 IntervalOffsetInMicroseconds。必須將它們提供給驅動程式。 這些變更是管線化的,因此會在幾個畫面內生效。您可能希望遊戲對延遲上升立即反應,但對延遲下降則緩慢反應。

調節延遲範例

圖 17. 調節延遲範例。 調節延遲範例 圖 17 顯示調節延遲的範例。 此範例假設遊戲為 60 Hz,畫面間隔為 16.7 毫秒。根據 SignalTime 與 GPUProcessTime 之間的差值,測得的延遲為 30 毫秒。例如,您決定安全餘裕為半個畫面,即 8.3 毫秒。這樣要求的總延遲就是 38.3 毫秒。 若要計算 PeriodInIntervals 與 IntervalOffsetInMicroseconds 這兩個參數,請參閱圖 17 中的圖表。圖表右側是目標 Vblank,也就是畫面必須準備好進行 Present 的時間。從該點往回推算 8.3 毫秒的安全餘裕,就得到預測畫面完成的時間。從那裡再往回推算測得的 30 毫秒延遲,就是您的 ORIGIN 點。 圖 17 將 38.3 毫秒 (38300) 除以 16.7 毫秒 (16667) 的畫面間隔,計算出以間隔計的畫面週期 PeriodInIntervals。結果無條件進位為三個間隔。 IntervalOffsetInMicroseconds 是畫面在第一個間隔中開始的位置。圖 17 中的計算顯示它是 11.7 毫秒。 總結來說,這表示目標 Vblank 是 ORIGIN 點之後的第三個 Vblank,而 ORIGIN 點位於畫面間隔中途 (11.7 毫秒)。 此流程並不太複雜,但有可能變得複雜。在同時處理其他事情的遊戲中,可能就會如此。 如果您的遊戲具有動態解析度,就必須將其納入結果考量。如果延遲非常高,您可以透過降低解析度來處理。有些遊戲會動態調節畫面播放速率,表示有時是 60 赫茲遊戲,有時是 120 赫茲遊戲。其他遊戲則在超過畫面預算時使用 ImmediateThreshold 進行撕裂。 您可以建立非常複雜的演算法來預測所有可能的情況。

畫面步調 API 的不建議用法

本節說明我們不建議的畫面步調 API 用法。

背景緩衝區未在約定時間內呈現

本主題到目前為止涵蓋的問題類似於一份合約。您同意畫面會在特定時間內完成。如果您未在約定時間內完成畫面,就可能發生掉格等問題。以往只有在 CPU 或 GPU 超出預算時才會掉格。現在,您可能做出延遲預測卻未能達成,即使 CPU 與 GPU 都在時間預算內,仍會掉格。

遊戲使用的交換鏈太短

當遊戲使用的交換鏈太短時,可能會發生停滯等問題。理想的交換鏈大小是 PeriodInIntervals 加一。例如,如果您使用的 PeriodInIntervals 等於 2,且 IntervalOffsetInMicroseconds 為 0,就需要大小為 3 的交換鏈。這是因為您有一個正在顯示的畫面、另一個正處於計算第二個間隔的畫面,以及第三個正處於計算第一個間隔的畫面。總共三個畫面同時存在。嚴格來說,它們需要不同的交換鏈緩衝區,否則可能會發生衝突。 在某些情況下,交換鏈太短不會造成任何損失,什麼事也不會發生。不過,在其他情況下,CPU 會在 PresentX 中停滯,或 GPU 會在 ResourceBarrier 中停滯。有時停滯不會影響畫面播放速率,有時則會。 您可以為上述每種情境建立範例。您選擇哪一種,取決於遊戲的運作方式。

遊戲只在啟動時設定一次 PeriodInIntervals 與 IntervalOffsetInMicroseconds

如果遊戲在啟動時設定新參數 PeriodInIntervals 與 IntervalOffsetInMicroseconds,之後便不再處理它們,就可能發生問題。這類似於以前的做法:事先設定目標延遲,然後無論遊戲中發生什麼事都維持相同的選擇。 如果您的延遲選擇過於積極或過於保守,就可能產生損失。過於積極,即使在預算內也會不必要地掉格。過於保守,延遲總是高於所需。

遊戲在 ORIGIN 事件發出訊號前就開始計算畫面

當您排程 ORIGIN 事件並等待它,但遊戲已開始畫面計算時,就會發生此問題。在此情況下,計算並未在您設定的時間開始,因此延遲會來回波動而變得無法確定。這會導致控制器輸入無法同步,也無法在 PIX 中追蹤畫面。
在本主題提出的問題中,這是最重要的一項。目前尚不清楚為何在您排程 ORIGIN 事件並等待它時,這只有在某些時候才有效。

示範

PIX System Monitor 中的畫面步調

圖 19. PIX System Monitor 中的畫面步調。 PIX System Monitor 中的畫面步調 圖 19 標示 PIX System Monitor 的 D3D (Direct3D) 區段。D3D 區段會追蹤對計算端對端畫面延遲很重要的事件。 示範說明下列元素。
  • Frames per Second:顧名思義。
  • Total Frame Latency:從 ORIGIN 事件到畫面翻轉並成為前景緩衝區的時間。
  • Frame Origin:ORIGIN 事件在 Vblank 之後多久發生 (IntervalOffsetInMicroseconds)?
  • Present to Flip:畫面在翻轉之前多早就已就緒 (PresentX 抵達 GPU)?
  • Wait for Signal:WaitFrameEventX(ORIGIN) 封鎖了多久?

Frame Pacing Sample

圖 20. Frame Pacing Sample UI。 Frame Pacing Sample 圖 20 顯示 Frame Pacing Sample 的 UI。此範例尚未公開發佈。此範例會在 CPU 與 GPU 上人為產生畫面時間,然後在 UI 中顯示結果。 UI 分為下列部分。
  • 功能表:
    • 位於右上角。
    • 分為兩個區段:
      • 畫面負載參數。
      • 畫面步調參數。
    • 畫面負載由計時器強制執行。
  • 圖表:
    • 位於左上角的三個折線圖。
      • 畫面時間/播放速率。
      • 理想延遲。
      • 延遲餘裕 (安全餘裕)。
    • 負值餘裕表示畫面延遲。
  • 時間軸:
    • 類似簡化的 PIX 計時擷取。
    • 顯示下列資訊。
      • CPU 更新。
      • CPU 轉譯。
      • GPU 圖形佇列。
      • GPU 計算佇列。
      • Flip。
    • Flip 會告訴您正在顯示哪一個交換鏈緩衝區。
    • 時間軸圖表依交換鏈緩衝區以色彩區分。
    • 圖 20 的範例有三個交換鏈緩衝區,以紫色、綠色與黃色表示。

小數畫面的延遲

先前的 API 不允許小數畫面的延遲。不過,新 API 允許,讓遊戲能以微秒為單位指定小數位移。 圖 21. 小數畫面的延遲 1/2。 小數畫面的延遲 1/2 圖 21 顯示沒有小數畫面延遲的範例。請注意 Frame Offset (ms) 為 0。CPU 更新 (ORIGIN 事件) 在 Vblank 時發生。這表示延遲是整數個畫面。 圖 22. 小數畫面的延遲 2/2。 小數畫面的延遲 2/2 圖 22 顯示 Frame Offset (ms) 設定為 3 的範例。這是不掉格情況下可設定的最高位移。這會使延遲餘裕接近 0,低得危險。請注意,CPU 更新開始的 ORIGIN 事件已不再與 Flip 結束的 Vblank 同步。

延遲與交換鏈大小脫鉤

圖 23. 延遲與交換鏈大小脫鉤 1/2。 使用新 API 時,延遲不再取決於交換鏈長度。此示範顯示下列情況會發生什麼事:
  • 交換鏈大小為我們建議的大小。
  • 交換鏈大小小於我們建議的大小。
延遲與交換鏈大小脫鉤 1/2 圖 23 顯示 Frame Period 設定為 2 的範例。這通常需要三個畫面緩衝區。請注意底部的計時列中有三種色彩:紫色、綠色與黃色。每種色彩代表一個交換鏈緩衝區。 圖 24. 延遲與交換鏈大小脫鉤 2/2。 延遲與交換鏈大小脫鉤 2/2 圖 24 顯示畫面緩衝區變更為 2 的範例。請注意底部的計時列中現在有兩種色彩:綠色與黃色。另請注意,它看起來與圖 23 類似。在圖 24 中,折線圖中的理想延遲為 30.2,延遲餘裕為 3.1。 如果新增另一個畫面緩衝區 (圖 23),則沒有任何變化,畫面延遲維持不變。額外的畫面緩衝區不會增加延遲,但會產生額外的記憶體成本。 此示範也顯示,即使畫面 N 的綠色 Flip 與畫面 N+2 的綠色列重疊,畫面播放速率也沒有改變。畫面播放速率穩定維持在 59.0 FPS。 仍可能發生停滯。例如,如果緩衝區在傳遞給 Present 時仍在顯示中,CPU 上的 BlockOnFence_SwapThrottle 可能會停滯。如果緩衝區在從 PRESENT 狀態轉換為可寫入狀態時仍在顯示中,GPU 上的 WaitOnSwapChainSurface 也可能停滯。這些作業能延後得越久,所需的緩衝就越少。 您可以在 Frame Pacing Sample 中縮短 CPU Update 與 CPU Render 的時間,使這些停滯發生。

延遲調節

圖 25. 延遲調節 1/4。 延遲調節 1/4 圖 25 顯示 CPU Update 增加至 14 毫秒的範例。請注意延遲餘裕為負值。遊戲錯過了畫面期限,導致掉格。根據功能表的 Frame load,沒有任何處理步驟的成本低於一個畫面間隔 (16.7 毫秒)。這就是延遲預測過於積極時會發生的情況。 圖 26. 延遲調節 2/4。 延遲調節 2/4 圖 26 顯示已啟動自動畫面步調模式的範例。它將 Frame Period 從 2 增加為 3,修正了掉格問題。請注意 Frame Offset 從 0.00 變更為 7.45 毫秒,而 Legacy margin 現在顯示 8.3 毫秒。 圖 27. 延遲調節 3/4。 延遲調節 3/4 圖 27 顯示已啟用 Auto Frame Load,以及每秒有一個畫面超出預算的情境。此「GPU 異常」會導致下一個畫面掉格。這會顯示在 Frame time 圖表與時間軸的間隙中。每秒發生一次異常,是因為延遲餘裕太低。 圖 28. 延遲調節 4/4。 延遲調節 4/4 圖 28 顯示相同情境下再次開啟 Auto Frame Pacing 模式。演算法透過降低延遲預測的積極程度來修正此問題。延遲餘裕增加至 8.3 毫秒,避免了掉格。延遲餘裕圖表不會降到 0 以下。

後續步驟

如果您想檢閱與本概觀相關的簡報資料,請從 XBOX Developer Download Secure Data Storage (SDS) 下載下列檔案。
  • 投影片:Xfest 2022 Graphics Track PowerPoints (Xfest2022GfxPPTs.ZIP) 中的 GR03_Understanding Frame Pacing and Latency with the GDKX Presentation APIs.pptx
  • 影片簡報:Xfest 2022 Graphics Track Videos (Xfest2022GfxVids.ZIP) 中的 GR03.mp4

下載 Microsoft PowerPoint 簡報與影片

  1. 前往 Game Development Kit (GDK) 下載。
  2. 在 Select file type 下,選取 Conference Materials,然後選取 Confirm。
  3. 在 Select build/version number 下,選擇下列其中一個圖形簡報。
    • Xfest 2022 Graphics Track PowerPoints
    • Xfest 2022 Graphics Track Videos
  4. 選取 Download Now,然後等待 .zip 檔案下載完成。
  5. 前往本機的 [下載] 資料夾,然後從壓縮資料夾中解壓縮 (擷取) 檔案。

下載本文提及的 Microsoft Game Development Kit 主機範例

  1. 前往 Game Development Kit (GDK) 下載。
  2. 在 Select file type 下,選取 GDK,然後選取 Confirm。
  3. 在 Select build/version number 下,選擇最新的 Microsoft GDKX (Sample only) 選項。
  4. 選取 Download Now,然後等待 .zip 檔案下載完成。
  5. 前往本機的 [下載] 資料夾,然後從壓縮資料夾中解壓縮 (擷取) 檔案。
  6. 選取 GDKSamples > Graphics,然後搜尋該範例。

另請參閱

遊戲串流簡介 遊戲串流延遲補償概觀 深入探討遊戲串流延遲補償
Last modified on October 6, 2026