OpenGL,测量gpu上的渲染时间

时间:2015-05-07 15:06:11

标签: opengl gpu timing opengl-4 elapsedtime

我遇到了一些重大的性能问题here

所以我想对gpu方面进行一些测量。

通过阅读thread我在绘制函数周围编写了这段代码,包括gl错误检查和swapBuffers()(自动交换确实被禁用)

        gl4.glBeginQuery(GL4.GL_TIME_ELAPSED, queryId[0]);
        {    
            draw(gl4);

            checkGlError(gl4);

            glad.swapBuffers();
        }
        gl4.glEndQuery(GL4.GL_TIME_ELAPSED);
        gl4.glGetQueryObjectiv(queryId[0], GL4.GL_QUERY_RESULT, frameGpuTime, 0);

由于OpenGL渲染命令应该是asynchronous(驱动程序可以缓冲多达X个命令,然后在一个批次中将它们全部发送到一起),我的问题基本上是关于:

  • 上面的代码是正确的

  • 我是正确的假设在新帧的开始处所有先前的GL命令(来自前一帧)已经在gpu上发送,执行和终止

  • 我是正确的假设当我得到glGetQueryObjectivGL_QUERY_RESULT的查询结果时,到目前为止所有GL命令都已终止?那就是OpenGL将等到结果可用(来自线程)?

1 个答案:

答案 0 :(得分:4)

是的,当您查询计时器时,它将阻塞直到数据可用,即直到GPU完成查询开始和结束之间发生的所有事情。为避免与GPU同步,您可以使用GL_QUERY_RESULT_AVAILABLE检查结果是否已经可用,然后再读取它们。这可能需要不那么简单的代码来密切关注打开的查询并定期检查它们,但它会对性能影响最小。每次等待这个价值都是杀死你表现的可靠方法。

编辑:要解决第二个问题,交换缓冲区并不一定意味着它会在操作成功之前阻塞。您可能会看到该行为,但它很可能只是一个隐式glFlush并且命令缓冲区尚未为空。这也是更想要的行为,因为理想情况下,您希望立即从下一帧开始并保持CPU命令缓冲区已填满。请查看实现文档以获取更多信息,因为这是实现定义。

编辑2:检查错误可能最终会成为隐式同步,因此当您等待命令流中的错误检查时,您可能会看到命令缓冲区清空。