【问题标题】:OpenGL ES 2.0 screen flickeringOpenGL ES 2.0 屏幕闪烁
【发布时间】:2012-08-20 08:28:55
【问题描述】:

我面临一个大问题。我正在使用带有 Android 4.0.3 的 Transformer tf101 选项卡。

我的应用正在使用自定义 OpenGL ES 2.0 表面。我正在用纹理渲染多个平面。这种纹理正在改变大约。每秒 20 次,通过传递字节数组进行更新。但是,在某些情况下,屏幕会开始闪烁并且不会渲染新的纹理。其他 UI 元素仍然具有响应性并按预期工作。似乎 OpenGL 上下文忽略了所有命令并且没有响应。

发生这种情况时,我的 logCat 中会显示几行:

08-20 10:31:15.390: D/NvOsDebugPrintf(2898): NvRmChannelSubmit: NvError_IoctlFailed with error code 1

紧随其后

08-20 10:31:15.390: D/NvOsDebugPrintf(2898): NvRmChannelSubmit failed (err = 13, SyncPointValue = 879005, returning = 0)

还有一些:

08-20 10:31:15.390: D/NvOsDebugPrintf(2898): NvRmChannelSubmit failed (err = 196623, SyncPointValue = 0)

这是我创建纹理平面的方法:

    m_nTextureStorage[0] = 0;

    GLES20.glGenTextures( 1, m_nTextureStorage, 0);
    GLES20.glActiveTexture( GLES20.GL_TEXTURE0 );
    GLES20.glBindTexture( GLES20.GL_TEXTURE_2D, m_nTextureStorage[ 0 ] );

    // Set filtering
    GLES20.glTexParameterf( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST );
    GLES20.glTexParameterf( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST );
    GLES20.glTexParameteri( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE );
    GLES20.glTexParameteri( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE );

我是这样画的:

GLES20.glEnable(GLES20.GL_TEXTURE_2D);
        GLES20.glEnable(GLES20.GL_DEPTH_TEST);
        GLES20.glActiveTexture( GLES20.GL_TEXTURE0 );

        //GLES20.glUniformMatrix4fv(m_HMVPMatrixUniform, 1, false, mvpMatrix, 0); 
        GLES20.glUseProgram( m_nProgramHandle );
        ByteBuffer oDataBuf = ByteBuffer.wrap( m_sTexture );

        m_HTextureUniform = GLES20.glGetUniformLocation( m_nProgramHandle, "uTexture" );
        m_HTextureCoordinate = GLES20.glGetAttribLocation( m_nProgramHandle, "TexCoordinate" );
        GLES20.glUniform1iv( m_HTextureUniform, 2, m_nTextureStorage, 0 );

        // get handle to the vertex shader's vPosition member
        m_nPositionHandle = GLES20.glGetAttribLocation( m_nProgramHandle, "vPosition" );


        // Prepare the triangle data
        GLES20.glTexImage2D( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, 640, 480,
                             0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, oDataBuf );

        // Prepare the triangle data
        GLES20.glVertexAttribPointer( m_nPositionHandle, 3, GLES20.GL_FLOAT, false, 12, m_oVertexBuffer );
        GLES20.glEnableVertexAttribArray( m_nPositionHandle );

        GLES20.glVertexAttribPointer( m_HTextureCoordinate, 2, GLES20.GL_FLOAT, false, 12, m_oTextureBuffer); 
        GLES20.glEnableVertexAttribArray( m_HTextureCoordinate );

        m_nMVPMatrixHandle = GLES20.glGetUniformLocation( m_nProgramHandle, "uMVPMatrix");

        // Apply the projection and view transformation
        GLES20.glUniformMatrix4fv( m_nMVPMatrixHandle, 1, false, mvpMatrix, 0);

        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);

OpenGL 渲染器通过传递 mvpMatrix 简单地调用我的 TexturedPlane 的绘制函数。我没有删除任何纹理,因为我已经读过 android 系统会自动处理它。

我认为这与 GPU 出现 OOM 有关,但我不确定,因为我没有找到与发布的错误消息相关的任何内容。

提前谢谢!

更新:

渲染模式设置为 RENDER_WHEN_DIRTY 。将其更改为RENDERMODE_CONTINOUSLY 后,问题消失了.. 很奇怪。由于这只是一种解决方法,没有解决方案,我仍在寻求帮助;)

将渲染模式保持在连续状态是不可取的,因为这会消耗大量处理器时间并且没有任何意义,因为只有在生成新纹理时才需要渲染。

【问题讨论】:

  • m_sTexture 是如何产生的?
  • 动态作为新字节[640 * 480];这仅进行一次。我对 java 和 OpenGL 很陌生。但是,我注意到,当闪烁开始时,Surface 会渲染最后 3 帧已通过.... 这表明这些帧仍存储在 GPU 内存中的某个位置。
  • 更新:似乎在纹理创建过程花费大量时间时更容易出现闪烁。创建新纹理最多可能需要一秒钟。如果是这种情况,闪烁会在几秒钟后开始。如果纹理生成时间低于 50 毫秒,则永远不会发生闪烁...这是否意味着闪烁是由某种同步问题触发的,因为 OpenGL 渲染和纹理创建在不同的线程中运行?
  • 你确定所有gl相关的函数调用都发生在渲染线程中吗?
  • 非常好的观点。不,我不是。我的渲染器能够处理各种“对象”。例如。用于标记区域的平面、十字等。这些对象是在此渲染线程之外创建的。 gl 调用在构造函数中完成。但是,在 OpenGL 启动并运行之前,没有“对象”被初始化......但由于我使用的是可重入锁,我确信只有 1 个线程正在访问 OpenGL,对吧?

标签: android opengl-es-2.0


【解决方案1】:

终于找到解决办法了。

当我在每个渲染圈之后调用 glFlush() 时,它工作正常。我没有在不同的纹理通道上渲染每个平面,到目前为止它工作得很好。感谢您的帮助。

【讨论】:

    【解决方案2】:

    当你调用..时:

    GLES20.glUniform1iv( m_HTextureUniform, 2, m_nTextureStorage, 0 );
    

    我认为that binds a particular texture unit to the sampler uniform。但是您传递了一个 texture 名称/对象/句柄/任何东西(这不是 texture unit。)也许这只是巧合,而您只传递了 0 (这可能是m_nTextureStorage,) 中的纹理名称,这恰好是正确/期望的值?

    或者这可能会导致用户空间驱动程序崩溃。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多