共用方式為


性能 — MRTK2

快速入門

最簡單的效能合理化方式是透過幀率,也就是你的應用程式每秒能渲染多少張圖片。 達到目標幀率非常重要,這取決於目標平台 (Windows Mixed RealityOculus 等) 。 例如,在 HoloLens 上,目標幀率是 60 FPS。 低幀率應用可能導致使用者體驗惡化,例如全 息影像穩定、世界追蹤、手部追蹤等。 為了協助開發者追蹤並達成高品質的幀率,Mixed Reality Toolkit 提供了多種工具與腳本。

視覺分析器

為了持續追蹤開發期間的效能,強烈建議在執行 & 除錯應用程式時,始終顯示幀率視覺化。 Mixed Reality Toolkit 提供視覺剖析器診斷工具,能即時提供應用程式檢視中當前 FPS 與記憶體使用情況的資訊。 視覺分析器可透過 MRTK 輪廓檢查器下的診斷系統設定進行設定。

此外,特別重要的是利用視覺分析器(Visual Profiler)來追蹤裝置上的幀率,而非在 Unity 編輯器或模擬器中執行。 當裝置運行於有 Release 配置建置時,最準確的效能結果會顯示出來。

注意事項

如果是為 Windows Mixed Reality 建置,請用 MASTER 配置建置來部署。

視覺分析器介面

優化視窗

MRTK 優化視窗提供資訊與自動化工具,協助混合實境開發者建立環境以達到最佳效能,並識別場景 & 資產中的潛在瓶頸。 Unity 中的某些關鍵配置能幫助混合實境專案提供更優化的結果。

一般來說,這些設定涉及對混合實境理想的渲染配置。 混合實境應用與傳統 3D 圖形開發不同,因為它有兩個螢幕 (也就是兩個眼睛,) 渲染整個場景。

以下推薦的設定可透過 MRTK 優化視窗在 Unity 專案中自動設定。

MRTK 優化視窗設定

Unity Profiler

Unity Profiler 是一個有用的工具,可以逐幀檢視應用程式效能細節。

CPU 使用時間

Unity Profiler 圖範例

為了維持舒適的幀率 (通常為每秒 60 幀) ,應用程式需要達到 CPU 時間的最大幀時間為 16.6 毫秒。 為了協助識別 MRTK 功能的成本,Microsoft Mixed Reality 工具包包含每幀內迴圈 () 程式碼路徑的標記。 這些標記採用以下格式,以協助理解所使用的具體功能:

[MRTK] className.methodName

注意事項

方法名稱後面可能還有其他資料。 此方法用來識別條件執行、可能成本高昂的功能,這些功能可透過對應用程式程式碼進行小幅修改來避免。

Unity Profiler 階層範例

在此範例中,階層結構擴展顯示 WindowsMixedRealityArticulatedHand 類別的 UpdateHandData 方法在分析幀期間佔用 0.44 毫秒的 CPU 時間。 這些資料可用來判斷效能問題是否與應用程式碼有關,或系統其他方面。

強烈建議開發者以類似方式進行應用程式程式碼的安裝。 應用程式碼儀器化的主要焦點在於事件處理程序,因為這些方法會隨著事件被觸發而被分配到 MRTK 更新迴圈。 MRTK 更新迴圈中的高幀時間可能反映事件處理方法中程式碼成本昂貴。

Single-Pass 實例化渲染

Unity 中 XR 的預設渲染配置是 多重通過(Multi-pass)。 這個設定指示 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 提供預設 值來控制 每個平台端點的渲染品質。 這些預設控制可啟用的圖形功能,如陰影、抗鋸齒、全域光照等。 建議降低這些設定並優化渲染時執行的計算次數。

步驟一: 更新混合實境 Unity 專案,使其使用 低品質 的等級設定
編輯>專案設定,然後選擇品質分類>,選擇 UWP 平台的低品質

步驟二: 對於每個 Unity 場景檔案,請關閉 即時全域照明
窗戶>渲染>燈光設定>取消勾選 即時全局照明

深度緩衝區共享 (HoloLens)

若為 Windows Mixed Reality 平台開發,特別是 HoloLens,啟用 XR 設定中的深度緩衝區共享有助於全息影像穩定。 然而,處理深度緩衝區可能會產生效能成本,尤其是在使用 24 位元深度格式時。 因此, 強烈建議 將深度緩衝區設定為 16 位元精度。

若因較低位元格式發生 z 戰鬥 ,請確認所有攝影機的 遠端剪輯平面 是否設定為該應用的最低值。 Unity 預設設定的 1000 公尺為 1000 公尺的剪輯平面。 在 HoloLens 上,50 公尺的遠端剪距平面通常足夠應付大多數應用場景。

注意事項

若使用 16 位元深度格式,模板緩衝區所需的效果將無法運作,因為 Unity 在此設定下不會建立模板緩衝區 。 反之,選擇 24 位元深度格式 通常會產生 8 位元的模板緩衝區(若適用於端點圖形平台)。

若使用需要模板緩衝區的 遮罩元件 ,請考慮改用 RectMask2D ,該元件不需要模板緩衝區,因此可搭配 16 位元深度格式使用。

注意事項

為了快速判斷場景中哪些物件無法視覺化寫入深度緩衝區,可以在 MRTK 配置檔的編輯器設定中使用 Render Depth Buffer 工具

優化網格資料

優化網格資料設定會嘗試移除應用程式中未使用的頂點屬性。 設定會透過重播每個材質的著色器通道來執行,這些材質在建構中每個網格上。 這對遊戲資料大小和執行效能來說是好事,但會大幅拖慢建置時間。

建議在開發時停用此設定,並在建立「Master」建置時重新啟用。 該設定可在編輯>專案設定>、播放器>、其他設定>、優化網格資料中找到。

一般建議

效能對混合實境開發者來說可能是一個模糊且不斷變化的挑戰,而關於效能合理化的知識範圍非常廣泛。 不過有一些通用性的建議,可以幫助你了解如何評估應用程式的效能。

將應用程式的執行簡化為執行在 CPUGPU 上的部分,從而辨識應用程式是否受限於任一元件,是有用的。 瓶頸可能跨越兩個處理單元,且有些特殊情境需要仔細調查。 不過,對於入門來說,了解應用程式執行時間最多的地點是很重要的。

GPU 有界

由於大多數混合實境應用平台採用 立體渲染,因此由於渲染「雙寬」螢幕的特性,GPU限制非常常見。 此外,像 HoloLens 或 Oculus Quest 這類行動混合實境平台,將受限於行動級 CPU & GPU 運算能力。

專注於 GPU 時,應用程式通常必須在每一幀完成兩個重要階段。

  1. 執行 頂點著色器
  2. 執行 像素著色器 (也稱為片段著色器)

不深入探討複雜的電腦圖形 & 渲染管線領域,每個著色器階段都是在 GPU 上執行的程式,產生後續內容。

  1. 頂點著色器將網格頂點轉換為螢幕空間中的座標 (即每個頂點執行的程式碼)
  2. 像素著色器會計算給定像素和網格片段要繪製的顏色 (也就是每像素執行的程式碼)

關於效能調校,通常專注於優化像素著色器的操作會更有效率。 應用程式可能只需要繪製一個立方體,這會是 8 個頂點。 然而,這個立方體所佔的螢幕空間很可能有數百萬個像素。 因此,將著色器程式碼減少 10 次運算,若在像素著色器上減少工作,將比頂點著色器節省更多工作。

這也是使用 MRTK Standard 著色器的主要原因之一,因為該著色器通常在每個像素 & 頂點執行指令數遠少於 Unity Standard 著色器,卻能達成相當的美學效果。

CPU 優化 GPU 優化
應用程式模擬邏輯 渲染作業
簡化物理 減少光照計算
簡化動畫 減少可繪製物件的多邊形數量 & #
管理垃圾回收 減少 # 透明物件
快取參考 避免後製/全螢幕效果

繪製呼叫實例化

Unity 中最常導致效能下降的錯誤之一,就是在執行時複製材質。 如果 GameObjects 共享相同材質和/或相同網格,可以透過 靜態批次動態批次GPU 實例化等技術,將它們優化成單一繪製呼叫。 然而,如果開發者在執行時修改 了渲染器材質 的屬性,Unity 會建立該材質的複製品。

例如,如果場景中有 100 個立方體,開發者可能想在執行時為每個立方體指派獨特的顏色。 在 C# 中存取 renderer.material.color 會讓 Unity 在記憶體中為這個特定渲染器/遊戲物件建立新的材質。 這 100 個立方體各自有自己的素材,因此無法合併成一個繪製呼叫,而是會變成 CPU 對 GPU 的 100 個繪製呼叫請求。

為了克服這個障礙,同時仍能為每個立方體分配獨特顏色,開發者應該善用 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 著色器統計範例

Unity Standard 著色器統計 1

MRTK Standard 著色器統計範例

MRTK Standard 著色器統計 2

另請參閱

統一

Windows Mixed Reality

Oculus

網格優化