UMA 優化:CPU 可存取紋理和標準 Swizzle
整合記憶體架構 (UMA) GPU 在離散 GPU 上提供一些效率優勢,尤其是在針對行動裝置進行優化時。 當 GPU 是 UMA 時提供資源 CPU 存取權,可以減少 CPU 與 GPU 之間發生的複製數量。 雖然我們不建議應用程式盲目授與 UMA 設計上所有資源的 CPU 存取權,但有機會藉由提供正確的資源 CPU 存取來提升效率。 不同於離散 GPU,CPU 在技術上可以具有 GPU 可存取之所有資源的指標。
CPU 可存取紋理的概觀
圖形管線中的CPU可存取紋理是UMA架構的一項功能,可讓CPU讀取和寫入紋理。 在較常見的離散 GPU 上,CPU 無法存取圖形管線中的紋理。
紋理的一般最佳做法建議是容納離散 GPU,這通常涉及遵循透過緩衝區上傳紋理數據中的程式,摘要如下:
- 沒有大部分紋理的任何 CPU 存取權。
- 將紋理配置設定為 D3D12_TEXTURE_LAYOUT_UNKNOWN。
- 使用 CopyTextureRegion 將紋理上傳至 GPU。
不過,在某些情況下,CPU 和 GPU 可能會經常在相同的數據上互動,讓對應紋理有助於節省電源,或加速特定適配卡或架構上的特定設計。 應用程式應該偵測到這些案例,並將不必要的複本優化。 在此情況下,為了獲得最佳效能,請考慮下列事項:
只有在D3D12_FEATURE_DATA_ARCHITECTURE::UMA 為 TRUE 時,才會開始娛樂對應紋理的更好效能。 然後在決定要在堆積上選擇要選擇的 CPU 快取屬性時,請注意 CacheCoherentUMA 。
利用紋理的CPU存取比緩衝區複雜得多。 GPU 最有效率的紋理配置很少row_major。 事實上,某些 GPU 只能在複製紋理數據時支援row_major紋理。
UMA GPU 應普遍受益於簡單的優化,以減少層級負載時間。 辨識 UMA 之後,應用程式可以將初始 CopyTextureRegion 優化,以填入 GPU 不會修改的紋理。 應用程式可以使用 WriteToSubresource 來避免了解實際的紋理配置,而不是使用D3D12_HEAP_TYPE_DEFAULT在堆積中建立紋理,以及封送處理紋理數據。
在 D3D12 中,使用 D3D12_TEXTURE_LAYOUT_UNKNOWN 建立的紋理,且沒有 CPU 存取對於頻繁的 GPU 轉譯和取樣最有效率。 在效能測試時,應該將這些紋理與 CPU 存取的D3D12_TEXTURE_LAYOUT_UNKNOWN進行比較,並使用 CPU 存取D3D12_TEXTURE_LAYOUT_STANDARD_SWIZZLE,以及交叉配接器支援的D3D12_TEXTURE_LAYOUT_ROW_MAJOR。
搭配 CPU 存取使用D3D12_TEXTURE_LAYOUT_UNKNOWN可讓 WriteToSubresource、ReadFromSubresource、Map(排除應用程式對指標的存取權)和 Unmap 的方法,但可以犧牲 GPU 存取的效率。
搭配 CPU 存取使用D3D12_TEXTURE_LAYOUT_STANDARD_SWIZZLE可啟用 WriteToSubresource、ReadFromSubresource、Map(它會傳回應用程式的有效指標),以及 Unmap。 它也可以犧牲 GPU 存取的效率超過 CPU 存取D3D12_TEXTURE_LAYOUT_UNKNOWN。
標準 Swizzle 概觀
D3D12 (和 D3D11.3) 引進標準多維度數據配置。 這樣做是為了讓多個處理單位在相同的數據上運作,而不需複製數據,或在多個版面配置之間撥動數據。 標準化的版面配置可透過網路效果提升效率,並允許演算法在假設特定模式時進行縮短。
如需紋理版面配置的詳細描述,請參閱 D3D12_TEXTURE_LAYOUT。
請注意,此標準旋轉是硬體功能,而且可能不受所有 GPU 支援。
如需令人眼花繚亂的背景資訊,請參閱 Z 順序曲線。
API
不同於 D3D11.3,D3D12 預設支援紋理對應,因此不需要查詢 D3D12_FEATURE_DATA_D3D12_OPTIONS。 不過,D3D12 不一定支援標準旋轉 - 此功能需要透過呼叫 CheckFeatureSupport 並檢查 D3D12_FEATURE_DATA_D3D12_OPTIONS 的 StandardSwizzle64KBSupported 字段來查詢。
下列 API 參考紋理對應:
列舉
結構
方法
- ID3D12Device::CreateCommittedResource :建立單一資源,並備份正確大小和對齊方式的堆積。
- ID3D12Device::CreateHeap :建立緩衝區或紋理的堆積。
- ID3D12Device::CreatePlacedResource :建立放在特定堆積中的資源,通常比 CreateHeap 更快建立資源的方法。
- ID3D12Device::CreateReservedResource :建立已保留但尚未認可或放在堆積中的資源。
- ID3D12CommandQueue::UpdateTileMappings :更新磚資源中磚位置與資源堆積中記憶體位置的對應。
- ID3D12Resource::Map :取得資源中指定數據的指標,並拒絕對子資源的 GPU 存取。
- ID3D12Resource::GetDesc :取得資源屬性。
- ID3D12Heap::GetDesc 會取得堆積屬性。
- ReadFromSubresource :從使用 Map 對應之紋理複製數據。
- WriteToSubresource :將數據複製到使用 Map 對應之紋理中。
資源和父堆積具有對齊需求:
- 適用於多重樣本紋理的 D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT (4MB)。
- 單一樣本紋理和緩衝區的D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT (64KB)。
- 線性子資源複製必須對齊D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT(512 個字節),數據列間距會對齊D3D12_TEXTURE_DATA_PITCH_ALIGNMENT(256 個字節)。
- 常數緩衝區檢視必須對齊D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT (256 個字節)。
小於 64KB 的紋理應該透過 CreateCommittedResource 來處理。
使用動態紋理(變更每個畫面的紋理),CPU 會以線性方式寫入上傳堆積,後面接著 GPU 複製作業。
一般而言,若要建立動態資源,請在上傳堆積中建立大型緩衝區(請參閱 緩衝區內的子位置)。 若要建立暫存資源,請在讀取回寫堆積中建立大型緩衝區。 若要建立預設靜態資源,請在預設堆積中建立相鄰的資源。 若要建立預設別名資源,請在預設堆積中建立重疊的資源。
WriteToSubresource 和 ReadFromSubresource 會在數據列主要版面配置與未定義的資源配置之間重新排列紋理數據。 作業是同步的,因此應用程式應該記住CPU排程。 應用程式一律可以將複製分解成較小的區域,或在另一個工作中排程此作業。 這些 CPU 複製作業不支援 MSAA 資源和具有不透明資源配置的深度樣板資源,而且會導致失敗。 不支持沒有兩個元素大小的乘冪格式,也會導致失敗。 可能會發生記憶體不足傳回碼。
相關主題