1. 程式人生 > >針對移動端特性的渲染優化(續)

針對移動端特性的渲染優化(續)

  • 關於depth buffer, depth 的深度一般有16位 24位 32位,非32位的深度在gpu的cache效能不好,儘量考慮32bit
  • 關於mipmapping,mipmap會增大記憶體,但是在之前我們更多的關注它的好處是增強了遠處物體的渲染效果,不會因為小畫素取樣大貼圖導致的閃爍,但是對於移動端頻寬功耗嚴重的情況下,mipmap還可以極大的增強的cache的命中率,減少對顯示卡記憶體的直接訪問,減少頻寬資源
  • 頻寬,在移動端,bandwith是一個多種裝置(cpu gpu audio等)共享的資源,而且處理器通過頻寬對儲存的訪問是一個很耗電的操作,所以,儘可能的提高在gpu內部cache上訪問的到的可能性,減少對記憶體訪問。無論是對程式碼的cache,貼圖的壓縮,mimapmap都是在做這種努力
  • profile效能的時候儘量使用frametime而不用fps去統計,首先從profile上來講能直接量化一幀效能的是幀時間,而幀率是幀時間的倒數,fps跟幀時間不是一個線性關係,例如從在每秒10fps的情況下,幀時間減少2ms,幀率只提高到10.2fps,而在25fps下,幀時間減少2ms,幀率確可以提高到26.3,所以可以看到在同樣減少了時間消耗的情況下,在高幀率區間,減少相同的瓶頸,幀率會越來越快,而在低幀率區間,減少相同的瓶頸,確不能得到更大的進步,直觀上說幀率是越優化越快的。結論就是我們通過fps的增長來衡量優化的好壞是不科學的,因為從30fps優化到35fps比從10fps優化到15fps要簡單的多
  • 為什麼drawcall這麼慢?很多人講我們要優化drawcall,並且說drawcall是優化了cpu瓶頸,而不是gpu瓶頸,為什麼?drawcall字面上說不就是渲染次數麼,那怎麼就不是減少gpu瓶頸了?嚴格來說,這句話應該說是在幾何資料量不變的情況下,分多個drawcall提交和少個drawcall提交對於cpu的效能損耗更大,首先從渲染上cpu和gpu是串聯在前後的流水線上的兩環,而gpu的運算能力要比cpu強很多,形象上可以看到gpu是一根粗水管,而cpu是一條細水管,在通常情況下,cpu提供過來的資料,對於gpu來說都是要更快處理完畢的,即cpu喂不飽gpu,也就是說對於相同量的資料,cpu連續的餵給gpu多次和一次喂多一點對於gpu來說區別不是很大,但是對於cpu就不一樣的。一個drawcall涉及到渲染狀態的設定和繪製資料的提交,在這個渲染狀態的設定中,cpu端極有可能要發生(記憶體分配(api在cpu一側的分配),資料拷貝(把資料從cpu一側拷貝到gpu一側,儘管移動端的視訊記憶體和主存公用,但是資料儲存的格式(如貼圖)是不一樣的,至少還要設計到格式的轉換),組裝command buffer,然後才能傳送給gpu,這個過程中可能還要設計到同步和等待,例如一個vbo正在gpu被處理而我現在又要改變它重新告訴gpu怎麼辦,那是不是要等gpu處理完?如果不等待那是不是要複製一個新的?)。此外對同樣一段大小的資料,分割成多個drawcall,導致了給gpu的資料流從多量少次變成了少量多次,使得gpu處於一種喂不飽狀態,沒有利用gpu的並行處理能力。 所以我們說drawcall是開銷,不是說繪製次數多了成瓶頸,而是伴隨著drawcall帶來的cpu一側的記憶體分配,資料拷貝,api呼叫,等待,同步,以及對gpu供給資料的低效造成的。
  • 渲染是一個流水線,在這個流水線上先後發生的會影響效能的依次可以分為cpu  api(drawcall) 幾何處理(vertex geometry shader) 原語彙編和三角形建立 畫素處理 頻寬這6大塊。效能瓶頸可能同時存在幾塊上,有時候我們需要遮蔽其中幾塊去定位效能瓶頸,例如通過profile工具把framebuffer設定到極小可以遮蔽pixel的處理,取樣一個虛假的極小的貼圖可以遮蔽頻寬的因素等等