Android Mali-400 上的重复帧

Repeated frames on Android Mali-400

在 Android 具有 Mali-400 GPU 的设备(Samsung Galaxy S II、Samsung Galaxy S3 Mini、Samsung Galaxy Note II)上,屏幕会随机开始显示重复帧。

示例从 0:51 到 1:01 以下视频 https://www.youtube.com/watch?v=5-p6Oy0BZmg

好像没有渲染新帧,而旧缓冲区中的内容又被显示了。游戏在重复的帧后面继续推进。

这不会发生在其他 GPU 上。

我读到了有关使用 glFlush 或 glFinish 的信息,但是 GLSurfaceView 在 onDrawFrame 之后执行 eglSwapBuffers 时会处理这个问题。

我读过有关 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 。然后,用正常的游戏图像覆盖后台缓冲区。

我不知道如何解决这个问题。

编辑

听从 Muzza 的建议后,我开始记录 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

如果 OpenGL 状态以某种方式变得无效,就会发生这种情况。图形驱动程序可以完全跳过帧。检查 Logcat 以查看驱动程序是否有任何输出,并在整个代码中添加 glGetError() 调用以查看是否出现任何错误。