Direct3D 11 到 Direct3D 12 的重要變更

Direct3D 12 代表從 Direct3D 11 程式設計模型的重大離開。 Direct3D 12 可讓應用程式更接近硬體。 透過更接近硬體,Direct3D 12 更快速且更有效率。 但是,使用 Direct3D 12 提高速度與效率的應用程式取捨,就是您負責的工作比使用 Direct3D 11 還要多。

Direct3D 12 是低階程式設計的傳回;它藉由介紹這些新功能,讓您更充分掌控遊戲和應用程式的圖形化元素:物件,代表管線的整體狀態、工作提交的命令清單和套件組合,以及資源存取的描述項堆積和資料表。

您的應用程式透過 Direct3D 12 提升速度與效率,但您負責的工作比 Direct3D 11 還要多。

明確同步處理

  • 在 Direct3D 12 中,CPU-GPU 同步處理現在是應用程式的明確責任,而且不再由執行時間隱含執行,因為它位於 Direct3D 11 中。 此事實也表示 Direct3D 12 不會對管線造成任何自動檢查,因此這同樣是應用程式的責任。
  • 在 Direct3D 12 中,應用程式負責管線資料更新。 也就是說,Direct3D 11 中的「Map/Lock-DISCARD」模式必須在 Direct3D 12 中手動執行。 在 Direct3D 11 中,如果您在呼叫 ID3D11DeviceCoNtext::MapD3D11_MAP_WRITE_DISCARD時,GPU 仍在使用緩衝區,則執行時間會傳回新記憶體區域的指標,而不是舊的緩衝區資料。 這可讓 GPU 繼續使用舊資料,而應用程式會將資料放在新的緩衝區中。 應用程式中不需要額外的記憶體管理;當 GPU 完成時,舊的緩衝區會自動重複使用或終結。
  • 在 Direct3D 12 中,所有動態更新 (包括常數緩衝區、動態頂點緩衝區、動態紋理等等) ,都會由應用程式明確控制。 這些動態更新包含任何必要的 GPU 柵欄或緩衝。 應用程式負責保留記憶體,直到不再需要為止。
  • Direct3D 12 只會針對介面的存留期使用 COM 樣式參考計數, (使用系結至裝置存留期之 Direct3D 的弱式參考模型) 。 所有資源和描述記憶體存留期都是應用程式唯一負責維護的適當持續時間,而且不會計算參考。 Direct3D 11 也會使用參考計數來管理介面相依性的存留期。

實體記憶體落地管理

Direct3D 12 應用程式必須防止多個佇列、多個配接器與 CPU 執行緒之間的競爭狀況。 D3D12 不再同步處理 CPU 和 GPU,也不支援資源重新命名或多重緩衝的便利機制。 柵欄必須用來避免多個處理單位在另一個處理單位使用它完成之前,從過度寫入的記憶體中避免多個處理單位。

Direct3D 12 應用程式必須在 GPU 讀取資料時,確保資料位於記憶體中。 每個物件所使用的記憶體都會在物件建立期間進行駐留。 呼叫這些方法的應用程式必須使用柵欄,以確保 GPU 不會存取已收回的物件。

資源屏障是另一種所需的同步處理類型,用來同步處理非常細微層級的資源和子資源轉換。

請參閱 Direct3D 12 中的記憶體管理

管線狀態物件

Direct3D 11 允許透過大型獨立物件集進行管線狀態操作。 例如,輸入組合器狀態、圖元著色器狀態、點陣化狀態和輸出合併狀態都可以獨立修改。 此設計提供方便且相對高階的圖形管線標記法,但不會利用新式硬體的功能,主要是因為各種狀態通常相依。 例如,許多 GPU 會將圖元著色器和輸出合併狀態結合成單一硬體標記法。 但因為 Direct3D 11 API 允許個別設定這些管線階段,所以顯示驅動程式無法解決管線狀態的問題,直到完成狀態,直到繪製時間為止。 此配置會延遲硬體狀態設定,這表示每個畫面的額外負荷和較少的繪製呼叫上限。

Direct3D 12 藉由將大部分管線狀態統一成不可變的管線狀態物件, (PS) 解決此配置,這會在建立時完成。 然後,硬體和驅動程式就可以立即將 PSO 轉換成執行 GPU 工作所需的任何硬體原生指令和狀態。 您仍然可以動態變更使用中的 PSO,但若要這麼做,硬體只需要直接將最少的預先計算狀態複製到硬體暫存器,而不是即時計算硬體狀態。 藉由使用 PSO,繪製呼叫額外負荷會大幅減少,而且每個畫面可以進行更多繪製呼叫。 如需 PSO 的詳細資訊,請參閱 在 Direct3D 12 中管理圖形管線狀態

命令清單和套件組合

在 Direct3D 11 中,所有工作提交都是透過 立即內容完成,這代表移至 GPU 的單一命令資料流程。 為了達到多執行緒調整,遊戲也有 可用的延遲內容 。 Direct3D 11 中的延後內容不會完全對應至硬體,因此在硬體中可以進行相對較少的工作。

Direct3D 12 會根據命令清單引進新的工作提交模型,其中包含在 GPU 上執行特定工作負載所需的完整資訊。 每個新的命令清單都包含資訊,例如要使用的 PSO、需要哪些紋理和緩衝區資源,以及所有繪製呼叫的引數。 因為每個命令清單都是獨立式的,而且不會繼承任何狀態,所以驅動程式可以預先計算所有必要的 GPU 命令,並以自由執行緒的方式預先計算。 唯一必要的序列程式是透過命令佇列將命令清單最終提交至 GPU。

除了命令清單之外,Direct3D 12 也引進第二層的工作預先計算: 套件組合。 不同于完全獨立且通常會建構、提交一次和捨棄的命令清單,套件組合會提供一種狀態繼承形式,以允許重複使用。 例如,如果遊戲想要繪製兩個具有不同紋理的字元模型,其中一種方法是使用兩組相同的繪製呼叫來記錄命令清單。 但另一種方法是「記錄」一個組合來繪製單一字元模型,然後使用不同資源在命令清單上「播放」套件組合兩次。 在後者的情況下,顯示驅動程式只需要計算適當的指示一次,而建立命令清單基本上相當於兩個低成本的函式呼叫。

如需命令清單和套件組合的詳細資訊,請參閱 Direct3D 12 中的工作提交

描述項堆積和資料表

Direct3D 11 中的資源系結高度抽象且方便,但讓許多新式硬體功能使用量過低。 在 Direct3D 11 中,遊戲會建立資源的 檢視 物件,然後將這些檢視系結至管線中各種著色器階段的數個 位置 。 著色器接著會從繪製時間固定的明確系結位置讀取資料。 此模型表示每當遊戲使用不同的資源繪製時,就必須將不同的檢視重新系結至不同的位置,然後再次呼叫繪製。 此案例也代表可藉由充分利用現代化硬體功能來消除的額外負荷。

Direct3D 12 會變更系結模型以符合新式硬體,並大幅改善效能。 Direct3D 12 不會要求獨立資源檢視和明確對應至位置,而是提供描述項堆積,讓遊戲建立其各種資源檢視。 此配置提供一種機制,讓 GPU 直接寫入硬體原生資源描述, (描述元) 到記憶體上線。 若要宣告管線要用於特定繪製呼叫的資源,遊戲會指定一或多個描述中繼資料表,代表完整描述元堆積的子範圍。 由於描述元堆積已經填入適當的硬體特定描述中繼資料,因此變更描述中繼資料表是非常低成本的作業。

除了描述元堆積和資料表所提供的改善效能之外,Direct3D 12 也允許在著色器中動態編制索引的資源,這可提供全新的彈性並解除鎖定新的轉譯技術。 例如,新式延後轉譯引擎通常會將某種材質或物件識別碼編碼為中繼 g 緩衝區。 在 Direct3D 11 中,這些引擎必須小心避免使用太多材質,因為包含一個 g 緩衝區中的太多資料可能會大幅降低最終轉譯階段的速度。 使用可動態編制索引的資源時,可以使用一千個材質的場景完成,就像只有 10 個一樣快速完成。

如需描述元堆積和資料表的詳細資訊,請參閱Direct3D 11 的系結模型資源系結和差異。

從 Direct3D 11 移植

從 Direct3D 11 移植是相關程式,如 從 Direct3D 11 移植到 Direct3D 12 中所述。 另請參閱 使用 Direct3D 11、Direct3D 10 和 Direct2D中的選項範圍。

瞭解 Direct3D 12