2015-01-11 35 views
0

我读过,优化OpenGL 2(尤其是ES)中非透明对象渲染顺序的最佳方法是优先避免上下文排序中的上下文更改(绑定不同的缓冲区,着色器程序等)。正在调用glBindBuffer,glUseProgram等与以前相同的值效率低下?

如果您使用已绑定的缓冲区调用glBindBuffer,或使用已经是当前程序等的着色器程序执行glUseProgram等操作,它们是否仍会导致低效的管线刷新,或者库是否足够灵巧以识别他们作为NOOPs?如果我可以在需要时绑定所有内容而无需跟踪已绑定的内容并检查它,它将使我的代码更简单。

回答

2

也许吧。这实际上不能一般回答。它完全依赖于实现。

司机是否应该检查冗余的状态变化是一个有点哲学的讨论,你不会找到共识。因此,您应该期望不同的供应商以不同的方式处理它,而且我甚至不一定会假设它在同一个驱动程序中针对所有状态一致地进行处理。

如果您针对的是特定平台,则应该对其进行测量。幸运的是,这很容易进行基准测试。如果你想覆盖广泛的平台/供应商,我会尽量减少冗余的状态变化。至少如果你可以选择相对便宜的话。如果你为此增加了很多开销,你可能会造成更多的伤害。

对此有不同看法的主要原因是检查冗余状态变化并非完全免费。如果司机这样做,则开销适用于每个人。如此写得好的应用程序(不会造成不必要的状态更改)会为优化写入不好的应用程序而付出代价。你可以争论的是非常不公平的。

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

0

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

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