效能 — MRTK2
快速入門
將效能合理化的最簡單方式是透過幀速率,或您的應用程式每秒可以轉譯影像的次數。 請務必符合目標幀速率,如 (目標平臺所述,也就是 Windows Mixed Reality、Oculus 等) 。 例如,在 HoloLens 上,目標幀速率是 60 FPS。 低幀速率應用程式可能會導致用戶體驗下降,例如 全像投影穩定、世界追蹤、手部追蹤等等。 為了協助開發人員追蹤並達到高品質的幀速率,Mixed Reality 工具組提供各種工具和腳本。
視覺分析工具
若要持續追蹤開發存留期的效能,強烈建議您在執行應用程式偵錯時,一律顯示幀速率視覺效果 &。 Mixed Reality 工具組提供 Visual Profiler 診斷工具,可提供應用程式檢視中目前 FPS 和記憶體使用量的實時資訊。 您可以透過 MRTK 設定檔偵測器下的診斷系統設定來設定 Visual Profiler。
此外,在裝置上執行時,使用 Visual Profiler 追蹤幀速率特別重要,而不是在 Unity 編輯器或模擬器中執行。 使用發行組態組建在裝置上執行時,將會描述最精確 的效能結果。
注意事項
如果建置 Windows Mixed Reality,請使用 MASTER 組態組建進行部署。
優化視窗
MRTK 優化視窗提供資訊和自動化工具,可協助混合實境開發人員設定其環境,以獲得最佳效能結果,並找出其場景 & 資產中的潛在瓶頸。 Unity 中的某些重要組態可協助為混合實境專案提供更優化的結果。
一般而言,這些設定牽涉到適用於混合實境的轉譯組態。 相較於傳統的 3D 圖形開發,混合實境應用程式是唯一的,因為有兩個螢幕 (也就是兩隻眼睛) 來呈現整個場景。
您可以利用 MRTK 優化視窗,在 Unity 專案中自動設定下列參考的建議設定。
Unity Profiler
Unity Profiler 是一個實用的工具,可依畫面格層級調查應用程式效能的詳細數據。
花費在 CPU 上的時間
若要維持舒適的幀速率 (通常每秒 60 個畫面格) ,應用程式必須達到 16.6 毫秒的 CPU 時間上限。 為了協助識別 MRTK 功能的成本,Microsoft Mixed Reality 工具組包含每個畫面) 程式代碼路徑的內部迴圈 (標記。 這些標記使用下列格式,以協助瞭解所使用的特定功能:
[MRTK] className.methodName
注意事項
方法名稱後面可能會有其他數據。 這可用來識別條件式執行且可能耗費大量資源的功能,而這些功能可能會因應用程式程序代碼的微小變更而避免。
在此範例中,階層已展開,以顯示 WindowsMixedRealityArticulatedHand 類別的 UpdateHandData 方法在分析框架期間耗用 0.44 毫秒的 CPU 時間。 此數據可用來協助判斷效能問題是否與應用程式程式碼或系統中的其他位置相關。
強烈建議開發人員以類似的方式檢測應用程式程式代碼。 應用程式程式代碼檢測的主要焦點區域是在事件處理程式內,因為這些方法會在引發事件時向 MRTK 更新循環收費。 MRTK 更新迴圈內的高畫面時間可能表示事件處理程式方法中的程序代碼成本很高。
Unity 的建議設定
Single-Pass 實例轉譯
Unity 中 XR 的預設轉譯組態是 多重傳遞。 此設定會指示 Unity 針對每個眼睛執行整個轉譯管線兩次。 您可以改為選取 [單一傳遞實例轉 譯] 來優化此功能。 此組態會利用 轉譯目標數位 來執行單一繪製呼叫,讓實例針對每個眼睛進入適當的 轉譯目標 。 此外,此模式允許在轉譯管線的單一執行中完成所有轉譯。 因此,選取 [單一傳遞實例轉譯] 做為混合實境應用程式的轉譯路徑,可以 節省 CPU & GPU 的大量時間 ,而這是建議的轉譯組態。
不過,為了對每個眼睛發出每個網格的單一繪製呼叫,所有著色器都必須支援 GPU 實 例。 實例可讓 GPU 在兩隻眼睛之間進行多任務繪製呼叫。 Unity 內建著色器以及 MRTK Standard 著色器預設會在著色器程式代碼中包含必要的實例指示。 如果為 Unity 撰寫自定義著色器,則可能需要更新這些著色器以支援單一傳遞實例轉譯。
自定義著色器的範例程序代碼
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID //Insert
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
UNITY_VERTEX_OUTPUT_STEREO //Insert
};
v2f vert (appdata v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v); //Insert
UNITY_INITIALIZE_OUTPUT(v2f, o); //Insert
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); //Insert
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
質量設定
Unity 提供 預設值來控制 每個平臺端點的轉譯品質。 這些預設會控制哪些圖形功能可以啟用,例如陰影、消除鋸齒、全域照明等等。 建議您降低這些設定,並將轉譯期間執行的計算數目優化。
步驟 1: 更新混合實境 Unity 專案以使用 低品質 層級設定
編輯>項目設定,然後選取 [品質 ] 類別 > 選取 UWP 平臺的 [低品質 ]
步驟 2: 針對每個 Unity 場景檔案,停用 即時全域照明
窗>渲染>光源設定>取消核取 即時全域照明
HoloLens (深度緩衝區共用)
如果針對 Windows Mixed Reality 平臺,特別是 HoloLens 進行開發,在 XR 設定下啟用深度緩衝區共用有助於防震全像投影。 不過,處理深度緩衝區可能會產生效能成本,特別是使用 24位深度格式時。 因此, 強烈建議 您將深度緩衝區設定為16位有效位數。
如果 z 衝突 是因為位格式較低而發生,請確認所有相機的 遠距裁剪平面 已設定為應用程式的最低可能值。 Unity 預設會將遠距裁剪平面設定為 1000m。 在 HoloLens 上,遠距 50 公分的裁剪平面通常足以滿足大部分的應用程式案例。
注意事項
如果使用 16位深度格式,樣板緩衝區所需的效果將無法運作,因為 Unity 不會在此設定中 建立樣板緩衝 區。 相反地選取 24 位深度格式 ,通常會在端點圖形平臺上建立 8 位樣板緩衝區。
如果使用需要樣板緩衝區的 遮罩元件 ,請考慮改用 RectMask2D ,這不需要樣板緩衝區,因此可以搭配 16 位深度格式使用。
注意事項
若要快速判斷場景中的哪些物件不會以可視化方式寫入深度緩衝區,您可以使用 MRTK 組態配置檔中 [編輯器 設定] 底下的轉譯深度緩衝區公用程式。
優化網格數據
[ 優化網格數據 ] 設定會嘗試移除應用程式內未使用的頂點屬性。 設定會透過在組建中每個網格上的每個材質傳入的每個著色器上執行 來執行此動作。 這適用於遊戲數據大小和運行時間效能,但可能會大幅阻礙建置時間。
建議您在開發期間停用此設定,並在「主要」組建建立期間重新啟用。 您可以在 [編輯>項目設定>播放>機] [其他設定>] 的 [優化網格數據] 下找到此設定。
一般建議
對於混合實境開發人員而言,效能可能是模棱兩可且不斷改變的挑戰,而合理化效能的知識範圍也非常龐大。 不過,有一些一般建議可讓您瞭解如何處理應用程式的效能。
將應用程式的執行簡化為 在CPU 或 GPU 上執行的片段,進而識別應用程式是否受任一元件所限定,會很有用。 可能同時存在跨越處理單位的瓶頸,以及一些必須仔細調查的獨特案例。 不過,若要開始使用,最好能掌握應用程式在最長時間執行的位置。
GPU 限定
由於混合實境應用程式的大部分平臺都使用 立體轉譯,因此由於轉譯「雙寬」畫面的本質,因此通常會以 GPU 系結。 Futhermore,HoloLens 或 Oculus Quest 等行動混合實境平臺會受限於行動類別 CPU & GPU 處理能力。
將焦點放在 GPU 時,應用程式通常必須完成每個畫面的兩個重要階段。
在不深入探討計算機圖形 & 轉譯管線的複雜欄位的情況下,每個著色器階段都是在 GPU 上執行以產生下列專案的程式。
- 頂點著色器會將網格頂點轉換成螢幕空間中的座標 (也就是每個頂點執行的程式代碼)
- 圖元著色器會計算指定圖元和網格片段的繪製色彩 (也就是每個圖元執行的程式代碼)
在效能微調方面,通常更著重於優化圖元著色器中的作業。 應用程式可能只需要繪製只有 8 個頂點的 Cube。 不過,Cube 佔用的螢幕空間可能依數百萬像素的順序排列。 因此,比起頂點著色器,減少著色器程序代碼的10個作業可大幅節省圖元著色器上的工作量。
這是利用 MRTK Standard 著色器的主要原因之一,因為此著色器通常會比 Unity Standard 著色器執行的每個圖元 & 頂點少許多指示,同時達到可比較的美觀結果。
CPU 優化 | GPU 優化 |
---|---|
應用程式模擬邏輯 | 轉譯作業 |
簡化物理 | 減少光源計算 |
簡化動畫 | 減少可繪製物件 & 多邊形計數 # |
管理垃圾收集 | 減少透明物件的數 |
快取參考 | 避免後置處理/全螢幕效果 |
繪製呼叫實例
Unity 中降低效能的最常見錯誤之一是在運行時間複製材質。 如果 GameObjects 共用相同的材質和/或是相同的網格,則可以透過 靜態批處理、 動態批處理和 GPU 實例等技術,將它們優化成單一繪製呼叫。 不過,如果開發人員在運行時間修改 轉譯器材質的 屬性,Unity 將會建立指派之材質的複製複本。
例如,如果場景中有100個 Cube,開發人員可能會想要在運行時間為每個 Cube 指派唯一的色彩。 在 C# 中存取 renderer.material.color 會讓 Unity 在記憶體中為此特定轉譯器/GameObject 建立新的材質。 100 個 Cube 中的每一個都會有自己的材質,因此它們無法合併成一個繪製呼叫,而是會變成從 CPU 到 GPU 的 100 個繪製呼叫要求。
若要克服此障礙,並且仍然為每個 Cube 指派唯一的色彩,開發人員應該利用 MaterialPropertyBlock。
private PropertyBlock m_PropertyBlock ;
private Renderer myRenderer;
private void Start()
{
myRenderer = GetComponent<Renderer>();
m_PropertyBlock = new MaterialPropertyBlock();
}
private void ChangeColor()
{
// Creates a copy of the material once for this renderer
myRenderer.material.color = Color.red;
// vs.
// Retains instancing capability for renderer
m_PropertyBlock.SetColor("_Color", Color.red);
myRenderer.SetPropertyBlock(m_PropertyBlock);
}
Unity 效能工具
Unity 提供內建在編輯器中的絕佳效能工具。
如果估計一個著色器與另一個著色器之間的粗略效能取捨,則編譯每個著色器並檢視每個著色器階段的作業數目會很有用。 您可以選取 著色器資產 ,然後按兩下 [ 編譯並顯示程式代碼 ] 按鈕來完成此作業。 這會編譯所有著色器變體,並使用結果開啟Visual Studio。 注意:所產生的統計數據結果可能會因使用指定著色器的材質上已啟用哪些功能而有所不同。 Unity 只會編譯目前專案中直接使用的著色器變體。
Unity Standard 著色器統計數據範例
MRTK Standard 著色器統計數據範例