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 varias 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 enteras 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 todos 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 todos los 0 a los 1 representa una progresión no lineal en la interpretación del 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", bajo condiciones de visualización "promedio", en una pantalla "promedio". 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 intervalo superior a una representación de intervalo inferior

  • Se usa round-to-zero durante la conversión a otro formato float. Si el destino es un formato entero o de punto fijo, se usa round-to-nearest-even, a menos que la conversión se documente explícitamente como el uso de otro comportamiento de redondeo, como round-to-nearest para FLOAT a SNORM, FLOAT a UNORM o FLOAT a SRGB. Otras excepciones son las instrucciones de 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 float de 32 bits grande se escribe en un RenderTarget flotante de 16 bits), el valor máximo representable (firmado correctamente), NO incluido el infinito firmado (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 intervalo 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 intervalo superior se convertirá en 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 intervalo superior

  • NaN en un formato de intervalo inferior se convertirá en 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á en la representación INF en el formato de intervalo superior si está disponible en el formato de intervalo 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 intervalo 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 de Denorm (porque Denorms en operaciones en floats de 32 bits vaciados para firmar 0 conservado).

Conversión de enteros

En la tabla siguiente se describen las conversiones de varias representaciones descritas anteriormente en 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 a 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 float (llámalo 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, dividido por 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.
  • Convierta 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 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. (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.
  • Convertir 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 (entero) restante se convierte directamente en un entero.
Esta conversión se 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 deje de crearse 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 de n-bit inicial, 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 unidad de último lugar (en el lado SRGB).
FLOAT SRGB A continuación se muestra la conversión FLOAT -> SRGB ideal.
Suponiendo que el componente de color SRGB de destino tenga 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
  • Convertir 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 (entero) restante se convierte directamente en un entero.
Esta conversión se 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 deje de crearse 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 fija en 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 cambiar 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 fijo 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" omnipresente es un caso especial de un entero de punto fijo con el decimal al final del número.

Las representaciones de número de punto fijo 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 de entero se almacena en el complemento de 2, al menos como se define aquí (aunque también se puede definir para enteros sin signo). La parte fraccionarcional se almacena en forma sin signo. 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 con la 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 simplemente significa agregar 256, ya que el decimal es de 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 de 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 de vértices recortadas posteriores en el rasterizador se acoplan a un 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 fijas acopladas del punto fijo.
  • Las coordenadas de textura para las operaciones de muestreo se acoplan 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 infinitomente preciso n*2f después del último paso anterior.
Entero de punto fijo FLOAT Supongamos que la representación de punto fija 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 fraccionaria. Supongamos que un número de punto fijo determinado, fxp, está en forma i.f (i bits enteros, 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)