3

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

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

4

2 回答 2

5

也许。这真的不能笼统地回答。它完全依赖于实现。

驱动程序是否应该检查冗余状态更改是一个有点哲学性的讨论,您不会就此达成共识。因此,您应该期望不同的供应商以不同的方式处理它,我什至不一定假设它在同一个驱动程序中的所有状态都得到一致的处理。

如果您针对特定平台,则应该对其进行衡量。幸运的是,这很容易进行基准测试。如果您想涵盖广泛的平台/供应商,我会尽量减少冗余的状态更改。至少如果你可以选择相对便宜地做到这一点。如果为此增加大量开销,则弊大于利。

对此意见不一的主要原因是检查冗余状态更改并非完全免费。如果驱动程序这样做,则开销适用于每个人。因此,编写良好的应用程序(不会进行不必要的状态更改)为使编写不佳的应用程序受益的优化付出了代价。你可以说这是非常不公平的。

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

于 2015-01-12T04:23:23.873 回答
0

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

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

于 2015-01-11T19:04:31.717 回答