2015-09-02 10 views
6

Próbuję wyrenderować HUD nad aplikacją OpenGL ES 2.0 napisaną w języku C na platformie ARM Linux.OpenGL ES 2.0 + Cairo: HUD

Obecnie używam dwóch trójkątów umieszczonych blisko zbliżonej płaszczyzny obcinania i umieszczających na nich teksturę. Tekstura ma rozmiar ekranu i jest przeważnie przezroczysta, z wyjątkiem części, w których tekst jest renderowany. Tekstura jest generowana za pomocą Pango/Cairo

Jeśli włączyłem HUD (odkomentowanie połączenia z render_ui), obecnie uzyskuję 50% skuteczność (od 60 do 30 klatek na sekundę).

Oto kod, aby uczynić 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"); 
} 

Musi być bardziej rozsądny sposób to zrobić.

+0

Co to jest GPU na twojej platformie (PowerVr, Adreno, Mali, Nvidia Tegra ...)? Co to jest rozdzielczość? –

+0

@VB_overflow Płyta główna Vivante GPU/Freescale iMX6. Rozdzielczość wynosi 1920x1080. – ReX357

Odpowiedz

3

Na urządzeniach mobilnych GPU są bardzo wrażliwe na mieszanie, to dla wielu powodów:

  • Blending zużywa większą przepustowość (trzeba czytać bieżącego piksela zmieszać go z nowym)
  • Mieszanie może złamać ukrytą powierzchnię optymalizacje usuwania
  • Mieszanie może również złamać płytki oparciu defered renderowania optymalizacje

Tak w skrócie GPU mobilnych miłości nieprzezroczyste wielokąty i nienawistne przezroczyste.

Zauważ, że całkowitą powierzchnię zajmowaną przez przezroczyste wielokątów na ekranie jest również bardzo ważne ze względu na „dachówka oparte” charakter większości GPU mobilnych (gdy płytka/bin jest pokryta przezroczystymi wielokątów można stracić pewne optymalizacje GPU dla tego).

Ponadto, ponieważ twierdzisz, że dostajesz ostry spadek od 60fps do 30fps, dochodzę do wniosku, że Twój GPU urządzenia blokuje się, czekając na synchronizację pionową ekranu 60Hz do zamiany, więc oznacza to, że twój ID ramki może być tylko wielokrotnością z 16ms, więc prawdopodobnie uzyskasz tylko wartości FPS: 60, 30, 15, 7,5, ...

Więc jeśli masz 60 klatek na sekundę, ale dodaj coś w głównej pętli aplikacji, co spowoduje spadek wartości teoretycznej fps na jedyne 57 fps, a następnie z powodu synchronizacji czasu w pionie, gwałtownie przejdziesz do 30 fps. VSync może być wyłączony, lub można użyć technik takich jak potrójne buforowanie, ale w przypadku OpenGLES sposób działania jest specyficzny dla sprzętu OS &, z którym pracujesz ... nie ma "oficjalnego sposobu działania, który działa na wszystkich urządzeniach ".

Tak, wiedząc to wszystko tutaj są pewne propozycje, aby wrócić do 60fps:

  1. Użyj zmniejszona rozdzielczość, ex: 1280x720 zamiast 1920x1080, w ten sposób zmniejsza wykorzystanie pasma & przetwarzanie fragmentu.Oczywiście nie jest idealny, ale można go wykorzystać jako test do potwierdzenia, że ​​masz problem z pasmem lub fragmentem (jeśli otrzymasz zwrot 60 klatek na sekundę po zmniejszeniu rozdzielczości, wtedy masz tego rodzaju problem)
  2. Użyj bufora wstecznego 16-bitowego (R5G6B5) zamiast 32-bitowego bufora wstecznego (R8G8B8A8), może to zmniejszyć zużycie pasma, ale z pewną utratą jakości wizualnej
  3. Zmniejszyć obszar powierzchni mieszanych: w twoim przypadku oznaczałoby to, że powinieneś uporządkować swoje teksty za pomocą "bloków", przy czym każdy blok pasuje do o ile to możliwe tekst podobny do tego z IOS docs:
  4. Znajdź sposób na wyłączenie Vsync na swoim urządzeniu/użyj potrójnego buforowania. Jeśli masz dostęp do dokumentów GPU Vivante (ja nie), to można to opisać w środku.

Punkt 3 to najlepsza rzecz do zrobienia (tak się działo w większości gier mobilnych, nad którymi pracowałem), jednak będzie to wymagało trochę nieistotnej dodatkowej pracy. Punkty 1, 2 i 3 są prostsze, ale są tylko "połowicznymi rozwiązaniami".

+0

Dziękuję, że to bardzo szczegółowa odpowiedź. Udało mi się uzyskać kopię zapasową FPS do 48 klatek na sekundę, usuwając wiele wywołań funkcji GlDisable & glEnable, które miały miejsce i nie były konieczne. Gpu wydaje się synchronizować przy 30, 48 i 60 fps. Jedną z dróg, którą chcę spróbować odkryć, jest brak obsługi KMS w jądrze, którego obecnie używam, a zatem nie jest zaimplementowana zerowa kopia, która mogłaby zaoszczędzić wiele połączeń typu memcpy. Ale miła praca, nagroda przyznana! – ReX357

+0

Dziękujemy! Dodatkowa uwaga: jeśli jesteś GPU związany ze względu na pełnoekranowy przezroczysty quad dla tekstów, to w pewnym momencie, niezależnie od dodanej optymalizacji strony procesora, nie uzyskasz już poprawy fps, a jedynym rozwiązaniem będzie oddzielenie tego dużego quada w sub quady pasujące do stref tekstowych lub zmniejsz rozdzielczość. Możesz łatwo sprawdzić, czy jesteś związany z GPU z powodu mieszania, przełączając twój quad na nieprzezroczysty zamiast przezroczystego lub zmniejszając rozdzielczość, jeśli uzyskasz fps w ten sposób, to jesteś związany z GPU. –