From 50f19e3a668b1b589bf00613d33c7c7c4e6a4954 Mon Sep 17 00:00:00 2001 From: Roland Scheidegger <sroland@vmware.com> Date: Mon, 11 Nov 2013 15:11:59 +0000 Subject: draw,llvmpipe: use exponent manipulation instead of exp2 for polygon offset Since we explicitly require a integer input we should avoid using exp2 math (even if we were using optimized versions), which turns the exp2 into a int sub (plus some casts). v2: fix bogus uint (needs to be int) math spotted by Matthew, fix comments Reviewed-by: Jose Fonseca <jfonseca@vmware.com> --- src/gallium/auxiliary/draw/draw_pipe_offset.c | 21 +++++++++++++-------- src/gallium/drivers/llvmpipe/lp_state_setup.c | 26 +++++++++++++++----------- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/gallium/auxiliary/draw/draw_pipe_offset.c b/src/gallium/auxiliary/draw/draw_pipe_offset.c index 8071bc77b80..34114035ac8 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_offset.c +++ b/src/gallium/auxiliary/draw/draw_pipe_offset.c @@ -90,18 +90,23 @@ static void do_offset_tri( struct draw_stage *stage, float dzdx = fabsf(a * inv_det); float dzdy = fabsf(b * inv_det); - float zoffset, maxz, bias, mult; + float zoffset, mult; mult = MAX2(dzdx, dzdy) * offset->scale; if (stage->draw->floating_point_depth) { - maxz = MAX3(v0[2], v1[2], v2[2]); - - /** - * XXX: TODO optimize this to quickly resolve a pow2 number through - * an exponent only operation. - */ - bias = offset->units * util_fast_exp2(util_get_float32_exponent(maxz) - 23); + float bias; + union fi maxz; + maxz.f = MAX3(v0[2], v1[2], v2[2]); + /* just do the math directly on shifted number */ + maxz.ui &= 0xff << 23; + maxz.i -= 23 << 23; + /* Clamping to zero means mrd will be zero for very small numbers, + * but specs do not indicate this should be prevented by clamping + * mrd to smallest normal number instead. */ + maxz.i = MAX2(maxz.i, 0); + + bias = offset->units * maxz.f; zoffset = bias + mult; } else { zoffset = offset->units + mult; diff --git a/src/gallium/drivers/llvmpipe/lp_state_setup.c b/src/gallium/drivers/llvmpipe/lp_state_setup.c index ccc9fb902f3..1685ddce5ab 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_state_setup.c @@ -31,6 +31,7 @@ #include "util/u_simple_list.h" #include "os/os_time.h" #include "gallivm/lp_bld_arit.h" +#include "gallivm/lp_bld_bitarit.h" #include "gallivm/lp_bld_const.h" #include "gallivm/lp_bld_debug.h" #include "gallivm/lp_bld_init.h" @@ -268,8 +269,6 @@ lp_do_offset_tri(struct gallivm_state *gallivm, LLVMValueRef zeroi = lp_build_const_int32(gallivm, 0); LLVMValueRef twoi = lp_build_const_int32(gallivm, 2); LLVMValueRef threei = lp_build_const_int32(gallivm, 3); - LLVMValueRef mantissa_bits, exp, bias; - LLVMValueRef maxz_value, maxz0z1_value; /* (res12) = cross(e,f).xy */ shuffles[0] = twoi; @@ -319,9 +318,13 @@ lp_do_offset_tri(struct gallivm_state *gallivm, * * NOTE: Assumes IEEE float32. */ + LLVMValueRef c23_shifted, exp_mask, bias, exp; + LLVMValueRef maxz_value, maxz0z1_value; + lp_build_context_init(&int_scalar_bld, gallivm, lp_type_int_vec(32, 32)); - mantissa_bits = lp_build_const_int32(gallivm, 23); + c23_shifted = lp_build_const_int32(gallivm, 23 << 23); + exp_mask = lp_build_const_int32(gallivm, 0xff << 23); maxz0z1_value = lp_build_max(&flt_scalar_bld, LLVMBuildExtractElement(b, attribv[0], twoi, ""), @@ -331,15 +334,16 @@ lp_do_offset_tri(struct gallivm_state *gallivm, LLVMBuildExtractElement(b, attribv[2], twoi, ""), maxz0z1_value); - /** - * XXX: TODO optimize this to quickly resolve a pow2 number through - * an exponent only operation. - */ - exp = lp_build_extract_exponent(&flt_scalar_bld, maxz_value, 0); - exp = lp_build_sub(&int_scalar_bld, exp, mantissa_bits); - exp = lp_build_int_to_float(&flt_scalar_bld, exp); + exp = LLVMBuildBitCast(b, maxz_value, int_scalar_bld.vec_type, ""); + exp = lp_build_and(&int_scalar_bld, exp, exp_mask); + exp = lp_build_sub(&int_scalar_bld, exp, c23_shifted); + /* Clamping to zero means mrd will be zero for very small numbers, + * but specs do not indicate this should be prevented by clamping + * mrd to smallest normal number instead. */ + exp = lp_build_max(&int_scalar_bld, exp, int_scalar_bld.zero); + exp = LLVMBuildBitCast(b, exp, flt_scalar_bld.vec_type, ""); - bias = LLVMBuildFMul(b, lp_build_exp2(&flt_scalar_bld, exp), + bias = LLVMBuildFMul(b, exp, lp_build_const_float(gallivm, key->pgon_offset_units), "bias"); -- cgit v1.2.3