2015-09-02 11 views
6

Sto provando a rendere un HUD su un'applicazione OpenGL ES 2.0 scritta in C su una piattaforma ARM Linux.OpenGL ES 2.0 + Cairo: HUD

Attualmente sto usando 2 triangoli posizionati vicino al piano di ritaglio vicino e affiancandoci sopra la trama. La trama è la dimensione dello schermo ed è per lo più trasparente ad eccezione delle parti in cui ho il rendering del testo. La texture viene generata utilizzando Pango/Cairo

Se accendo l'HUD (decomprimendo la chiamata a render_ui), al momento subisco un calo di prestazioni del 50% (passa da 60 fps a 30 fps).

ecco il codice per rendere l'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"); 
} 

Ci deve essere un modo più sensato di fare questo.

+0

Qual è la GPU sulla tua piattaforma (PowerVr, Adreno, Mali, Nvidia Tegra ...)? Inoltre, qual è la risoluzione? –

+0

@VB_overflow Scheda Vivante GPU/Freescale iMX6. La risoluzione è 1920x1080. – ReX357

risposta

3

Sui dispositivi mobili le GPU sono molto sensibili a fusione, questo per diverse ragioni:

  • Blending consuma più banda (bisogno di leggere pixel corrente di mescolare con uno nuovo)
  • Blending può rompere superficie nascosta ottimizzazioni di rimozione
  • Blending possono anche rompere piastrelle basato defered rendendo ottimizzazioni

Così, in breve amore GPU mobile poligoni opachi e odiano quelli trasparenti.

Nota che la superficie totale occupata da poligoni trasparenti sullo schermo è molto importante anche a causa della "base tile" la natura della maggior parte delle GPU mobili (quando una tessera/bin è coperto da poligoni trasparenti si può perdere alcune ottimizzazioni GPU per questo).

Inoltre, dal momento che dici di ottenere una forte diminuzione da 60fps a 30fps, concluderei che la tua GPU del dispositivo sta bloccando, aspettando che la sincronizzazione verticale dello schermo 60Hz si scambia, quindi questo significa che il tuo frame DT può essere solo multiplo di 16ms, quindi probabilmente solo si può ottenere i valori fps come: 60, 30, 15, 7.5, ...

quindi, se tu fossi a 60fps, ma aggiunge qualcosa nella vostra applicazione ciclo principale che far cadere il teorico fps a solo 57fps, quindi a causa della sincronia verticale wait, bruscamente andrai a 30fps. VSync può essere disabilitato, o tecniche come il triplo buffering possono essere utilizzate per mitigarlo, ma con OpenGLES il modo di farlo è specifico per l'hardware dell'OS & con cui stai lavorando ... non esiste un "modo ufficiale di farlo che funzioni su tutti i dispositivi ".

Quindi, sapendo tutto questo ecco alcune proposte per tornare a 60fps:

  1. utilizzare una risoluzione ridotta, es: 1280x720, invece di 1920x1080, questo ridurrà l'utilizzo della larghezza di banda di elaborazione & frammento.Ovviamente non è l'ideale, ma potrebbe essere usato come test per confermare di avere un problema di larghezza di banda o frammento (se ottieni 60fps indietro dopo aver ridotto la risoluzione, hai questo tipo di problema)
  2. Usa backbuffer a 16 bit (R5G6B5) invece di backbuffer a 32 bit (R8G8B8A8), questo può ridurre l'utilizzo di banda larga, ma con una perdita di qualità visiva
  3. Ridurre l'area delle superfici miste: nel tuo caso ciò significherebbe che dovresti organizzare i tuoi testi per "blocchi", ogni blocco adatto come il più possibile il testo come in questa immagine da IOS docs: enter image description here
  4. Trova un modo per disattivare Vsync sul dispositivo/utilizzare il buffering triplo. Se si ha accesso ai documenti GPU Vivante (non lo faccio), questo può essere descritto all'interno.

Il punto 3 è la cosa migliore da fare (questo è ciò che è stato fatto nella maggior parte dei giochi mobili su cui ho lavorato), tuttavia questo richiederà un lavoro extra non trascurabile. I punti 1, 2 e 3 sono più semplici ma sono solo "mezze soluzioni".

+0

Grazie questa è una risposta molto dettagliata. Sono stato in grado di ottenere il backup dei miei fps a 48fps rimuovendo molte chiamate glDisable e glEnable che stavano accadendo e non erano necessarie. La gpu sembra sincronizzare a 30, 48 e 60 fps. Una via che voglio provare è che non esiste il supporto KMS sul kernel che attualmente utilizzo e quindi non viene implementata la copia zero che potrebbe salvare molte chiamate memcpy. Ma bel lavoro, la ricompensa è stata premiata! – ReX357

+0

Grazie! Un'ulteriore nota: se si è vincolati alla GPU a causa del quad di schermo intero trasparente per i testi, a un certo punto, qualunque sia l'ottimizzazione della parte della cpu che si aggiunge, non si otterrà più un miglioramento del fps, e quindi l'unica soluzione sarà quella di separare questo grande quad in sub quad che adattano le zone di testo o riducono la risoluzione. È possibile testare facilmente se si è vincolati alla GPU a causa della miscelazione, cambiando il quadrante in modo che sia opaco anziché trasparente o riducendo la risoluzione, se si ottiene un fps in questo modo si è vincolati alla GPU. –