gallivm: generalize 4x4f->1x16ub special case conversion
authorRoland Scheidegger <sroland@vmware.com>
Thu, 22 Dec 2016 02:51:40 +0000 (03:51 +0100)
committerRoland Scheidegger <sroland@vmware.com>
Fri, 6 Jan 2017 22:13:34 +0000 (23:13 +0100)
commit6e7ce1ef55b138ed2cdedb40cbc010b523de8743
tree75376ed731562e711fc19e98c0336e9739d638db
parent04480a04b10524e156cb01d5f7bd8ec02fcc4a67
gallivm: generalize 4x4f->1x16ub special case conversion

This special packing path can be easily extended to handle not just
float->unorm8 but also float->snorm8 and uint32->uint8 and int32->int8
(i.e. all interesting cases for llvmpipe fs backend code).
The packing parts all stay the same (only the last step packing will
be signed->signed instead of signed->unsigned but luckily even sse2 can do
both).
While here also note some bugs with that (we keep the bugs identical to
what we did before on x86, albeit other archs may differ). In particular
float->unorm8 too large values will still get clamped to 0, not 255, and for
float->snorm8 NaNs will end up as -1, not 0 (but we do the clamp against 1.0
there to prevent too large values ending up as -1.0 - this is inconsistent
to unorm8 handling but is what we ended up before, I'm not sure we can get
away without it). This is quite fishy in any case as we depend on
arch-dependent behavior of the iround (my understanding is in fact with
altivec the conversion would actually saturate although I've no idea about
NaNs, so probably wouldn't need to do anything for snorm).
(There are only minimal piglit tests for unorm clamping behavior AFAICT, in
particular nothing seems to test values which are too large to be handled by
the float->int conversion.)
For uint32->uint8 we also do a min against MAX_INT, since the source for
the packs is always signed (again, on x86 - should probably be able to
express these arch-dependent bits better some day).

Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
src/gallium/auxiliary/gallivm/lp_bld_conv.c