Правила с плавающей запятой
Direct3D поддерживает несколько представлений с плавающей запятой. Все вычисления с плавающей запятой работают подмножеством правил IEEE 754 32-разрядной точности с плавающей запятой.
32-разрядные правила с плавающей запятой
Существует два набора правил: те, которые соответствуют IEEE-754, и те, которые отклоняются от стандарта.
Правила IEEE-754
Некоторые из этих правил являются одним вариантом, где IEEE-754 предлагает варианты выбора.
Деление на 0 производит +/-INF, за исключением 0/0, что приводит к naN.
Log of (+/-) 0 создает -INF.
журнал отрицательного значения (кроме -0) создает NaN.
Обратный квадратный корень (rsq) или квадратный корень (sqrt) отрицательного числа производит NaN.
Исключение равно -0; sqrt(-0) производит -0, а rsq(-0) производит -INF.
INF - INF = NaN
(+/-) INF / (+/-)INF = NaN
(+/-) INF * 0 = NaN
NaN (any OP) any-value = NaN
Сравнения EQ, GT, GE, LT и LE, если оба операнда — NaN возвращает FALSE.
Сравнения игнорируют знак 0 (поэтому +0 равно -0).
Сравнение NE, если оба операнда — NaN возвращает ЗНАЧЕНИЕ TRUE.
Сравнение любого значения, отличного от NaN, с +/-INF, возвращает правильный результат.
Отклонения или дополнительные требования к правилам IEEE-754
IEEE-754 требует операций с плавающей запятой для получения результата, который является ближайшим представляемым значением к бесконечно точному результату, известному как округление до ближайшего.
Direct3D 11 и вверх определяют то же требование, что и IEEE-754: 32-разрядные операции с плавающей запятой создают результат, который находится в пределах 0,5 единицы последней точки (ULP) бесконечно точного результата. Это означает, что, например, оборудование может усечь результаты до 32-разрядного, а не выполнять округление до ближайшего, так как это приведет к ошибке не более 0,5 ULP. Это правило применяется только к добавлению, вычитании и умножению.
Более ранние версии Direct3D определяют более слабое требование, чем IEEE-754: 32-разрядные операции с плавающей запятой создают результат, который находится в пределах одного единицы последнего места (1 ULP) бесконечно точного результата. Это означает, что, например, оборудование может усечь результаты до 32-разрядной, а не выполнять округление до ближайшего, так как это приведет к ошибке не более одного ULP.
Нет поддержки исключений с плавающей запятой, битов состояния или ловушек.
Денормы очищаются до знака, сохраненного нулевой на входных и выходных данных любой математической операции с плавающей запятой. Исключения создаются для любой операции ввода-вывода или перемещения данных, которая не управляет данными.
Состояния, содержащие значения с плавающей запятой, такие как значения Viewport MinDepth/MaxDepth или BorderColor, могут быть предоставлены как значения денорма и могут быть удалены до их использования оборудованием.
Минимальное или максимальное количество операций смыть денормы для сравнения, но результат может или не быть денормирован.
Входные данные NaN для операции всегда создают naN для выходных данных. Но точный битовый шаблон NaN не требуется для того, чтобы оставаться неизменным (если операция не является необработанной инструкцией перемещения , которая не изменяет данные.)
Минимальное или максимальное количество операций, для которых только один операнду является NaN, возвращает другой операнд в результате (вопреки правилам сравнения мы рассмотрели раньше). Это правило IEEE 754R.
Спецификация IEEE-754R для операций с плавающей запятой min и max указывает, что если одно из входных данных в минимальное или максимальное значение является тихим значением QNaN, результатом операции является другой параметр. Например:
min(x,QNaN) == min(QNaN,x) == x (same for max)
Редакция спецификации IEEE-754R приняла другое поведение для min и max, если одно входное значение является "сигнальным" значением SNaN и значением QNaN:
min(x,SNaN) == min(SNaN,x) == QNaN (same for max)
Как правило, Direct3D соответствует стандартам арифметики: IEEE-754 и IEEE-754R. Но в этом случае у нас есть отклонение.
Арифметические правила в Direct3D 10 и более поздних версиях не делают никаких различий между тихими и сигнальными значениями NaN (QNaN и SNaN). Все значения NaN обрабатываются одинаково. В случае min и max поведение Direct3D для любого значения NaN похоже на то, как QNaN обрабатывается в определении IEEE-754R. (Для полноты — если оба входных данных являются NaN, возвращается любое значение NaN.)
Другое правило IEEE 754R заключается в том, что min(-0,+0) == min(+0,-0) == -0 и max(-0,+0) == max(+0,-0) == +0, которая учитывает знак, в отличие от правил сравнения для подписанного нуля (как мы видели ранее). Direct3D рекомендует здесь поведение IEEE 754R, но не применяет его; Результат сравнения нулей может зависеть от порядка параметров, используя сравнение, которое игнорирует знаки.
x*1.0f всегда приводит к x (за исключением денормированных).
x/1.0f всегда приводит к x (за исключением денорма с очисткой).
x +/- 0.0f всегда приводит к x (за исключением денорма с очисткой). Но -0 + 0 = +0.
Спутанные операции (такие как безумные, dp3) дают результаты, которые не менее точны, чем худшее возможное последовательное упорядочивание оценки непроверенного расширения операции. Определение наихудшего возможного упорядочивания в целях терпимости не является фиксированным определением для данной операции сплавленной операции; он зависит от конкретных значений входных данных. Отдельные шаги в неисправном расширении допускаются каждый из 1 допустимых разрешений ULP (или для любых инструкций Direct3D вызовы с более неоплачиваемой терпимостью, чем 1 ULP, тем более слабая терпимость разрешена).
Неисплавленные операции соответствуют тем же правилам NaN, что и неисплавленные операции.
sqrt и rcp имеют 1 отказоустойчивость ULP. Шейдер взаимной и взаимной квадратной корневой инструкции, rcp и rsq имеют свое собственное отдельное расслабленное требование точности.
Умножьте и разделите каждую операцию на 32-разрядном уровне точности с плавающей запятой (точность до 0,5 ULP для умножения, 1,0 ULP для взаимной точности). Если x/y реализован напрямую, результаты должны иметь большую или равную точность, чем двухфакторный метод.
64-разрядные правила с плавающей запятой (двойная точность)
Аппаратные и отображаемые драйверы также поддерживают двойную точность с плавающей запятой. Чтобы указать поддержку, при вызове ID3D11Device::CheckFeatureSupport с D3D11_FEATURE_DOUBLES драйвер задает значение DoublePrecisionFloatShaderOps D3D11_FEATURE_DATA_DOUBLES значение TRUE. Затем драйвер и оборудование должны поддерживать все инструкции с плавающей запятой двойной точности.
Инструкции по двойной точности соответствуют требованиям к поведению IEEE 754R.
Поддержка создания денормализованных значений требуется для данных двойной точности (без поведения очистки до нуля). Аналогичным образом инструкции не считывают денормализованные данные как подписанный ноль, они учитывают значение денорма.
16-разрядные правила с плавающей запятой
Direct3D также поддерживает 16-разрядные представления чисел с плавающей запятой.
Формат:
- 1 бит знака (s)в позиции бита MSB
- 5 бит предвзятой экспоненты (e)
- 10 бит дроби (f), с дополнительным скрытым битом
Значение float16 (v) следует следующим правилам:
- если e == 31 и f != 0, то v — NaN независимо от s
- если e == 31 и f == 0, то v = (-1)s*бесконечность (подписанный бесконечность)
- значение e от 0 до 31, то v = (-1)s*2(e-15)*(1.f)
- если e == 0 и f != 0, то v = (-1)s*2(e-14)*(0.f) (денормализованные числа)
- if e == 0 и f == 0, а затем v = (-1)s*0 (подписанный ноль)
32-разрядные правила с плавающей запятой также содержат 16-разрядные числа с плавающей запятой, скорректированные для битового макета, описанного ранее. Ниже приведены исключения:
- Точность. Неисправные операции с 16-разрядными числами с плавающей запятой создают результат, который является ближайшим реплицируемым значением к бесконечно точному результату (округляется до ближайшего, на 754, применяется к 16-разрядным значениям). 32-разрядные правила с плавающей запятой соответствуют 1 допустимости ULP, 16-разрядные правила с плавающей запятой соответствуют 0,5 ULP для неисправных операций и 0,6 ULP для операций с плавающей запятой.
- 16-разрядные числа с плавающей запятой сохраняют денормы.
11-разрядные и 10-разрядные правила с плавающей запятой
Direct3D также поддерживает 11-разрядные и 10-разрядные форматы с плавающей запятой.
Формат:
- Нет бита знака
- 5 бит предвзятой экспоненты (e)
- 6 бит дроби (f) для 11-разрядного формата, 5 бит дроби (f) для 10-разрядного формата с дополнительным скрытым битом в любом случае.
Значение float11/float10 (v) соответствует следующим правилам:
- если e == 31 и f != 0, то v — NaN
- если e == 31 и f == 0, то v = +бесконечность
- значение e от 0 до 31, то v = 2(e-15)*(1.f)
- если e == 0 и f != 0, то v = *2(e-14)*(0.f) (денормализованные числа)
- если e == 0 и f == 0, то v = 0 (ноль)
32-разрядные правила с плавающей запятой также содержат 11-разрядные и 10-разрядные числа с плавающей запятой, скорректированные для битового макета, описанного ранее. Исключения:
- Точность: 32-разрядные правила с плавающей запятой соответствуют 0,5 ULP.
- 10/11-разрядные числа с плавающей запятой сохраняют денормы.
- Любая операция, которая приведет к тому, что число меньше нуля, зажато к нулю.
Связанные темы