summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Fonseca <[email protected]>2010-10-08 19:48:16 +0100
committerJosé Fonseca <[email protected]>2010-10-08 19:48:16 +0100
commit3fde8167a5d9c1e845053ae4e6a9cd49628adc71 (patch)
treed2038c9c08512c07f236069e10a5252f17f05280
parent438390418d27838bcfcb5bbb4c486db45dbaa44d (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.c32
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_swizzle.c77
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_swizzle.h8
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.