Reglas de conversión de datos

En las secciones siguientes se describe cómo Direct3D controla las conversiones entre tipos de datos.

Terminología del tipo de datos

El siguiente conjunto de términos se usa posteriormente para caracterizar diversas conversiones de formato.

Término Definición
SNORM Entero normalizado con signo, lo que significa que para un número de complemento de n bits 2, el valor máximo significa 1,0f (por ejemplo, el valor de 5 bits 01111 se asigna a 1,0f) y el valor mínimo significa -1,0f (por ejemplo, el valor de 5 bits 10000 se asigna a -1,0f). Además, el segundo número mínimo se asigna a -1,0f (por ejemplo, el valor de 5 bits 10001 se asigna a -1,0f). Por lo tanto, hay dos representaciones de enteros para -1.0f. Hay una sola representación para 0,0f y una sola representación para 1,0f. Esto da como resultado un conjunto de representaciones de enteros para valores de punto flotante espaciado uniformemente en el intervalo (-1,0f... 0,0f) y también un conjunto complementario de representaciones para números en el intervalo (0,0f... 1.0f)
UNORM Entero normalizado sin signo, lo que significa que para un número de n bits, todos los 0 significan 0,0f y los 1 significan 1,0f. Se representa una secuencia de valores de punto flotante espaciado uniformemente de 0,0f a 1,0f. Por ejemplo, un UNORM de 2 bits representa 0,0f, 1/3, 2/3 y 1,0f.
SINT Entero con signo. 2 entero de complemento. Por ejemplo, un SINT de 3 bits representa los valores enteros -4, -3, -2, -1, 0, 1, 2, 3.
UINT Entero sin signo. Por ejemplo, un UINT de 3 bits representa los valores enteros 0, 1, 2, 3, 4, 5, 6, 7.
FLOAT Valor de punto flotante en cualquiera de las representaciones definidas por Direct3D.
SRGB De forma similar a UNORM, en que para un número de n bits, todos los 0 significan 0,0f y todos los 1 significan 1,0f. Sin embargo, a diferencia de UNORM, con SRGB, la secuencia de codificaciones de enteros sin signo entre los 0 y los 1 representa una progresión no lineal en la interpretación de punto flotante de los números, entre 0,0f y 1,0f. Aproximadamente, si esta progresión no lineal, SRGB, se muestra como una secuencia de colores, aparecería como una rampa lineal de niveles de luminosidad a un observador "promedio", en condiciones de visualización "media", en una pantalla "media". Para obtener detalles completos, consulte el estándar de color SRGB, IEC 61996-2-1, en IEC (Comisión Electrotécnica Internacional).

 

Conversión de punto flotante

Cada vez que se produce una conversión de punto flotante entre diferentes representaciones, incluidas las representaciones de punto no flotante o desde ellas, se aplican las reglas siguientes.

Conververtir de una representación de rango superior a una representación de intervalo inferior

  • Round-to-zero se usa durante la conversión a otro formato float. Si el destino es un formato entero o de punto fijo, se usa round-to-near-even, a menos que la conversión se documente explícitamente como el uso de otro comportamiento de redondeo, como redondeo al más cercano para FLOAT a SNORM, FLOAT a UNORM o FLOAT a SRGB. Otras excepciones son las instrucciones del sombreador ftoi y ftou, que usan redondeo a cero. Por último, las conversiones float-to-fixed usadas por el muestreador de textura y el rasterizador tienen una tolerancia especificada medida en Unit-Last-Place desde un ideal infinitamente preciso.
  • En el caso de los valores de origen mayores que el intervalo dinámico de un formato de destino de intervalo inferior (por ejemplo, un valor flotante grande de 32 bits se escribe en un RenderTarget flotante de 16 bits), el valor máximo representable (firmado correctamente), NO incluido el infinito con signo (debido al redondeo a cero descrito anteriormente).
  • NaN en un formato de intervalo superior se convertirá en representación NaN en el formato de intervalo inferior si la representación naN existe en el formato de intervalo inferior. Si el formato inferior no tiene una representación NaN, el resultado será 0.
  • INF en un formato de rango superior se convertirá en INF en el formato de intervalo inferior si está disponible. Si el formato inferior no tiene una representación INF, se convertirá al valor máximo que se puede representar. El signo se conservará si está disponible en el formato de destino.
  • Denorm en un formato de rango superior se convertirá a la representación Denorm en el formato de intervalo inferior si está disponible en el formato de intervalo inferior y la conversión es posible; de lo contrario, el resultado es 0. El bit de signo se conservará si está disponible en el formato de destino.

Conversión de una representación de intervalo inferior a una representación de rango superior

  • NaN en un formato de intervalo inferior se convertirá a la representación NaN en el formato de intervalo superior si está disponible en el formato de intervalo superior. Si el formato de intervalo superior no tiene una representación NaN, se convertirá en 0.
  • INF en un formato de intervalo inferior se convertirá a la representación INF en el formato de rango superior si está disponible en el formato de rango superior. Si el formato superior no tiene una representación INF, se convertirá al valor máximo que se puede representar (MAX_FLOAT en ese formato). El signo se conservará si está disponible en el formato de destino.
  • Denorm en un formato de intervalo inferior se convertirá en una representación normalizada en el formato de rango superior si es posible, o bien en una representación Denorm en el formato de intervalo superior si existe la representación Denorm. Con errores, si el formato de intervalo superior no tiene una representación Denorm, se convertirá en 0. El signo se conservará si está disponible en el formato de destino. Tenga en cuenta que los números flotantes de 32 bits cuentan como un formato sin una representación Denorm (porque Denorms en operaciones en floats de 32 bits vacían para firmar 0).

Conversión de enteros

En la tabla siguiente se describen las conversiones de varias representaciones descritas anteriormente a otras representaciones. Solo se muestran las conversiones que se producen realmente en Direct3D.

Tipo de datos de origen Tipo de datos de destino Regla de conversión
SNORM FLOAT Dado un valor entero de n bits que representa el intervalo con signo [-1.0f a 1.0f], la conversión al punto flotante es la siguiente.
  • El valor más negativo se asigna a -1,0f. Por ejemplo, el valor de 5 bits 10000 se asigna a -1,0f.
  • Cada otro valor se convierte en un valor float (llámelo c) y, a continuación, result = c * (1,0f / (2⁽ⁿ⁻⁾-1)). Por ejemplo, el valor de 5 bits 10001 se convierte en -15.0f y, a continuación, se divide entre 15,0f, lo que produce -1,0f.
FLOAT SNORM Dado un número de punto flotante, la conversión a un valor entero de n bits que representa el intervalo con signo [-1.0f a 1.0f] es el siguiente.
  • Deje que c represente el valor inicial.
  • Si c es NaN, el resultado es 0.
  • Si c > 1.0f, incluido INF, se sujeta a 1.0f.
  • Si c < -1.0f, incluido -INF, se sujeta a -1.0f.
  • Convertir de escala flotante a escala de enteros: c = c * (2ⁿ⁻¹-1).
  • Convierta en un entero como se indica a continuación.
    • Si c >= 0, c = c + 0,5f; en caso contrario, c = c - 0,5f.
    • Quite la fracción decimal y el valor de punto flotante restante (entero) se convierte directamente en un entero.
Esta conversión permite una tolerancia de D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_Unit-Last-Place Unit-Last-Place (en el lado entero). Esto significa que después de convertir de float a escala de enteros, cualquier valor dentro de D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit-Last-Place de un valor de formato de destino representable se permite asignar a ese valor. El requisito adicional de invertibilidad de datos garantiza que la conversión no deje de crearse en el intervalo y se puedan alcanzar todos los valores de salida. (En las constantes que se muestran aquí, xx debe reemplazarse por la versión de Direct3D, por ejemplo 10, 11 o 12).
UNORM FLOAT El valor inicial de n bits se convierte en float (0,0f, 1,0f, 2,0f, etc.) y, a continuación, dividido por (2ⁿ-1).
FLOAT UNORM Deje que c represente el valor inicial.
  • Si c es NaN, el resultado es 0.
  • Si c > 1.0f, incluido INF, se sujeta a 1.0f.
  • Si c < 0,0f, incluido -INF, se sujeta a 0,0f.
  • Convierta de escala flotante a escala de enteros: c = c * (2ⁿ-1).
  • Convertir en entero.
    • c = c + 0,5f.
    • La fracción decimal se quita y el valor de punto flotante restante (entero) se convierte directamente en un entero.
Esta conversión permite una tolerancia de D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit-Last-Place (en el lado entero). Esto significa que después de convertir de float a escala de enteros, cualquier valor dentro de D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit-Last-Place de un valor de formato de destino representable se permite asignar a ese valor. El requisito adicional de invertibilidad de datos garantiza que la conversión no se desincree en el intervalo y se puedan alcanzar todos los valores de salida.
SRGB FLOAT A continuación se muestra la conversión ideal de SRGB a FLOAT.
  • Tome el valor inicial de n bits, conviértelo en float (0,0f, 1,0f, 2,0f, etc.); llame a este c.
  • c = c * (1.0f / (2ⁿ-1))
  • Si (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
Esta conversión se permite una tolerancia de D3Dxx_SRGB_TO_FLOAT_TOLERANCE_IN_ULP Unit-Last-Place (en el lado SRGB).
FLOAT SRGB A continuación se muestra la conversión IDEAL FLOAT -> SRGB.
Suponiendo que el componente de color SRGB de destino tiene n bits:
  • Supongamos que el valor inicial es c.
  • Si c es NaN, el resultado es 0.
  • Si c > 1.0f, incluido INF, se sujeta a 1.0f.
  • Si c < 0,0f, incluido -INF, se sujeta a 0,0f.
  • Si (c <= D3Dxx_FLOAT_TO_SRGB_THRESHOLD) entonces: c = D3Dxx_FLOAT_TO_SRGB_SCALE_1 * c, else: 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
  • Convierta de escala flotante a escala de enteros: c = c * (2ⁿ-1).
  • Convertir en entero:
    • c = c + 0,5f.
    • La fracción decimal se quita y el valor de punto flotante restante (entero) se convierte directamente en un entero.
Esta conversión permite una tolerancia de D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit-Last-Place (en el lado entero). Esto significa que después de convertir de float a escala de enteros, cualquier valor dentro de D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP Unit-Last-Place de un valor de formato de destino representable se permite asignar a ese valor. El requisito adicional de invertibilidad de datos garantiza que la conversión no se desincree en el intervalo y se puedan alcanzar todos los valores de salida.
SINT SINT con más bits Para convertir de SINT a UN SINT con más bits, el bit más significativo (MSB) del número inicial es "sign-extended" a los bits adicionales disponibles en el formato de destino.
UINT SINT con más bits Para convertir de UINT a un SINT con más bits, el número se copia en los bits menos significativos (LSB) del formato de destino y los MSB adicionales se rellenan con 0.
SINT UINT con más bits Para convertir de SINT a UINT con más bits: si es negativo, el valor se sujeta a 0. De lo contrario, el número se copia en los LSB del formato de destino y los MSB adicionales se rellenan con 0.
UINT UINT con más bits Para convertir de UINT a UINT con más bits, el número se copia en los LSB del formato de destino y los MSB adicionales se rellenan con 0.
SINT o UINT SINT o UINT con menos o iguales bits Para convertir de un SINT o UINT a SINT o UINT con menos o iguales bits (o cambios en la firma), el valor inicial se limita simplemente al intervalo del formato de destino.

 

Conversión de enteros de punto fijo

Los enteros de punto fijos son simplemente enteros de algún tamaño de bits que tienen un separador decimal implícito en una ubicación fija.

El tipo de datos "entero" ubicuo es un caso especial de un entero de punto fijo con el decimal al final del número.

Las representaciones fijas de números de punto se caracterizan por: i.f, donde i es el número de bits enteros y f es el número de bits fraccionarios. Por ejemplo, 16,8 significa 16 bits enteros seguidos de 8 bits de fracción. La parte entera se almacena en el complemento de 2, al menos como se define aquí (aunque también se puede definir igual para enteros sin signo). La parte fraccionarcional se almacena en forma sin firmar. La parte fraccionarcional siempre representa la fracción positiva entre los dos valores enteros más cercanos, empezando por el más negativo.

Las operaciones de suma y resta en números de punto fijo se realizan simplemente mediante aritmética de enteros estándar, sin tener en cuenta dónde se encuentra el decimal implícito. Agregar 1 a un número fijo de 16,8 solo significa agregar 256, ya que el decimal es 8 posiciones desde el extremo menos significativo del número. Otras operaciones, como la multiplicación, se pueden realizar simplemente mediante aritmética de enteros, siempre que se tenga en cuenta el efecto en el decimal fijo. Por ejemplo, multiplicar dos enteros 16,8 mediante una multiplicación de enteros genera un resultado de 32,16.

Las representaciones de enteros de punto fijo se usan de dos maneras en Direct3D.

  • Las posiciones posteriores del vértice recortado en el rasterizador se ajustan al punto fijo para distribuir uniformemente la precisión en el área RenderTarget. Muchas operaciones de rasterizador, incluida la selección de caras como un ejemplo, se producen en posiciones fijas acopladas de punto, mientras que otras operaciones, como la configuración del interpolador de atributos, usan posiciones que se han convertido de nuevo en punto flotante desde las posiciones acopladas de punto fijo.
  • Las coordenadas de textura para las operaciones de muestreo se ajustan a un punto fijo (después de escalarse por tamaño de textura), para distribuir uniformemente la precisión entre el espacio de textura, al elegir ubicaciones o pesos de pulsación de filtro. Los valores de peso se convierten de nuevo en punto flotante antes de que se realice el filtrado real aritmético.
Tipo de datos de origen Tipo de datos de destino Regla de conversión
FLOAT Entero de punto fijo A continuación se muestra el procedimiento general para convertir un número de punto flotante n en un entero de punto fijo i.f, donde i es el número de bits enteros (con signo) y f es el número de bits fraccionarios.
  • Compute FixedMin = -2⁽ⁱ⁻¹⁾
  • Compute FixedMax = 2⁽ⁱ⁻¹⁾ - 2(-f)
  • Si n es un NaN, result = 0; si n es +Inf, result = FixedMax*2f; si n es -Inf, result = FixedMin*2f
  • Si n >= FixedMax, result = Fixedmax*2f; si n <= FixedMin, result = FixedMin*2f
  • De lo contrario, calcule n*2f y convierta en entero.
Se permiten implementaciones D3Dxx_FLOAT32_TO_INTEGER_TOLERANCE_IN_ULP tolerancia Unit-Last-Place en el resultado entero, en lugar del valor infinito n*2f después del último paso anterior.
Entero de punto fijo FLOAT Supongamos que la representación de punto fijo específica que se convierte en float no contiene más de un total de 24 bits de información, no más de 23 bits de los cuales se encuentra en el componente fraccional. Supongamos que un número de punto fijo determinado, fxp, está en forma i.f (entero de bits i, fracción de bits f). La conversión a float es similar al pseudocódigo siguiente.
float result = (float)(fxp >> f) + // extract integer
((float)(fxp & (2f - 1)) / (2f)); extraer fracción

 

Recursos (Direct3D 10)