首先抛出结论: 大多数GL函数在使用时会被缓冲, 并在以后实际执行. 这意味着不能将CPU和GPU视为两个处理器同时工作. 通常情况下, CPU会执行一系列缓存的GL函数, 并且一旦将它们传递给GPU, 它就会执行它们. 这意味着无法可靠地控制执行特定GL功能所需的时间.
关于这方面的研究主要参考自博客【OpenGL】glFinish()和glFlush()函数详解-[转]
通常情况下, OpenGL指令不是立即执行的. 它们首先被送到指令缓冲区, 然后才被送到硬件执行. glFinish和glFlush都是强制将命令缓冲区的内容提交给硬件执行.
1. glFinish()函数
glFinish()将缓冲区的指令立即送往硬件执行, 但是要一直等到硬件执行完这些指令之后才返回. 如果直接绘制到前缓冲, 就需要调用这个函数, 确保绘制完毕. 如果使用双缓冲, 则这个函数不会有太大作用.
2. glFlush()函数
glFlush()清空缓冲区, 将指令送往缓硬件立即执行, 但是它是将命令传送完毕之后立即返回, 不会等待指令执行完毕. 这些指令会在有限时间内执行完毕.
如果直接绘制到前缓冲, 那么OpenGL的绘制将不会有任何延迟. 设想有一个复杂的场景, 有很多物体需要绘制. 当调用glFlush时, 物体会一个一个地出现在屏幕上. 但是, 如果使用双缓冲, 这个函数将不会有什么影响, 因为直到交换缓冲区的时候变化才显现出来.
如果你使用的是双缓冲, 那么可能这两个函数都不需要用到. 缓冲区交换操作会隐式将命令送去执行.
3. glFinish和glFlush的区别
看起来这两个函数很相似, 但是仍然是有区别的. 一般, 使用glFlush的目的是确保在调用之后, CPU没有OpenGL相关的事情需要做-命令会送到硬件执行. 调用glFinish的目的是确保当返回之后, 没有相关工作留下需要继续做.
4. glFinish会造成性能下降
如果调用glFinish, 通常会带来性能上的损失. 因为它会是的GPU和CPU之间的并行性丧失. 一般, 我们提交给驱动的任务被分组, 然后被送到硬件上(在缓冲区交换的时候). 如果调用glFinish, 就强制驱动将命令送到GPU. 然后CPU等待直到被传送的命令全部执行完毕. 这样在GPU工作的整个期间内, CPU没有工作(至少在这个线程上). 而在CPU工作时(通常是在对命令分组), GPU没有工作, 因此造成性能上的下降.
因此, 应该尽量减少使用此函数. 此函数的一个应用是: 调试bug. 如果我传输到硬件的某条命令造成了GPU的崩溃, 找出使得GPU崩溃的那条指令的简单方法是在每个绘制操作之后调用这个函数. 这样就可以准确找出造成崩溃的命令. 另外, Direct3D不支持Finish概念.
PS: 判断自己的显卡是否使用双缓冲的代码如下:
GLboolean isDoubleBuffer; glGetBooleanv(GL_DOUBLEBUFFER, &isDoubleBuffer);