Share via


資料類型轉換

下列各節將說明 Direct3D 如何處理資料類型之間的轉換。

資料類型術語

接下來將使用下方提供的這組詞彙來描述各種格式轉換的特性。

詞彙 定義
SNORM 帶正號的正規化整數,代表 n 位元 2 的補數,最大值為 1.0f (例如,5 位元值 01111 會對應至 1.0f),最小值則為 -1.0f (例如,5 位元值 10000 會對應至 -1.0f)。 此外,第二個最小值會對應至 -1.0f (例如,5 位元值 10001 會對應至 -1.0f)。 因此,-1.0f 有兩種整數表示法。 而 0.0f 和 1.0f 都只有單一表示法。 這會針對範圍 (-1.0f...0.0f) 內平均分布的浮點值產生一組整數表示法,也會針對範圍 (0.0f...1.0f) 內數字產生一組互補的表示法。
UNORM 不帶正負號的正規化整數,代表針對 n 位元的數字,所有 0 都代表 0.0f,而所有 1 則代表 1.0f。 表示從 0.0f 到 1.0f 之平均分布的浮點值序列。 舉例來說,2 位元 UNORM 代表 0.0f、1/3、2/3 和 1.0f。
SINT 帶正負號的整數。 2 的整數補數。 舉例來說,3 位元 SINT 代表整數值 -4、-3、-2、-1、0、1、2、3。
UINT 不帶正負號的整數。 舉例來說,3 位元 UINT 代表整數值 0、1、2、3、4、5、6、7。
FLOAT 在 Direct3D 所定義之任何表現方式中的浮點值。
SRGB 與 UNORM 相似,也就是針對 n 位元的數字,所有 0 都代表 0.0f,而所有 1 則代表 1.0f。 但與 UNORM 的差異在於:對 SRGB 而言,所有 0 到所有 1 之間不帶正負號的整數編碼序列,會代表在 0.0f 到 1.0f 之間數字浮點解譯的非線性進展。 大致上,如果這個非線性進展 SRGB 顯示為色彩序列,就會顯示為「平均」觀察者在「平均」檢視條件下於「平均」顯示器上之亮度的線性漸層。 如需完整的詳細資訊,請參閱國際電子電機委員會 (IEC) 的《SRGB 色彩標準 IEC 61996-2-1》。

 

上述詞彙經常用來做為「格式名稱修飾詞」,以描述資料在記憶體中的配置方式,以及從記憶體傳輸至或傳輸自管線單位 (例如著色器) 之傳輸路徑 (可能包含篩選) 中執行的轉換。

浮點轉換

每當不同表示法之間發生浮點轉換時 (包括轉換至或轉換自非浮點表示法),就會套用下列規則。

從較高範圍的表示法轉換至較低範圍的表示法

  • 在轉換至另一個浮點格式期間,會使用四捨五入至零。 如果目標為整數或固定點格式,就會使用四捨五入至最接近的偶數,除非轉換明確記錄為使用其他四捨五入行為,例如適用於從 FLOAT 四捨五入至最接近的 SNORM、從 FLOAT 四捨五入至最接近的 UNORM,或從 FLOAT 四捨五入至最接近的 SRGB。 其他例外狀況則包括 ftoi 和 ftou 著色器指示,該指示會使用四捨五入至零。 最後,紋理取樣器和轉譯器使用的浮動至固定的轉換,則會採用來自無限精確理想之最小精度單位所測量的指定容錯。
  • 對於大於較低範圍目標格式之動態範圍的來源值 (例如,將大型 32 位元浮點值寫入 16 位數浮點 RenderTarget),最大的可表示 (帶適當正負號) 值結果並不會包含帶正負號的無限大 (因先前所提到的四捨五入至零之故)。
  • 如果 NaN 表示法在較低範圍格式中適用,則較高範圍格式中的 NaN 將轉換為較低範圍格式中的 NaN 表示法。 如果較低格式沒有 NaN 表示法,結果將為 0。
  • 如果適用,則較高範圍格式中的 INF 將轉換為較低範圍格式中的 INF。 如果較低格式沒有 INF 表示法,則將轉換為可表示的最大值。 如果適用於目標格式,則正負號將保留。
  • 如果適用於較低範圍格式,且可進行轉換,則較高範圍格式中的非正規化值將轉換為較低範圍格式中的非正規化表示法,否則結果將為 0。 如果適用於目標格式,則正負號位元將保留。

從較低範圍的表示法轉換至較高範圍的表示法

  • 如果在較高範圍格式中適用,則較低範圍格式中的 NaN 將轉換為較高範圍格式中的 NaN 表示法。 如果較高範圍格式沒有 NaN 表示法,則將轉換為 0。
  • 如果在較高範圍格式中適用,則較低範圍格式中的 INF 將轉換為較高範圍格式中的 INF 表示法。 如果較高格式沒有 INF 表示法,則將轉換為可表示的最大值。 如果適用於目標格式,則正負號將保留。
  • 如果可以,則較低範圍格式中的非正規化值將轉換為較高範圍格式中的正規化表示法,或在非正規化表示法存在的情況下,轉換為較高範圍格式中的非正規化表示法。 在上述兩種情況都不成立之下,如果較高範圍格式沒有非正規化表示法,則將轉換為 0。 如果適用於目標格式,則正負號將保留。 請注意,32 位元浮點數會視為沒有非正規化表示法的格式 (因為在 32 位元浮點數運算中的非正規化值會排清為保留正負號的 0)。

整數轉換

下表將說明從上述各種表示法轉換為其他表示法的轉換作業。 只會顯示在 Direct3D 中實際發生的轉換。

針對整數,除非另有指定,否則,所有從整數表示法轉換至/自下方所述浮點表示法的所有轉換都會實際完成。

來源資料類型 目的地資料類型 轉換規則
SNORM FLOAT

將表示帶正負號範圍 [-1.0f 至 1.0f] 的 n 位元整數值轉換至浮點,會如下方所示。

  • 最大負數值會對應至 -1.0f。 例如,5 位元值 10000 會對應至 -1.0f。
  • 其他所有值都會轉換為浮點 (稱為 c),然後結果 = c * (1.0f / (2⁽ⁿ⁻¹⁾-1))。 例如,5 位元值 10001 會轉換為 -15.0f,然後除以 15.0f,進而得到 -1.0f。
FLOAT SNORM

將浮點數轉換為表示帶正負號範圍 [-1.0f 至 1.0f] 的 n 位元整數值,會如下方所示。

  • 由 c 代表起始值。
  • 如果 c 為 NaN,結果將為 0。
  • 如果 c > 1.0f,包括 INF,則會限縮為 1.0f。
  • 如果 c < -1.0f,包括 -INF,則會限縮為 -1.0f。
  • 從浮點小數位數轉換為整數小數位數:c = c * (2ⁿ⁻¹-1)。
  • 轉換為整數,會如下所示。
    • 如果 c >= 0,則 c = c + 0.5f,否則,c = c - 0.5f。
    • 捨去小數,而其餘浮點 (整數) 值則直接轉換為整數。

此一轉換允許 (整數側) D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_Unit-Last-Place 最小精度單位的容錯。 這表示,從浮點小數位數轉換為整數小數位數後,可表示目標格式值之 D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP 最小精度單位中的任何值都允許對應至該值。 額外的資料可逆性需求可確保轉換在整個範圍之間不會遞減,而可達成所有輸出值。 (在此處所示的常數中,xx 應使用 Direct3D 版本取而代之,例如 10、11 或 12。)

UNORM FLOAT

起始得 n 位元值會轉換為浮點 (0.0f、1.0f、2.0f 等),然後除以 (2ⁿ-1)。

FLOAT UNORM

由 c 代表起始值。

  • 如果 c 為 NaN,結果將為 0。
  • 如果 c > 1.0f,包括 INF,則會限縮為 1.0f。
  • 如果 c < 0.0f,包括 -INF,則會限縮為 0.0f。
  • 從浮點小數位數轉換為整數小數位數:c = c * (2ⁿ-1)。
  • 轉換為整數。
    • c = c + 0.5f。
    • 小數遭到捨去,而其餘浮點 (整數) 值則直接轉換為整數。

此一轉換允許 (整數側) D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP 最小精度單位的容錯。 這表示,從浮點小數位數轉換為整數小數位數後,可表示目標格式值之 D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP 最小精度單位中的任何值都允許對應至該值。 額外的資料可逆性需求可確保轉換在整個範圍之間不會遞減,而可達成所有輸出值。

SRGB FLOAT

下方為理想的 SRGB 至 FLOAT 轉換。

  • 將起始的 n 位元值轉換為浮點值 (0.0f、1.0f、2.0f 等);將此稱為 c。
  • c = c * (1.0f / (2ⁿ-1))
  • 如果 (c < = D3Dxx_SRGB_TO_FLOAT_THRESHOLD) 那麼:結果 = c / D3Dxx_SRGB_TO_FLOAT_DENOMINATOR_1,否則:結果 = ((c + D3Dxx_SRGB_TO_FLOAT_OFFSET)/D3Dxx_SRGB_TO_FLOAT_DENOMINATOR_2)D3Dxx_SRGB_TO_FLOAT_EXPONENT

此一轉換允許 (SRGB 側) D3Dxx_SRGB_TO_FLOAT_TOLERANCE_IN_ULP 最小精度單位的容錯。

FLOAT SRGB

下方為理想的 FLOAT -> SRGB 轉換。

假設目標 SRGB 色彩元件有 n 位元:

  • 假設起始值為 c。
  • 如果 c 為 NaN,結果將為 0。
  • 如果 c > 1.0f,包括 INF,則會限縮為 1.0f。
  • 如果 c < 0.0f,包括 -INF,則會限縮為 0.0f。
  • 如果 (c <= D3Dxx_FLOAT_TO_SRGB_THRESHOLD),那麼:c = D3Dxx_FLOAT_TO_SRGB_SCALE_1 * c,否則:c = D3Dxx_FLOAT_TO_SRGB_SCALE_2 * c(D3Dxx_FLOAT_TO_SRGB_EXPONENT_NUMERATOR/D3Dxx_FLOAT_TO_SRGB_EXPONENT_DENOMINATOR) - D3Dxx_FLOAT_TO_SRGB_OFFSET
  • 從浮點小數位數轉換為整數小數位數:c = c * (2ⁿ-1)。
  • 轉換為整數:
    • c = c + 0.5f。
    • 小數遭到捨去,而其餘浮點 (整數) 值則直接轉換為整數。

此一轉換允許 (整數側) D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP 最小精度單位的容錯。 這表示,從浮點小數位數轉換為整數小數位數後,可表示目標格式值之 D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP 最小精度單位中的任何值都允許對應至該值。 額外的資料可逆性需求可確保轉換在整個範圍之間不會遞減,而可達成所有輸出值。

SINT 更多位元的 SINT

若要從 SINT 轉換為更多位元的 SINT,起始數字的最高階位元 (MSB) 會「擴充其正負號」至目標格式中適用的位元。

UINT 更多位元的 SINT

若要將 UINT 轉換為更多位元的 SINT,數字會複製為目標格式的最小顯著性位元 (LSB),而額外的 MSB 則會以 0 填補。

SINT 更多位元的 UINT

若要從 SINT 轉換為更多位元的 UINT:如果為負數,則值會限縮為 0。 否則,數字會複製為目標格式的 LSB,而額外的 MSB 則會以 0 填補。

UINT 更多位元的 UINT

若要從 UINT 轉換為更多位元的 UINT,數字會複製為目標格式的 LSB,而額外的 MSB 則會以 0 填補。

SINT 或 UINT 更少或相同位元的 SINT 或 UINT

若要從 SINT 或 UINT 轉換為更少或相同位元的 SINT 或 UINT (和/或變更帶正負號狀態),則起始值會限縮為目標格式的範圍。

 

固定點整數轉換

固定點整數為具有部分位元大小,並在固定位置隱含小數點的整數。

無所不在的「integer」資料類型為固定點整數中的特殊情況,會將小數點放在數字結尾處。

固定點數表示法會以 i.f 做為特性描述,當中的 i 為整數位元的數字,而 f 則為小數位元的數字。 例如,16.8 代表 16 位元的整數,而後面則緊接著 8 位元的小數。 整數部分會儲存在 2 的補數中,這至少如此處所定義的一樣 (雖然同樣可為不帶正負號的整數進行定義)。 小數部分會以不帶正負號的形式加以儲存。 小數部分一律會代表介於兩個最接近整數值之間的正小數,並從最大負數開始。

固定點數的加減運算會使用標準整數算術執行,完全無需考量隱含的小數點位於何處。 將 1 加至 16.8 固定點數中,即代表只加入 256,因為小數位於從數字的小顯著性結尾處開始計算的 8 位數。 而乘法等其他運算,也可使用整數算數進行,只要將固定小數位數的影響列入考量即可。 例如,使用整數乘法程序將兩個 16.8 整數相乘,就會產生 32.16 的結果。

Direct3D 中的固定點整數表示法會透過兩種方式使用。

  • 轉譯器中剪裁後的頂點位置會貼齊固定點,以在 RenderTarget 區域中統一分配精確度。 許多轉譯器作業 (包括表面剔除) 都會發生在固定點位置上,而其他運算 (例如屬性內插補點設定) 則會使用已從固定點貼齊位置轉換回浮點的位置。
  • 取樣作業的紋理座標會貼齊至固定點 (依照紋理大小縮放後),以在選擇篩選點選位置/權重時,於紋理空間內統一分配精確度。 權重值會先轉換回浮點,再執行實際的篩選算數。
來源資料類型 目的地資料類型 轉換規則
FLOAT 固定點整數

下列是將浮點數 n 轉換為固定點整數 i.f 的一般程序,當中的 i 為 (帶正負號) 整數位元的數字,而 f 為小數位元的數字。

  • 計算 FixedMin = -2⁽ⁱ⁻¹⁾
  • 計算 FixedMax = 2⁽ⁱ⁻¹⁾ - 2(-f)
  • 如果 n 為 NaN,則結果 = 0;如果 n 為 +Inf,則結果 = FixedMax*2f;如果 n 為 -Inf,則結果 = FixedMin*2f
  • 如果 n >= FixedMax,則結果 = Fixedmax*2f;如果 n <= FixedMin,則結果 = FixedMin*2f
  • 否則會計算 n*2f,並轉換為整數。

實作結果為允許整數結果中 D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP 最小精度單位的容錯,而非上方最後一個步驟後的無限精確值 n*2f

固定點整數 FLOAT

假設將指定的固定點表示法轉換為浮點不會包含超過 24 位元的資訊,而當中有不超過 23 位元的資訊位於小數元件中。 假設指定的浮點數 fxp 採用 i.f 形式 (i 位元整數、f 位元小數)。 浮點的轉換會與下列虛擬程式碼相似。

浮點結果 = (float)(fxp >> f) + // 擷取整數

((float)(fxp & (2f - 1)) / (2f)); // 擷取整數

 

附錄