共用方式為


D3D12 增強式屏障

增強型屏障的 DDI 介面可在 Windows 11 22H2 WDK (WDDM 3.0) 版中使用。 若要在 22H2 (或舊版作業系統上使用增強的屏障) ,您必須安裝 1.706.4 預覽的 Agility SDK

D3D12 增強屏障可讓開發人員獨立控制 GPU 工作同步處理、紋理配置轉換,以及快取排清 (「資源記憶體取」) 。 此功能提供一組 Direct3D API 和 DIS,可讓開發人員獨立控制 GPU 工作同步處理、紋理配置轉換,以及快取排清 (資源記憶體存取) 。

增強的屏障會以更具表達性的屏障類型取代 舊版資源 屏障。 功能包括下列各項:

  • 同步處理延遲較少。
  • 減少過多的快取排清。
  • 沒有二元升階和衰減規則。
  • 快速、彈性的資源別名 (各種別名拓撲) 。
  • 在屏障轉換期間捨棄。
  • 支援並行讀取/寫入,包括相同資源複製 (自我複製) 。
  • 支援異步捨棄、複製、解析和清除命令。

增強的屏障比舊版資源屏障更簡單,但較不明確,因此讓開發人員更容易使用。

報告增強的屏障支援

增強的屏障功能目前不是硬體或驅動程式需求。 驅動程式會將 D3D12DDI_D3D12_OPTIONS_DATA_0089EnhancedBarriersSupported 成員設定為 TRUE,以指出支援。

  • D3D12DDI_FEATURE_VERSION_VIDEO_0088_0是定義 Windows 11 中引進的 D3D12 增強屏障里程碑初步實作的版本號碼。

D3D12 增強式屏障回呼函式

指出支持增強式屏障的驅動程式會實作下列回呼函式:

設計詳細數據

驅動程式通常會使用三個不同的作業來處理舊版資源屏障:

  1. 同步處理 GPU 工作。
  2. 執行任何必要的快取排清作業。
  3. 執行任何必要的版面配置變更。

增強的屏障可讓開發人員分別控制每個作業。

增強型屏障的類型

增強型屏障有三種類型:

範圍障礙會 取代 舊版資源屏障。 提供範圍屏障,以便完全實作舊版資源屏障,且不會遺失明顯的效能。

  • 所有屏障類型都會控制 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 工作都必須同步處理,才能存取相依數據。

增強的屏障介面會使用明確的 SyncBeforeSyncAfter 值作為邏輯位字段遮罩。 在執行屏障之前,屏障必須等候所有上述命令 SyncBefore 範圍完成。 同樣地,屏障必須封鎖所有後續 的 SyncAfter 範圍,直到屏障完成為止。 D3D12DDI_BARRIER_SYNC 指定 GPU 與屏障相關的同步處理範圍。

如需詳細資訊,請參閱 增強式屏障規格

版面配置轉換

紋理子資源可以針對各種訪問方法使用不同的版面配置。 例如,當做轉譯目標或深度樣板使用時,通常會壓縮紋理,而且通常會取消壓縮著色器讀取或複製命令。 紋理屏障會使用 LayoutBeforeLayoutAfterD3D12DDI_BARRIER_LAYOUT 值來描述版面配置轉換。

只有紋理需要版面配置轉換,因此它們只會以 D3D12DDI_TEXTURE_BARRIER 數據結構表示。

LayoutBeforeLayoutAfter 都必須與執行屏障的佇列類型相容。 例如,計算佇列無法將子資源轉換成或移出 D3D12DDI_BARRIER_LAYOUT_RENDER_TARGET

為了提供定義完善的屏障順序,完成一連串屏障之後子資源的配置是序列中最後的 LayoutAfter

存取轉換

由於會快取許多 GPU 寫入作業,因此任何從寫入許可權到另一個寫入許可權的屏障,或唯讀存取可能需要快取排清。 增強的屏障 API 會使用存取轉換來表示必須針對特定的新存取類型顯示子資源的記憶體。 就像版面配置轉換一樣,如果已知相關聯子資源的記憶體已經可供所需的使用存取權,就可能不需要某些存取轉換。

存取轉換的表示方式如下:

  • 針對紋理,作為D3D12DDI_TEXTURE_BARRIER結構的一部分。
  • 針對緩衝區,作為D3D12DDI_BUFFER_BARRIER結構的一部分。

存取轉換不會執行同步處理。 在屏障中使用適當的 SyncBeforeSyncAfter 值來處理相依存取之間的同步處理。

對指定的 AccessAfter 顯示 AccessBefore 不保證資源記憶體也適用於不同的存取類型。 例如:

MyTexBarrier.AccessBefore=D3D12DDI_BARRIER_ACCESS_UNORDERED_ACCESS;
MyTexBarrier.AccessAfter=D3D12DDI_BARRIER_ACCESS_SHADER_RESOURCE;

此存取轉換表示後續著色器讀取存取權相依於先前未排序的 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 時,就會發出偵錯層警告。

單一佇列同時存取

增強的屏障允許相同緩衝區上的並行讀取/寫入作業,或在相同的命令佇列中同時存取紋理。

緩衝區和同時存取資源一律支援來自一個佇列的寫入存取,以及一或多個其他佇列的非相依讀取存取權。 這項支援是因為這類資源一律使用 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狀態,因此無法複製到本身。)

放置的資源元數據初始化

舊版資源屏障設計需要新放置和啟用的別名紋理資源,才能由 Clear、Copy 或 Discard 初始化,再作為轉譯目標或深度樣板資源使用。 此需求是因為轉譯目標和深度樣板資源通常會使用必須初始化的壓縮元數據,才能讓數據有效。 同樣適用於具有新更新磚對應的保留紋理。

增強的屏障支援在屏障中捨棄的選項。 屏障配置會從D3D12DDI_BARRIER_LAYOUT_UNDEFINED轉換成任何可能壓縮的配置 (例如,D3D12DDI_BARRIER_LAYOUT_RENDER_TARGET、D3D12DDI_BARRIER_LAYOUT_DEPTH_STENCIL、D3D12DDI_BARRIER_LAYOUT_UNORDERED_ACCESS) 必須在D3D12DDI_TEXTURE_BARRIER::Flags 成員中有D3D12DDI_TEXTURE_BARRIER_FLAG_DISCARD時初始化壓縮元數據。

除了轉譯目標和深度/樣板資源之外,還有類似的UAV紋理壓縮優化,舊版屏障模型不支援。

屏障排序

屏障會依轉寄順序排入佇列 (API 呼叫順序、屏障群組索引、屏障陣列索引) 。 相同子資源上的多個屏障必須運作,就像障礙以佇列順序完成一樣。

具有相符 SyncAfter 範圍的佇列屏障,這些範圍可能會寫入相同的記憶體,必須依佇列順序完成所有寫入。 這項需求可避免在支持資源別名的屏障上進行數據競爭。 例如,資源「停用」的屏障必須在另一個在相同記憶體上啟用不同資源的屏障之前排清任何快取,才能清除元數據。