複製和存取資源資料
使用情況旗標會指出應用程式計畫如何使用資源資料,以盡可能將資源配置給記憶體中最講求效能的區域。 資源資料會在資源之間進行複製,以利 CPU 或 GPU 在不影響效能的情況下加以存取。
您不一定會要將資源視為在視訊記憶體或系統記憶體中建立的項目,甚或判斷執行階段是否應管理記憶體。 在 Windows 顯示器驅動程式模型 (WDDM) 的架構中,應用程式會使用不同的使用狀況旗標來建立 Direct3D 資源,以指出應用程式計畫如何使用資源資料。 這個驅動程式模型會使用資源將記憶體視覺化;作業系統/驅動程式/記憶體管理員需負責根據預期的使用情況,將資源配置給記憶體中最講求效能的區域。
在預設情況下,資源會提供給 GPU。 有時,資源資料需要提供給 CPU。 您需要對 API 方法的運作方式具有一定的了解,才能複製資源資料,好讓適當的處理器能在無需影響效能的情況下加以存取。
複製資源資料
Direct3D 執行 Create 呼叫時,會在記憶體中建立資源。 它們可在視訊記憶體、系統記憶體或其他任何類型的記憶體中建立。 由於 WDDM 驅動程式模型會將這個記憶體視覺化,因此,應用程式無需追蹤資源會於哪個類型的記憶體中建立。
在最理想的情況下,所有資源都會位於視訊記憶體中,好讓 GPU 能立即加以存取。 不過,有時也需讓 CPU 讀取資源資料,或讓 GPU 存取 CPU 寫入的資源資料。 Direct3D 會透過要求應用程式指定使用情況來處理上述不同情境,然後在必要時提供多個方法來複製資源。
視資源建立的方式而定,基礎資料不一定能直接存取。 這表示,資源資料必須從來源資源複製至可供適當處理器存取的另一個資源中。 針對 Direct3D,GPU 可直接存取預設資源,而 CPU 則可直接存取動態和暫存資源。
資源建立後,就無法變更其使用情況, 而是需要改將任一資源的內容複製至以不同使用情況建立的另一資源中。 您可將資源資料從任一資源複製至另一資源中,或將資料從記憶體複製至資源中。
資源主要可劃分為兩大類型:可對應資源和不可對應資源。 動態或暫存使用情況建立的資源為可對應資源,預設或不可變使用情況建立的資源則為不可對應資源。
不可對應資源之間可快速無比地複製資料,因為這是最常見的情況,已進行最佳化,且可順利執行。 由於這些資源無法讓 CPU 直接存取,它們會進行最佳化,以利 GPU 快速操作。
在可對應資源之間複製資料,則會發生較多問題,原因在於,效能將視資源建立時採用的使用情況而定。 舉例來說,GPU 能相當快速地讀取動態資源,卻無法加以寫入,而 GPU 則無法直接寫入或讀取暫存資源。
應用程式若有意從採用預設使用情況的資源,將資料複製至採用暫存使用情況的資源 (好讓 CPU 讀取資料,卻造成 GPU 回讀問題),就必須謹慎地進行這項作業。 詳情請參閱下方的存取資源資料。
存取資源資料
存取資源少不了對應資源;就本質上而言,對應意味著應用程式要嘗試向 CPU 提供記憶體存取權限。 對應資源以讓 CPU 能存取基礎記憶體的程序,可能會造成某些效能瓶頸,而基於此一原因,勢必需要謹慎處理這項作業的執行方式和時機。
如果應用程式嘗試在錯誤的時間對應資源,就有可能造成效能中斷。 如果應用程式嘗試在作業完成前存取作業結果,將會導致管線停滯。
在錯誤的時間執行對應作業,極有可能迫使 GPU 和 CPU 彼此同步,繼而造成效能嚴重下滑。 如果在 GPU 完成將其複製至可供 CPU 對應的資源前,應用程式想要存取該資源,就會發生這個同步處理作業。
效能考量
建議可將電腦視為透過一個或多個 CPU 及一個或多個 GPU 等兩大主要處理器類型,以執行為平行架構的機器 如同任何平行架構,只要每個處理器都已排程足夠的作業來避免發生閒置,而其中一個處理器無需等候另一個處理器就能進行作業,即可實現最佳效能。
而 GPU/CPU 平行處理的最糟情況,就是必須迫使任一處理器等候另一處理器完成的工作結果。 Direct3D 可提供非同步的複製方法,以免除上述成本;而這也意味著,複製不一定要在方法傳回時執行。
此一做法的優勢,在於直到 CPU 存取資料,因而呼叫 Map 為止,應用程式都無需承擔實際複製資料所衍生的效能成本。 若在資料實際複製完成後才呼叫 Map 方法,將不會發生任何效能損失。 另一方面,若在資料完成複製前呼叫 Map 方法,則管線將發生停滯。
Direct3D 中的非同步呼叫 (絕大多數的方法,尤其是轉譯呼叫,皆採用此一模式) 會儲存在所謂的命令緩衝區中。 這個緩衝區位於圖形驅動程式內部,且會用來批次呼叫基礎硬體,以盡可能避免在 Microsoft Windows 中從使用者模式切換至核心模式,從而衍生高額的成本。
命令緩衝區會進行排清,繼而在下列四種情況下的任一情況中造成使用者/核心模式切換。
- 呼叫 Present 時。
- 呼叫 Flush 時。
- 命令緩衝區已滿;其大小會動態調整,並受作業系統和圖形驅動程式控制。
- CPU 需要存取在命令緩衝區中等候執行之命令所產生的結果。
在上述四種情況中,第四種情況對效能最為至關重要。 如果應用程式發出呼叫來複製資源或子資源,該呼叫就會排入命令緩衝區的佇列。
之後,如果在命令緩衝區排清前,應用程式嘗試對應身為複製呼叫目標的暫存資源,則管線將發生停滯,原因在於:除了需要執行 Copy 方法呼叫之外,也必須執行命令緩衝區中的其他所有緩衝命令。 此舉將導致 GPU 和 CPU 同步處理,因為在 GPU 清空命令緩衝區,最後填入 CPU 所需的資源同時,CPU 將需等候存取暫存資源。 當 GPU 完成複製後,CPU 將開始存取暫存資源,但在上述期間內,GPU 將發生閒置。
在執行階段中頻繁執行上述作業,將導致效能嚴重降低。 正因如此,對應以預設使用情況建立的資源時,請務必謹慎行事。 應用程式需要等候足夠的時間,好讓命令緩衝區能順利清空,如此才能先執行完這些命令,再嘗試對應與之對應的暫存資源。
應用程式應等候多久? 至少兩個框架,因為如此即可在 CPU 和 GPU 之間進行平行處理,以利充分運用。 GPU 的運作方式在於:當應用程式會透過將呼叫提交至命令暫存區來處理框架 N 時,GPU 會忙著執行來自上一個框架 (也就是 N-1) 的呼叫。
因此,如果應用程式想要對應源自於視訊記憶體的資源,並複製位於框架 N 的資源,這個呼叫將於框架 N+1 實際著手執行,也就是當應用程式正提交下一個框架的呼叫時。 當應用程式正在處理框架 N+2 時,複製作業應該已完成。
Frame | GPU/CPU 狀態 |
---|---|
否 |
|
N + 1 |
|
N + 2 |
|
N + 3 |
|
N + 4 |
相關主題