2015-09-02 23 views
6

Ich versuche, ein HUD über eine OpenGL ES 2.0-Anwendung, die in C geschrieben wurde, auf einer ARM Linux-Plattform zu rendern.OpenGL ES 2.0 + Kairo: HUD

Ich verwende derzeit zwei Dreiecke in der Nähe der Clipping-Ebene und kacheln die Textur auf ihnen. Die Textur ist die Größe des Bildschirms und ist größtenteils transparent mit Ausnahme der Teile, wo ich Text gerendert habe. Die Textur wird erzeugt mit Pango/Cairo

Wenn ich das HUD (auskommentieren den Aufruf von render_ui), mache ich derzeit einen 50% Performance-Hit (Geht von 60fps auf 30fps).

Hier ist der Code das HUD zu machen:

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"); 
} 

Es gibt eine sinnvollere Art und Weise, dies zu tun sein muss.

+0

Was ist die GPU auf Ihrer Plattform (PowerVr, Adreno, Mali, Nvidia Tegra ...)? Was ist die Auflösung? –

+0

@VB_overflow Vivante GPU/Freescale iMX6-Karte. Die Auflösung beträgt 1920 x 1080. – ReX357

Antwort

3

Auf mobilen Geräten GPUs sind sehr empfindlich auf Blending, dies aus mehreren Gründen:

  • Blending mehr Bandbreite verbraucht (müssen aktuelle Pixel lesen, ihn durch einen neuen mischen)
  • Blending kann versteckte Oberfläche brechen Entfernung Optimierungen
  • Das Mischen kann auch Fliese brechen basierend defered Rendering Optimierungen

Also kurz gesagt mobilen GPUs Liebe opake Polygone und hasse transparente.

Beachten Sie, dass die gesamte Oberfläche durch transparente Polygone auf dem Bildschirm belegt ist auch sehr wichtig aufgrund der „Kachel basierte“ Natur der meisten mobilen GPUs (wenn eine Kachel/bin durch transparente Polygone bedeckt ist, können Sie einige GPU-Optimierungen verlieren dafür).

Auch, da Sie sagen, dass Sie einen scharfen Rückgang von 60fps auf 30fps bekommen, würde ich schließen, dass Ihr Gerät GPU blockiert, warten auf den Bildschirm 60Hz Vertikalsynchronisation zu tauschen, so dass Ihr Rahmen DT kann nur ein Vielfaches sein von 16ms, so können Sie wahrscheinlich nur fps Werte wie erhalten: 60, 30, 15, 7,5, ...

also, wenn Sie bei 60fps waren, aber etwas in Ihrer App Hauptschleife hinzuzufügen, die die theoretische fallen würden fps auf nur 57 fps, dann wegen der vertikalen sync warten Sie abrupt auf 30 fps. VSync kann deaktiviert werden, oder Techniken wie Triple-Buffering können verwendet werden, um dies zu mildern, aber mit OpenGLES ist die Art, dies zu tun spezifisch für die OS & Hardware, mit der Sie arbeiten ... es gibt keine "offizielle Art, es zu tun, die funktioniert auf allen Geräten ".

Also, das alles hier zu wissen, sind einige Sätze zu 60 fps zu kommen:

  1. Verwenden Sie eine reduzierte Auflösung, ex: 1280x720 statt 1920x1080, wird diese Bandbreitennutzung & Fragment Verarbeitung zu reduzieren.Nicht ideal natürlich, aber das könnte als ein Test verwendet werden, um zu bestätigen, dass Sie ein Bandwith oder Fragment Problem haben (wenn Sie 60fps zurück erhalten, nachdem Sie Auflösung reduziert haben)
  2. Verwenden Sie 16 Bit (R5G6B5) Backbuffer anstelle von 32Bit Backbuffer (R8G8B8A8), kann dies die Bandbreitenauslastung reduzieren, aber mit einem gewissen Qualitätsverlust
  3. Bereich der gemischten Flächen reduzieren: in Ihrem Fall würde dies bedeuten, dass Sie Ihre Texte nach "Blöcken" organisieren sollten so viel wie möglich der Text wie in diesem Bild von IOS docs: enter image description here
  4. Finden Sie eine Möglichkeit, Vsync auf Ihrem Gerät zu deaktivieren/Triple-Pufferung verwenden. Wenn Sie Zugang zu Vivante GPU Docs haben (ich nicht), kann dies im Inneren beschrieben werden.

Punkt 3 ist die beste Sache zu tun (das ist, was in den meisten mobilen Spielen, an denen ich gearbeitet habe, gemacht wurde), aber dies wird einige nicht vernachlässigbare zusätzliche Arbeit benötigen. Punkte 1, 2 und 3 sind einfacher, aber sind nur "halbe Lösungen".

+0

Vielen Dank das ist eine sehr detaillierte Antwort. Ich konnte mein fps-Backup auf 48 fps bringen, indem ich viele glDisable- und glEnable-Aufrufe entfernte, die gerade stattfanden und nicht notwendig waren. Die GPU scheint bei 30, 48 und 60 fps zu synchronisieren. Eine Möglichkeit, die ich ausprobieren möchte, ist, dass es keine KMS-Unterstützung für den Kernel gibt, den ich momentan benutze, und daher keine Nullkopie implementiert ist, die viele Memcpy-Aufrufe speichern könnte. Aber nette Arbeit, Kopfgeld vergeben! – ReX357

+0

Danke! Eine zusätzliche Anmerkung: Wenn Sie wegen des transparenten Vollbild-Quads für Texte GPU-gebunden sind, dann werden Sie irgendwann, egal welche CPU-seitige Optimierung Sie hinzufügen, keine fps-Verbesserung mehr bekommen, und dann ist die einzige Lösung, dieses große Quad zu trennen Unter-Quads, die in die Textzonen passen oder die Auflösung reduzieren. Sie können leicht testen, ob Sie GPU gebunden sind wegen der Mischung, indem Sie Ihr Quad als undurchsichtig anstelle von transparent oder durch Verringerung der Auflösung, wenn Sie fps, indem Sie dies tun, dann sind Sie GPU gebunden. –