10

所以我在翻阅橙皮书(第 3 版)时偶然发现了第 9 章中关于不变限定符的一段话。它说:

invariant限定符指示编译器并链接到忽略与输出计算不直接相关的表达式和函数。

这段代码出现在两个类似的代码片段之后:

uniform mat4 MVPmatrix;
// ...

in vec4 MCVertex;
// ...

a(); // does not modify gl_Position, MVP or MCVertex

// ...
// Transform vertex to clip space
gl_Position = MVP * MCVertex;

uniform mat4 MVPmatrix;
// ...

invariant gl_Position;
in vec4 MCVertex;
// ...

a(); // does not modify gl_Position, MVP or MCVertex

// ...
// Transform vertex to clip space
gl_Position = MVP * MCVertex;

这本书接着说:

无论什么不相关的函数或表达式链接到着色器,第一种情况可能会或可能不会以完全相同的方式计算转换后的位置。如果使用多通道算法多次渲染相同的几何图形,这可能会导致渲染问题。

这让我很困惑。如果a()绝不影响计算变换位置所涉及的变量,那么计算将如何变化?(以及如何添加invariant帮助呢?)。参考第一句话,“忽略不相关的功能”到底是什么意思?他们只是没有被处决吗?

4

2 回答 2

12

的目的invariant是确保您正在执行的计算将始终产生相同的结果,无论着色器优化器将对着色器做什么(特别是跨多个着色器编译)。

我发现橙皮书的措辞很差(正如您所指出的那样具有误导性)。GLSL 规范(语言 1.2)第 4.6 节更加清晰:

在本节中,方差是指在不同程序中从同一个表达式得到不同值的可能性。例如,假设两个顶点着色器,在不同的程序中,每个设置 gl_Position 在两个着色器中具有相同的表达式,并且当两个着色器运行时该表达式的输入值是相同的。由于两个着色器的独立编译,有可能在两个着色器运行时分配给 gl_Position 的值并不完全相同。在此示例中,这可能会导致多通道算法中的几何对齐问题。一般来说,着色器之间的这种差异是允许的。当特定输出变量不存在这种方差时,该变量称为不变。

它继续解释说,invariant预选赛让你保证避免这个问题。

于 2013-09-25T11:24:43.300 回答
4

invariant关键字是,(简而言之,与 Bahbar 更详细的答案相反)更多关于可能出现在多个几何通道中的非常细微的计算差异。

这是一个例子:你在屏幕上画了一个任意的、奇怪的(为了让它更难)三角形。光栅化器获取归一化的顶点并计算它占据的所有片段,然后在其上运行片段着色器。现在,假设您想在其上精确地绘制另一个三角形,但 3 小时后,当您的 PC 被淹没时,温度下降,同时您正在吃午饭。然后重新编译着色器,然后...

所有这些都可能影响光栅化器。着色器优化可能会启动并对输出进行微小的更改。虽然在技术上仍然是正确的,但结果不一定与第一个三角形完全相同,“问题”将是第一个三角形留下的一些像素。

invariant确保采取可能较慢的方法。请注意,我不是驱动程序架构师,但总的来说,这可能意味着一些额外的状态重置、清理或有时状态堆栈推送/弹出。只有这样,你才剩下“干净”的计算状态,只要你的硬件没问题,结果应该是完全一样的。

于 2013-09-25T12:57:11.060 回答