不使用激活的Attrib会有影响吗?

Jul*_*let 6 c++ opengl glsl

我应该在切换到使用较少(或不同位置)属性的程序着色器时禁用着色器属性吗?

我使用glEnableVertexAttribArray()/ glDisableVertexAttribArray()启用和禁用这些属性.

是否有任何性能影响,或者它是否会带来一些错误,或者启用/禁用将比激活所有属性慢并让它们激活?

Ret*_*adi 6

OP很可能已经理解了第一部分,但是让我重申一些关于顶点属性的要点,以便为更有趣的部分设置基础.我假设所有顶点数据都来自缓冲区,而不是谈论glVertexAttrib3f()使用类似调用来为属性设置"常量"值的情况.

  • glEnableVertexAttribArray()glVertexAttribPointer()调用指定顶点属性被启用,并描述了GPU应该如何检索它们的值.这包括它们在内存中的位置,它们有多少组件,它们的类型,步幅等.我将在本答案的其余部分中将这些调用指定的收集状态称为"顶点属性状态".
  • 顶点属性状态不是着色器程序状态的一部分.它存在于顶点属性对象(VAO)中,以及其他一些相关状态.因此,绑定不同的程序不会改变顶点属性状态.仅绑定不同的VAO,或者当然进行上述调用之一.
  • 顶点属性被绑定到attribute/ in通过设置的位置,在顶点着色器变量in的变量.这指定了每个in变量的值应来自哪个顶点属性.位置值是程序状态的一部分.

基于此,当绑定不同的程序时,必须in正确设置变量的位置以引用所需的属性.只要相同的属性始终用于着色器,在构建着色器时只需执行一次.除此之外,着色器使用的所有属性都必须glEnableVertexAttribArray()通过绑定或包含状态的VAO 来启用.

现在,最后讨论问题的核心:如果启用了程序未使用的属性,会发生什么?

我相信启用未使用的属性是完全合法的.至少我从未在规范中看到任何其他说法.我刚刚检查过,仍然没有发现任何东西.因此,启用未使用的属性不会产生任何错误.

这会影响性能吗?简短的回答是它可能.让我们看看两个假设的硬件架构:

  • 架构A读取了顶点着色器代码中的顶点属性值.
  • 架构B具有固定的功能单元,用于读取顶点属性值.该固定功能单元由顶点属性状态控制,并将值写入片上存储器,其中顶点着色器实例拾取它们.

对于体系结构A,启用未使用的属性将完全没有效果.他们根本就不会被阅读.

对于体系结构B,固定功能单元可能会读取未使用的属性.顶点着色器最终不会使用它们,但它们仍然可以从主/视频存储器读入片上存储器.驱动程序可以通过检查当前着色器使用哪些属性来避免这种情况,并仅使用这些属性设置固定功能单元.缺点是每次绑定新着色器时都必须检查/更新固定功能单元的状态设置,否则这是不必要的.但它阻止从内存中读取未使用的属性.

更进一步,让我们说我们最终会从内存中读取未使用的属性.一般来说,这种伤害是否以及多少是不可能回答的.直观地说,如果属性是交错的,我希望它很重要,并且未使用的属性与使用的属性在同一个缓存行中.另一方面,如果读取未使用的属性会导致额外的缓存未命中,则至少会使用内存带宽并消耗功率.

总之,我不相信有一个明确而简单的答案.有可能启用未使用的属性根本不会受到伤害,或者很少.但无论如何我会亲自禁用它们.它有可能产生重大影响,而且很容易做到.特别是如果使用VAO,通常可以通过单个glBindVertexArray()调用设置整个顶点属性状态,因此启用/禁用所需的属性不需要额外的API调用.