OpenGL ES 2.0 + Cairo: HUD

I am trying to display a HUD on top of an OpenGL ES 2.0 application written in C on an ARM Linux platform.

Currently, I am using 2 triangles located close to the clipping plane and laying texture on them. Texture is the size of the screen and is mostly transparent, with the exception of those parts where I have text. Texture created with Pango / Cairo

If I turn on the HUD (uncomment the render_ui call), I am currently getting a 50% performance hit (going from 60 frames per second to 30 frames per second).

Here is the code to display the HUD:

void render_ui(OGL_STATE_T *state) { glUseProgram(state->uiHandle); matIdentity(modelViewMatrix); matTranslate(modelViewMatrix, 0, 0, -0.51); const GLfloat *mvMat2 = modelViewMatrix; glViewport(0,0,state->screen_width, state->screen_height); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glBindBuffer(GL_ARRAY_BUFFER, state->uiVB); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, state->uiIB); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, state->uiTex); glUniform1i(_uiTexUniform, 0); glUniformMatrix4fv(_uiProjectionUniform, 1, 0, pMat); glUniformMatrix4fv(_uiModelViewUniform, 1, 0, mvMat2); glVertexAttribPointer(_uiPositionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0); glVertexAttribPointer(_uiColorSlot, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid *) (sizeof(GLfloat) * 3)); glVertexAttribPointer(_uiTexCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid *) (sizeof(GLfloat) * 7)); glEnableVertexAttribArray(_uiPositionSlot); glEnableVertexAttribArray(_uiColorSlot); glEnableVertexAttribArray(_uiTexCoordSlot); glDrawElements(GL_TRIANGLES, uiIndicesArraySize / uiIndicesElementSize, GL_UNSIGNED_BYTE, 0); glDisableVertexAttribArray(_uiTexCoordSlot); glDisable(GL_BLEND); GLenum err; if ((err = glGetError()) != GL_NO_ERROR) printf("There was an error"); } 

There should be a smarter way to do this.

+6
source share
1 answer

On mobile devices, GPUs are very sensitive to mixing, for several reasons:

  • Mixing consumes more bandwidth (you need to read the current pixel to mix it with the new one)
  • Blending may interfere with the optimization of removing hidden surfaces.
  • Blending may also interfere with optimization of tile-based deferred rendering.

Therefore, short mobile GPUs like opaque polygons and hate transparent ones.

Please note that the total area occupied by transparent polygons on the screen is also very important due to the “tile-based” nature of most mobile GPUs (when a tile / bin is covered with transparent polygons, you may lose some GPU optimizations for it).

In addition, since you are saying that you are experiencing a sharp drop from 60 frames per second to 30 frames per second, I would conclude that your device’s GPU is blocked, waiting for the on-screen synchronization at 60 Hz to be replaced, so this means that your DT frame can only be a multiple of 16 ms, so you can probably only get fps values ​​like: 60, 30, 15, 7.5, ...

So, if you were at 60 frames per second, but add something to the main loop of the application, which will reduce the theoretical fps to 57 frames per second, then because of waiting for vertical synchronization, you will jump sharply to 30 frames per second. VSync can be turned off, or methods like triple buffering can be used to mitigate this, but with OpenGLES the way to do it is specific to the OS and the equipment you work with ... there is no "official way to do this that works on all devices "

So, knowing all this, here are some suggestions to return to 60fps:

  • Use a reduced resolution, for example: 1280x720 instead of 1920x1080, this will reduce the use of bandwidth and fragment processing. Of course, this is not ideal, but it can be used as a test to confirm that you have a problem with the bandwidth or fragment (if you get 60 frames per second after lowering the resolution, then you have such a problem).
  • Use a 16-bit (R5G6B5) backbuffer instead of the 32bits backbuffer (R8G8B8A8), this can reduce the use of bandwidth, but with some visual loss of quality
  • Reduce the area of ​​mixed surfaces: in your case, this will mean that you need to arrange your texts using “blocks”, with each block as close as possible to text similar to this image from IOS docs : enter image description here
  • Find a way to disable Vsync on your device / use triple buffering. If you have access to Vivante GPU documents (I don’t know), this can be described internally.

Point 3 is the best thing to do (this is what was done in most of the mobile games I worked on), however it will require some minor additional work. Points 1, 2, and 3 are simpler, but are only “half solutions”.

+3
source

All Articles