OpenGL程序的时机



我已经学会了足够的OpenGL/Glut(使用Pyopengl(来提出一个简单的程序,该程序设置了片段着色器,绘制全屏四边形,并与显示器同步生成框架(Shadertoy风格(。我在某种程度上也了解图形管道。

我不明白的是OpenGL程序和图形管道如何融合在一起。特别是,在我的Glut显示回调中,

# set uniforms
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)  # draw quad
glutSwapBuffers()

我想通过通过glDrawArrays给出顶点来激活顶点着色器,该顶点会产生片段(像素(。但是,碎片着色器是否在glDrawArrays之后立即启动?有碎片,所以它可以做点什么。另一方面,仍然有可能进一步绘制命令创建进一步的顶点,这可以a(产生新的片段,b(覆盖现有的片段。

我介绍了该程序,发现99%的时间用于glutSwapBuffers。当然,这部分是由于等待垂直同步的原因,但是当我使用非常苛刻的片段着色器时,它会保持这种状态,从而大大降低了帧速率。这表明片段着色器仅在glutSwapBuffers中的某个地方激活。这是正确的吗?

我知道片段着色器是在GPU上执行的,而不是CPU,但似乎CPU(程序(等待直到GPU(阴暗器(完成,在glutSwapBuffers ...

我介绍了该程序,发现99%的时间用于glutSwapBuffers。当然,这部分是由于等待垂直同步的原因,但是当我使用非常苛刻的片段着色器时,它会保持这种状态,从而大大降低了帧速率。这表明片段着色器仅在glutSwapBuffers中激活。是 正确吗?

否。该逻辑完全有缺陷。这里的要点是片段着色器在GPU 上运行,该片段与CPU完全不同步。您不是在测量碎片着色器,而是在测量一些隐式的CPU-GPU同步 - 看起来您的实现同步缓冲区交换(如果超过太多框架可能已经排队(,那么所有您的所有测量都是CPU的时间必须等待GPU。而且,如果您增加了GPU工作量而没有大大增加CPU工作量,那么您的CPU将花费更多的时间等待。

OpenGL本身并未定义任何此内容,因此所有细节最终都是完全特定于实现的。规格只是保证了实现的行为,就好像片段是按照您绘制原语的顺序生成的(例如,在启用混合的情况下,实际顺序变为相关的van ion vlydraw spenarios(。但是,在什么时候生成片段,以及在片段着色器的顶点处理和调用之间可能发生哪些优化,这完全是您无法控制的。GPU可能采用基于瓷砖的栅格化方案,其中实际的片段阴影被延迟一点(如果可能的话(以提高效率并避免过高。

请注意,大多数GPU驱动程序的工作完全不同步。当您调用gl*()命令时,它在处理之前返回。它可能仅排队以进行以后的处理(例如,在另一个驱动程序线程中(,并最终将在某些转移到GPU的GPU特定命令缓冲区中转换。例如,您可能最终会出现隐式CPU-GPU同步(或带有驱动程序线程的CPU-CPU(,例如,当您在绘制呼叫后读取后帧缓冲程序数据时,这将暗示所有以前的GL命令都将刷新用于处理,并且CPU将在检索图像数据之前等待处理处理 - 这也是使此类回复如此慢的原因。

因此,任何CPU端的OpenGL代码措施都是完全没有意义的。您需要在GPU 上测量时间,这就是计时器查询的目的。

最新更新