调用glBindBuffer,glUseProgram等与低效率相同的值?

时间:2015-01-11 18:08:02

标签: opengl-es-2.0 opengl-2.0

我已经读过,优化OpenGL 2(尤其是ES)中非透明对象的渲染顺序的最佳方法是优先考虑避免上下文更改(绑定不同的缓冲区,着色器程序等)而不是深度排序。

如果您执行类似调用已绑定缓冲区的glBindBuffer,或者使用已经是当前程序等的着色器程序的glUseProgram,它们仍然会导致低效的管道刷新,或者库是否足够聪明地识别它们作为NOOP?如果我可以在需要时绑定所有内容而不必跟踪已经绑定的内容并检查它,那么它将使我的代码更简单。

2 个答案:

答案 0 :(得分:3)

也许。这一般无法得到回答。它完全取决于实现。

司机是否应该检查多余的状态变化是一种有点哲学的讨论,而你却未能就此达成共识。因此,您应该期望不同的供应商以不同的方式处理它,并且我甚至不必假设它在同一驱动程序中对所有状态一致地处理。

如果您要定位特定平台,则应进行衡量。幸运的是,这很容易进行基准测试。如果您想覆盖各种平台/供应商,我会尽量减少冗余状态变化。至少如果你有选择以相对便宜的方式做到这一点。如果你为此增加了很多开销,那么你可能弊大于利。

对此有不同意见的主要原因是检查冗余状态变化并非完全免费。如果驱动程序执行此操作,则开销适用于每个人。如此精心编写的应用程序(不会进行不必要的状态更改)会为优化程序付出代价,从而使编写得不好的应用程序受益。你可以争辩说这是非常不公平的。

实际上,通常会进行这些检查,特别是如果状态变化本身相当昂贵。当然,如果状态变化非常便宜,那么不值得添加支票。这些检查通常会通过针对重要应用/游戏基准的性能优化来实现。不幸的是,许多应用程序/游戏使用OpenGL的效率非常低,驱动程序必须为重要的基准测试产生最佳结果。在这些情况下,过滤掉冗余状态更改是常见的优化。

答案 1 :(得分:0)

我们的每个glBindBuffer或glUseProgram等调用都会在队列中创建一个命令对象。一段时间后,将在gpu上执行此队列。这里有2个瓶颈。 1)要在队列中创建命令对象,我们的代码必须转移到内核模式到驱动程序。通常这种操作有一些滞后。 2)GPU将逐个执行我们的命令,并检查已经绑定的缓冲区,GPU必须读取和解码命令。

为了避免第二个驱动程序必须跟踪当前状态,我认为opengl驱动程序不会这样做。