diff options
author | Adam Jackson <[email protected]> | 2013-06-24 09:48:56 -0400 |
---|---|---|
committer | Adam Jackson <[email protected]> | 2013-06-24 09:48:56 -0400 |
commit | 2151d893fbd4a4be092098170e2fbca8c35797a5 (patch) | |
tree | 88af00d0b64d08bf04d33f972709db32aecf884d /src/gallium/auxiliary/gallivm | |
parent | d282f4ea9b99e4eefec8ce0664cdf49d53d7b052 (diff) |
gallium: Fix llvmpipe on big-endian machines
Squashed commit of the following:
commit 0857a7e105bfcbc4d1431b2cc56612094c747ca3
Author: Richard Sandiford <[email protected]>
Date: Tue Jun 18 12:25:07 2013 -0400
gallivm: Fix lp_build_rgba8_to_fi32_soa for big endian
Reviewed-by: Adam Jackson <[email protected]>
Signed-off-by: Richard Sandiford <[email protected]>
commit 0d65131649a8aa140e2db228ba779d685c4333e3
Author: Richard Sandiford <[email protected]>
Date: Tue Jun 18 12:25:07 2013 -0400
gallivm: Fix big-endian machines
This adds a bit-shift count to the format table, and adds the concept of
vector or bitwise alignment on gathers.
Reviewed-by: Adam Jackson <[email protected]>
Signed-off-by: Richard Sandiford <[email protected]>
commit 9740bda9b7dc894b629ed38be9b51059ce90818f
Author: Richard Sandiford <[email protected]>
Date: Tue Jun 18 12:25:07 2013 -0400
llvmpipe: Fix convert_to_blend_type on big-endian
Reviewed-by: Adam Jackson <[email protected]>
Signed-off-by: Richard Sandiford <[email protected]>
commit ae037c2de0f029e4e99371c0de25560484f0d8df
Author: Richard Sandiford <[email protected]>
Date: Tue Jun 18 12:25:06 2013 -0400
util: Convert color pack to packed formats
This fixes them on big-endian.
Reviewed-by: Adam Jackson <[email protected]>
Signed-off-by: Richard Sandiford <[email protected]>
commit 5b05ac0c89ae092ea8ba5bba9f739708d7396b5c
Author: Richard Sandiford <[email protected]>
Date: Tue Jun 18 12:25:06 2013 -0400
graw-xlib: Convert to packed formats
Reviewed-by: Adam Jackson <[email protected]>
Signed-off-by: Richard Sandiford <[email protected]>
commit 51396e7d098cb6ff794391cf11afe4dbf86dbea0
Author: Richard Sandiford <[email protected]>
Date: Tue Jun 18 12:25:06 2013 -0400
format: Convert to packed formats
Reviewed-by: Adam Jackson <[email protected]>
Signed-off-by: Richard Sandiford <[email protected]>
commit 417b60bc66eb450e68a92ab0e47f76e292b385e6
Author: Adam Jackson <[email protected]>
Date: Tue Jun 18 12:25:06 2013 -0400
st/dri: Convert to packed formats
Reviewed-by: Adam Jackson <[email protected]>
Signed-off-by: Richard Sandiford <[email protected]>
commit 0934b2e022a5e0847d312c40734e2b44cac52fd8
Author: Richard Sandiford <[email protected]>
Date: Tue Jun 18 12:25:06 2013 -0400
st/xlib: Convert to packed formats
Reviewed-by: Adam Jackson <[email protected]>
Signed-off-by: Richard Sandiford <[email protected]>
commit a307ea3c3716a706963acce7966b5e405ba11db9
Author: Richard Sandiford <[email protected]>
Date: Tue Jun 18 12:25:06 2013 -0400
gbm: Convert to packed formats
Reviewed-by: Adam Jackson <[email protected]>
Signed-off-by: Richard Sandiford <[email protected]>
commit 53eebdd253e1960a645ea278f31d7ef6a6cf4aeb
Author: Richard Sandiford <[email protected]>
Date: Tue Jun 18 12:25:06 2013 -0400
tests: Convert to packed formats
Reviewed-by: Adam Jackson <[email protected]>
Signed-off-by: Richard Sandiford <[email protected]>
commit 2f77fe3ee524945eacd546efcac34f7799fb3124
Author: Adam Jackson <[email protected]>
Date: Tue Jun 18 13:07:37 2013 -0400
gallium: Document packed formats
Signed-off-by: Adam Jackson <[email protected]>
commit 1f1017159ce951f922210a430de9229f91f62714
Author: Richard Sandiford <[email protected]>
Date: Tue Jun 18 12:25:06 2013 -0400
gallium: Introduce 32-bit packed format names
These are for interacting with buffers natively described in terms of
bit shifts, like X11 visuals:
uint32_t xyzw8888 = (x << 0) | (y << 8) | (z << 16) | (w << 24);
Define these in terms of (endian-dependent) aliases to the array-style
format names.
Reviewed-by: Adam Jackson <[email protected]>
Signed-off-by: Richard Sandiford <[email protected]>
commit 6cc7ab1ee66ed668da78c1d951dfd7782b4e786a
Author: Adam Jackson <[email protected]>
Date: Mon Jun 3 12:10:32 2013 -0400
gallium: Document format name conventions
v2:
- Fix a channel name thinko (Michel Dänzer)
- Elaborate on SCALED versus INT
- Add links to DirectX and FOURCC docs
Signed-off-by: Adam Jackson <[email protected]>
commit df4d269e7fb62051a3c029b84147465001e5776e
Author: Adam Jackson <[email protected]>
Date: Tue Jun 18 12:25:06 2013 -0400
gallivm: Remove all notion of byte-swapping
Signed-off-by: Adam Jackson <[email protected]>
Signed-off-by: Adam Jackson <[email protected]>
Diffstat (limited to 'src/gallium/auxiliary/gallivm')
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_conv.c | 76 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_conv.h | 11 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_format_aos.c | 31 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_format_aos_array.c | 56 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_format_soa.c | 21 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c | 2 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_gather.c | 25 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_gather.h | 6 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c | 4 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_swizzle.c | 80 |
10 files changed, 104 insertions, 208 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_conv.c b/src/gallium/auxiliary/gallivm/lp_bld_conv.c index f11361ac06b..cbea966882a 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_conv.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_conv.c @@ -80,82 +80,6 @@ /** - * Byte swap on element. It will construct a call to intrinsic llvm.bswap - * based on the type. - * - * @param res element to byte swap. - * @param type int16_t, int32_t, int64_t, float or double - * @param - */ -LLVMValueRef -lp_build_bswap(struct gallivm_state *gallivm, - LLVMValueRef res, - struct lp_type type) -{ - LLVMTypeRef int_type = LLVMIntTypeInContext(gallivm->context, - type.width); - const char *intrinsic = NULL; - if (type.width == 8) - return res; - if (type.width == 16) - intrinsic = "llvm.bswap.i16"; - else if (type.width == 32) - intrinsic = "llvm.bswap.i32"; - else if (type.width == 64) - intrinsic = "llvm.bswap.i64"; - - assert (intrinsic != NULL); - - /* In case of a floating-point type cast to a int of same size and then - * cast back to fp type. - */ - if (type.floating) - res = LLVMBuildBitCast(gallivm->builder, res, int_type, ""); - res = lp_build_intrinsic_unary(gallivm->builder, intrinsic, int_type, res); - if (type.floating) - res = LLVMBuildBitCast(gallivm->builder, res, - lp_build_elem_type(gallivm, type), ""); - return res; -} - - -/** - * Byte swap every element in the vector. - * - * @param packed <vector> to convert - * @param src_type <vector> type of int16_t, int32_t, int64_t, float or - * double - * @param dst_type <vector> type to return - */ -LLVMValueRef -lp_build_bswap_vec(struct gallivm_state *gallivm, - LLVMValueRef packed, - struct lp_type src_type_vec, - struct lp_type dst_type_vec) -{ - LLVMBuilderRef builder = gallivm->builder; - LLVMTypeRef dst_type = lp_build_elem_type(gallivm, dst_type_vec); - LLVMValueRef res; - - if (src_type_vec.length == 1) { - res = lp_build_bswap(gallivm, packed, src_type_vec); - res = LLVMBuildBitCast(gallivm->builder, res, dst_type, ""); - } else { - unsigned i; - res = LLVMGetUndef(lp_build_vec_type(gallivm, dst_type_vec)); - for (i = 0; i < src_type_vec.length; ++i) { - LLVMValueRef index = lp_build_const_int32(gallivm, i); - LLVMValueRef elem = LLVMBuildExtractElement(builder, packed, index, ""); - elem = lp_build_bswap(gallivm, elem, src_type_vec); - elem = LLVMBuildBitCast(gallivm->builder, elem, dst_type, ""); - res = LLVMBuildInsertElement(gallivm->builder, res, elem, index, ""); - } - } - return res; -} - - -/** * Converts int16 half-float to float32 * Note this can be performed in 1 instruction if vcvtph2ps exists (f16c/cvt16) * [llvm.x86.vcvtph2ps / _mm_cvtph_ps] diff --git a/src/gallium/auxiliary/gallivm/lp_bld_conv.h b/src/gallium/auxiliary/gallivm/lp_bld_conv.h index d7dfed85187..42a11137473 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_conv.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_conv.h @@ -43,17 +43,6 @@ struct lp_type; LLVMValueRef -lp_build_bswap(struct gallivm_state *gallivm, - LLVMValueRef res, - struct lp_type type); - -LLVMValueRef -lp_build_bswap_vec(struct gallivm_state *gallivm, - LLVMValueRef packed, - struct lp_type src_type, - struct lp_type dst_type); - -LLVMValueRef lp_build_half_to_float(struct gallivm_state *gallivm, LLVMValueRef src); diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c b/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c index 6a1bf6765d7..af755d460c1 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c @@ -139,12 +139,12 @@ format_matches_type(const struct util_format_description *desc, /** - * Unpack a single pixel into its RGBA components. + * Unpack a single pixel into its XYZW components. * * @param desc the pixel format for the packed pixel value * @param packed integer pixel in a format such as PIPE_FORMAT_B8G8R8A8_UNORM * - * @return RGBA in a float[4] or ubyte[4] or ushort[4] vector. + * @return XYZW in a float[4] or ubyte[4] or ushort[4] vector. */ static INLINE LLVMValueRef lp_build_unpack_arith_rgba_aos(struct gallivm_state *gallivm, @@ -159,7 +159,6 @@ lp_build_unpack_arith_rgba_aos(struct gallivm_state *gallivm, boolean normalized; boolean needs_uitofp; - unsigned shift; unsigned i; /* TODO: Support more formats */ @@ -172,10 +171,6 @@ lp_build_unpack_arith_rgba_aos(struct gallivm_state *gallivm, * matches floating point size */ assert (LLVMTypeOf(packed) == LLVMInt32TypeInContext(gallivm->context)); -#ifdef PIPE_ARCH_BIG_ENDIAN - packed = lp_build_bswap(gallivm, packed, lp_type_uint(32)); -#endif - /* Broadcast the packed value to all four channels * before: packed = BGRA * after: packed = {BGRA, BGRA, BGRA, BGRA} @@ -194,11 +189,11 @@ lp_build_unpack_arith_rgba_aos(struct gallivm_state *gallivm, /* Initialize vector constants */ normalized = FALSE; needs_uitofp = FALSE; - shift = 0; /* Loop over 4 color components */ for (i = 0; i < 4; ++i) { unsigned bits = desc->channel[i].size; + unsigned shift = desc->channel[i].shift; if (desc->channel[i].type == UTIL_FORMAT_TYPE_VOID) { shifts[i] = LLVMGetUndef(LLVMInt32TypeInContext(gallivm->context)); @@ -224,12 +219,10 @@ lp_build_unpack_arith_rgba_aos(struct gallivm_state *gallivm, else scales[i] = lp_build_const_float(gallivm, 1.0); } - - shift += bits; } - /* Ex: convert packed = {BGRA, BGRA, BGRA, BGRA} - * into masked = {B, G, R, A} + /* Ex: convert packed = {XYZW, XYZW, XYZW, XYZW} + * into masked = {X, Y, Z, W} */ shifted = LLVMBuildLShr(builder, packed, LLVMConstVector(shifts, 4), ""); masked = LLVMBuildAnd(builder, shifted, LLVMConstVector(masks, 4), ""); @@ -276,7 +269,6 @@ lp_build_pack_rgba_aos(struct gallivm_state *gallivm, LLVMValueRef shifts[4]; LLVMValueRef scales[4]; boolean normalized; - unsigned shift; unsigned i, j; assert(desc->layout == UTIL_FORMAT_LAYOUT_PLAIN); @@ -302,9 +294,9 @@ lp_build_pack_rgba_aos(struct gallivm_state *gallivm, LLVMConstVector(swizzles, 4), ""); normalized = FALSE; - shift = 0; for (i = 0; i < 4; ++i) { unsigned bits = desc->channel[i].size; + unsigned shift = desc->channel[i].shift; if (desc->channel[i].type == UTIL_FORMAT_TYPE_VOID) { shifts[i] = LLVMGetUndef(LLVMInt32TypeInContext(gallivm->context)); @@ -325,8 +317,6 @@ lp_build_pack_rgba_aos(struct gallivm_state *gallivm, else scales[i] = lp_build_const_float(gallivm, 1.0); } - - shift += bits; } if (normalized) @@ -410,16 +400,11 @@ lp_build_fetch_rgba_aos(struct gallivm_state *gallivm, packed = lp_build_gather(gallivm, type.length/4, format_desc->block.bits, type.width*4, - base_ptr, offset); + base_ptr, offset, TRUE); assert(format_desc->block.bits <= vec_len); packed = LLVMBuildBitCast(gallivm->builder, packed, dst_vec_type, ""); -#ifdef PIPE_ARCH_BIG_ENDIAN - if (type.floating) - packed = lp_build_bswap_vec(gallivm, packed, type, - lp_type_float_vec(type.width, vec_len)); -#endif return lp_build_format_swizzle_aos(format_desc, &bld, packed); } @@ -453,7 +438,7 @@ lp_build_fetch_rgba_aos(struct gallivm_state *gallivm, packed = lp_build_gather_elem(gallivm, num_pixels, format_desc->block.bits, 32, - base_ptr, offset, k); + base_ptr, offset, k, FALSE); tmps[k] = lp_build_unpack_arith_rgba_aos(gallivm, format_desc, diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_aos_array.c b/src/gallium/auxiliary/gallivm/lp_bld_format_aos_array.c index 3402a0b1530..ee3ca86c000 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_format_aos_array.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_format_aos_array.c @@ -40,58 +40,6 @@ #include "pipe/p_state.h" -#ifdef PIPE_ARCH_BIG_ENDIAN -static LLVMValueRef -lp_build_read_int_bswap(struct gallivm_state *gallivm, - LLVMValueRef base_ptr, - unsigned src_width, - LLVMTypeRef src_type, - unsigned i, - LLVMTypeRef dst_type) -{ - LLVMBuilderRef builder = gallivm->builder; - LLVMValueRef index = lp_build_const_int32(gallivm, i); - LLVMValueRef ptr = LLVMBuildGEP(builder, base_ptr, &index, 1, ""); - LLVMValueRef res = LLVMBuildLoad(builder, ptr, ""); - res = lp_build_bswap(gallivm, res, lp_type_uint(src_width)); - return LLVMBuildBitCast(builder, res, dst_type, ""); -} - -static LLVMValueRef -lp_build_fetch_read_big_endian(struct gallivm_state *gallivm, - struct lp_type src_type, - LLVMValueRef base_ptr) -{ - LLVMBuilderRef builder = gallivm->builder; - unsigned src_width = src_type.width; - unsigned length = src_type.length; - LLVMTypeRef src_elem_type = LLVMIntTypeInContext(gallivm->context, src_width); - LLVMTypeRef dst_elem_type = lp_build_elem_type (gallivm, src_type); - LLVMTypeRef src_ptr_type = LLVMPointerType(src_elem_type, 0); - LLVMValueRef res; - - base_ptr = LLVMBuildPointerCast(builder, base_ptr, src_ptr_type, ""); - if (length == 1) { - /* Scalar */ - res = lp_build_read_int_bswap(gallivm, base_ptr, src_width, src_elem_type, - 0, dst_elem_type); - } else { - /* Vector */ - LLVMTypeRef dst_vec_type = LLVMVectorType(dst_elem_type, length); - unsigned i; - - res = LLVMGetUndef(dst_vec_type); - for (i = 0; i < length; ++i) { - LLVMValueRef index = lp_build_const_int32(gallivm, i); - LLVMValueRef elem = lp_build_read_int_bswap(gallivm, base_ptr, src_width, - src_elem_type, i, dst_elem_type); - res = LLVMBuildInsertElement(builder, res, elem, index, ""); - } - } - - return res; -} -#endif /** * @brief lp_build_fetch_rgba_aos_array @@ -124,13 +72,9 @@ lp_build_fetch_rgba_aos_array(struct gallivm_state *gallivm, /* Read whole vector from memory, unaligned */ ptr = LLVMBuildGEP(builder, base_ptr, &offset, 1, ""); -#ifdef PIPE_ARCH_BIG_ENDIAN - res = lp_build_fetch_read_big_endian(gallivm, src_type, ptr); -#else ptr = LLVMBuildPointerCast(builder, ptr, LLVMPointerType(src_vec_type, 0), ""); res = LLVMBuildLoad(builder, ptr, ""); lp_set_load_alignment(res, src_type.width / 8); -#endif /* Truncate doubles to float */ if (src_type.floating && src_type.width == 64) { diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c index edc24424289..4c6bd81047a 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c @@ -115,7 +115,6 @@ lp_build_unpack_rgba_soa(struct gallivm_state *gallivm, LLVMBuilderRef builder = gallivm->builder; struct lp_build_context bld; LLVMValueRef inputs[4]; - unsigned start; unsigned chan; assert(format_desc->layout == UTIL_FORMAT_LAYOUT_PLAIN); @@ -128,9 +127,9 @@ lp_build_unpack_rgba_soa(struct gallivm_state *gallivm, lp_build_context_init(&bld, gallivm, type); /* Decode the input vector components */ - start = 0; for (chan = 0; chan < format_desc->nr_channels; ++chan) { const unsigned width = format_desc->channel[chan].size; + const unsigned start = format_desc->channel[chan].shift; const unsigned stop = start + width; LLVMValueRef input; @@ -256,8 +255,6 @@ lp_build_unpack_rgba_soa(struct gallivm_state *gallivm, } inputs[chan] = input; - - start = stop; } lp_build_format_swizzle_soa(format_desc, &bld, inputs, rgba_out); @@ -291,7 +288,11 @@ lp_build_rgba8_to_fi32_soa(struct gallivm_state *gallivm, /* Decode the input vector components */ for (chan = 0; chan < 4; ++chan) { +#ifdef PIPE_ARCH_LITTLE_ENDIAN unsigned start = chan*8; +#else + unsigned start = (3-chan)*8; +#endif unsigned stop = start + 8; LLVMValueRef input; @@ -360,13 +361,14 @@ lp_build_fetch_rgba_soa(struct gallivm_state *gallivm, /* * gather the texels from the texture - * Ex: packed = {BGRA, BGRA, BGRA, BGRA}. + * Ex: packed = {XYZW, XYZW, XYZW, XYZW} */ + assert(format_desc->block.bits <= type.width); packed = lp_build_gather(gallivm, type.length, format_desc->block.bits, type.width, - base_ptr, offset); + base_ptr, offset, FALSE); /* * convert texels to float rgba @@ -391,7 +393,8 @@ lp_build_fetch_rgba_soa(struct gallivm_state *gallivm, packed = lp_build_gather(gallivm, type.length, format_desc->block.bits, - type.width, base_ptr, offset); + type.width, base_ptr, offset, + FALSE); if (format_desc->format == PIPE_FORMAT_R11G11B10_FLOAT) { lp_build_r11g11b10_to_float(gallivm, packed, rgba_out); } @@ -418,14 +421,14 @@ lp_build_fetch_rgba_soa(struct gallivm_state *gallivm, LLVMValueRef s_offset = lp_build_const_int_vec(gallivm, type, 4); offset = LLVMBuildAdd(builder, offset, s_offset, ""); packed = lp_build_gather(gallivm, type.length, - 32, type.width, base_ptr, offset); + 32, type.width, base_ptr, offset, FALSE); packed = LLVMBuildAnd(builder, packed, lp_build_const_int_vec(gallivm, type, mask), ""); } else { assert (format_desc->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT); packed = lp_build_gather(gallivm, type.length, - 32, type.width, base_ptr, offset); + 32, type.width, base_ptr, offset, TRUE); packed = LLVMBuildBitCast(builder, packed, lp_build_vec_type(gallivm, type), ""); } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c b/src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c index e542abce0cc..873f354c040 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c @@ -497,7 +497,7 @@ lp_build_fetch_subsampled_rgba_aos(struct gallivm_state *gallivm, assert(format_desc->block.width == 2); assert(format_desc->block.height == 1); - packed = lp_build_gather(gallivm, n, 32, 32, base_ptr, offset); + packed = lp_build_gather(gallivm, n, 32, 32, base_ptr, offset, FALSE); (void)j; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_gather.c b/src/gallium/auxiliary/gallivm/lp_bld_gather.c index eefb23a946f..9155d811c06 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_gather.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_gather.c @@ -78,7 +78,8 @@ lp_build_gather_elem(struct gallivm_state *gallivm, unsigned dst_width, LLVMValueRef base_ptr, LLVMValueRef offsets, - unsigned i) + unsigned i, + boolean vector_justify) { LLVMTypeRef src_type = LLVMIntTypeInContext(gallivm->context, src_width); LLVMTypeRef src_ptr_type = LLVMPointerType(src_type, 0); @@ -97,10 +98,12 @@ lp_build_gather_elem(struct gallivm_state *gallivm, res = LLVMBuildTrunc(gallivm->builder, res, dst_elem_type, ""); } else if (src_width < dst_width) { res = LLVMBuildZExt(gallivm->builder, res, dst_elem_type, ""); + if (vector_justify) { #ifdef PIPE_ARCH_BIG_ENDIAN - res = LLVMBuildShl(gallivm->builder, res, - LLVMConstInt(dst_elem_type, dst_width - src_width, 0), ""); + res = LLVMBuildShl(gallivm->builder, res, + LLVMConstInt(dst_elem_type, dst_width - src_width, 0), ""); #endif + } } return res; @@ -112,11 +115,20 @@ lp_build_gather_elem(struct gallivm_state *gallivm, * Use for fetching texels from a texture. * For SSE, typical values are length=4, src_width=32, dst_width=32. * + * When src_width < dst_width, the return value can be justified in + * one of two ways: + * "integer justification" is used when the caller treats the destination + * as a packed integer bitmask, as described by the channels' "shift" and + * "width" fields; + * "vector justification" is used when the caller casts the destination + * to a vector and needs channel X to be in vector element 0. + * * @param length length of the offsets * @param src_width src element width in bits * @param dst_width result element width in bits (src will be expanded to fit) * @param base_ptr base pointer, should be a i8 pointer type. * @param offsets vector with offsets + * @param vector_justify select vector rather than integer justification */ LLVMValueRef lp_build_gather(struct gallivm_state *gallivm, @@ -124,7 +136,8 @@ lp_build_gather(struct gallivm_state *gallivm, unsigned src_width, unsigned dst_width, LLVMValueRef base_ptr, - LLVMValueRef offsets) + LLVMValueRef offsets, + boolean vector_justify) { LLVMValueRef res; @@ -132,7 +145,7 @@ lp_build_gather(struct gallivm_state *gallivm, /* Scalar */ return lp_build_gather_elem(gallivm, length, src_width, dst_width, - base_ptr, offsets, 0); + base_ptr, offsets, 0, vector_justify); } else { /* Vector */ @@ -146,7 +159,7 @@ lp_build_gather(struct gallivm_state *gallivm, LLVMValueRef elem; elem = lp_build_gather_elem(gallivm, length, src_width, dst_width, - base_ptr, offsets, i); + base_ptr, offsets, i, vector_justify); res = LLVMBuildInsertElement(gallivm->builder, res, elem, index, ""); } } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_gather.h b/src/gallium/auxiliary/gallivm/lp_bld_gather.h index 8e4c07d82b8..ee694732d36 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_gather.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_gather.h @@ -47,7 +47,8 @@ lp_build_gather_elem(struct gallivm_state *gallivm, unsigned dst_width, LLVMValueRef base_ptr, LLVMValueRef offsets, - unsigned i); + unsigned i, + boolean vector_justify); LLVMValueRef lp_build_gather(struct gallivm_state *gallivm, @@ -55,7 +56,8 @@ lp_build_gather(struct gallivm_state *gallivm, unsigned src_width, unsigned dst_width, LLVMValueRef base_ptr, - LLVMValueRef offsets); + LLVMValueRef offsets, + boolean vector_justify); LLVMValueRef lp_build_gather_values(struct gallivm_state * gallivm, diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c index c31b05d7022..104c24d83b9 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c @@ -531,7 +531,7 @@ lp_build_sample_fetch_image_nearest(struct lp_build_sample_context *bld, bld->texel_type.length, bld->format_desc->block.bits, bld->texel_type.width, - data_ptr, offset); + data_ptr, offset, TRUE); rgba8 = LLVMBuildBitCast(builder, rgba8, u8n_vec_type, ""); } @@ -893,7 +893,7 @@ lp_build_sample_fetch_image_linear(struct lp_build_sample_context *bld, bld->texel_type.length, bld->format_desc->block.bits, bld->texel_type.width, - data_ptr, offset[k][j][i]); + data_ptr, offset[k][j][i], TRUE); rgba8 = LLVMBuildBitCast(builder, rgba8, u8n_vec_type, ""); } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_swizzle.c b/src/gallium/auxiliary/gallivm/lp_bld_swizzle.c index 08d817a28f5..79116bcf391 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_swizzle.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_swizzle.c @@ -217,6 +217,20 @@ lp_build_swizzle_scalar_aos(struct lp_build_context *bld, a = LLVMBuildBitCast(builder, a, lp_build_vec_type(bld->gallivm, type2), ""); + /* + * Vector element 0 is always channel X. + * + * 76 54 32 10 (array numbering) + * Little endian reg in: YX YX YX YX + * Little endian reg out: YY YY YY YY if shift right (shift == -1) + * XX XX XX XX if shift left (shift == 1) + * + * 01 23 45 67 (array numbering) + * Big endian reg in: XY XY XY XY + * Big endian reg out: YY YY YY YY if shift left (shift == 1) + * XX XX XX XX if shift right (shift == -1) + * + */ #ifdef PIPE_ARCH_LITTLE_ENDIAN shift = channel == 0 ? 1 : -1; #else @@ -240,10 +254,23 @@ lp_build_swizzle_scalar_aos(struct lp_build_context *bld, /* * Bit mask and recursive shifts * + * Little-endian registers: + * + * 7654 3210 + * WZYX WZYX .... WZYX <= input + * 00Y0 00Y0 .... 00Y0 <= mask + * 00YY 00YY .... 00YY <= shift right 1 (shift amount -1) + * YYYY YYYY .... YYYY <= shift left 2 (shift amount 2) + * + * Big-endian registers: + * + * 0123 4567 * XYZW XYZW .... XYZW <= input - * 0Y00 0Y00 .... 0Y00 - * YY00 YY00 .... YY00 - * YYYY YYYY .... YYYY <= output + * 0Y00 0Y00 .... 0Y00 <= mask + * YY00 YY00 .... YY00 <= shift left 1 (shift amount 1) + * YYYY YYYY .... YYYY <= shift right 2 (shift amount -2) + * + * shifts[] gives little-endian shift amounts; we need to negate for big-endian. */ struct lp_type type4; const int shifts[4][2] = { @@ -274,14 +301,15 @@ lp_build_swizzle_scalar_aos(struct lp_build_context *bld, LLVMValueRef tmp = NULL; int shift = shifts[channel][i]; -#ifdef PIPE_ARCH_LITTLE_ENDIAN + /* See endianness diagram above */ +#ifdef PIPE_ARCH_BIG_ENDIAN shift = -shift; #endif if(shift > 0) - tmp = LLVMBuildLShr(builder, a, lp_build_const_int_vec(bld->gallivm, type4, shift*type.width), ""); + tmp = LLVMBuildShl(builder, a, lp_build_const_int_vec(bld->gallivm, type4, shift*type.width), ""); if(shift < 0) - tmp = LLVMBuildShl(builder, a, lp_build_const_int_vec(bld->gallivm, type4, -shift*type.width), ""); + tmp = LLVMBuildLShr(builder, a, lp_build_const_int_vec(bld->gallivm, type4, -shift*type.width), ""); assert(tmp); if(tmp) @@ -474,21 +502,39 @@ lp_build_swizzle_aos(struct lp_build_context *bld, /* * Mask and shift the channels, trying to group as many channels in the - * same shift as possible + * same shift as possible. The shift amount is positive for shifts left + * and negative for shifts right. */ for (shift = -3; shift <= 3; ++shift) { uint64_t mask = 0; assert(type4.width <= sizeof(mask)*8); + /* + * Vector element numbers follow the XYZW order, so 0 is always X, etc. + * After widening 4 times we have: + * + * 3210 + * Little-endian register layout: WZYX + * + * 0123 + * Big-endian register layout: XYZW + * + * For little-endian, higher-numbered channels are obtained by a shift right + * (negative shift amount) and lower-numbered channels by a shift left + * (positive shift amount). The opposite is true for big-endian. + */ for (chan = 0; chan < 4; ++chan) { - /* FIXME: big endian */ - if (swizzles[chan] < 4 && - chan - swizzles[chan] == shift) { + if (swizzles[chan] < 4) { + /* We need to move channel swizzles[chan] into channel chan */ #ifdef PIPE_ARCH_LITTLE_ENDIAN - mask |= ((1ULL << type.width) - 1) << (swizzles[chan] * type.width); + if (swizzles[chan] - chan == -shift) { + mask |= ((1ULL << type.width) - 1) << (swizzles[chan] * type.width); + } #else - mask |= ((1ULL << type.width) - 1) << (type4.width - type.width) >> (swizzles[chan] * type.width); + if (swizzles[chan] - chan == shift) { + mask |= ((1ULL << type.width) - 1) << (type4.width - type.width) >> (swizzles[chan] * type.width); + } #endif } } @@ -502,21 +548,11 @@ lp_build_swizzle_aos(struct lp_build_context *bld, masked = LLVMBuildAnd(builder, a, lp_build_const_int_vec(bld->gallivm, type4, mask), ""); if (shift > 0) { -#ifdef PIPE_ARCH_LITTLE_ENDIAN shifted = LLVMBuildShl(builder, masked, lp_build_const_int_vec(bld->gallivm, type4, shift*type.width), ""); -#else - shifted = LLVMBuildLShr(builder, masked, - lp_build_const_int_vec(bld->gallivm, type4, shift*type.width), ""); -#endif } else if (shift < 0) { -#ifdef PIPE_ARCH_LITTLE_ENDIAN shifted = LLVMBuildLShr(builder, masked, lp_build_const_int_vec(bld->gallivm, type4, -shift*type.width), ""); -#else - shifted = LLVMBuildShl(builder, masked, - lp_build_const_int_vec(bld->gallivm, type4, -shift*type.width), ""); -#endif } else { shifted = masked; } |