通過使用描述符類型,您可以將資源綁定到著色器,并指定如何訪問這些資源。這可在 CPU 和 GPU 之間實現高效通信,并使著色器能夠在渲染期間訪問必要的數據。
推薦
- 首選“無綁定”設計。
- 使用無界數組描述符,指向包含幀所需的所有已知紋理、緩沖區和加速結構的大型描述符表或集合。
- 預先上傳盡可能多的數據(紋理、每繪制常量和每幀常量),并通過這些描述符數組進行訪問。
- 這種設計還可以更輕松地實現光線追蹤,即允許訪問每個著色器中的每個紋理和緩沖區。
- 將描述符緩存在 GPU 可見的描述符堆 (DirectX 12) 或具有已知偏移量的集合 (Vulkan) 上。這降低了 CPU 開銷,幾乎消除了復制描述符的需求。
- 使用堆的多個副本以優雅方式處理描述符更改,例如流式傳輸紋理和緩沖區。但不要超過 1M 和 2K 的限制。有關更多信息,請參閱本博文后面的 不推薦 小節。
- 使用根 (DirectX 12) 或推送 (Vulkan) 常量。它們是每次繪制傳輸不同常量的最快方法。
- 在 Pascal 上:對于常量數據,首選 CBV 而非 SRV.
- 一般來說,SRV 緩沖區的速度要比 <=Pascal 上的 CBV 緩沖區慢。
- Volta 及更高版本的性能相當。
- 更好的方法是嘗試使用根常量。
- 即使對于不經常更改的數據(例如,材質數據、通道數據和每幀數據),它們也可以更快。
DirectX 12
- 您可以隨意更大限度地使用完整的 64
DWORD
根簽名中可用的數據類型。 - GPU 和 CPU 上的性能排名:
- 根常量是最快的,沒有間接,并且可以直接索引。
- 根 CBV/SRV/UAV 是第二快,具有單向和無邊界檢查。
- 描述符表速度最慢,需要檢查兩個間接和邊界。
- 例如 HLSL SM 6.6,使用動態資源綁定。
- 這樣,您可以從根簽名中省略一些描述符表,以獲得更多的根常量和其他數據空間。有關更多信息,請參閱 正在開發中:HLSL 著色器模型 6.6。
- 切換根簽名是一項快速操作。
- 使用多個根簽名來提高綁定效率可能是一種有效的策略。
- 這對于非無綁定設計尤其如此。
- 在不必要地重新綁定大量數據時,它可能效率低下。切換根簽名會導致現有綁定丟失。
- 在某些情況下,使用 Root Signature 1.1 可以獲得略高的性能。
- 特別是,使用
DATA_STATIC_SET_AT_EXECUTE
盡可能讓驅動程序提前內聯一些數據。 - 這不是高優先級;僅在方便時使用。
- 特別是,使用
Vulkan
- 盡量減少管道布局中描述符集的數量。
- 使用動態統一緩沖區和存儲緩沖區進行每次繪制調用更改。
- 首選使用組合圖像和采樣器描述符。
- Vulkan 1.2 支持將存儲緩沖區的設備地址作為 64 位值傳遞給著色器。這可實現 DirectX 或 HLSL 中無法使用的類似指針的工作流(例如投射)。GLSL 通過
GL_EXT_buffer_reference (2)
并使用SPV_EXT_physical_storage_buffer
。嘗試優化buffer_reference_align
因為硬件可以相應地利用更廣泛的內存加載操作。
不推薦
- 整個應用程序(GPU 可見)的活動描述符和采樣器總數不得超過 100 萬個。
- 否則,在切換描述符堆 (DirectX 12) 時,整個 GPU 的工作流可能會停滯。
- 每當超過限制時,它都會降低命令列表的異步執行效率。
- 在 Vulkan 上,驅動程序會自動執行描述符的重復數據刪除。前面提到的限制僅計入獨特的變體。
- 通常情況下,請盡量低于
VkPhysicalDeviceLimits
.
- 通常情況下,請盡量低于
- 盡可能避免使用類型化的 UAV 負載或存儲。
DirectX 12
- 防止在幀期間過度創建或復制描述符。
- 永久性地保留描述符,而不是在每一幀中重新分配或復制它們。
- 在描述符表中使用根 CBV 而非 CBV.
- 無需調用
CreateConstantBufferView
具有根 CBV.
- 無需調用
- 仔細選擇較小的描述符表也可以改善這種情況。
- 盡可能將重復的描述符減少為相同的資源。
- 示例:不應在描述符 0、10、20、30、40、50 等中引用紋理 0.
- 相反,請嘗試更改描述符表的布局,以便能夠多次重用相同的描述符。
Vulkan
- 不要在單個描述符集中存在過于稀疏的綁定偏移。
- 盡可能緊密地打包。
- 未使用的綁定索引會浪費內存并降低緩存效率。
?