1. 程式人生 > >Mali GPU OpenGL ES 應用性能優化--基本方法

Mali GPU OpenGL ES 應用性能優化--基本方法

term 定位 mil nis 標誌位 compiler lte void 解決

1. 經常使用優化工具

技術分享


2. 經常使用優化方案

OpenGL ES優化的主要工作是在圖形管道中找到影響性能的bottleneck,其bottleneck一般表如今下面幾方面:

? 在應用程序代碼中。如沖突檢測
? GPU與主內存間的傳輸數據
? 在VP(Vertex Processor)中的頂點處理
? 在FP(Fragment Processor)中的片斷處理

可通過DS-5 Streamline來定位性能瓶頸(Locate bottleneck)。為了獲取更好的性能。可從下面詳細功能著手優化:

2.1 紋理(Texture)

高分辨率的紋理占用大量的內存。它是Mali GPU上的主要負荷,可從下面幾方面進行優化:
?

除非必要,盡量不要使用大紋理
? 總是打開紋理映射(mipmapping)。有時可能降低了渲染質量
? 假設可能,排序三角形,當按render的次序render時,使其有相互覆蓋的三角形放在一起
? 壓縮紋理。可降低內存占用、傳輸帶寬。Mali-400 MP GPU支持ETC紋理壓縮(每一個像素占4bits,且不支持alpha通道),GPU硬件可解壓ETC紋理,缺點是將降低圖像質量

2.2 抗鋸齒(Anti-aliasing)

? GPU支持4x Full Scene Anti-Aliasing (FSAA),其性能損失微不足道;當創建context和rendering surface時,可通過選擇EGL配置(EGL_SAMPLES=4)來激活4x FSAA
?

Mali GPU還支持16x FSAA,其性能將下降到4x FSAA的1/4

2.3 繪圖模式(Draw Mode)

對於大的網格,一個頂點被包括在多個三角形中,這種頂點被處理的次數依賴調用的繪圖函數:

? glDrawElements:每一個頂點僅被處理一次,效率更高。


? glDrawArrays:每一個頂點數據在每一個使用它的三角形中被傳輸和處理一次

按使用的次序存儲頂點數據。能夠改善頂點Cache效果。而且降低了從RAM到頂點Cache傳輸的數據量。

2.4 頂點緩沖對象(Vertex Buffer Objects)

? 使用頂點數組(Vertex Array)存儲的頂點數據位於client內存(即主內存)。當調用glDrawArrays或glDrawElements時,將把這些頂點數據從client內存copy到圖形內存。

? Vertex Buffer Objects同意OpenGL ES2.0應用在高性能的圖形內存中分配且Cahce頂點數據,然後從此內存中進行渲染。這樣就避免了每當Draw一個原語時重發數據。

? Vertex Buffer Objects分類:
1) 數組緩沖對象(array buffer objects):由GL_ARRAY_BUFFER標識。用於存儲頂點數據(Vertex Data)
2) 元素數組緩沖對象(element array buffer objects):由GL_ELEMENT_ARRAY_BUFFER標識。用於存原語索引(indices of primitive)

2.5 數據精度(Data Precision)

在可能的情況下。盡量使用低精度的數據,避免使用浮點和其他32位數據類型:
? 定義頂點位置使用GL_SHORT
? 定義Surface Normal使用GL_BYTE
? 定義顏色使用GL_UNSIGNED_BYTE

2.6 處理的數據量(Volume of Data Processed)

要從下面幾方面降低Mali GPU處理的數據量:
? 僅僅畫當前幀看得見的原語:可在應用中通過clipping或frustum clulling來實現
? 使用ETC壓縮紋理
? 依據深度排序幾何體:依照從前到後的順序排序幾何體,依據深度排序draw調用。

2.7 渲染目標(Render Targets)

下面因素與渲染目標有關:
? 依照因素(cause-and-effect)順序渲染全部的紋理
1)在紋理被使用之前render to textures
2)最後渲染後臺緩沖區
? 一次僅僅繪制到一個渲染目標:確保繪制下一個目標之前,已經完畢當前目標的全部調用
? 不要在一幀中改動紋理:當調用API之前。設置好全部當前幀須要的紋理

2.8 處理管道(Processing Pipeline)

下面因素與圖形處理管道有關:

? 使用eglSwapBuffers:
假設應用顯示動畫,確保通過調用eglSwapBuffers來結束一幀。應用接著產生下一幀。這樣以確保在計算下一幀時。當前幀仍可穩定顯示。

? 避免使用glReadPixels:
即使讀取非常少像素,對性能影響也比較大,由於它暫停了處理管理

? 限制glDrawElements中頂點個數:
在調用glDrawElements之後,在曾經的操作(如:頂點著色、變換、光照)完畢之後才開始創建多邊形列表。為了使之並行。確保單次glDrawElements調用中包括的頂點數不要超過當前幀中全部頂點數的1/5。這在馬上調用glDrawArrays之前或之後特別重要。

2.9 著色器程序(Shader Programs)

? 首先運行Shader編譯:在應用程序啟動時。且在開始向驅動發送頂點或紋理數據之前,完畢Shading語言編譯器全部相關的調用
? 使用自己定義著色器程序:把大的Shader程序採裁剪成每一個Surface所須要的,而不使用大而全的Shader程序。小而精的Shader程序通常運行得更快
? 考慮程序大小:能夠使用Offline Shader Compiler檢測程序大小。

一個GPU指令能夠包括一系列ESSL操作
? 循環和條件分支:不要手動展開循環。相反。把數據放到數組中,然後在可能的地方使用for循環。當然,也能夠使用if語句。
? 避免使用過多的varyings:在shader編程時,在Fragment Shader程序中,盡量節約使用varings;由於在VP與內存或FP與內存間傳遞varings時須要消耗內存帶寬
? 避免使用過多的矩陣乘法:4x4的矩陣與4x1的向量相乘,須要運行16次乘法和12次加法,是非常昂貴的。假設須要一個向量與多個矩陣相乘,則向量依次與每一個矩陣相乘,而不要先把全部的矩陣相乘,然後再與向量相乘
? 評估程序的代價:經常使用的代價級別例如以下表所看到的,使用Offline Shader Compiler能夠更精確地獲取程序的代價。

技術分享

2.10 著色器運算(Shader Arithmetic)

? 頂點處理器基於32位浮點值工作:Vertex Shader使用浮點表示整數。

為了避免32位值,設置Vertex Shader程序的輸出varing的精度為mediump或lowp。
? Fragment Shader使用16位浮點值工作:其構成為:sign;5位指數,以抵消15。10位尾數。用一個隱含的最顯著1位

2.11 其他

? 使用點精靈:
而不是三角形或四邊形來表示顆粒實體

? 使用適當尺寸的三角形:
避免使用長而細的三角形。FP(Fragment Processor 或Pixel Processor)總是處理4個鄰近Fragment的組。因此處理1個像素寬度的Strip比處理2個像素寬度的Strip耗用很多其他的時間。

? 優化狀態變化:
避免狀態來回變化,能夠把同樣狀態的調用組織在一起,以降低狀態變化

? 清除整個Framebuffer:
總是調用glClear清除整個Framebuffer。假設可能,在清除framebuffer時,清除全部的buffer,如:color、depth, and stencil buffers。

void glClear(GLbitfield mask);
參數說明:
GLbitfield:能夠使用 | 運算符組合不同的緩沖標誌位,表明須要清除的緩沖,比如glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)表示要清除顏色緩沖以及深度緩沖,能夠使用下面標誌位:
1)GL_COLOR_BUFFER_BIT: 當前可寫的顏色緩沖
2)GL_DEPTH_BUFFER_BIT: 深度緩沖
3)GL_ACCUM_BUFFER_BIT: 累積緩沖
  4)GL_STENCIL_BUFFER_BIT: 模板緩沖

? 最小化draw調用:
當調用glDrawArrays或glDrawElements時,GPU驅動須要收集全部當前OpenGL ES狀態、紋理和頂點屬性數據。然後驅動處理這些數據並產生可在GPU硬件上運行的命令,以運行真正的draw調用。

此操作能夠耗費大量的時間,所以假設運行多次調用。它將成為rendering的性能瓶頸。假設多個對象具有同樣的rendering參數。但使用不同的紋理,則能夠把紋理合並到一個大的紋理中。並調整其相應的紋理坐標就可以。

? 避免使用glFlush和glFinish
除非你無法避開,否則不要調用glFlush或glFinish,而使用eglSwapBuffers來觸發一幀的結束。

(註:glFlush僅僅是把命令發送給Server,但並不等待運行完畢。

假設須要等到Server運行完畢時才返回。則須要調用glFinish,但它嚴重影響性能。)

3. 發現和消除bottleneck

基本方法:

1) 使用專業工具(如DS-5 Streamline)

2) 在值得懷疑的圖形管理階段。添加或降低負荷,然後觀察性能變化情況

發現和消除bottleneck可參考下面方案:

問題點解決方式
Application code
Reduce the amount of processing that is unrelated to OpenGL ES calls, such as input processing, game logic, collision detection, and audio processing.
Driver overhead
Group geometry with similar state together and eliminate unnecessary state changes.
Vertex attribute transfer
Use smaller data types for the values. Also, use a more economical triangle scheme, and in general use glDrawElements rather than glDrawArrays.
Vertex shader processing, or Transform
and Lighting in OpenGL ES 1.1
Try the following options:
1) Use glDrawElements rather than glDrawArrays.
2) For OpenGL ES 1.1, reduce the number of lights.
2) Minimize the transformations of texture coordinates. You can avoid these transformations by setting the transformation matrix using OpenGL ES 1.1 function glLoadIdentity.
3) For OpenGL ES 2.0, simplify the vertex shader program.
Polygon list building
Use fewer graphics primitives. Also, avoid drawing significant amounts of the total geometry in any single call to glDrawElements.
Varying data transfer
In OpenGL ES 1.1, use fewer texture coordinates. In OpenGL ES 2.0, use fewer varyings, and specify lower precision on varying variables out of the vertex shader.
Fragment shader processing, texture, color sum, and fog in OpenGL ES 1.1
Lower the resolution of the render target or reduce the size of the viewport.
For OpenGL ES 1.1, use fewer texture stages.
For OpenGL ES 2.0, simplify the fragment shader program.
Texture bandwidth
Try the following options:
1)use fewer texture stages
2)lower the size of the textures, by using a smaller data format for each pixel, lower resolution, or texture compression
3)use a simpler texture filtering mode
4)collapse texture coordinates so that they always read from the same position in the texture.


Transfer to display framebuffer
Try the following options:
1) use a mode with lower pixel precision
2) lower the resolution of the render target.

4. ESSL限定值

OpenGL ES Shading Language規範定義了各種著色器資源(shader resources)大小的最小值。在Mali GPU實現中,當中一些值大於規範中定義的最小值。經常使用的例如以下表所看到的:

技術分享


Mali GPU OpenGL ES 應用性能優化--基本方法