Conversión exacta de UNORM8 a coma flotante: dos multiplicaciones bastan

Fuentes: Exact UNORM8 to float

Los formatos UNORM8 almacenan un valor en el intervalo [0, 1] como un entero sin signo de 8 bits en GPUs. La conversión exacta a coma flotante consistiría, en aritmética exacta, en dividir el entero por 255. Sin embargo, la especificación funcional de D3D11.3 desaconseja exigir una precisión de 1/2 ULP por considerarla costosa, aunque el autor constata que la mayoría de GPUs ya realizan conversiones exactas en la práctica.

El artículo describe tres vías para garantizar un resultado bit-exacto. La primera recurre a la doble precisión: convertir el entero a double, multiplicar por 1,0/255,0 y redondear a float32. Es trivial de verificar por fuerza bruta sobre los 256 valores posibles, pero introduce una dependencia de float64, no siempre deseable en pipelines gráficos.

La segunda evita los doubles y se apoya en una serie geométrica: 1/255 = 1/256 + 1/65536 + 1/16777216 + …, cuyos denominadores son potencias de dos y se reducen a desplazamientos exactos. Empaquetando los términos necesarios en dos constantes precalculadas (k0 y k1), la conversión queda en dos multiplicaciones y una suma tras el cast entero→float, o en dos operaciones en coma flotante si se dispone de FMA.

La tercera, propuesta por Alexandre Mutel, es la más elegante: el recíproco de 255·3 sí produce redondeo correcto en float32, y multiplicar enteros en [0, 255] por 3 cabe de forma exacta en la mantisa de 24 bits. Con dos multiplicaciones —primero por 3 y luego por el recípropo precalculado— se obtiene la conversión exacta sin divisiones, sin doubles y sin series. El autor la declara ganadora por su simplicidad y rendimiento uniforme en cualquier hardware compatible con IEEE-754.