渲染引擎的資源載入優化

2022-06-30 15:06:07

渲染引擎的資源載入優化

針對一個渲染引擎的效能,最主要的當然是實時渲染的影格率。另一方面,對於輕型的引擎來說,使用者不會對場景載入
保有一個較長的載入時間的心理預期,最好是,點選按鍵,瞬間整個場景出現,畢竟輕量應用場景不是重型遊戲。針對
這種需求,我們需要對資源載入做一個全面的效能排查與優化。

Steps

根據《Unix程式設計藝術》中的描述,效能優化最好是不要優化,如果要優化那麼花費一點時間把 bottle neck 找到是很有
必要的。所以在我的優化工作中,我首先對整個系統做了較為完整的 profile. 我大致將整個資源載入部分邏輯分成了
自頂向下的三層:

  1. meshrender 層:整個場景存在若干個 meshrender,該層級統計各個 meshrender 的載入時間
  2. resource 層:每個meshrender 依賴若干資源:mesh, material, skin/animation 等等
  3. detailed resource 層:對每個 resource 的詳盡的分部統計,不同的 resource 步驟也不同

MeshRender

對我們的整個引擎的載入部分,分層級自上而下統計,對每個 meshrender 統計得到的情況如下表,其中分別有幾個模組:
Mesh Material Skin 各佔一部分,同時圖片的載入已經使用了非同步執行緒載入方式,故不統計在總時間內(載入圖的子
執行緒在主載入執行緒完成任務之前就已經完成結束)。從下表資料看,Mesh 與 Material 均佔較大部分的比例,所以在下面
detailed 層,專門針對這兩個部分繼續剖析。

- Img Load(Async) Mesh Material Skin Others Total
Current 31.07 40.85 101.70 8.27 3.04 153.86

Detailed

Detailed 分析分別對幾個不同的模組進行了分析。其中 Mesh 的載入雖然耗時較長,但是實際時間絕大部分用在將 mesh
資料從檔案中讀取到記憶體,並沒有發現其他可能浪費時間的耗時操作,邏輯上也比較簡單,故結論是無優化空間。

另外 Material 部分,其邏輯就比單純載入一塊 mesh 的buffer 要複雜許多了。其中包括了特定物件 MaterialAsset 的
建立與初始化,shader 的載入以及解析,啟動非同步讀圖執行緒等等。具體的耗時分佈如下表所示。

- Get AbsPath Material Asset Shader Async load imgs Others Total
Current 1.38 1.77 8.20 1.71 1.10 14.15

其中 shader 部分是耗時大頭,此處 shader 並不僅僅包括 shader 檔案的載入,還有其中一些 uniform 變數的解析,
探究其邏輯發現兩點

  • shader 檔案讀取存在一次多餘的 copy
  • 其中有一個超過20個 case 的 switch 語句

針對這兩者情況我都做了相應的優化

  • 使用資料指標代替原有的 std::vector<> 在傳遞時幾乎沒有損耗
  • 使用查表的方式替代 switch-case 語句,提高效能同時也提升程式碼質量,減少圈複雜度,同時更便於維護和更新

優化以後的資料如下表

- Get AbsPath Material Asset Shader Async load imgs Others Total
Current 1.38 1.77 8.20 1.71 1.10 14.15
Optimize 1.52 1.85 7.44 1.28 0.52 12.61

在 Skin 的載入部分同樣找到了部分多餘的值 copy 操作,優化為參照後資料略有提升。

總結

最後我們來看一下總體的效能提升情況

- Img Load(Async) Mesh Material Skin Others Total
Current 31.07 40.85 101.70 8.27 3.04 153.86
Optimize 33.62 36.40 80.81 6.88 3.28 127.37
Performance of resource loading

              Mesh                    Material               Skin Others
before opt  xxxxxxxxxxxxxx|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|xxx|x|
after opt   xxxxxxxxxxxx|xxxxxxxxxxxxxxxxxxxxxxxxxxx|xx|x|