【问题标题】:Using a single texture image unit with multiple sampler uniforms使用具有多个采样器制服的单个纹理图像单元
【发布时间】:2013-10-20 02:11:26
【问题描述】:

我正在编写一个批处理系统来跟踪当前绑定的纹理,以避免不必要的glBindTexture() 调用。我不确定我是否需要跟踪特定批次已经使用了哪些纹理,以便如果一个纹理被使用两次,它将绑定到另一个需要它的第二个采样器的 TIU。

OpenGL 应用程序可以为同一着色器阶段内的多个采样器使用相同的纹理图像单元吗?不同着色器阶段的采样器呢?例如:

片段着色器:

...
uniform sampler2D samp1;
uniform sampler2D samp2;

void main() { ... }

主程序:

...
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex_id);
glUniform1i(samp1_location, 0);
glUniform1i(samp2_location, 0);
...

我看不出这有什么不可行的原因,但是如果着色器程序还包含这样的顶点着色器呢:

顶点着色器:

...
uniform sampler2D samp1;

void main() { ... }

在这种情况下,OpenGL 应该将samp1 的两个实例视为引用相同的位置。因此,在顶点着色器和片段着色器中使用了相同的纹理单元。我已经读过在两个不同的着色器阶段使用相同的纹理对GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 的影响是双重的,但这似乎与此相矛盾。

在对我的硬件 (HD 6870) 的快速测试中,以下所有场景都按预期工作:

  • 1 TIU 用于同一着色器阶段的 2 个采样器制服
  • 1 个 TIU 用于 1 个采样器制服,用于 2 个着色器阶段
  • 1 TIU 用于 2 件采样制服,每件制服都出现在不同的阶段。

但是,我不知道这是否是我对所有硬件/驱动程序的预期行为,或者是否会影响性能。

【问题讨论】:

  • 顺便问一下,您如何确定使用的纹理图像单元的数量?作为实现要求,您基本上每个阶段获得 16 个纹理图像单元,并且您可以在 GL3.2+(有 3 个阶段)中绑定多达 16*3 = 48 个独特的纹理。 GL4.x 有 5 个阶段,因此最多放弃 16*5 = 80。您应该将每个阶段使用的 TIU 数相加以获得准确的总数。

标签: opengl glsl opengl-3


【解决方案1】:

希望这会消除您的一些困惑,我使用的是旧版本的规范。为简单起见,较新的版本有两个额外的阶段(镶嵌控制/评估),因此讨论会稍微复杂一些。

OpenGL 3.3 (Core Profile) - 2.11。顶点着色器 - 第 80 页

纹理访问

着色器能够查找纹理贴图。顶点、几何或片段着色器可用的纹理图像单元的最大数量分别是与实现相关的常量GL_MAX_VERTEX_TEXTURE_IMAGE_UNITSGL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITSGL_MAX_TEXTURE_IMAGE_UNITS 的值。顶点着色器、几何着色器和片段着色器组合使用的值不能超过GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 纹理图像单元的值。如果多个顶点着色器、几何着色器和片段处理阶段访问同一个纹理图像单元,则每个此类访问单独计入GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 限制。

该限制是根据每个阶段中使用的唯一采样器的数量施加的。就使用确定而言,具有不同名称但引用相同纹理单元的两个采样器制服实际上是相同的。用法是指做类似texture (sampler, coords) 的事情,如果这还不明显的话。仅仅声明一个采样器并为其分配一个值不会让您更接近实现定义的限制,您实际上必须在运行时使用采样器和如果它与同一阶段中另一个使用的采样器具有相同的值,则不计入。

至于多次使用同一个纹理对象,不,这不是GL_MAX_..._IMAGE_UNITS 限制的全部意义所在。如果需要,您可以将相同的纹理绑定到所有 48 个纹理单元(GL3.3 中的最低实现要求 - 这实际上要求每个阶段至少有 16 个纹理),此限制是指您使用的不同采样器的数量(再次,请参阅以上)在着色器阶段。如果您需要将同一个纹理绑定到多个纹理单元,您可能需要将其绑定到最近邻过滤一次,而另一次使用线性或不同的包裹状态。

如果您想了解所有驱动程序/硬件的预期行为,请始终查阅正式的 OpenGL 规范。我为您挑选了相关信息,但是如果您将来学习如何通过这些信息搜索重要的详细信息,将会对您有所帮助。自 OpenGL 1.0 以来的所有规范均可从以下地址免费获得:http://www.opengl.org/registry/

【讨论】:

  • 感谢您的出色回复!我的印象是传递给 glActiveTexture 的枚举(因此也是采样器统一值)直接对应于 TIU,这引起了我的困惑。所以澄清一下,在多个着色器阶段中通过相同的绑定点(glUniform 值)使用纹理是非常好的,只要遵守每个阶段和组合的限制,因为驱动程序实际上在幕后使用了 2 个不同的 TIU ?
  • 其他一切都是正确的。只要您尊重 TIU 的每阶段限制和总体限制,您就可以继续前进。如前所述,GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 的默认实现最小值刚好足够大,以确保每个阶段都可以拥有自己的 16 个独特纹理集。在多个阶段重复使用相同的纹理图像单元并没有错,但它会在运行时计入组合限制。
猜你喜欢
  • 2018-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-06
  • 2013-09-02
  • 1970-01-01
  • 2017-12-27
相关资源
最近更新 更多