Unity5 (5.0-5.2) Shader编译机制初探 - 小心,Shader在吞噬你的内存
又被Unity坑了一把,簡單說下吧,下面都是流水賬,結論就寫在最后了,就是Unity5 - 5.2的shader編譯機制真是不咋地。
1.Why Always me?
問題是這樣的,我照著Unity5 的Standard shader寫了一個給我們工程用的簡化版的標準Shader以及配合使用的ShadergGUI,里面融合了很多功能,包括支持法線啊、uv動畫啊、半透鏤空等等,通過shader_feature定義的宏將這些效果融合到一個shader里,這樣既方便了美術,也方便了shader的管理,不用像原來一樣工程里亂七八糟的一堆shader了。
不過后期在真機測試的時候遇到了一個問題,就是我通過EnableKeyword來動態修改材質表現在設備上不好使了。當時第一想法就是Shader中那么多條件宏在build的時候被Unity自動strip掉了,因為我們大部分的資源都打包成了Assetbundle包,工程實際只有一個空場景,Shader資源都放在了Resources目錄下。如果說因為build的場景和資源里不包含shader的一些variant而被Unity自動去掉了這也是可以理解的。于是我就想GraphicsSettings里不是有個Always Included Shaders么,按照字面意思理解把shader放到那里去總是可以了吧,于是我就按下圖設置了下。嘿!還真就好了!
2.100MB WTF?
既然這樣好了,那看來真機調試時其他的一些問題比如角色表現增強效果應該也是這個原因嘍,那索性把其他的shader也都加進來吧,省的后面再出問題。別說這招真是包治百病,單機界面里我們還用了不少Standar shader,也就添加進來吧。ok,一切問題解決。。。。。。了嗎?
第二天測試就告訴我這個版本閃退頻繁,一查都是內存爆了。拿Instrument一看我靠,一登錄就快300MB了,看下Allocation,編譯Shader居然就用了100多MB。難道說跟昨天把Standard Shader加進去導致的?雖然是很懷疑不過既然調試已經定位到這里還是試一下吧,于是乎把Standard shader從Always Included Shaders列表中移除再發布,嘿!還真就好了!
3.真相水落石出
現在的情況就是
1.真機運行時Shader.EnableKeyword不好使,應該是因為Unity在Build時自動把沒有用到的variant刪減掉了(不是結論)
2.通過Always Included Shaders設置解決了問題,不過導致內存大量增加,應該是因為Unity在啟動時把該列表內的Shader的全部variant都展開編譯了出來,所以一方面解決了上面的問題,一方面卻增大了內存,而至于內存為什么會增加如此之多,那只能靠猜的了。
既然這樣,那就要想辦法解決Shader的內存占用了,既然全部variant占據的空間太大就部分加載唄,正好Unity5增加了個ShaderVariantCollection這么個東西,看看好不好用。結果。。。。。多天的各種實驗全部以失敗告終,這包括:
1.創建ShaderVariantCollection資源,包含目標shader的全部variant,并添加到GraphicsSettings的Preload Shaders列表中
2.通過代碼創建ShaderVariantCollection,并調用WarmUp接口
=========================流水賬分割線==================================
下面總結下我分析出來的Unity5.0 - 5.2的Shader編譯加載策略
1. 發布工程時,Unity 會將全部multi_compile定義宏組合成的variant編譯并加入包中
2. 發布工程時,Unity 會將全部關聯材質引用到的variant編譯并加入包中
3. 發布工程時,Unity會將Always Included Shaders列表中全部Shader的全部variant編譯并加入包中
4. Build Assetbundle時,Unity會將關聯的Shader的全部由multi_compile定義的variant以及使用到的variant編譯并加入包中
總結
以上是生活随笔為你收集整理的Unity5 (5.0-5.2) Shader编译机制初探 - 小心,Shader在吞噬你的内存的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 推荐两个好用的小工具
- 下一篇: Cadence导出Excel格式BOM表