盡可能簡化。
以CPU約4.65Ghz~4.8Ghz單核心頻率(zen3測),與12th intel間在不同情況下可能產生-10~10%IPC差異。(5800X3D大致上同等條件差異可能也差不多,除非大量繪製、遊戲script產生過多GC(垃圾收集)等會額外產生至15-30%IPC,考慮頻率稍低後約快20%+)
不可見avatar,但已經加載的情況:
物理骨骼,總計32個avatar的情況下,平均每個avatar活動的物理骨骼變換(transform)約在160~350左右,平均約256個(與poor->very poor標準一致)*32個約8192個,會產生約5~6ms的CPU frametime。
平常測量狀態約30% L3 cache miss(以system PCM採樣),正常情況下重負荷約45~55% L3 cache miss,最終約重6ms(8000個物理骨骼變換)。
蒙皮與動畫判定驅動骨骼(不以動畫控制器是否僅計算變換、剔除、全工作為準),以蒙皮網格是否離屏(以相機空間或稱作屏幕、螢幕空間內可見為準),或蒙皮網格上包圍盒計算骨骼驅動。(而avatar牆後剔除則以整體的包圍盒計算,所以較難剔除,需要烘培場景包圍盒)
過於靠近avatar或一些設置時,每個骨骼變換成本約物理骨骼變換的一半左右,所以8000個(30個avatar)約會產生3ms+6ms共計9ms。(單個組件過少、過多會影響組織,影響約增加10~30%,在這裡已經包含或忽略些,假設已盡可能減少組件浪費)
Udon script開銷根據遊戲房和一般交流房放置的邏輯,大致上3~5ms,平均4ms。
動畫方面,根據動畫層是否頻繁進入狀態轉移和持續更新會增加50%開銷,是否開啟WD(沒有開啟會單層累加狀態+50%)等等,最終大概30個avatar動畫層(均約50層總計)會產生相當多的資料沖洗L3cache,7ms->8ms左右。(採自定義動畫部分,由avatar描述符中定義的一個動畫控制器覆蓋,會照順序執行五六個動畫控制器或採VRchat內建,最終變成單一個動畫控制器執行,按累加算。)
部分較沉重大量未開WD的設計『相對』落後,還有更多奇怪過於高層如130~170層總計動畫,會導致平均3x加速降低至2x,因為單個動畫控制器過於沉重會降低可並行調度的效率。
如果你有大量短(10層~20層甚至更短)大量動畫控制器不做實事更改很多變換(transform)和設置物件活動狀態或組件狀態,基本上可以加速6x以上,但很難。(大量動畫控制器彼此之間相對獨立,可以利用到16thread)
部分過重的avatar,其容量通常較大而相對考慮較少不使用混合樹(blend tree)降低層數,一般也容易濫用約束等,先不考慮約束的情況下在15個avatar情況下可能占用13~15ms自定義動畫開銷。
約束部分經過VRC約束改進,深度為1時的遠程約束每1000個約0.25ms(透過Unity約束加載約0.75ms),但是深度加深還有一些部分未測試是否更改的特性,實際使用上如MA等工具會產生每1000個約束約1.5~2ms的CPU frametime,甚至更高。(估計深度約4~6)(相對0.75ms慢不少)
上述測試項目是使用Unity約束加載時轉換為VRC約束,需要頻繁檢測動畫狀態等開銷,故較為沉重,透過新推出有許多問題的SDK 3.7版本在編輯器中轉換為VRC約束後,平均每1000個約束約0.9~1.1ms。(估計深度為4~6)(相比0.25ms慢數倍)
大量大容量avatar(100MB下載大小)較容易擁有100~300個約束,但一些小容量(如30MB~50MB)也相對容易出現50~200個約束,一個房間內全開avatar可能會總計高達3000個以上的約束,約產生6~7ms這個3.1版本後的約束開銷。
遠程方面可以概算為:物理骨骼約要消耗掉6~9ms、動畫約8ms~12ms,約束約佔據6~7ms左右,這代表其他人的avatar對於自己CPU的開銷。
世界本身佔據約4ms。
採用相對低的計算下6+8+6+4ms,不包含自身就已經需要超過24ms了。
本身(自己)方面:
如果你使用過於大量物理骨骼並且沒有關閉,無法享受與其他人視角相等的福利,無法依據蒙皮網格->骨骼->物理骨骼方式計算,重如2048個變換左右(256個物理骨骼組件平均使用8個骨骼變換),你會產生大概相當於3~4ms左右的CPU frametime,請記得關閉。
動畫與遠程一致,但也請不要使用過高總計的層數,盡可能使用混合樹做開關等功能,除非單層的不能製造時差和速度問題以致於無法滿足需求。(170層即使沒有『狀態轉移+未開WD』也將重達3ms,而100層約1ms,在高層數70~100多層會有開始逐漸明顯化的平方倍,維護內部狀態的成本會逐漸呈現平方增長。)
約束方面是遠程的三倍,包含鏡像克隆與陰影克隆兩個實作,不太明白為何如此設計(與headchop等設計需要自身視角避免遮擋有關系?)
※註:此處指無法按需克隆,在自身的avatar許多部份是完全工作,並且也使得克隆系統複製多倍並始終運作。
因為本地並不需要過多同步給遠程,遠程同步本質上是動畫控制器基礎avatar設定甚至是插值按追蹤點計算,或使用動畫參數同步,所需要的頻寬很少。所以本地設計考量與遠程沒太大關係,是為了自身是否正確而設計。
外加以下的可見性開銷,本身蒙皮外還必須計算相應的骨骼開銷。(每1000個物理骨骼0.6~0.7ms,骨骼減半(0.3ms+),如果蒙皮網格活動則該骨骼也相應需要運動,這方面大概250~350個左右。)
在古早版本前的實作,透過bug使得骨骼不納入統計(刪除蒙皮。)仍然會導致足夠大的CPU開銷,現在官方已經修改Unity實作,不會產生遠程、本身開銷。(任何擁有Unity企業,每個月需要支付不斐的金額,可以獲得Unity原始碼與技術支援(有條件門檻在),所以VRchat一些特性無法單純靠Unity測量可以獲得。)
自身avatar根據不同條件約0.5ms~5ms都有,甚至有更沉重的,很輕也可以低至0.1ms。
使用VRC約束(編輯器轉換)可以將每1000個成本(深度4~6這個估計值)6ms~7ms降低至3.5~4ms。
可見時:
外加蒙皮網格約每10個產生0.5ms(本地完全繪製不剔除)30個約產生1.5ms,可以靠大cache的CPU降低開銷。(可見時)(包含骨骼變換成本,大致估計,本身將會計算所有活動蒙皮網格+蒙皮依賴的骨骼。(關閉骨骼無法阻止蒙皮計算,因為骨骼相當於一個空物件僅提供變換值,關閉骨骼可以關閉上面的物理骨骼、約束等附加組件。)
本身avatar需要執行至少鏡像克隆於最終渲染結果相關組件,甚至可能會包含陰影克隆,所以成本會大於其他人的遠程avatar。
(不包含動畫,但動畫需要一些本身參數成本等並同步至遠端)
遠程大量觀看10~30個avatar時約產生(平均10個活動蒙皮+平均每個蒙皮3個材料)產生3~6ms的主執行緒影響。(同時負責渲染、彩現的獨立執行緒負荷會很接近主執行緒程度的負荷,但不影響太多frametime。)
渲染執行緒包含最多渲染影響,甚至會包含驅動開銷和系統調用繪製開銷等,但除少部分會超過主執行緒成為最重負荷外,主執行緒管理等作業仍然沉重。
_________最終計算___________
你常態性上盡可能開啟avatar,且不要太離譜的情況下開銷大概會如以下。
你使用了一個自身avatar開銷大概3ms左右。
你處於一個遊戲房,Udon+房間本身開銷共計4ms。
30至32個人左右,你產生大概大概6ms的物理骨骼開銷。
大量濫用MA這些工具製作的avatar約束,使得房間內總計占用約3000個約束,你消耗掉了大概7ms。
動畫有好有壞,有盡可能改善使用混合樹,也有少數(1~2個)過於沉重的大量動畫層,消耗掉大概8ms。
在不可見的時候你約產生28ms左右,大概35~36fps。
在可見時約不同範圍avatar可見剔除,你大概額外增加了3~6ms(燈光普遍不多),所以你只有29~32fps。(如果有燈光大面積會將負荷增加到6~10ms+,部分人使用沉重自帶燈光avatar稍為增加1~2ms)
考慮極端情況可以濫用自身燈光與放出足夠範圍燈光影響,考慮4~8ms則(DPS使用頂點燈不影響,像素型燈光才會產生大量setpasscall影響(佔據99%繪製影響)和些drawcall等)大概在27~31fps左右。
_______未來最優情況_________
考慮到物理骨骼已經足夠簡單且考慮夠多了,即使不關閉script仍在遠程規避影響,且計算方面採用全遍歷去處理兩三個大陣列計算,雖然無法做靜態不動時的剔除,但估計能改進的佔比不會太大。
物理骨骼向Unity引擎請求transform約影響16~23%的佔比,理論上可以透過靜態保存避免處理不動部分但困難。
約束仍然不確定是否能大幅改進,仍然希望善用新釋放出的編輯器SDK的API等手段去改善關閉約束,因為約束部分會占用大量頻繁逐幀設定與依賴性排序,尤其是排序,所以深度等會導致需要逐次求解完依賴的部分才能求解到自己,繼而增長耗時。
無法像是骨骼一樣在該物件階層下自尾部到根部逐漸遍歷計算局部至全局的transform,所以開銷會更高些。(跟骨骼繪製開銷另外算)
動畫這個講爛了,也很難去改善是整個核心,牽一髮動全身,希望盡可能使用混合樹等手段壓低,直到沒辦法未來也許會使用基於script(腳本)驅動的設計吧,不過以前古早動畫控制器就是這樣做的...現在版本拿去做邏輯很浪費。
不過未來Unity也將放出改善性能版本的全新動畫控制器設計,但Unity6正式發布時還是看不見,仍不確定什麼時候正式出來。不知道是否未來VRchat會考慮支援,不過VRchat把舊動畫系統的丟出白名單了,沒辦法用更簡單有效方式改善。
動畫方面仍然可以將人型動畫綁定於Unity avatar定義改為非人型,但是動畫相當不通用,而無狀態+WD開銷時可能佔據50%層間更新成本,實際上也約30%左右層間更新成本,而層間更新佔據90~99%+的動畫成本影響。
但由於人型avatar為主,而且方便通用有標準,所以仍然佔據主流,所以即使能透過通用動畫綁定節省約30%動畫開銷也沒人做。
人力成本上動畫>綁定>模型(包含UV展開與繪製)...可能不切實際吧?
Udon2方面...
Udon2初期以webassmebly解釋器+blazor與mono runtime,約函數使用平均快三倍、實作性能快50倍以上,保守估計約能將3~5ms降低至2ms以下,空房間本身自帶檢測邏輯等實作,需要花1ms,所以包含一些Udon實作後很容易超過2ms。
如果能做很好大概可以到6ms(物理骨骼)+2ms(動畫幾乎混合樹所以很少層數)+約束0.5ms(盡量關閉與轉換成VRC約束)+本身開銷0.5ms+地圖與Udon 2ms。
大概有90fps(11ms),而現在Udon 4ms頂多只能到70多fps,可見時大概60~70fps來回,曾經在大量使用小改的booth上模型時的房間內才能見到如此多人也多幀,而並非依賴公開的簡單模型。
以上數值沒有任何爆VRAM或處於加載等情況,如果有你的fps數值通常更低或更高。(加載或不加載狀態不會執行太多產生影響,部分可能會編譯Shader而較重。)
所以算完和測量後能明白為什麼幀數如此低了,想盡可能看到avatar外觀可以在安全模式中關閉自定義動畫,約可以節省掉7ms(8ms減至1ms基本開銷)甚至10~15ms的情況,在目前3.1版本中,約能從35fps提升到47fps,提升34%。
自己avatar別太沉重,在約束總體使用量更低且使用VRC約束(編輯器轉換),約降低至1000~500個約束,此時約估0.6ms~1.3ms,也能提高到大概45fps左右,結合關閉自定義動畫能提高到60~70fps。
另外以上測試均規避了,CPU多核心瓶頸,如果多核心瓶頸會使得逐漸往多執行緒負荷為主的動畫影響,如果你僅只有4core的CPU,即使使用SMT也並不能有效減緩,動畫影響會比上述更大也就是frametime數值更大。(建議使用6core以上CPU,包含steamVR甚至開啟其他應用可能需要7~8core才足夠,否則會可能在開啟SMT下容易超過50%使用率)
多核心利用率尚未瓶頸時(未開啟SMT時100%,開啟時50%),由主執行緒負荷佔據主導,所以約束將產生足夠大的frametime佔比,否則動畫將是足夠沉重的。
除了動畫外,大多數遊戲功能受限於樹狀結構修改transform,並行度僅限於3~4core(transform 3+1個處理相應的邏輯,或有些是1transform thread+1處理邏輯如渲染骨骼動畫,或物理骨骼這類1transform+2physbones thread)
海量物理碰撞(足夠接近時而非單純大量),會使得多核心足夠滿載並產生沉重的L3 cache miss等,但VRchat中幾乎不太可能會出現,碰撞等計算影響甚至納入物理骨骼碰撞計算(不可基於網格計算),都只能納入雜項中,影響佔據整體3%以內。
物理骨骼的求解方式規避了大量計算物理骨骼碰撞的成本,以順序遍歷陣列求解,另外每個基於膠囊和球體這樣最便宜的計算,而非基於方形甚至長方形等需要兩倍的計算成本(雖然仍然很低)。
布料受限於PCIE通道(邏輯上的)傳輸大量頂點資料和複製等成本,所以僅只能使用2~3core,並且非常嚴重的L3 cache miss,成本上非常沉重,所以在遊戲中幾乎沒有人使用布料,不容易進行交互外,會嚴重降低CPU與GPU的效率和低幀數,除非每個人僅只使用幾百個頂點。
但一個網格經由定義後都納入影響,通常的booth上的模型中單個網格可能都3000~8000個頂點仍然足夠重。
其他部分如聯繫人機制(avatar動態中,在SDK內部中歸類於物理骨骼的一部份),即使上千個處於過於接近持續工作狀態,仍然影響不0.5ms甚至更低,而且一般統計很難一個房間破千。
許多部份均納入雜項中,約佔據整體3~5%(通常低佔比如3%),在低fps時可以忽略不算,不會對整數部分有多少影響。(例如25ms(40fps)->26ms+(38fps),甚至本身就能納入房間的基本開銷內了,加上Udon大概4ms...)
自身物件例如物理骨骼、蒙皮與骨骼動畫、約束、布料等均可能因鏡像克隆及陰影克隆影響,所以在自身視角方面較容易牽涉到最終渲染效果部分的成本需*2~*3倍。
粒子系統不具備該特性,所以不需要*2~*3倍。(仍不建議濫用)
鏡像克隆與陰影克隆如其名,是針對『人物』也就是avatar在鏡子與陰影的效果,為了能夠有效於鏡子、陰影可見性判定而複製多份並與本身一起持續運作,這在遠程中通常不具備該效果。(也可能具有,看版本更改但通常不會在更新中明示)
原因是Unity相機並不聰明到可以有效解決任何可見性判斷,並非不出現在鏡子中就能省去該部分開銷,在常規遊戲中甚至其他遊戲引擎中你仍需要想辦法處理進行關閉鏡子,更別提控制一個鏡子內反射物體的計算,甚至是陰影可見性計算,這將導致昂貴的渲染成本。
牽涉動態物體較為複雜,於本地實施兩種克隆系統複製並持續運作,會增加CPU成本,但解決了不可見鏡像目標、陰影等GPU渲染成本。
※註:克隆成本不會重複計算,意味著擁有大量陰影、VRchat鏡子開啟不會導致克隆非常多倍,但仍然不建議濫用,這會導致嚴重GPU瓶頸。
(遠程按需克隆或無需克隆,有時候你開啟鏡子(面向鏡子且可見時)會不只提高GPU負荷也提高不少CPU負荷,同時一些時候克隆同步或遠程可能會出bug,例如你使用約束的劍以拿到手中,鏡中卻仍然在背上而遠程也可能會發生類似事件)
且本身動畫不僅是完全運作外,也會產生本身的參數成本,例如處理8bit整數和8bit浮點(實際上是定點數,範圍是0.至0.01~1),與1bit需要做轉換(計算機本質上最低操作8bit(1byte),需要利用計算轉換才能操作1bit),大致上大量參數會消耗掉1ms以上(1000bit+)。
動畫參數當前版本允許最大8192bit(1024byte)(VRchat參數表),允許256bit(32byte)做參數表內同步遠程。
(僅適用本身的avatar不適用遠端,遠端僅同步參數)
所以同樣的avatar在自身遠比其他人(遠端avatar)貴的多。
__________________
綜上所述,經計算完目前盡可能全開所有人avatar常態能維持35~40fps不可見avatar(做VRchat範圍avatar剔除)已經算普遍情況,如果有一定幅度可見你只有30fps甚至更低。
即使運氣好大量減少約束使用,使用較低自身開銷的avatar仍然只能維持約50fps,只有盡可能改善動畫,接近booth模型原本模樣層數差異不大,才可能超過60fps。
如果你運氣很好將可能逼近70fps,這幾乎是當前版本全開(30人+)的上限。除非更多人選擇使用poor甚至更低的模型才能拔高幀數。
機器人屬於人型avatar定義用VRchat內建動畫,有可能比非人型簡單的模型更為重...
_________________________________
一般而言越大的模型通常全方面都較差,可以建議提前設置約200MB下載/500MB未壓縮大小解決特別差的模型,若仍然有漏網之魚是因為可以透過緊縮紋理(Crunch紋理壓縮),這將導致紋理記憶體大小錯誤被計算後,以更小的體積納入未壓縮大小統計。
這可能促使更容易堆積和濫用許多組件,有更差勁許多的性能。一些情況下未壓縮大小500MB仍然可能有約150MB網格記憶體+1GB左右的紋理記憶體,最終在不含Shader緩衝區的成本下產生接近1.2GB的VRAM開銷。(盡管此次主題是CPU frametime,仍會提醒該部份)
部份創作者利用工具致使不正常而無法計算未壓縮大小,會使未壓縮大小處於Pending(等待計算),這些問題仍然需要官方修復處理。
大概9月將實施新avatar限制,在7/17以前(也就是7/16(包含))暫時不受新限制,任何於該時間點後更新或上傳的avatar,需要接受客戶端/伺服器檢查,不通過將阻止200MB下載/500MB未壓縮大小模型使用。(超過200MB或超過500MB未壓縮大小都將回退到public avatar替換,甚至是有色彩的機器人)
當前已經實施了SDK限制,於7/24(asian 7/25)於SDK 3.6.2(beta)中限制,而正式SDK於3.7版本8/16(asian 8/17)實施限制,不可上傳超過下載大小200MB或未壓縮大小500MB的avatar。
在晚一些時候將實施溯源政策,將所有avatar超過新標準一概限制,我個人估計將晚一個小版本。之後在阻止使用後會公布時間進行刪除作業,如果到時候不選擇更新符合新限制,將徹底刪除該avatar而導致在其他人收藏的avatar中變為刪除。
阻止使用後將無法點選avatar進行切換,也將踢出使用該avatar狀態。