GLSL除法与乘法

GLSL division vs multiplication

假设我有类似的东西:

float foo;

float bar = baz / foo;
float qux = quux / foo;

当我执行以下操作时会发生什么:

foo = 1./foo;
float bar = baz * foo;    //can i expect roughly the same number as with division?
floar qux = quux * foo;   //is it always going to be faster?

鉴于硬件 webgl 可以 运行 的广泛范围,我是否可以预期在编译时会发生这样的事情,还是像这样编写它总是更安全?

也很好奇

uniform float invFoo;
...
bar = baz * invFoo;
//instead of:
uniform float foo;
...
bar = baz / foo;

不太明白this:

// A stupid compiler might use these as written: a divide, then add.
vec4 result1 = (value / 2.0) + 1.0;
vec4 result2 = (value / 2.0) - 1.0;
vec4 result3 = (value / -2.0) + 1.0;

// There are most likely converted to a single MAD operation (per line).
vec4 result1 = (value * 0.5) + 1.0;
vec4 result2 = (value * 0.5) - 1.0;
vec4 result3 = (value * -0.5) + 1.0;

我不明白愚蠢的编译器在这种情况下做了什么。是否缺少这可以作为单个 MAD 指令完成,或者是否缺少除法可以表示为乘法(同时缺少 MAD)。

此外,将这样的东西分组但四处移动怎么样:

vec2 foo,bar;
float baz;

baz = 1./baz;
vec2 temp = vec2( foo.x , bar.x ) * baz; //move but do one mult?
foo.x = temp.x;
bar.x = temp.y;

can i expect roughly the same number as with division?

严格来说,没有:

$ cat a.cc
#include <iostream>

int main() {
    const float a = 1.40129846e-45f;
    const float b = a;

    std::cout << "b / a:       " << (b / a) << std::endl;
    std::cout << "b * (1 / a): " <<(b * (1.f / a)) << std::endl;

    return 0;
}
$ clang++ a.cc && ./a.out
b / a:       1
b * (1 / a): inf
$

然而,在现实生活中或多或少的例子中,乘法和除法可以得出接近的结果。其他任何事情都取决于您将使用结果的计算的稳定性。如果这些计算不稳定(即,如果任何参数发生轻微变化,则此类计算的结果会发生显着变化),则结果可能会有所不同。因此,您需要了解您使用的值,尤其是您获得的精度。 GLSL 浮点数并不总是 32 位 IEEE 浮点数,它们可能不太精确。

Is it missing that this can be done as a single MAD instruction, or is it missing that the division can be expressed as a multiplication (at the same time missing the MAD).

取决于特定编译器的特定怪癖,但可能是第二件事。