浮点规则 (Direct3D 11)

Direct3D 11 支持多个浮点表示形式。 所有浮点计算都在 IEEE 754 32 位单精度浮点规则的定义的子集下运行。

32 位浮点规则

有两组规则:符合 IEEE-754 的规则,以及那些偏离标准的规则。

推崇的 IEEE-754 规则

这些规则中的一些是 IEEE-754 提供选择的单个选项。

  • 除以 0 产生 +/- INF,除了会导致 NaN 的 0/0 以外。
  • (+/-) 0 的 log 产生 -INF。 负值(-0 除外)的 log 产生 NaN。
  • 负数的倒数平方根 (rsq) 或平方根 (sqrt) 产生 NaN。 异常为 -0;sqrt(-0) 生成 -0,rsq(-0) 生成 -INF。
  • INF - INF = NaN
  • (+/-)INF / (+/-)INF = NaN
  • (+/-)INF * 0 = NaN
  • NaN(任何 OP)任何值 = NaN
  • 当任一或两个操作数为 NaN 时,EQ、GT、GE、LT 和 LE 的比较返回 FALSE
  • 比较忽略 0 的符号(因此 +0 等于 -0)。
  • 比较 NE 时,如果任一或两个操作数为 NaN,则返回 TRUE
  • 任何非 NaN 值与 +/- INF 的比较返回正确的结果。

IEEE-754 规则的偏差或其他要求

  • IEEE-754 要求浮点运算产生结果,该结果是最接近无限精确结果的可表示值,称为最近舍入。 Direct3D 11 定义了相同的要求:32 位浮点运算生成的结果与在无限精确结果的最后 0.5 个单位 (ULP) 以内。 这意味着,例如,允许硬件将结果截断为 32 位,而不是执行舍入到最接近的偶数,这将导致最多 0.5 ULP 的错误。此规则仅适用于加法、减法和乘法。

  • 不支持浮点异常、状态位或陷阱。

  • Denorm 在任何浮点数学运算的输入和输出上被刷新为符号保留的零。 对于任何不涉及数据操作的数据输入/输出或数据传输操作,均有例外。

  • 包含浮点值的状态(如 Viewport MinDepth/MaxDepth、BorderColor 值)可以作为非正规化数提供,并且在硬件使用它们之前可能会被刷新,也可能不会被刷新。

  • 最小值或最大值运算会刷新 denorm 以进行比较,但结果可能会或可能不会刷新 denorm。

  • 在运算中输入 NaN 始终在输出上产生 NaN。 但是,NaN 的确切位模式不需要保持不变(除非操作是原始移动指令——不修改数据)。

  • 在最小或最大运算中,如果只有一个操作数是 NaN,则返回另一个操作数作为结果(这与我们之前查看的比较规则相反)。 这是 IEEE 754R 规则。

    Direct3D 10 及更高版本中的算术规则不会区分“quiet”和“signaling”NaN 值(QNaN 与 SNaN)。 所有“NaN”值都以相同的方式进行处理。

  • 如果 min() 或 max() 的两个输入均为 NaN,则返回任何 NaN。

  • IEEE 754R 规则规定,min(-0,+0) == min(+0,-0) == -0, and max(-0,+0) == max(+0,-0) == +0,这体现了符号的保留。 这与带符号零的比较规则(如上所述)形成鲜明对比。 Direct3D 11 在此处建议 IEEE 754R 行为,但不强制实施;使用忽略符号的比较,允许将零进行比较的结果取决于参数的顺序。

  • x*1.0f 的结果始终是 x(除了 denorm 刷新)。

  • x/1.0f 的结果始终是 x(除了 denorm 刷新)。

  • x +/- 0.0f 的结果始终是 x(除了 denorm 刷新)。 但是 -0 + 0 = +0。

  • 融合运算(例如 mad、dp3)产生的结果与运算的未融合扩展的评估的最差的串行排序一样准确。 考虑容差时,最差可能顺序的定义并不是对给定融合运算的固定定义;它依赖于输入的特定值。 允许未融合扩展中的各个步骤出现 1 个 ULP 容差(或者,Direct3D 调用的命令具有比 1 个 ULP 更宽松的容差,则允许出现更宽松的容差)。

  • 融合操作遵循与非融合操作相同的 NaN 规则。

  • sqrt 和 rcp 具有 1 个 ULP 容差。 着色器倒数指令和倒数平方根指令 rcprsq 拥有各自的宽松精度要求。

  • 乘法和除法运算为 32 位浮点精度水平(乘法的精度为 0.5 ULP,倒数的精度为 1.0 ULP)。 如果直接实现 x/y,则结果的准确性必须大于或等于两步方法。

64 位(双精度)浮点规则

硬件和显示驱动程序(可选)支持双精度浮点。 若要指示支持,当使用 D3D11_FEATURE_DOUBLES 调用 ID3D11Device::CheckFeatureSupport 时,驱动程序将 D3D11_FEATURE_DATA_DOUBLES 的 DoublePrecisionFloatShaderOps 设置为 TRUE。 然后,驱动程序和硬件必须支持所有双精度浮点指令。

双精度指令遵循 IEEE 754R 行为要求。

双精度数据需要支持生成非标准化值(无刷新到零行为)。 同样地,指令不将非标准化数据读取为符号零,它们接受 denorm 值。

16 位浮点规则

Direct3D 11 还支持浮点数的 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) (非规范化数字)
  • 如果 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 位浮点数保留 denorm。

11 位和 10 位浮点规则

Direct3D 11 还支持 11 位和 10 位浮点格式。

格式:

  • 没有符号位
  • 5 位偏置指数 (e)
  • 6 位分数 (f) 表示 11 位格式,5 位分数 (f) 表示 10 位格式,在任一情况下都附加隐藏位。

float11/float10 值(v)遵循以下规则:

  • 如果 e == 31 和 f != 0,则 v 为 NaN
  • 如果 e == 31 和 f == 0,则 v = +infinity
  • 如果 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 位浮点数保留 denorm。
  • 任何会导致数字小于零的操作都限制为零。

Resources

纹理