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

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)存儲的頂點數據位於客戶端內存(即主內存),當調用glDrawArrays或glDrawElements時,將把這些頂點數據從客戶端內存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實現中,其中一些值大於規範中定義的最小值。常用的如下表所示:



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章