Я пытаюсь реализовать эмулированную двойную точность в GLSL, и я наблюдаю странную разницу в поведении, приводящую к незначительным ошибкам с плавающей запятой в GLSL.
Рассмотрим следующий фрагментный шейдер, записывающий в 4-плавающую текстуру для вывода на печать.
layout (location = 0) out vec4 Output
uniform float s;
void main()
{
float a = 0.1f;
float b = s;
const float split = 8193.0; // = 2^13 + 1
float ca = split * a;
float cb = split * b;
float v1a = ca - (ca - a);
float v1b = cb - (cb - b);
Output = vec4(a,b,v1a,v1b);
}
Это вывод, который я наблюдаю
GLSL выход с униформой:
a = 0.1 0x3dcccccd
b = 2.86129e-06 0x36400497
v1a = 0.0999756 0x3dccc000
v1b = 2.86129e-06 0x36400497
Теперь, с заданными значениями b1
и b2
в качестве входных данных, значение v2b
не имеет ожидаемого результата. Или, по крайней мере, он не имеет такой же результат, как на процессоре (как видно здесь ):
C ++ вывод:
a = 0.100000 0x3dcccccd
b = 0.000003 0x36400497
v1a = 0.099976 0x3dccc000
v1b = 0.000003 0x36400000
Обратите внимание на расхождение для значения v1b
(0x36400497
против 0x36400000
).
Поэтому, чтобы выяснить, что происходит (и кто был прав), я попытался повторить вычисления в GLSL, заменив равномерное значение константой, используя слегка модифицированный шейдер, где я заменил унифицированное значение на его значение. .
layout (location = 0) out vec4 Output
void main()
{
float a = 0.1f;
float b = uintBitsToFloat(0x36400497u);
const float split = 8193.0; // = 2^13 + 1
float ca = split * a;
float cb = split * b;
float v1a = ca - (ca - a);
float v1b = cb - (cb - b);
Output = vec4(a,b,v1a,v1b);
}
На этот раз я получаю тот же вывод, что и версия C ++ того же вычисления.
GLSL-вывод с константами:
a = 0.1 0x3dcccccd
b = 2.86129e-06 0x36400497
v1a = 0.0999756 0x3dccc000
v1b = 2.86102e-06 0x36400000
Мой вопрос: что заставляет вычисления с плавающей запятой вести себя по-разному между однородной переменной и константой? Это какая-то закулисная оптимизация компилятора?
Вот строки моего поставщика OpenGL от Intel GPU моего ноутбука, но я также наблюдал такое же поведение на карте nVidia.
Renderer : Intel(R) HD Graphics 520
Vendor : Intel
OpenGL : 4.5.0 - Build 23.20.16.4973
GLSL : 4.50 - Build 23.20.16.4973