与glUniform *的隐式同步

时间:2015-06-11 14:36:55

标签: performance opengl

以下GL代码中是否存在隐式同步?

glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(prg);

glUniform1f(loc, a);
glDrawArrays(GL_TRIANGLES, 0, N);

glUniform1f(loc, b);                     // <-- Implicit synchronization??
glDrawArrays(GL_TRIANGLES, 0, N);

swapBuffers();

2 个答案:

答案 0 :(得分:4)

与往常一样,OpenGL实现可以按照自己喜欢的方式处理事物,只要它能够产生正确的行为。因此,没有办法说出必须如何工作。

话虽如此,更新制服是一项常见的操作,并且强制GPU和CPU之间的同步以进行统一更新对于性能而言将是可怕的。

最简单的方式来描述这种最有可能在现实中起作用的方式是你所做的OpenGL调用是在一个稍后由GPU执行的命令流中编码的。当您进行glUniform()调用时,这将生成一个命令以更新统一值,并将该命令附加到命令流。稍后它将由GPU执行,同时绘制调用也是同一命令流的一部分。

只有当GPU执行命令(主要在glUniform()调用返回后很久才会发生)时,GPU才会更新实际值。

答案 1 :(得分:1)

很可能没有。

在大多数现代多线程驱动程序实现中,整个帧(包括glDraw*调用)可能是异步的。因此,CPU几乎总是比GPU领先几帧。 仅在查询状态(glGet*)或执行大内存传输(例如缓冲区更新)时才会发生同步。

当然,细节取决于具体供应商的软件和硬件实施,操作系统,甚至驱动程序版本等。

另见:

NVidia -- Detecting CPU-GPU Sync Points [PDF]

P.S。 正在开发新的API来解决这些(和更多)问题,主要是让程序员明确控制同步过程: