D3D12 增強障礙
Windows 11 22H2 WDK 版 (WDDM 3.0) 中提供增強屏障的 DDI 介面。 若要在 22H2(或舊版作業系統)上使用增強障礙,您必須安裝 1.706.4 預覽的 Agility SDK。
D3D12 增強障礙可讓開發人員獨立控制 GPU 工作同步處理、紋理配置轉換,以及快取排清(資源記憶體取)。 這項功能提供一組 Direct3D API 和 DIS,可讓開發人員獨立控制 GPU 工作同步處理、紋理配置轉換,以及快取排清(資源記憶體存取)。
增強障礙會以更具表現力的屏障類型取代舊版資源屏障。 他們具有下列功能:
- 較少的同步處理延遲。
- 減少過多的快取排清。
- 沒有神秘的促銷和衰敗規則。
- 快速、彈性的資源別名(不同的別名拓撲)。
- 在屏障轉換期間捨棄。
- 支援並行讀取/寫入,包括相同資源複製(自我複製)。
- 支援異步捨棄、複製、解析和清除命令。
增強的屏障並不比舊版資源屏障簡單,但較不明確,因此更容易供開發人員使用。
報告增強的屏障支援
增強障礙功能目前不是硬體或驅動程式需求。 驅動程式會將 D3D12DDI_D3D12_OPTIONS_DATA_0089 的 EnhancedBarriersSupported 成員設定為 TRUE,以指出支援。
- D3D12DDI_FEATURE_VERSION_VIDEO_0088_0是定義 Windows 11 中引進的 D3D12 增強式屏障里程碑的初步實作版本號碼。
D3D12 增強式屏障回呼函式
指出增強屏障支持的驅動程式會實作下列回呼函式:
- PFND3D12DDI_BARRIER_0088
- PFND3D12DDI_CREATEHEAPANDRESOURCE_0088
- PFND3D12DDI_CALCPRIVATEHEAPANDRESOURCESIZES_0088
- PFND3D12DDI_CHECKRESOURCEALLOCATIONINFO_0088
設計詳細數據
驅動程式通常會使用三個不同的作業來處理舊版資源屏障:
- 同步處理 GPU 工作。
- 執行任何必要的快取排清作業。
- 執行任何必要的版面配置變更。
增強的屏障可讓開發人員分別控制每個作業。
增強障礙的類型
增強障礙有三種類型:
範圍屏障會 取代 舊版資源屏障。 提供範圍障礙,以便完全實作舊版資源屏障,且不會遺失明顯的效能。
所有屏障類型都會控制 GPU 工作同步處理和屏障前後的讀取或寫入存取類型。
紋理屏障會額外管理紋理子資源的版面配置。 子資源選取範圍可以表示為 Mip、陣列和平面配量的範圍,以及舊版資源屏障所使用的熟悉單選或全部選項。
緩衝區屏障和全域屏障只會控制同步處理和資源存取,而且不會影響資源配置(緩衝區沒有版面配置)。 全域屏障會影響所有快取的記憶體,因此它們的成本很高,而且只有在範圍較廣的屏障不足時,才應該使用。
紋理屏障
- 控制紋理子資源的快取排清、記憶體配置和同步處理。
- 只能搭配紋理資源使用。
- 允許選取單一子資源、所有子資源或子資源一致的範圍(也就是 mip 範圍和數位範圍)。
- 必須提供有效的非 NULL 資源指標。
緩衝區屏障
- 控制緩衝區資源的快取排清和同步處理。
- 只能與緩衝區資源搭配使用。
- 不同於紋理,緩衝區只有單一子資源,而且沒有可轉換的配置。
- 必須提供有效的非 NULL 資源指標。
全球障礙
- 控制單一命令佇列中所有指示之資源存取類型的快取排清和同步處理。
- 對紋理配置沒有任何影響。
- 需要提供類似舊版 NULL UAV 屏障和 NULL/NULL 別名屏障的功能。
由於全域屏障不會轉換紋理配置,因此全域屏障無法用於轉換,否則需要配置變更。 例如,全域屏障無法用來將非同時存取紋理從D3D12DDI_BARRIER_ACCESS_RENDER_TARGET轉換為D3D12DDI_BARRIER_ACCESS_SHADER_RESOURCE,因為這也需要從D3D12DDI_BARRIER_LAYOUT_RENDER_TARGET變更為D3D12DDI_BARRIER_LAYOUT_SHADER_RESOURCE。
同步處理
圖形處理器的設計目的是盡可能平行地執行工作。 相依於先前 GPU 工作的任何 GPU 工作都必須同步處理,才能存取相依數據。
增強式屏障介面會使用明確的 SyncBefore 和 SyncAfter 值作為邏輯位字段遮罩。 在執行屏障之前,屏障必須等候所有上述命令 SyncBefore 範圍完成。 同樣地,屏障必須封鎖所有後續 的 SyncAfter 範圍,直到屏障完成為止。 D3D12DDI_BARRIER_SYNC指定 GPU 與屏障相關的同步處理範圍。
如需詳細資訊,請參閱 增強障礙規格。
版面配置轉換
紋理子資源可以針對各種存取方法使用不同的版面配置。 例如,當做轉譯目標或深度樣板使用時,通常會壓縮紋理,而且通常未壓縮著色器讀取或複製命令。 紋理屏障會使用 LayoutBefore 和 LayoutAfter D3D12DDI_BARRIER_LAYOUT值來描述版面配置轉換。
只有紋理才需要版面配置轉換,因此它們只會以 D3D12DDI_TEXTURE_BARRIER 數據結構表示。
LayoutBefore 和 LayoutAfter 都必須與執行屏障的佇列類型相容。 例如,計算佇列無法將子資源轉換成或移出 D3D12DDI_BARRIER_LAYOUT_RENDER_TARGET。
為了提供妥善定義的屏障順序,完成一連串屏障之後子資源的版面配置是序列中最後 的 LayoutAfter 。
存取轉換
由於會快取許多 GPU 寫入作業,因此從寫入存取到另一個寫入存取權的任何屏障,或只讀存取可能需要快取排清。 增強的屏障 API 會使用存取轉換,指出特定新存取類型必須顯示子資源記憶體。 如同版面配置轉換,如果已知相關聯的子資源記憶體已可供所需使用,則可能需要某些存取轉換。
存取轉換會以下欄方式表示:
- 針對紋理,做為D3D12DDI_TEXTURE_BARRIER結構的一部分。
- 針對緩衝區,作為D3D12DDI_BUFFER_BARRIER結構的一部分。
存取轉換不會執行同步處理。 預期相依存取之間的同步處理會使用屏障中適當的 SyncBefore 和 SyncAfter 值來處理。
指定 AccessAfter 所顯示的 AccessBefore 不保證對不同的存取類型也可以看到資源記憶體。 例如:
MyTexBarrier.AccessBefore=D3D12DDI_BARRIER_ACCESS_UNORDERED_ACCESS;
MyTexBarrier.AccessAfter=D3D12DDI_BARRIER_ACCESS_SHADER_RESOURCE;
此存取轉換表示後續著色器讀取存取權相依於先前的 unordered-access-write。 不過,如果硬體能夠直接從 UAV 快取讀取著色器資源,驅動程式可能不會實際排清 UAV 快取。
D3D12DDI_BARRIER_ACCESS_COMMON
D3D12DDI_BARRIER_ACCESS_COMMON是一種特殊的存取類型,表示任何配置相容存取。 轉換至 D3D12DDI_BARRIER_ACCESS_COMMON 表示子資源數據必須在屏障之後可供任何配置相容存取使用。 由於緩衝區沒有配置, D3D12DDI_BARRIER_ACCESS_COMMON 只是表示任何與緩衝區相容的存取。
將D3D12DDI_BARRIER_ACCESS_COMMON指定為屏障中的 AccessBefore 表示所有寫入存取類型的集合。 不建議使用 D3D12DDI_BARRIER_ACCESS_COMMON 作為 AccessBefore ,因為它可能會導致成本高昂、非預期的快取排清。 相反地,鼓勵開發人員只使用最窄的寫入存取位,以適當限制屏障額外負荷。 當 AccessBefore 設定為D3D12DDI_BARRIER_ACCESS_COMMON時,就會發出偵錯層警告。
單一佇列同時存取
增強的屏障允許相同緩衝區上的並行讀取/寫入作業,或在同一個命令佇列中同時存取紋理。
緩衝區和同時存取資源一律支援從具有並行、非Ependent、從一或多個其他佇列讀取存取的佇列寫入存取權。 這項支援是因為這類資源一律會使用 COMMON 配置,而且沒有讀取/寫入危害,因為讀取不得相依於並行寫入。 (舊版資源屏障規則不允許將寫入狀態位與任何其他狀態位結合。因此,資源無法使用舊版資源屏障在相同的佇列中同時讀取和寫入。
一次寫入器原則仍適用,因為兩個看似非重疊的寫入區域可能仍有重疊的快取行。
子資源範圍
開發人員通常會想要轉換一系列子資源。 例如,轉換指定紋理陣列的完整 Mip 鏈結,或針對所有數位配量轉換單一 Mip 層級。 增強的屏障可讓開發人員使用 D3D12DDI_BARRIER_SUBRESOURCE_RANGE 結構來轉換邏輯上相鄰的子資源範圍。 (舊版資源狀態轉換屏障僅提供開發人員以不可部分完成方式轉換 所有 子資源狀態或單一子資源狀態的選項。
計算和直接佇列配置
針對直接和計算佇列,保證下列 增強式屏障配置 相同:
- D3D12DDI_BARRIER_LAYOUT_GENERIC_READ
- D3D12DDI_BARRIER_LAYOUT_UNORDERED_ACCESS
- D3D12DDI_BARRIER_LAYOUT_SHADER_RESOURCE
- D3D12DDI_BARRIER_LAYOUT_COPY_SOURCE
- D3D12DDI_BARRIER_LAYOUT_COPY_DEST
其中一個配置中的子資源可用於直接佇列或計算佇列中,而不需要配置轉換。
在某些硬體上,如果先前或後續存取也位於直接佇列上,直接佇列上的配置轉換屏障可能會大幅加快。 強烈建議您使用下列配置來存取直接佇列上的資源:
- D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_GENERIC_READ
- D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_UNORDERED_ACCESS
- D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_SHADER_RESOURCE
- D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_COPY_SOURCE
- D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_COPY_DEST
DIRECT_QUEUE配置變體與計算佇列不相容,且無法在計算命令清單屏障中使用。 不過,它們與直接佇列中的計算作業相容。
無障礙存取
由於 ExecuteCommandLists 界限之間不能有擱置的命令或快取排清作業,因此緩衝區一開始可能會在 ExecuteCommandLists 範圍中存取,而不會有障礙。 同樣地,在下列情況下,紋理子資源也可能一開始存取,而不會有障礙:
- 子資源配置與存取類型相容。
- 任何必要的壓縮元數據會初始化。
版面配置中的紋理子資源D3D12DDI_BARRIER_LAYOUT_COMMON(或佇列特定的常見配置,例如D3D12DDI_BARRIER_LAYOUT_DIRECT_QUEUE_COMMON),在 ExecuteCommandLists 命令數據流中無法存取任何可能未完成的讀取或寫入作業,而不需使用下列任何一種存取類型來存取屏障:
- D3D12DDI_BARRIER_ACCESS_SHADER_RESOURCE
- D3D12DDI_BARRIER_ACCESS_COPY_SOURCE
- D3D12DDI_BARRIER_ACCESS_COPY_DEST
此外,使用佇列特定通用配置的緩衝區或紋理可以使用D3D12DDI_BARRIER_ACCESS_UNORDERED_ACCESS,而不需要障礙。
緩衝區和同時存取紋理(使用 D3D12DDI_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS 旗標建立的紋理)一開始可以在 ExecuteCommandLists 命令數據流中存取,而不需使用下列任何存取類型來障礙:
- D3D12DDI_BARRIER_ACCESS_VERTEX_BUFFER
- D3D12DDI_BARRIER_ACCESS_CONSTANT_BUFFER
- D3D12DDI_BARRIER_ACCESS_INDEX_BUFFER
- D3D12DDI_BARRIER_ACCESS_RENDER_TARGET
- D3D12DDI_BARRIER_ACCESS_UNORDERED_ACCESS
- D3D12DDI_BARRIER_ACCESS_SHADER_RESOURCE
- D3D12DDI_BARRIER_ACCESS_STREAM_OUTPUT
- D3D12DDI_BARRIER_ACCESS_INDIRECT_ARGUMENT
- D3D12DDI_BARRIER_ACCESS_COPY_DEST
- D3D12DDI_BARRIER_ACCESS_COPY_SOURCE
- D3D12DDI_BARRIER_ACCESS_RESOLVE_DEST
- D3D12DDI_BARRIER_ACCESS_RESOLVE_SOURCE
- D3D12DDI_BARRIER_ACCESS_PREDICATION
後續存取也可以進行,而沒有一個以上的寫入存取類型的障礙。 不過,除了D3D12DDI_BARRIER_ACCESS_RENDER_TARGET之外,屏障必須用來排清對相同資源的循序寫入。
自我資源複製
雖然與增強障礙無關,但允許從子資源某個區域複製到另一個非互動區域的能力是高度要求的功能。 透過增強的屏障,具有通用配置的子資源可以做為相同 CopyBufferRegion 或 CopyTextureRegion 呼叫中的來源和目的地。 在與來源和目的地記憶體區域交集之間的複本會產生未定義的結果。 偵錯層必須針對這類結果進行驗證。 (舊版資源屏障設計不允許子資源同時處於D3D12DDI_RESOURCE_STATE_COPY_SOURCE和D3D12DDI_RESOURCE_STATE_COPY_DEST狀態,因此無法複製到本身。
放置的資源元數據初始化
舊版資源屏障設計需要清除、複製或捨棄,才能在做為轉譯目標或深度樣板資源之前,先初始化新放置和啟動的別名紋理資源。 這是因為轉譯目標和深度樣板資源通常會使用必須初始化的壓縮元數據,才能讓數據有效。 同樣適用於具有新更新磚對應的保留紋理。
增強的屏障支援 [捨棄] 作為屏障一部分的選項。 屏障版面配置從D3D12DDI_BARRIER_LAYOUT_UNDEFINED轉換成任何可能壓縮的配置(例如,D3D12DDI_BARRIER_LAYOUT_RENDER_TARGET、D3D12DDI_BARRIER_LAYOUT_DEPTH_STENCIL、D3D12DDI_BARRIER_LAYOUT_UNORDERED_ACCESS)必須在D3D12DDI_TEXTURE_BARRIER_FLAG_DISCARD存在於 D3D12DDI_TEXTURE_BARRIER::Flags 成員中時初始化壓縮元數據。
除了轉譯目標和深度/樣板資源之外,舊版屏障模型還支持類似的UAV紋理壓縮優化。
障礙順序
屏障會依轉送順序排入佇列(API 呼叫順序、屏障群組索引、屏障陣列-index)。 相同子資源上的多個屏障必須運作,就像障礙以佇列順序完成一樣。
具有可能 寫入相同記憶體之 SyncAfter 範圍的佇列屏障必須依佇列順序完成所有寫入。 這項需求可避免在支持資源別名的屏障上進行數據競爭。 例如,停用資源的屏障必須排清任何快取,才能在相同記憶體上啟動不同資源的另一個屏障之前清除任何快取,才能清除元數據。