OpenGL ES 2.0:非常不一致的帧率

Posted

技术标签:

【中文标题】OpenGL ES 2.0:非常不一致的帧率【英文标题】:OpenGL E.S. 2.0: Very inconsistent framerate 【发布时间】:2013-10-26 09:29:12 【问题描述】:

我已经创建了一个简单的 android 应用程序,如下所示:

活动:

public class MainActivity extends Activity 
    private GLSurfaceView mGLView;

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        mGLView = new MyGLSurfaceView(this);
        setContentView(mGLView);
    

OpenGL 表面:

class MyGLSurfaceView extends GLSurfaceView 

    public MyGLSurfaceView(Context context)
        super(context);

        // Create an OpenGL ES 2.0 context
        setEGLContextClientVersion(2);

        // Set the Renderer for drawing on the GLSurfaceView
        setRenderer(new MyGL20Renderer());
    

渲染器:

public class MyGL20Renderer implements GLSurfaceView.Renderer 

    private long mCurrentTime;

    public void onSurfaceCreated(GL10 unused, EGLConfig config) 
        // Set the background frame color
        GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
    

    @Override
    public void onDrawFrame(GL10 unused) 

        final long newTime = getSystemTime();
        final long dt = newTime - mCurrentTime;
        mCurrentTime = newTime;

        Log.e("test", "dt: "+dt);

        // Redraw background color
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    

    @Override
    public void onSurfaceChanged(GL10 unused, int width, int height) 
        GLES20.glViewport(0, 0, width, height);
    

    private long getSystemTime() 
        return System.nanoTime()/1000L;
    


如您所见,对于每一帧,我采用 nanoTime 并将其除以 1000 以获得微秒时间。

现在,当我查看onDrawFrame() 中产生的输出时,我得到了不同值的所有方式:

(此处为原始尺寸:http://s14.directupload.net/images/131026/97pse5wo.png)。

x-scale 只是框架。每帧一个值。 y-scale 是增量时间,dt 在onDrawFrame() 中计算。这是上一帧绘制所需的时间(以微秒为单位)。

现在我完全理解,由于以下原因,这些值不会停留在 16666:

无法完美确定增量时间。此外,将纳米时间除以 1000 并将其转换为 long 会导致一些计算错误 系统必须等待eglSwapBuffers() 一旦函数onDrawFrame() 完成,这仅意味着OpenGL 命令已发送到管道。但这并不意味着命令已经处理完毕。

但我似乎仍然无法理解为什么我得到如此高的抖动结果,而我基本上什么都不计算。

问题的根源是什么?

测试环境:

HTC One CyanogenMod 10.2 (Android 4.3)

如果有人能复制这个,我会很高兴的。

【问题讨论】:

【参考方案1】:

您会发现帧率不一致是由于 Log 语句造成的。如果您存储数据点,然后一次将它们全部记录下来,您会发现帧速率更加一致。使用类似以下的内容来记录数据。我每 1000 帧执行一次,得到的 dt 约为 16500-18500。

    mDt[mStoredDtCount] = dt;
    mStoredDtCount++;
    if (mStoredDtCount == DT_MAX_COUNT) 
        while (mStoredDtCount > 0) 
            mStoredDtCount--;
            Log.e("test2", "dt: "+mDt[mStoredDtCount]);
        
    

【讨论】:

嗯,我不确定这是不是真的。我已经用你的方法完成了,现在得到这个图表(大约一分钟捕获):s14.directupload.net/images/131026/m7bg6dd8.png 我唯一的想法是看看你的设备是否在帧之间进行垃圾收集。 我已从日志输出中删除过滤器并将其设置为“详细”。在整个运行时没有一条关于 GC 的消息。 如果您想将源代码压缩并上传到某个地方,我会在我的设备上试用您的代码。 您好 levis501,感谢您的回答。我在这里上传了一个 zip:file-upload.net/download-8228041/FramerateTest.zip.html 它包含 .apk 以及源代码。

以上是关于OpenGL ES 2.0:非常不一致的帧率的主要内容,如果未能解决你的问题,请参考以下文章

AudioTrack 采样率不一致

用于模糊的 OpenGL ES 2.0 片段着色器速度慢且质量低

结合 UIView 动画块和 OpenGL ES 渲染

javacv 设置帧率(续)

如何在 iPhone OpenGL ES 2.0 中在渲染和呈现帧缓冲区之间切换?

使用 MediaCodec 和 MediaMuxer 录制视频,但码率和帧率不正确