C- OpenGL实际更新屏幕需要多长时间



我在C中有一个简单的OpenGL测试应用程序,该应用程序响应关键输入而绘制不同的内容。(MESA 8.0.4,使用MESA-EGL和GLFW,Ubuntu,ubuntu 12.04lts在具有NVIDIA GTX650的PC上进行了尝试)。抽签非常简单/快速(旋转三角形类型的东西)。我的测试代码不会以任何方式故意限制帧率,它看起来像这样:

while (true)
{
    draw();
    swap_buffers();
}

我已经非常仔细地定时了,我发现一个eglSwapBuffers()(或GlfwSwapBuffers)的时间是〜16.6毫秒。从之后的时间呼叫 eglSwapBuffers() 的时间仅比此呼叫要小一点,即使绘制的内容非常简单。交换缓冲区调用所需的时间远远低于1毫秒。

但是,从应用程序将其绘制以响应按键按下的绘制的时间到屏幕上显示的更改是> 150ms (价值8-9帧)。这是通过屏幕的摄像头记录和60fps的键盘记录来测量的。(注意:是的,我没有办法衡量从密钥按到应用程序中需要多长时间的方法。我假设它是<< 150ms)。

因此,问题:

  1. 在呼叫交换缓冲区和实际出现在屏幕上的呼叫之间的图形在哪里?为什么要延迟?它肯定看起来像该应用程序始终在屏幕前绘制许多帧。

  2. OpenGL应用程序可以采取什么措施使屏幕上立即抽取?(即:没有缓冲,只需阻止抽奖完成;我不需要高吞吐量,我确实需要低延迟)

  3. 应用程序可以做些什么才能使上述立即抽奖尽可能快地发生?

  4. 应用程序如何知道屏幕上实际上是什么?(或者,当前缓冲延迟是多长时间/多少帧?)

  • 在呼叫交换缓冲区和实际出现在屏幕上的呼叫之间的图形在哪里?为什么要延迟?肯定看起来该应用程序一直在屏幕前绘制许多帧。

命令是排队的,无论是在backbuffer上抽出的什么,请等到下一个vsync如果您设置了swapInterval,并且在下一个VSYNC中,应显示此缓冲区。

  • OpenGL应用程序可以采取什么措施使屏幕立即绘制?(即:没有缓冲,只需阻止抽奖完成;我不需要高吞吐量,我确实需要低延迟)

使用glFinish将确保在此API返回之前绘制所有内容,但无法控制它何时实际上到达Swapinterval设置以外的其他。

  • 应用程序可以做些什么来使上述立即抽奖尽可能快地发生?应用程序如何知道屏幕上实际上是什么?(或者,当前缓冲延迟是多长时间/多少帧?)

通常,您可以使用Sync(类似于http://www.khronos.org/registry/egl/extensions/nv/egl_nv_sync.txt)来找到这一点。

您确定测量延迟的方法是正确的吗?如果密钥输入实际上在PC中有很大的延迟怎么办?您是否从代码中收到的事件中,在Shapbuffers之后的点上测量了延迟?

您必须了解GPU具有特殊专用的内存(在船上)。在最基本的层面上,此内存用于保存您在屏幕上看到的编码像素(也用于图形硬件加速度和其他内容,但这现在不重要)。因为它花费时间从主RAM到GPU RAM加载框架,所以您可以获得闪烁的效果:在短时间内,您可以看到背景而不是应该显示的内容。尽管这种复制的发生得非常快,但它对于人眼很明显,非常烦人。

为此,我们使用一种称为 double Buffering 的技术。基本上是双重缓冲通过在GPU RAM中有附加的帧缓冲区(可以是一个或多个)来起作用(根据您正在使用的图形库和GPU,但两个足以工作),并使用指针指示应该哪个帧应显示。因此,在显示第一帧时,您已经在主RAM中的图像结构上使用某些draw()函数在代码中创建下一个,然后将此图像复制到您的GPU RAM(同时仍显示上一个帧),然后将其复制调用 eglSwapBuffers()指针切换到您的返回缓冲区(我从您的问题中猜到了,我对OpenGL不熟悉,但这很普遍)。您可以想象这种指针开关不需要太多时间。希望您现在看到直接将图像写在屏幕上实际上会导致更多的延迟(并且令人讨厌的闪烁)。

也〜16.6毫秒听起来不那么多。我认为大多数时间都丢失了/设置所需的数据结构,而不是真正的图形计算本身(您可以通过绘制背景来测试)。

最后,我喜欢补充说,I/O通常很慢(大多数程序中最慢),而150ms的速度根本不长(仍然是眨眼的两倍)。

啊,是的,您发现了OpenGL和显示系统的相互作用的一种特点直到大约2年前,它也完全理解它)。那么这里发生了什么:

SwapBuffers做了两件事:

  1. 它将(私有)命令排队到命令队列,该命令也用于opengl绘图呼叫,该示意呼叫本质上是 flags 一个缓冲区与图形系统的缓冲区交换
  2. 它使OpenGL齐平均所有排队的绘图命令(到后缓冲区)

除此之外,Swapbuffers本身无济于事。但是这两件事有有趣的后果。一个是,Swapbuffers将立即返回。但是,一旦将"反向缓冲区交换"标志设置(由排队命令)设置,后缓冲区将锁定,以锁定任何会改变其内容的操作。因此,只要没有打电话就会改变后缓冲区的内容,就不会阻塞。并且会更改后缓冲区内容的命令将停止OpenGL命令队列,直到换后缓冲区并释放了更多命令。

现在,OpenGL命令队列的长度是抽象的。但是通常的行为是,一个OpenGL绘图命令将阻止,等待队列齐平响应已发生的交换缓冲区。

我建议您使用一些高性能,高分辨率计时器作为时钟源来喷涂程序,以查看延迟的确切位置。

延迟将由驱动程序和显示本身确定。即使您直接写给硬件,也会受到后者的限制。

该应用程序只能做很多事情(即,快速绘制,过程输入尽可能接近或在绘图过程中,甚至可能在翻转时修改缓冲区)来减轻此功能。之后,您将受到其他工程师的摆布,包括硬件和软件。

,如果没有外部监视,您无法分辨延迟是什么。

另外,不要假设您的输入(应用程序键盘)也很低!

最新更新