Правила с плавающей запятой

Direct3D поддерживает несколько представлений с плавающей запятой. Все вычисления с плавающей запятой выполняются в определенном подмножестве 32-битных правил с плавающей запятой одинарной точности IEEE 754.

32-разрядные правила с плавающей запятой

Существует два набора правил: тех, что соответствуют стандарту IEEE-754, и тех, что отклоняются от него.

Заслуженные правила IEEE-754

Некоторые из этих правил безальтернативны, если стандарт IEEE-754 предоставляет несколько вариантов.

  • При делении на ноль получается положительное или отрицательное бесконечное число, за исключением деления нуля на ноль, в результате которого получается не число.

  • Результатом логарифма положительного или отрицательного нуля является отрицательное бесконечное число.  

    Результатом логарифма отрицательного значения (отличного от отрицательного нуля) является не число.

  • Результатом извлечения обратного квадратного корня (rsq) или квадратного корня (sqrt) из отрицательного числа является не число.  

    Исключение — отрицательный ноль; результатом sqrt(-0) является -0, а результатом rsq(-0) — отрицательное бесконечное число.

  • Разностью двух бесконечных чисел является не число.

  • Отношением между положительным или отрицательным бесконечным числом и вторым таким же числом является не число.

  • (+/-) INF * 0 = NaN

  • Результатом любой операции между не числом и любым значением является не число.

  • Сравнения EQ, GT, GE, LT и LE, в которых один или оба операнда являются не числами, возвращают FALSE.

  • В сравнениях знак нуля игнорируется (то есть положительный ноль равен отрицательному).

  • Сравнение NE, в котором один или оба операнда являются не числами, возвращает TRUE.

  • Сравнение любого значения, не являющегося не числом, с положительным или отрицательным бесконечным числом возвращает верный результат.

Отклонения или дополнительные требования от правил 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, могут предоставляться как денормализованные значения, а также могут сбрасываться, прежде чем их использует оборудование.

  • Операции минимизации или максимизации сбрасывают денормализованные числа для сравнения, но результат в виде денормализованного числа может не быть сброшен.

  • Если входными данными для операции является не число, выходными данными обязательно будет не число. Но точный битовый шаблон не числа не обязательно должен оставаться неизменным (если только выполняемая операция не является инструкцией перемещения необработанных данных, при которой данные не изменяются.)

  • Операции минимизации или максимизации, в которых только один операнд является не числом, возвращают другой операнд в качестве результата (вопреки рассмотренным ранее правилам сравнения). Это правило IEEE 754R.

    Согласно спецификации IEEE-754R для операций минимизации и максимизации с плавающей точкой, если одна из частей входных данных для минимизации или максимизации является значением в виде несигнального не числа (QNaN), результатом операции будет второй параметр. Пример:

    min(x,QNaN) == min(QNaN,x) == x (same for max)
    

    В одной из редакций спецификации IEEE-754R было принято другое поведение для минимального и максимального значений, если одна часть входных данных является значением в виде "сигнального" не числа (SNaN), а вторая — значением QNaN.

    min(x,SNaN) == min(SNaN,x) == QNaN (same for max)
    
    

    Как правило, Direct3D следует стандартам арифметических действий: IEEE-754 и IEEE-754R. Но в этом случае происходит отклонение.

    Арифметические правила в Direct3D 10 и более поздних версиях не проводят различия между значениями в виде несигнальных и сигнальных не чисел (QNaN и SNaN). Все значения в виде не чисел обрабатываются одинаково. В случае с минимизацией и максимизацией поведение Direct3D относительно любого значения в виде не числа аналогично обработке QNaN по определению IEEE-754R. (Для полноты: если обе части входных данных являются не числами, возвращается любое значение в виде не числа.)

  • Еще одно правило 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.

  • Совмещенные операции (например, mad, dp3) выдают не менее точные результаты, чем худшее возможное последовательное упорядочение вычисления несовмещенного расширения операции. Определение худшего возможного упорядочения, в целях допуска, не является фиксированным определением для данной совмещенной операции. Оно зависит от конкретных значений входных данных. Для каждого отдельного этапа несовмещенного расширения разрешен допуск в 1 ULP (для любых инструкций, вызываемых Direct3D с допуском больше 1 ULP, разрешен больший допуск).

  • Совмещенные операции следуют тем же правилам относительно не чисел, что и несовмещенные операции.

  • Допуск для sqrt и rcp составляет 1 ULP. Для инструкций обратного числа шейдера и обратного квадратного корня, rcp и rsq, действует особое требование со сниженной точностью.

  • Умножение и деление выполняются на 32-разрядном уровне точности с плавающей точкой (точность до 0,5 ULP при умножении, 1 ULP при получении обратного числа). При прямой реализации x/y точность результатов должна быть выше, чем при двухшаговом методе, или идентична ему.

64-разрядные правила с плавающей запятой (двойная точность)

Драйверы оборудования и дисплея могут поддерживать операции с плавающей точкой двойной точности. Чтобы указать поддержку, при вызове ID3D11Device::CheckFeatureSupport с D3D11_FEATURE_DOUBLES драйвер устанавливает для параметра DoublePrecisionFloatShaderOpsD3D11_FEATURE_DATA_DOUBLES значение TRUE. В этом случае драйвер и оборудование должны поддерживать все инструкции с плавающей точкой двойной точности.

Инструкции двойной точности соответствуют требованиям к поведению IEEE 754R.

Для данных двойной точности (без сброса до нуля) требуется поддержка генерирования денормализованных значений. Подобным образом, инструкции не считывают денормализованные данные как ноль со знаком, а учитывают денормализованное значение.

16-разрядные правила с плавающей запятой

Direct3D также поддерживает 16-разрядные представления чисел с плавающей точкой.

Формат:

  • 1 бит знака (s) в положении старшего разряда;
  • 5 битов смещенного порядка (e);
  • 10 дробных битов (f) с дополнительным скрытым битом.

Значение float16 (v) соответствует следующим правилам:

  • если e == 31 и f != 0, то v — не число независимо от s;
  • если e == 31 и f == 0, то v = (-1)s*infinity (бесконечность со знаком)
  • Если значение e находится в диапазоне от 0 до 31, то v = (-1)s*2(e-15)*(1.f)
  • если e == 0 и f != 0, то v = (-1)s*2(e-14)*(0.f) (денормализованные числа)
  • если e == 0 и f == 0, то v = (-1)s*0 (ноль со знаком)

32-разрядные правила с плавающей точкой также действуют для 16-разрядных чисел с плавающей точкой с корректировкой для описанной ранее структуры битов. Но есть следующие исключения:

  • Точность. Несовмещенные операции над 16-разрядными числами с плавающей точкой выдают результат в виде представляемого значения, ближайшего к бесконечно точному результату (согласно IEEE-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 — не число;
  • если 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-разрядные числа с плавающей тачкой сохраняют денормализованные значения.
  • Любая операция, в результате которой получается число меньше нуля, прикрепляется к нулю.

Приложения

Ресурсы

Текстуры