Повторные кадры на Android Mali-400
На устройствах Android с графическим процессором Mali-400 (Samsung Galaxy S II, Samsung Galaxy S3 Mini, Samsung Galaxy Note II) в случайное время на экране будут появляться повторяющиеся кадры.
Пример с 0:51 до 1:01 на следующем видео https://www.youtube.com/watch?v=5-p6Oy0BZmg
Кажется, что новые кадры не отображаются, и то, что было в старом буфере, показывается снова. Игра продолжает продвигаться за повторяющимися кадрами.
Это не происходит на других графических процессорах.
Я читал об использовании glFlush или glFinish, но GLSurfaceView заботится об этом при выполнении eglSwapBuffers после onDrawFrame.
Я читал о причудах Mali-400, например, лучше использовать варьирование для текстурных координат или использовать lowp, но это не помогает. Вот шейдеры для справки:
Вершинный шейдер:
// Vertex Shader
attribute vec4 position;
attribute vec4 colorModelIn;
attribute vec4 colorVertexIn;
varying lowp vec4 colorOut;
uniform mat4 modelViewProjectionMatrix;
uniform mat4 modelMatrix;
attribute vec2 TexCoordIn;
varying lowp vec2 TexCoordOut;
uniform bool bUseVertexColor;
void main()
{
if( bUseVertexColor ){
colorOut = colorVertexIn * colorModelIn;
} else {
colorOut = colorModelIn;
}
TexCoordOut = TexCoordIn;
gl_Position = modelViewProjectionMatrix * modelMatrix * position;
}
Фрагмент шейдера:
// Fragment shader
varying lowp vec4 colorOut;
varying lowp vec2 TexCoordOut;
uniform sampler2D Texture;
uniform bool bUseTexture;
void main()
{
if( bUseTexture ){
gl_FragColor = colorOut * texture2D(Texture, TexCoordOut);
} else {
gl_FragColor = colorOut;
}
}
Я знаю, что эти шейдеры не оптимальны, и что я иду по пути воспроизведения фиксированного конвейера.
Рендеринг возвращается к нормальному состоянию через некоторое время или после прикосновения к экрану. Единственная причина, по которой я могу вернуться к нормальной жизни при прикосновении, заключается в том, что я использую цветовое кодирование для обнаружения прикосновения к объекту. Я рендерил изображение в задний буфер и glReadPixels из него. Затем перезаписать задний буфер обычным игровым образом.
У меня нет идей о том, как атаковать эту проблему.
РЕДАКТИРОВАТЬ
Следуя совету Муззы, я начал регистрировать ошибки GL. glGetInteger и glBindBuffer сообщают о нехватке памяти.
Выше я говорил, что проблема решается через некоторое время. Когда это происходит, они появляются в журналах:
01-23 21:57:52.956: D/WebView(9860): onSizeChanged - w:480 h:75
01-23 21:57:53.126: D/TilesManager(9860): new EGLContext from framework: 40e00bd0
01-23 21:57:53.126: D/GLWebViewState(9860): Reinit shader
01-23 21:57:53.171: D/GLWebViewState(9860): Reinit transferQueue
1 ответ
Это может произойти, если состояние OpenGL каким-то образом станет недействительным. Графические драйверы могут просто пропустить кадры полностью. Проверьте Logcat, чтобы увидеть, есть ли какие-либо выходные данные от драйверов, и добавьте вызовы glGetError() по всему коду, чтобы увидеть, появляется ли какая-либо ошибка там.