diff options
author | José Fonseca <[email protected]> | 2010-10-08 19:48:16 +0100 |
---|---|---|
committer | José Fonseca <[email protected]> | 2010-10-08 19:48:16 +0100 |
commit | 3fde8167a5d9c1e845053ae4e6a9cd49628adc71 (patch) | |
tree | d2038c9c08512c07f236069e10a5252f17f05280 | |
parent | 438390418d27838bcfcb5bbb4c486db45dbaa44d (diff) |
gallivm: Help for combined extraction and broadcasting.
Doesn't change generated code quality, but saves some typing.
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_sample.c | 32 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_swizzle.c | 77 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_swizzle.h | 8 |
3 files changed, 102 insertions, 15 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.c b/src/gallium/auxiliary/gallivm/lp_bld_sample.c index 6a684a9a0bf..7a64392d3c1 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.c @@ -639,7 +639,6 @@ lp_build_mipmap_level_sizes(struct lp_build_sample_context *bld, const unsigned dims = bld->dims; LLVMValueRef ilevel_vec; LLVMValueRef size_vec; - LLVMValueRef width, height, depth; LLVMTypeRef i32t = LLVMInt32Type(); ilevel_vec = lp_build_broadcast_scalar(&bld->int_size_bld, ilevel); @@ -649,18 +648,19 @@ lp_build_mipmap_level_sizes(struct lp_build_sample_context *bld, */ size_vec = lp_build_minify(&bld->int_size_bld, bld->int_size, ilevel_vec); - if (dims <= 1) { - width = size_vec; - } - else { - width = LLVMBuildExtractElement(bld->builder, size_vec, - LLVMConstInt(i32t, 0, 0), ""); - } - *out_width_vec = lp_build_broadcast_scalar(&bld->int_coord_bld, width); + *out_width_vec = lp_build_extract_broadcast(bld->builder, + bld->int_size_type, + bld->int_coord_type, + size_vec, + LLVMConstInt(i32t, 0, 0)); if (dims >= 2) { - height = LLVMBuildExtractElement(bld->builder, size_vec, - LLVMConstInt(i32t, 1, 0), ""); - *out_height_vec = lp_build_broadcast_scalar(&bld->int_coord_bld, height); + + *out_height_vec = lp_build_extract_broadcast(bld->builder, + bld->int_size_type, + bld->int_coord_type, + size_vec, + LLVMConstInt(i32t, 1, 0)); + *row_stride_vec = lp_build_get_level_stride_vec(bld, bld->row_stride_array, ilevel); @@ -669,9 +669,11 @@ lp_build_mipmap_level_sizes(struct lp_build_sample_context *bld, bld->img_stride_array, ilevel); if (dims == 3) { - depth = LLVMBuildExtractElement(bld->builder, size_vec, - LLVMConstInt(i32t, 2, 0), ""); - *out_depth_vec = lp_build_broadcast_scalar(&bld->int_coord_bld, depth); + *out_depth_vec = lp_build_extract_broadcast(bld->builder, + bld->int_size_type, + bld->int_coord_type, + size_vec, + LLVMConstInt(i32t, 2, 0)); } } } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_swizzle.c b/src/gallium/auxiliary/gallivm/lp_bld_swizzle.c index 2e9e8386de0..4685a90e418 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_swizzle.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_swizzle.c @@ -101,6 +101,83 @@ lp_build_broadcast_scalar(struct lp_build_context *bld, /** + * Combined extract and broadcast (or a mere shuffle when the two types match) + */ +LLVMValueRef +lp_build_extract_broadcast(LLVMBuilderRef builder, + struct lp_type src_type, + struct lp_type dst_type, + LLVMValueRef vector, + LLVMValueRef index) +{ + LLVMTypeRef i32t = LLVMInt32Type(); + LLVMValueRef res; + + assert(src_type.floating == dst_type.floating); + assert(src_type.width == dst_type.width); + + assert(lp_check_value(src_type, vector)); + assert(LLVMTypeOf(index) == i32t); + + if (src_type.length == 1) { + if (dst_type.length == 1) { + /* + * Trivial scalar -> scalar. + */ + + res = vector; + } + else { + /* + * Broadcast scalar -> vector. + */ + + res = lp_build_broadcast(builder, + lp_build_vec_type(dst_type), + vector); + } + } + else { + if (dst_type.length == src_type.length) { + /* + * Special shuffle of the same size. + */ + + LLVMValueRef shuffle; + shuffle = lp_build_broadcast(builder, + LLVMVectorType(i32t, dst_type.length), + index); + res = LLVMBuildShuffleVector(builder, vector, + LLVMGetUndef(lp_build_vec_type(dst_type)), + shuffle, ""); + } + else { + LLVMValueRef scalar; + scalar = LLVMBuildExtractElement(builder, vector, index, ""); + if (dst_type.length == 1) { + /* + * Trivial extract scalar from vector. + */ + + res = scalar; + } + else { + /* + * General case of different sized vectors. + */ + + res = lp_build_broadcast(builder, + lp_build_vec_type(dst_type), + vector); + } + } + } + + return res; +} + + +/** * Swizzle one channel into all other three channels. */ LLVMValueRef diff --git a/src/gallium/auxiliary/gallivm/lp_bld_swizzle.h b/src/gallium/auxiliary/gallivm/lp_bld_swizzle.h index f9b6a5e7258..fdea8442aef 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_swizzle.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_swizzle.h @@ -55,6 +55,14 @@ lp_build_broadcast_scalar(struct lp_build_context *bld, LLVMValueRef scalar); +LLVMValueRef +lp_build_extract_broadcast(LLVMBuilderRef builder, + struct lp_type src_type, + struct lp_type dst_type, + LLVMValueRef vector, + LLVMValueRef index); + + /** * Broadcast one channel of a vector composed of arrays of XYZW structures into * all four channel. |