共用方式為


浮點規則

Direct3D 支援數個浮點表示法。 所有浮點運算都會在 IEEE 754 32 位單精度浮點規則的已定義子集下運作。

32 位浮點規則

有兩組規則:符合 IEEE-754 的規則,以及偏離標準的規則。

恪守 IEEE-754 規則

其中有些規則是 IEEE-754 提供選擇的單一選項。

  • 用 0 除會產生 +/- INF,但 0 除以 0 將導致 NaN。

  • (+/-) 0 的記錄會產生 -INF。  

    對負值(-0除外)取對數會產生 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)。

  • 當任一或兩個操作數為 NaN 時,比較 NE 會傳回 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的誤差。

  • 不支援浮點數例外、狀態位元或陷阱。

  • 非正規化數在任何浮點數學運算的輸入和輸出時,會被轉換為保留符號的零。 不會操作數據的任何 I/O 或數據移動作業都屬於例外情況。

  • 包含浮點值的狀態,例如 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)
    

    當一個輸入是「訊號型」SNaN 值或 QNaN 值時,IEEE-754R 規格的修訂在 min 和 max 函數上的行為會有所不同:

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

    一般而言,Direct3D 遵循算術的標準:IEEE-754 和 IEEE-754R。 但在這種情況下,我們出現了偏差。

    Direct3D 10 和之後版本中的算術規則不區分靜態 NaN 值與信號 NaN 值(QNaN 與 SNaN)。 所有 NaN 值都會以相同的方式處理。 在 min 和 max 的情況下,任何 NaN 值的 Direct3D 行為就像在 IEEE-754R 定義中處理 QNaN 的方式一樣。 (為了完整性 - 如果這兩個輸入都是 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。

  • 融合運算(如 mad、dp3)所產生的結果,其精確度不會低於評估未融合運算擴展的最差序列順序。 針對容錯目的,最差可能排序的定義不是指定融合運算的固定定義;這取決於輸入的特定值。 未融合擴展中的個別步驟均允許 1 個 ULP 容差(或對於 Direct3D 所呼叫的任何指令,若具有比 1 ULP 更寬鬆的容差,則允許更寬鬆的容差)。

  • Fused 作業遵循與非融合作業相同的 NaN 規則。

  • sqrt 和 rcp 有 1 個 ULP 容錯。 著色器倒數和倒數平方根指令,rcprsq,有其自己的寬鬆精度要求。

  • 乘法和除法各自在 32 位浮點數精確度層級運行(乘法的精確度為 0.5 ULP,倒數運算的精確度為 1.0 ULP)。 如果直接實作 x/y,結果必須大於或等於雙步驟方法的精確度。

64 位 (雙精確度) 浮點規則

硬體和顯示驅動程式選擇性地支援雙精確度浮點數。 若要指出支援,當您使用 D3D11_FEATURE_DOUBLES呼叫 ID3D11Device::CheckFeatureSupport 時,驅動程式會將 DoublePrecisionFloatShaderOpsD3D11_FEATURE_DATA_DOUBLES 設為 TRUE。 驅動程式和硬體然後必須支援所有雙精度浮點指令。

雙精確度指示遵循 IEEE 754R 行為需求。

雙精度數據需要生成反正規化值的支持(不包括歸零行為)。 同樣地,指令不會將反規化數據解讀為有符號的零,而是會保留其反規化值。

16 位浮點規則

Direct3D 也支援浮點數的 16 位表示法。

格式:

  • MSB 位位置中的 1 個符號位元
  • 5 位偏差指數 (e)
  • 10 位元的分數部分(f),以及一個額外的隱藏位元

float16 值 (v) 遵循下列規則:

  • 如果 e == 31 和 f != 0,則無論 s 為何,v 都是 NaN
  • 如果 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)
  • 11 位格式的分數部分(f)有 6 位,10 位格式的分數部分(f)有 5 位,這兩種情況下,都有一個額外的隱藏位。

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 位浮點數會保留非規範化數。
  • 任何會導致數值小於零的運算都會限制為零。

附錄

資源

紋理