2015-09-02 4 views
6

Я пытаюсь отобразить HUD поверх приложения OpenGL ES 2.0, написанного на C на платформе ARM Linux.OpenGL ES 2.0 + Cairo: HUD

В настоящее время я использую 2 треугольника, расположенных близко к плоскости отсечения и облицовки текстуры на них. Текстура - это размер экрана и в основном прозрачная, за исключением тех частей, где у меня есть текст. Текстура создается с помощью Pango/Cairo

Если я включаю HUD (раскомментирую вызов для render_ui), в настоящее время я получаю 50% -ный удар производительности (Goes from 60fps to 30fps).

Вот код, чтобы сделать 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"); 
} 

Там должен быть более разумным способом сделать это.

+0

Что такое GPU на вашей платформе (PowerVr, Adreno, Mali, Nvidia Tegra ...)? И что такое резолюция? –

+0

@VB_overflow Vivante GPU/плата Freescale iMX6. Разрешение - 1920x1080. – ReX357

ответ

3

На мобильных устройствах графических процессоров очень чувствительны к смешению, это по нескольким причинам:

  • Blending потребляет больше пропускной способность (необходимо прочитать текущий пиксель, чтобы смешать его с новым)
  • Blending может сломаться скрытой поверхность оптимизация удаления
  • Blending также может сломать плитку на основе defered рендеринга оптимизаций

Таким образом, в короткий мобильных графических процессоров любви непрозрачные многоугольники и ненавидящие прозрачные.

Обратите внимание, что общей поверхности, занятую прозрачными полигонами на экране также очень важно из-за «плитку на основе» природа большинство мобильных графических процессоров (когда плитка/бен покрыт прозрачными многоугольниками вы можете потерять некоторые GPU оптимизацию для этого).

Кроме того, поскольку вы говорите, что получаете резкое падение с 60 кадров в секунду до 30 кадров в секунду, я бы пришел к выводу, что ваш графический процессор устройства блокируется, ожидая, что экранная синхронизация на 60 Гц будет заменена, поэтому это означает, что ваш фрейм DT может быть только кратным из 16 мс, поэтому вы, вероятно, можете получить только значения fps, такие как: 60, 30, 15, 7.5, ...

Итак, если бы вы были на скорости 60 кадров в секунду, но добавляли что-то в основной цикл приложения, который бы сбросил теорему fps до 57 кадров в секунду, то из-за ожидания вертикальной синхронизации вы резко перейдете на 30 кадров в секунду. VSync может быть отключен, или методы, такие как тройная буферизация, могут использоваться для смягчения этого, но с OpenGLES способ сделать это специфичен для оборудования OS &, с которым вы работаете ... нет «официального способа сделать это, который работает на всех устройствах ".

Итак, зная все это вот некоторые предложения, чтобы вернуться к 60fps:

  1. Используйте уменьшенное разрешение, например: 1280x720 вместо 1920х1080, это позволит сократить использование полосой пропускания & обработки фрагмента.Разумеется, это не идеальный вариант, но это можно было бы использовать в качестве теста, чтобы подтвердить, что у вас есть проблема с полосой пропускания или фрагмента (если вы получили 60 кадров в секунду после уменьшения разрешения, то у вас есть такая проблема)
  2. Используйте 16-битный (R5G6B5) бэкбуффер вместо 32bits backbuffer (R8G8B8A8) это может уменьшить использование полосы пропускания, но с некоторой потере качества изображения
  3. Уменьшите площадь смешанных поверхностей: в вашем случае это будет означать, что вы должны упорядочить свои тексты с помощью «блоков», причем каждый блок должен быть как насколько это возможно, как на картинке, как на этом рисунке из IOS docs: enter image description here
  4. Найдите способ отключения Vsync на вашем устройстве/использование тройной буферизации. Если у вас есть доступ к документам Vivante GPU (я не знаю), это может быть описано внутри.

Пункт 3 - это лучшее, что нужно сделать (это то, что было сделано в большинстве мобильных игр, над которыми я работал), однако это потребует некоторой незначительной дополнительной работы. Точки 1, 2 и 3 более просты, но являются лишь «половинными решениями».

+0

Спасибо, это очень подробный ответ. Я смог получить резервную копию fps до 48 кадров в секунду, удалив много вызовов glDisable & glEnable, которые происходили и которые не были необходимы. Кажется, что gpu синхронизируется на 30, 48 и 60 кадров в секунду. Один из способов, которые я хочу попробовать исследовать, - это отсутствие поддержки KMS для ядра, которое я использую в настоящее время, и поэтому нулевая копия не реализована, что может сэкономить много вызовов memcpy. Но приятная работа, награда! – ReX357

+0

Спасибо! Дополнительная заметка: если вы используете GPU из-за полноэкранного прозрачного квадрата для текстов, то в какой-то момент, независимо от оптимизации стороны процессора, вы не получите больше улучшения fps, и тогда единственным решением будет отделить этот большой квадрант подкатегории, подгоняющие текстовые зоны или уменьшающие разрешение. Вы можете легко протестировать, если вы привязаны к GPU из-за смешивания, переключив квад, чтобы быть непрозрачным, а не прозрачным или уменьшающим разрешение, если вы получаете fps, делая это, тогда вы привязаны к GPU. –