在片段着色器中计算纹理坐标时,为什么访问纹理要慢得多?


11

在GLSL中使用纹理时,最好在顶点着色器中计算最终的纹理坐标,然后使用varyings 将其移交给片段着色器。在y坐标中进行简单翻转的示例:

// Vertex shader
attribute vec2 texture;
varying highp vec2 texCoord;
// ...
void main() {
    texCoord = vec2(texture.x, 1.0-texture.y);
    // ...
}

// Fragment shader
varying highp vec2 textureCoordinates;
uniform sampler2D tex;
// ...
void main() {
    highp vec4 texColor = texture2D(tex, texCoord);
    // ...
}

如果vec2(0.5)在片段着色器中执行y坐标的翻转或什至更简单的操作(如添加到纹理坐标),则纹理访问会慢得多。为什么?


需要注意的是,例如,使用它们的加权总和来混合两个纹理在时间上要便宜得多,并且还需要针对每个像素完成,因此纹理坐标本身的计算似乎并不那么昂贵。


1
我的猜测是,如果UV坐标是用VS计算的,则纹理单元可以在PS启动时开始预取它们。如果它们是在PS中计算的,则纹理单元必须首先等待。
RichieSams 2015年

2
首先,这被称为“相关纹理读取”,以防它有助于您的搜索。
艾伦·沃尔夫

您是否有一些测量结果显示出性能差异?我实际上并不期望会有太大的区别。纹理获取延迟应该会淹没一些ALU操作。顺便说一句,从属纹理读取是存在两个(或更多)纹理读取的位置,第二个的坐标取决于第一个的输出。由于两个纹理读取之间要求严格的排序,因此速度较慢。
内森·里德

好吧,在片段着色器中进行的任何操作都将比在顶点着色器中进行的操作更为昂贵。每个三角形需要调用顶点着色器3次,但是取决于片段的屏幕大小,它可能需要更多数量级的片段着色器。
glampert

@NathanReed我认为您不必将“依赖纹理读取”限制为仅来自先前纹理访问的内容。我可能还会包括在碎片着色器中计算出的所有坐标,这与仅根据顶点属性的线性(很好,带有透视图的双曲线)插值可以确定的坐标相反。
西蒙F

Answers:


11

您所说的在移动开发社区中通常被称为“依赖纹理读取”。它是某些硬件的实现细节,因此,它是否真正影响性能实际上取决于GPU。通常,您会在Apple硬件中看到PowerVR GPU带来的东西,因为ImaginationApple都明确提到了它。文档。如果我没记错的话,问题基本上出在GPU中的硬件上,它将在片段着色器甚至开始运行之前就开始预取纹理,从而可以更好地隐藏延迟。我链接的文档提到它不再是Series6硬件上的问题,因此至少在较新的Apple硬件上,您不必担心。老实说,我不确定其他移动GPU,因为这不是我的专业领域。您应该尝试并查阅其文档以确保确定。

如果您决定在此问题上进行一些Google搜索,请注意,您可能会发现一些较旧的材料正在谈论较旧的台式机硬件上的依赖纹理获取。在早期的像素/片段着色器基础上,术语“从属纹理获取”是指使用依赖于先前纹理获取的UV地址。经典示例是凹凸贴图环境地图渲染,您想在其中使用基于法线贴图的反射矢量来采样环境贴图。在这种较旧的硬件上,存在一些重大的性能影响,而且我认为某些非常旧的GPU甚至不支持它。使用现代的GPU,硬件和着色器ISA变得更加通用,因此性能情况也更加复杂。


顺便说一句:我在iPad 3上体验到了。所以也许这实际上是特定于硬件的。
Nero
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.