OpenGL,测量 gpu 上的渲染时间
OpenGL, measuring rendering time on gpu
我有一些大的性能问题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 个命令,然后再将它们一起发送到一批中),我的问题本质上是 if:
上面的代码是正确的
我假设在新帧开始时所有先前的 GL 命令(来自上一帧)都已在 gpu 上发送、执行和终止
我假设当我使用 glGetQueryObjectiv
和 GL_QUERY_RESULT
获得查询结果时,到目前为止所有 GL 命令都已终止?那就是 OpenGL 会等到结果可用(从线程)?
是的,当您查询计时器时,它会阻塞直到数据可用,即直到 GPU 完成查询开始和结束之间发生的所有事情。为避免与 GPU 同步,您可以使用 GL_QUERY_RESULT_AVAILABLE
检查结果是否已经可用,然后才读取它们。这可能需要不太直接的代码来密切关注打开的查询并定期检查它们,但它对性能的影响最小。每次都等待这个值肯定会扼杀你的表现。
编辑:为了解决您的第二个问题,交换缓冲区并不一定意味着它将阻塞直到操作成功。您可能会看到这种行为,但它很可能只是一个隐含的 glFlush
并且命令缓冲区还不是空的。这也是更需要的行为,因为理想情况下,您希望立即开始下一帧并保持 CPU 命令缓冲区已满。不过,请查看实施文档以获取更多信息,因为这是实施定义的。
编辑 2:顺便说一下,检查错误可能最终成为隐式同步,因此当您等待命令流中的错误检查时,您可能会看到命令缓冲区清空。
我有一些大的性能问题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 个命令,然后再将它们一起发送到一批中),我的问题本质上是 if:
上面的代码是正确的
我假设在新帧开始时所有先前的 GL 命令(来自上一帧)都已在 gpu 上发送、执行和终止
我假设当我使用
glGetQueryObjectiv
和GL_QUERY_RESULT
获得查询结果时,到目前为止所有 GL 命令都已终止?那就是 OpenGL 会等到结果可用(从线程)?
是的,当您查询计时器时,它会阻塞直到数据可用,即直到 GPU 完成查询开始和结束之间发生的所有事情。为避免与 GPU 同步,您可以使用 GL_QUERY_RESULT_AVAILABLE
检查结果是否已经可用,然后才读取它们。这可能需要不太直接的代码来密切关注打开的查询并定期检查它们,但它对性能的影响最小。每次都等待这个值肯定会扼杀你的表现。
编辑:为了解决您的第二个问题,交换缓冲区并不一定意味着它将阻塞直到操作成功。您可能会看到这种行为,但它很可能只是一个隐含的 glFlush
并且命令缓冲区还不是空的。这也是更需要的行为,因为理想情况下,您希望立即开始下一帧并保持 CPU 命令缓冲区已满。不过,请查看实施文档以获取更多信息,因为这是实施定义的。
编辑 2:顺便说一下,检查错误可能最终成为隐式同步,因此当您等待命令流中的错误检查时,您可能会看到命令缓冲区清空。