summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJosé Fonseca <[email protected]>2010-10-06 14:06:14 +0100
committerJosé Fonseca <[email protected]>2010-10-06 18:46:29 +0100
commit4648846bd6c376877f024ccf300ceac5b0b3dcd6 (patch)
tree46bab37d4f04b5ff498de00495db0684f7b5338c /src
parentdf3505b19341424a605be703a27f50ea585ad71f (diff)
gallivm: Use a faster (and less accurate) log2 in lod computation.
Diffstat (limited to 'src')
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_arit.c44
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_arit.h5
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_sample.c4
3 files changed, 53 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.c b/src/gallium/auxiliary/gallivm/lp_bld_arit.c
index 3f9c250ad57..ff94f498acf 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_arit.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.c
@@ -2286,3 +2286,47 @@ lp_build_log2(struct lp_build_context *bld,
lp_build_log2_approx(bld, x, NULL, NULL, &res);
return res;
}
+
+
+/**
+ * Faster (and less accurate) log2.
+ *
+ * log2(x) = floor(log2(x)) + frac(x)
+ *
+ * See http://www.flipcode.com/archives/Fast_log_Function.shtml
+ */
+LLVMValueRef
+lp_build_fast_log2(struct lp_build_context *bld,
+ LLVMValueRef x)
+{
+ const struct lp_type type = bld->type;
+ LLVMTypeRef vec_type = bld->vec_type;
+ LLVMTypeRef int_vec_type = bld->int_vec_type;
+
+ unsigned mantissa = lp_mantissa(type);
+ LLVMValueRef mantmask = lp_build_const_int_vec(type, (1ULL << mantissa) - 1);
+ LLVMValueRef one = LLVMConstBitCast(bld->one, int_vec_type);
+
+ LLVMValueRef ipart;
+ LLVMValueRef fpart;
+
+ assert(lp_check_value(bld->type, x));
+
+ assert(type.floating);
+
+ x = LLVMBuildBitCast(bld->builder, x, int_vec_type, "");
+
+ /* ipart = floor(log2(x)) - 1 */
+ ipart = LLVMBuildLShr(bld->builder, x, lp_build_const_int_vec(type, mantissa), "");
+ ipart = LLVMBuildAnd(bld->builder, ipart, lp_build_const_int_vec(type, 255), "");
+ ipart = LLVMBuildSub(bld->builder, ipart, lp_build_const_int_vec(type, 128), "");
+ ipart = LLVMBuildSIToFP(bld->builder, ipart, vec_type, "");
+
+ /* fpart = 1.0 + frac(x) */
+ fpart = LLVMBuildAnd(bld->builder, x, mantmask, "");
+ fpart = LLVMBuildOr(bld->builder, fpart, one, "");
+ fpart = LLVMBuildBitCast(bld->builder, fpart, vec_type, "");
+
+ /* floor(log2(x)) + frac(x) */
+ return LLVMBuildFAdd(bld->builder, ipart, fpart, "");
+}
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.h b/src/gallium/auxiliary/gallivm/lp_bld_arit.h
index 31efa9921ce..3ed4fec2333 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_arit.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.h
@@ -212,6 +212,11 @@ LLVMValueRef
lp_build_log2(struct lp_build_context *bld,
LLVMValueRef a);
+LLVMValueRef
+lp_build_fast_log2(struct lp_build_context *bld,
+ LLVMValueRef a);
+
+
void
lp_build_exp2_approx(struct lp_build_context *bld,
LLVMValueRef x,
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.c b/src/gallium/auxiliary/gallivm/lp_bld_sample.c
index aee94c1b866..9dee653eee8 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.c
@@ -243,7 +243,11 @@ lp_build_lod_selector(struct lp_build_sample_context *bld,
}
/* compute lod = log2(rho) */
+#if 0
lod = lp_build_log2(float_bld, rho);
+#else
+ lod = lp_build_fast_log2(float_bld, rho);
+#endif
/* add shader lod bias */
if (lod_bias) {