Unity-加載紋理和網格數(shù)據
Unity 可從磁盤加載紋理和網格數(shù)據,并以兩種不同方式將數(shù)據上傳到 GPU:同步或異步。這兩個過程稱為同步上傳管線和異步上傳管線。
當 Unity 使用同步上傳管線時,在加載和上傳數(shù)據時無法執(zhí)行其他任務。這種情況下可能會導致應用程序出現(xiàn)明顯的暫停。當 Unity 使用異步上傳管線時,數(shù)據在后臺加載和上傳,同時可以執(zhí)行其他任務。
如果某個紋理或網格適合異步上傳管線,則 Unity 會自動使用異步上傳管線。如果某個紋理或網格不適合異步上傳管線,則 Unity 會自動使用同步上傳管線。
工作原理
同步和異步上傳管線之間的主要區(qū)別是 Unity 在構建時保存數(shù)據的位置,這會影響 Unity 在運行時加載數(shù)據的方式。
在同步上傳管線中,Unity 必須在單個幀中同時加載紋理或網格的元數(shù)據(標頭數(shù)據)和紋素或頂點數(shù)據(二進制數(shù)據)。在異步上傳管線中,Unity 必須在單個幀中僅加載標頭數(shù)據,并可以在后續(xù)幀中將二進制數(shù)據流式傳輸?shù)?GPU。
在同步上傳管線中:
在構建時,Unity 將網格或紋理的標頭數(shù)據和二進制數(shù)據都寫入同一 .res 文件。
在運行時,當應用程序需要紋理或網格的時候,Unity 將該紋理或網格的標頭數(shù)據和二進制數(shù)據從 .res 文件加載到內存中。當所有數(shù)據都位于內存中時,Unity 隨后將二進制數(shù)據從內存上傳到 GPU。加載和上傳操作主要發(fā)生在主線程上的單個幀中。
在異步上傳管線中:
在構建時,Unity 將標頭數(shù)據寫入到一個 .res 文件,而將二進制數(shù)據寫入到另一個單獨的 .resS 文件。
在運行時,當應用程序需要紋理或網格的時候,Unity 將標頭數(shù)據從 .res 文件加載到內存中。當標頭數(shù)據位于內存中時,Unity 隨后使用固定大小的環(huán)形緩沖區(qū)將二進制數(shù)據從 .resS 文件流式傳輸?shù)?GPU。Unity 使用多個線程通過幾個幀流式傳輸二進制數(shù)據。請注意,在 Unity 已了解 GPU 硬件的某些游戲主機平臺上,Unity 會跳過環(huán)形緩沖區(qū)并直接加載到 GPU 內存中。
紋理和網格數(shù)據適合的上傳管線
如果滿足以下條件,紋理適合異步上傳管線:
紋理未啟用讀/寫權限。
紋理不在 Resources 文件夾中。
如果構建目標是 Android,在項目的構建設置 (Build Settings) 中啟用了 LZ4 壓縮。
請注意,如果使用?LoadImage(byte[] data)
?來加載紋理,即使?jié)M足上述條件,仍會強制 Unity 使用同步上傳管線。
如果滿足以下條件,網格適合異步上傳管線:
網格未啟用讀/寫權限。
網格不在 Resources 文件夾中。
網格沒有?BlendShape。
Unity 尚未將動態(tài)批處理 (Dynamic Batching) 應用于網格,原因是網格不適合進行動態(tài)批處理,或者是因為禁用了動態(tài)批處理。有關動態(tài)批處理的更多信息,請參閱繪制調用批處理。
粒子系統(tǒng)、地形或網格碰撞體不需要網格頂點/索引數(shù)據。
網格沒有骨骼權重。
網格拓撲不是四邊形。
網格資源的?meshCompression?設置為?Off。 如果構建目標是 Android,在項目的構建設置 (Build Settings) 中啟用了 LZ4 壓縮。
在所有其他情況下,Unity 會同步加載紋理和網格。
如何識別 Unity 所使用的上傳管線
可使用性能分析器或其他性能分析工具通過觀察線程活動和性能分析器標記來確定 Unity 在何時使用了異步上傳管線。
以下內容表明 Unity 正在使用異步上傳管線來上傳紋理或網格:
AsyncUploadManager.ScheduleAsyncRead、AsyncReadManager.ReadFile 和 Async.DirectTextureLoadBegin 性能分析器標記。
AsyncRead 線程上的活動。
如果沒有看到此活動,則表明 Unity 沒有使用異步上傳管線。
請注意,以下性能分析器標記并不表示 Unity 正在使用異步上傳管線;Unity 調用它們來檢查是否需要進行任何異步上傳工作:
Initialization.AsyncUploadTimeSlicedUpdate
AsyncUploadManager.AsyncResourceUpload
AsyncUploadManager.ScheduleAsyncCommands
配置異步上傳管線
可配置異步上傳管線的以下設置。請注意,無法配置同步上傳管線的設置。
Async Upload Buffer
Unity 重復使用單個環(huán)形緩沖區(qū)將紋理和網格數(shù)據流式傳輸?shù)?GPU。如此將減少所需的內存分配次數(shù)。
Async Upload Buffer?決定了此環(huán)形緩沖區(qū)的大?。ㄒ?MB 為單位)。該值的最小大小為 2,最大大小為 512。
Unity 會自動調整緩沖區(qū)的大小以適應當前加載的最大紋理或網格。這可能是一個緩慢的操作,尤其是在 Unity 必須多次執(zhí)行該操作的情況下;例如,如果要加載許多大于默認緩沖區(qū)大小的紋理,則屬于這種情況。為了減少 Unity 必須調整緩沖區(qū)大小的次數(shù),請設置該值以適合您期望加載的最大值。通常這是場景中最大的紋理。
可在 Quality settings 窗口中或使用?QualitySettings.asyncUploadBufferSize?API 來配置該值。
Async Upload Time Slice
Async Upload Time Slice?是 CPU 將紋理或網格數(shù)據上傳到 GPU 時花費的時間量(以毫秒/幀為單位)。
較大的值表示數(shù)據將更快地在 GPU 上準備就緒,但是 CPU 將在這些幀期間花費更多時間進行上傳操作。請注意,只有在緩沖區(qū)中有數(shù)據等待上傳到 GPU 時,Unity 才使用此時間進行上傳;如果沒有等待的數(shù)據,Unity 可以將此時間用于其他操作。
可在 Quality settings 窗口中或使用?QualitySettings.asyncUploadTimeSlice?API 來配置該值。
其他信息
有關異步上傳紋理和網格數(shù)據的更多信息,請參閱 Unity 博客文章:優(yōu)化加載性能:了解異步上傳管線 (Optimizing loading performance: Understanding the Async Upload Pipeline)。