Conversione del tipo di dati

Le sezioni seguenti descrivono come Direct3D gestisce le conversioni tra tipi di dati.

Terminologia dei tipi di dati

Il seguente set di termini viene usato successivamente per caratterizzare varie conversioni di formato.

Termine Definizione
SNORM Numero intero normalizzato con segno, ovvero per il numero di complemento di un bit 2, il valore massimo indica 1,0f (ad esempio, il valore a 5 bit 01111 corrisponde a 1,0f) e il valore minimo indica -1,0f (ad esempio, il valore a 5 bit 10000 corrisponde a -1,0f). Inoltre, il secondo numero minimo viene mappato a -1,0f (ad esempio, il valore a 5 bit 10001 corrisponde a -1,0f). Esistono quindi due rappresentazioni di numero intero per -1,0f. Esiste una singola rappresentazione per 0,0f e una singola rappresentazione per 1,0f. Ciò comporta un set di rappresentazioni di numero intero per i valori a virgola mobile uniformemente spaziati nell'intervallo (-1,0f...0,0f) e un insieme complementare di rappresentazioni per numeri nell'intervallo (0,0f...1,0f).
UNORM Numero intero normalizzato senza segno, ovvero per un numero a n bit, tutti gli 0 significano 0,0f e tutti i valori di 1 significano 1,0f. Viene rappresentata una sequenza di valori a virgola mobile con spaziatura uniforme da 0,0f a 1,0f. Ad esempio, uno UNORM a 2 bit rappresenta 0,0f, 1/3, 2/3 e 1,0f.
SINT Numero intero con segno. Numero intero con complemento di 2. ad esempio, un SINT a 3 bit rappresenta i valori integrali -4, -3, -2, -1, 0, 1, 2, 3.
UINT Numero intero senza segno. ad esempio, un UINT a 3 bit rappresenta i valori integrali 0, 1, 2, 3, 4, 5, 6, 7.
FLOAT Valore a virgola mobile in una delle rappresentazioni definite da Direct3D.
SRGB Analogamente a UNORM, nel senso di un numero a n bit, tutti gli 0 significano 0,0f e tutti gli 1 significano 1,0f. Tuttavia, a differenza di UNORM, con SRGB la sequenza di codifiche intere senza segno tra tutti gli 0 e tutti gli 1 rappresentano una progressione non lineare nell'interpretazione a virgola mobile dei numeri, tra 0,0f e 1,0f. Approssimativamente, se questa progressione non lineare, SRGB, viene visualizzata come una sequenza di colori, appare come una rampa lineare di livelli di luminosità a un osservatore "medio", in condizioni di visualizzazione "medie", su un display "medio". Per informazioni dettagliate, vedere lo standard di colore SRGB, IEC 61996-2-1, presso IEC (International Electrotechnical Commission).

 

I termini precedenti vengono spesso usati come "Modificatori nome formato", in cui descrivono sia il modo in cui i dati vengono disposti in memoria che la conversione da eseguire nel percorso di trasporto (potenzialmente incluso il filtro) dalla memoria a o da un'unità pipeline, ad esempio uno shader.

Conversione del punto a virgola mobile

Ogni volta che si verifica una conversione a virgola mobile tra rappresentazioni diverse, incluse le rappresentazioni a virgola mobile o da rappresentazioni non a virgola mobile, si applicano le seguenti regole.

Conversione da una rappresentazione di intervallo superiore a una rappresentazione di intervallo inferiore

  • L'arrotondamento a zero viene utilizzato durante la conversione in un altro formato float. Se la destinazione è un formato intero o a virgola fissa, viene usato numero pari più vicino, salvo che la conversione non sia documentata in modo esplicito come l'uso di un altro metodo di arrotondamento, ad esempio il numero più vicino per FLOAT a SNORM, FLOAT a UNORM o FLOAT a SRGB. Altre eccezioni sono le istruzioni ftoi e ftou shader, che usano il numero più vicino allo zero. Infine, le conversioni float-to-fixed usate dal campionatore di texture e dal rasterizzatore hanno una tolleranza specificata misurata in unità ulP da un ideale infinitamente preciso.
  • Per i valori di origine maggiori rispetto all'intervallo dinamico di un formato di destinazione di intervallo inferiore (ad esempio, un valore float a 32 bit elevato viene scritto in un oggetto RenderTarget a 16 bit), il valore massimo rappresentabile (con segno appropriato) non include l'infinito con segno (a causa dell'arrotondamento a zero descritto in precedenza).
  • NaN in un formato di intervallo superiore verrà convertito in rappresentazione NaN nel formato di intervallo inferiore se la rappresentazione NaN esiste nel formato di intervallo inferiore. Se il formato inferiore non ha una rappresentazione NaN, il risultato sarà 0.
  • INF in un formato di intervallo superiore verrà convertito in INF nel formato di intervallo inferiore, se disponibile. Se il formato inferiore non ha una rappresentazione INF, verrà convertito nel valore massimo rappresentabile. Il segno verrà mantenuto se disponibile nel formato di destinazione.
  • Il valore denormalizzato in un formato di intervallo superiore verrà convertito nella rappresentazione Denorm nel formato di intervallo inferiore, se disponibile nel formato di intervallo inferiore e la conversione è possibile, altrimenti il risultato è 0. Il bit segno verrà mantenuto se disponibile nel formato di destinazione.

Conversione da una rappresentazione di intervallo inferiore a una rappresentazione di intervallo superiore

  • I NaN in un formato di intervallo inferiore vengono convertiti nella rappresentazione NaN nel formato di intervallo superiore, se disponibile in quest'ultimo. Se il formato di intervallo superiore non ha una rappresentazione NaN, verrà convertito in 0.
  • I INF in un formato di intervallo inferiore vengono convertiti nella rappresentazione INF nel formato di intervallo superiore, se disponibile in quest'ultimo. Se il formato superiore non ha una rappresentazione INF, verrà convertito nel valore massimo rappresentabile (MAX_FLOAT in tale formato). Il segno verrà mantenuto se disponibile nel formato di destinazione.
  • Il valore denormalizzato in un formato di intervallo inferiore verrà convertito in una rappresentazione normalizzata nel formato di intervallo superiore, se possibile, oppure in una rappresentazione Denorm nel formato di intervallo superiore se la rappresentazione Denorm esiste. In caso contrario, se il formato di intervallo superiore non ha una rappresentazione Denorm, verrà convertito in 0. Il segno verrà mantenuto se disponibile nel formato di destinazione. Si noti che i numeri float a 32 bit vengono conteggiati come formato senza una rappresentazione Denorm (poiché i valori denormalizzati nelle operazioni sui float a 32 bit si allineano al segno conservato 0).

Conversione integer

Nella tabella seguente vengono descritte le conversioni da varie rappresentazioni descritte in precedenza in altre rappresentazioni. Vengono visualizzate solo le conversioni effettivamente eseguite in Direct3D.

Con i numeri interi, a meno che non diversamente specificato, tutte le conversioni in/da rappresentazioni integer a rappresentazioni float descritte di seguito verranno eseguite con esattezza.

Tipo di dati di origine Tipo di dati di destinazione Regola di conversione
SNORM FLOAT

Dato un valore intero a n bit che rappresenta l'intervallo con segno [-1.0f a 1.0f], la conversione in virgola mobile è la seguente.

  • Il valore più negativo è mappato a -1,0f. ad esempio, il valore a 5 bit 10000 viene mappato a -1,0f.
  • Ogni altro valore viene convertito in float (denominato c) e quindi il risultato è = c * (1,0f / (2⁽ⁿ⁻¹⁾-1)). Ad esempio, il valore a 5 bit 10001 viene convertito in -15,0f e quindi diviso per 15,0f, che restituisce -1,0f.
FLOAT SNORM

Dato un numero in virgola mobile, la conversione in un valore intero a n bit che rappresenta l'intervallo firmato [da -1,0f a 1,0f] avviene come segue.

  • Lasciare che c rappresenti il valore iniziale.
  • Se c è NaN, il risultato è 0.
  • Se c > 1.0f, incluso INF, viene bloccato su 1,0f.
  • Se c < - 1.0f, incluso - INF, viene bloccato su -1,0f.
  • Convertire da scala float a scala integer: c = c * (2ⁿ⁻¹-1).
  • Convertire in un numero intero come indicato di seguito.
    • Se c >= 0, c = c + 0,5f, in caso contrario, c = c - 0,5f.
    • Eliminare la frazione decimale e il valore a virgola mobile rimanente (integrale) viene convertito direttamente in un numero intero.

Questa conversione è consentita una tolleranza D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_Unit-Last-Place Unit-Last-Place (sul lato integer). Ciò significa che dopo la conversione da una scalabilità float a integer, qualsiasi valore all'interno di D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit-Last-Place di un valore di formato di destinazione rappresentabile è autorizzato a eseguire il mapping a tale valore. Il requisito aggiuntivo di invertibilità dei dati garantisce che la conversione non venga generata nell'intervallo e che tutti i valori di output siano raggiungibili. Nelle costanti illustrate di seguito, xx deve essere sostituito con la versione Direct3D, ad esempio 10, 11 o 12.

UNORM FLOAT

Il valore iniziale di n bit viene convertito in float (0,0f, 1,0f, 2,0f e così via) e quindi diviso per (2ⁿ-1).

FLOAT UNORM

Lasciare che c rappresenti il valore iniziale.

  • Se c è NaN, il risultato è 0.
  • Se c > 1.0f, incluso INF, viene bloccato su 1,0f.
  • Se c < 0.0f, incluso -INF, viene bloccato a 0,0f.
  • Convertire da scala float a scala integer: c = c * (2ⁿ-1).
  • Converti in integer.
    • c = c + 0,5f.
    • La frazione decimale viene eliminata e il valore a virgola mobile rimanente (integrale) viene convertito direttamente in un numero intero.

In questa conversione è consentita una tolleranza D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit-Last-Place (sul lato intero). Ciò significa che dopo la conversione da una scalabilità float a integer, qualsiasi valore all'interno di D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit-Last-Place di un valore di formato di destinazione rappresentabile è autorizzato a eseguire il mapping a tale valore. Il requisito aggiuntivo di invertibilità dei dati garantisce che la conversione non venga generata nell'intervallo e che tutti i valori di output siano raggiungibili.

SRGB FLOAT

Di seguito è riportata la conversione ideale da SRGB a FLOAT.

  • Assumere il valore n bit iniziale, convertirlo in float (0,0f, 1,0f, 2,0f e così via) e denominarlo c.
  • c = c * (1.0f / (2ⁿ-1))
  • Se (c < = D3Dxx_SRGB_TO_FLOAT_THRESHOLD) then: result = c / D3Dxx_SRGB_TO_FLOAT_DENOMINATOR_1, else: result = ((c + D3Dxx_SRGB_TO_FLOAT_OFFSET)/D3Dxx_SRGB_TO_FLOAT_DENOMINATOR_2)D3Dxx_SRGB_TO_FLOAT_EXPONENT

In questa conversione è consentita una tolleranza D3Dxx_SRGB_TO_FLOAT_TOLERANCE_IN_ULP Unit-Last-Place (sul lato intero).

FLOAT SRGB

Di seguito è riportata la conversione ideale da FLOAT -> a SRGB.

Si supponga che il componente colore SRGB di destinazione abbia n bit:

  • Si supponga che il valore iniziale sia c.
  • Se c è NaN, il risultato è 0.
  • Se c > 1.0f, incluso INF, viene bloccato su 1,0f.
  • Se c < 0.0f, incluso -INF, viene bloccato a 0,0f.
  • Se (c <= D3Dxx_FLOAT_TO_SRGB_THRESHOLD) then: c = D3Dxx_FLOAT_TO_SRGB_SCALE_1 * c, else: c = D3Dxx_FLOAT_TO_SRGB_SCALE_2 * c(D3Dxx_FLOAT_TO_SRGB_EXPONENT_NUMERATOR/D3D xx_FLOAT_TO_SRGB_EXPONENT_DENOMINATOR) - D3Dxx_FLOAT_TO_SRGB_OFFSET
  • Convertire da scala float a scala integer: c = c * (2ⁿ-1).
  • Converti in integer:
    • c = c + 0,5f.
    • La frazione decimale viene eliminata e il valore a virgola mobile rimanente (integrale) viene convertito direttamente in un numero intero.

In questa conversione è consentita una tolleranza D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit-Last-Place (sul lato intero). Ciò significa che dopo la conversione da una scalabilità float a integer, qualsiasi valore all'interno di D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit-Last-Place di un valore di formato di destinazione rappresentabile è autorizzato a eseguire il mapping a tale valore. Il requisito aggiuntivo di invertibilità dei dati garantisce che la conversione non venga generata nell'intervallo e che tutti i valori di output siano raggiungibili.

SINT SINT con più bit

Per eseguire la conversione da SINT a SINT con più bit, il bit più significativo (MSB) del numero iniziale è "sign-extended (esteso con segno)" ai bit aggiuntivi disponibili nel formato di destinazione.

UINT SINT con più bit

Per eseguire la conversione da UINT a SINT con più bit, il numero viene copiato nei bit meno significativi del formato di destinazione (LSB) e gli MSB aggiuntivi vengono riempiti con 0.

SINT UINT con più bit

Per eseguire la conversione da SINT a UINT con più bit: se negativo, il valore viene bloccato su 0. In caso contrario, il numero viene copiato nei LSB del formato di destinazione e gli MSB aggiuntivi vengono riempiti con 0.

UINT UINT con più bit

Per eseguire la conversione da UINT a UINT con più bit, il numero viene copiato nei LSB del formato di destinazione e gli MSB aggiuntivi vengono riempiti con 0.

SINT o UINT SINT o UINT con un numero minore o uguale di bit

Per eseguire la conversione da SINT o UINT a SINT o UINT con bit minori o uguali (e/o modifica della firma), il valore iniziale viene semplicemente bloccato nell'intervallo del formato di destinazione.

 

Conversione integer a virgola fissa

I numeri interi a virgola fissa sono semplicemente numeri interi di alcune dimensioni di bit che hanno un separatore decimale implicito in una posizione fissa.

Il tipo di dati "integer" universale è un caso speciale di un numero intero a virgola fissa con il separatore decimale alla fine del numero.

Le rappresentazioni dei numeri a virgola fissa sono caratterizzate da: ad esempio, dove i è il numero di bit interi e f è il numero di bit frazionari. Ad esempio, 16,8 indica un numero intero a 16 bit seguito da 8 bit di frazione. La parte integer viene archiviata nel complemento di 2, almeno come definito qui (anche se può essere definita ugualmente per numeri interi senza segno). La parte frazionaria viene archiviata in formato senza segno. La parte frazionaria rappresenta sempre la frazione positiva tra i due valori integrali più vicini, a partire dal più negativo.

Le operazioni di addizione e sottrazione sui numeri a virgola fissa vengono eseguite semplicemente usando il calcolo standard dei numeri interi, senza alcuna considerazione per la posizione decimale implicita. Aggiungere 1 a un numero in virgola fissa 16,8 significa semplicemente aggiungere 256, poiché il decimale si trova a 8 posizioni dall'estremità meno significativa del numero. È possibile eseguire anche altre operazioni, ad esempio la moltiplicazione, usando semplicemente il calcolo del numero intero, a condizione che l'effetto sul decimale fisso sia da prendere in considerazione. Ad esempio, la moltiplicazione di due numeri interi da 16,8 usando una moltiplicazione di numeri interi produce un risultato di 32,16.

Le rappresentazioni integer a virgola fissa vengono usate in due modi in Direct3D.

  • Le posizioni dei vertici successivamente ritagliate nel rasterizzatore vengono spostati fino alla virgola fissa, per distribuire in modo uniforme la precisione nell'area RenderTarget. Molte operazioni di rasterizzatore, tra cui l'eliminazione del lato anteriore a titolo di esempio, si verificano in posizioni a virgola fissa, mentre altre operazioni, ad esempio l'impostazione dell'interpolatore di attributi, usano posizioni che sono state riconvertite in virgola mobile dalle posizioni a virgola fissa.
  • Le coordinate delle texture per le operazioni di campionamento vengono ritagliate al punto fisso (dopo essere state ridimensionate in base alle dimensioni della texture), per distribuire in modo uniforme la precisione nello spazio delle texture, scegliendo posizioni/pesi del tocco del filtro. I valori di peso vengono convertiti in virgola mobile prima dell'esecuzione dell'aritmetica effettiva del filtraggio.
Tipo di dati di origine Tipo di dati di destinazione Regola di conversione
FLOAT Numero intero a virgola fissa

Di seguito è riportata la procedura generale per la conversione di un numero a virgola mobile n in un numero intero a virgola fissa i.f, dove i è il numero di bit interi (con segno) e f è il numero di bit frazionari.

  • Calcolo FixedMin = -2⁽ⁱ⁻¹⁾
  • Calcolo FixedMax = 2⁽ⁱ⁻¹⁾ - 2(-f)
  • Se n è un NaN, allora = 0; se n è +Inf, allora = FixedMax*2f; se n è -Inf, allora = FixedMin*2f
  • Se n >= FixedMax, allora = Fixedmax*2f; se n <= FixedMin, allora = FixedMin*2f
  • In caso contrario, calcolare n*2f e convertirlo in integer.

Sono consentite implementazioni D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP tolleranza Unit-Last-Place nel risultato integer, anziché il valore infinito preciso n*2f dopo l'ultimo passaggio precedente.

Numero intero a virgola fissa FLOAT

Si supponga che la rappresentazione specifica in virgola fissa da convertire in float non contenga più di un totale di 24 bit di informazioni, di cui non più di 23 bit nella componente frazionaria. Supponiamo che un dato numero in virgola fissa, fxp, sia in forma i.f (dove i sta per bit intero, f per bit frazione) La conversione in float è simile allo pseudocodice seguente.

float result = (float)(fxp >> f) + // extract integer

((float)(fxp & (2f - 1)) / (2f)); // extract fraction

 

Appendici