diff options
author | Richard Sandiford <[email protected]> | 2014-07-21 16:53:34 +0100 |
---|---|---|
committer | Dave Airlie <[email protected]> | 2014-09-16 14:02:54 +1000 |
commit | 0a7f9fe42b457f7c0cd2a37477a6dc20a45baca8 (patch) | |
tree | c9f155c16dce1d11904a776e8f89e180faf3acde /src/gallium/auxiliary | |
parent | f6e71ff9eb44ed87bd6ac5cc705076d1a789d0ea (diff) |
gallivm: Add SNORM clamping to lp_build_{add, sub}
...fixing the associated TODO.
Reviewed-by: Roland Scheidegger <[email protected]>
Signed-off-by: Richard Sandiford <[email protected]>
Diffstat (limited to 'src/gallium/auxiliary')
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_arit.c | 34 |
1 files changed, 28 insertions, 6 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.c b/src/gallium/auxiliary/gallivm/lp_bld_arit.c index f9c07998f28..fd1bf80c695 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_arit.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.c @@ -522,9 +522,20 @@ lp_build_add(struct lp_build_context *bld, return lp_build_intrinsic_binary(builder, intrinsic, lp_build_vec_type(bld->gallivm, bld->type), a, b); } - /* TODO: handle signed case */ - if(type.norm && !type.floating && !type.fixed && !type.sign) - a = lp_build_min_simple(bld, a, lp_build_comp(bld, b), GALLIVM_NAN_BEHAVIOR_UNDEFINED); + if(type.norm && !type.floating && !type.fixed) { + if (type.sign) { + uint64_t sign = (uint64_t)1 << (type.width - 1); + LLVMValueRef max_val = lp_build_const_int_vec(bld->gallivm, type, sign - 1); + LLVMValueRef min_val = lp_build_const_int_vec(bld->gallivm, type, sign); + /* a_clamp_max is the maximum a for positive b, + a_clamp_min is the minimum a for negative b. */ + LLVMValueRef a_clamp_max = lp_build_min_simple(bld, a, LLVMBuildSub(builder, max_val, b, ""), GALLIVM_NAN_BEHAVIOR_UNDEFINED); + LLVMValueRef a_clamp_min = lp_build_max_simple(bld, a, LLVMBuildSub(builder, min_val, b, ""), GALLIVM_NAN_BEHAVIOR_UNDEFINED); + a = lp_build_select(bld, lp_build_cmp(bld, PIPE_FUNC_GREATER, b, bld->zero), a_clamp_max, a_clamp_min); + } else { + a = lp_build_min_simple(bld, a, lp_build_comp(bld, b), GALLIVM_NAN_BEHAVIOR_UNDEFINED); + } + } if(LLVMIsConstant(a) && LLVMIsConstant(b)) if (type.floating) @@ -803,9 +814,20 @@ lp_build_sub(struct lp_build_context *bld, return lp_build_intrinsic_binary(builder, intrinsic, lp_build_vec_type(bld->gallivm, bld->type), a, b); } - /* TODO: handle signed case */ - if(type.norm && !type.floating && !type.fixed && !type.sign) - a = lp_build_max_simple(bld, a, b, GALLIVM_NAN_BEHAVIOR_UNDEFINED); + if(type.norm && !type.floating && !type.fixed) { + if (type.sign) { + uint64_t sign = (uint64_t)1 << (type.width - 1); + LLVMValueRef max_val = lp_build_const_int_vec(bld->gallivm, type, sign - 1); + LLVMValueRef min_val = lp_build_const_int_vec(bld->gallivm, type, sign); + /* a_clamp_max is the maximum a for negative b, + a_clamp_min is the minimum a for positive b. */ + LLVMValueRef a_clamp_max = lp_build_min_simple(bld, a, LLVMBuildAdd(builder, max_val, b, ""), GALLIVM_NAN_BEHAVIOR_UNDEFINED); + LLVMValueRef a_clamp_min = lp_build_max_simple(bld, a, LLVMBuildAdd(builder, min_val, b, ""), GALLIVM_NAN_BEHAVIOR_UNDEFINED); + a = lp_build_select(bld, lp_build_cmp(bld, PIPE_FUNC_GREATER, b, bld->zero), a_clamp_min, a_clamp_max); + } else { + a = lp_build_max_simple(bld, a, b, GALLIVM_NAN_BEHAVIOR_UNDEFINED); + } + } if(LLVMIsConstant(a) && LLVMIsConstant(b)) if (type.floating) |