在OpenGL中绑定纹理

15

所以我正在分批渲染我的场景,以尝试最小化状态更改。 由于我的着色器通常需要多个纹理,因此我同时将其中几个绑定到不同的纹理单元。其中一些纹理在多个批次中使用,因此甚至可以保持绑定。

现在我的问题是,在一个批次期间是否可以重新绑定我需要的所有纹理,即使其中一些可能已经绑定了?还是应该检查已绑定的纹理,并仅绑定新的纹理? glBindTexture 有多昂贵?我正在使用着色器,将未使用的纹理绑定到着色器不会采样的纹理单元,这会有影响吗?还是应该解除绑定它们?

我主要问的是“如何使其快速”,而不是“如何做到”。

编辑:如果我提供代码,是否有帮助?

4个回答

13

GPU编程的圣经规则是:你和GPU交流越少,她就越爱你。 glBindTexture函数比在CPU上进行单一条件检查要昂贵得多,因此对于频繁的状态更改,我认为你应该看看是否需要将新的纹理索引传输到GPU。


2
显示列表已经被弃用了,所以最好根本不要使用它们。 - Thomas
1
glBindTexture很,就像任何状态改变(glEnable等)一样。在您的代码中尽可能避免它们。如果还没有被说服,请通过gDEBbugger运行程序并查看其结果。 - Calvin1602
重新绑定所有纹理的优点在于我不需要更改着色器uniforms(例如,我始终可以依赖于“metal_2”在texture_2中)。我想我必须对其进行分析,我不确定uniform sets与glBindTexture的性能差异。 - Hannesh

5
答案很难,因为任何强大的GL实现都应该将绑定已绑定纹理作为优化的无操作。您应该尝试进行基准测试,以查看是否有条件会产生差异。
同样适用于纹理单元中未使用的纹理,因为GL实现确实知道最终使用了哪些纹理单元,所以具有未使用的纹理单元不会影响性能(作为优化)。

3
不要指望GL实现会进行这种优化。 - joeld
这是一个合理的假设。现在的GPU通常有几组状态,驱动程序会进行调整(请参阅Tom Forsynth的博客中的一篇长文)。这意味着即使更改纹理也不一定会停顿(尽管这是最坏情况下的假设,但仍然应该这样做)。这种资源管理方式显然只能在实现跟踪绑定内容并且不重复应用更改时才能完成。这并不能保证任何事情,但这是一个现实的假设。 - Damon
另外,当重新绑定对象时,存在缓存未命中问题,这是nVidia指出其无需绑定图形扩展(“一个新的瓶颈”)的主要原因。据报道,由于驱动程序必须获取状态以检查每个绑定的内容以及它是否有效等等,因此会发生很多缓存未命中。因此,即使在驱动程序中进行了优化,避免不必要的绑定仍然不是一个坏主意。 - Damon
有人知道OpenTK是否默认执行此操作吗? - Krythic

0

跟踪您绑定的纹理(不要使用 glGet(GL_TEXTURE_BINDING_2D) ),只有在更改时才重新绑定。一些驱动程序会为您执行此操作,而另一些则不会。

如果您事先知道要针对哪个平台,那么很容易进行简单的基准测试,以查看它会产生多大的差异。

您还可以按照使用的纹理对批次进行排序,以最小化纹理更改。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接