From 529c5e77402012aa0c0a11ee71a1a65e51edb496 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Sat, 10 Oct 2015 22:05:58 +0200 Subject: [PATCH] gallivm: implement the correct version of LRP The previous version has precision issues. This can be a problem with tessellation. Sadly, I can't find the article where I read it anymore. I'm not sure if the unsafe-fp-math flag would be enough to revert this. v2: added the comment --- src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c index 0ad78b0..3d5e2cb 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c @@ -538,12 +538,19 @@ lrp_emit( struct lp_build_tgsi_context * bld_base, struct lp_build_emit_data * emit_data) { - LLVMValueRef tmp; - tmp = lp_build_emit_llvm_binary(bld_base, TGSI_OPCODE_SUB, - emit_data->args[1], - emit_data->args[2]); - emit_data->output[emit_data->chan] = lp_build_emit_llvm_ternary(bld_base, - TGSI_OPCODE_MAD, emit_data->args[0], tmp, emit_data->args[2]); + struct lp_build_context *bld = &bld_base->base; + LLVMValueRef inv, a, b; + + /* This uses the correct version: (1 - t)*a + t*b + * + * An alternative version is "a + t*(b-a)". The problem is this version + * doesn't return "b" for t = 1, because "a + (b-a)" isn't equal to "b" + * because of the floating-point rounding. + */ + inv = lp_build_sub(bld, bld_base->base.one, emit_data->args[0]); + a = lp_build_mul(bld, emit_data->args[1], emit_data->args[0]); + b = lp_build_mul(bld, emit_data->args[2], inv); + emit_data->output[emit_data->chan] = lp_build_add(bld, a, b); } /* TGSI_OPCODE_MAD */ -- 2.7.4