diff options
author | Luca Barbieri <[email protected]> | 2010-03-24 18:12:45 +0100 |
---|---|---|
committer | Michal Krol <[email protected]> | 2010-04-01 13:33:07 +0200 |
commit | 3ff175d6de89ad92d167362355501f99d06f0f97 (patch) | |
tree | 6332294693fc3581785927a9df6013aecf9aca22 /src/gallium/auxiliary/util/u_half.h | |
parent | 110e039d0df08ae1642adf4bd20f07992b9ffe9c (diff) |
gallium/util: add fast half float conversion functions
This adds a fast half float conversion facility to Gallium.
Mesa already contains such a facility, but using a much worse algorithm.
This one is an implementation of
www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf
and uses a branch-less algorithm with some lookup tables small enough
to fit in the L1 cache.
Ideally, Mesa should start using these functions too, but I'm not sure
how to arrange that with the current build system.
A new "u_gctors.cpp" is added that defines a global C++ constructor
allowing to initialize to conversion lookup tables at library init.
Diffstat (limited to 'src/gallium/auxiliary/util/u_half.h')
-rw-r--r-- | src/gallium/auxiliary/util/u_half.h | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/util/u_half.h b/src/gallium/auxiliary/util/u_half.h new file mode 100644 index 00000000000..464d43df8a0 --- /dev/null +++ b/src/gallium/auxiliary/util/u_half.h @@ -0,0 +1,55 @@ +#ifndef U_HALF_H +#define U_HALF_H + +#include "pipe/p_compiler.h" + +extern uint32_t util_half_to_float_mantissa_table[2048]; +extern uint32_t util_half_to_float_exponent_table[64]; +extern uint32_t util_half_to_float_offset_table[64]; +extern uint16_t util_float_to_half_base_table[512]; +extern uint8_t util_float_to_half_shift_table[512]; + +/* + * Note that if the half float is a signaling NaN, the x87 FPU will turn + * it into a quiet NaN immediately upon loading into a float. + * + * Additionally, denormals may be flushed to zero. + * + * To avoid this, use the floatui functions instead of the float ones + * when just doing conversion rather than computation on the resulting + * floats. + */ + +static INLINE uint32_t +util_half_to_floatui(half h) +{ + unsigned exp = h >> 10; + return util_half_to_float_mantissa_table[util_half_to_float_offset_table[exp] + (h & 0x3ff)] + + util_half_to_float_exponent_table[exp]; +} + +static INLINE float +util_half_to_float(half h) +{ + union {float f; uint32_t v;} r; + r.v = util_half_to_floatui(h); + return r.f; +} + +static INLINE half +util_floatui_to_half(uint32_t v) +{ + unsigned signexp = v >> 23; + return util_float_to_half_base_table[signexp] + + ((v & 0x007fffff) >> util_float_to_half_shift_table[signexp]); +} + +static INLINE half +util_float_to_half(float f) +{ + union {float f; uint32_t v;} i; + i.f = f; + return util_floatui_to_half(i.v); +} + +#endif /* U_HALF_H */ |