[Mesa-dev] [PATCH 1/3] gallivm: use correct rounding for linear wrap mode (in the aos int path)
Roland Scheidegger
sroland at vmware.com
Fri Feb 14 18:03:16 PST 2014
Am 15.02.2014 01:54, schrieb sroland at vmware.com:
> From: Jeff Muizelaar <jmuizelaar at mozilla.com>
>
> The previous method for converting coords to ints was sligthly inaccurate
> (effectively losing 1bit from the 8bit lerp weight). This is probably
> especially noticeable when trying to draw a pixel-aligned texture.
> As an example, for a 100x100 texture after dernormalization the texture
> coords in this case would turn up as
> 0.5, 1.5, 2.5, 3.5, 4.5, ...
> After the mul by 256, conversion to int and 128 subtraction, they end up as
> 0, 256, 512, 768, 1024, ...
> which gets us the correct coords/weights of
> 0/0, 1/0, 2/0, 3/0, 4/0, ...
> But even LSB errors (which are unavoidable) in the input coords may cause
> these coords/weights to be wrong, e.g. for a coord of 3.49999 we'd get a
> coord/weight of 2/255 instead.
>
> Fix this by using round-to-nearest int instead of FPToSi (trunc). Should be
> equally fast on x86 sse though other archs probably suffer a little.
> ---
> src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c | 14 ++++++++------
> 1 file changed, 8 insertions(+), 6 deletions(-)
>
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c
> index c35b628..1d87ee8 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c
> @@ -987,7 +987,6 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld,
> const unsigned dims = bld->dims;
> LLVMBuilderRef builder = bld->gallivm->builder;
> struct lp_build_context i32;
> - LLVMTypeRef i32_vec_type;
> LLVMValueRef i32_c8, i32_c128, i32_c255;
> LLVMValueRef width_vec, height_vec, depth_vec;
> LLVMValueRef s_ipart, s_fpart, s_float;
> @@ -1003,8 +1002,6 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld,
>
> lp_build_context_init(&i32, bld->gallivm, lp_type_int_vec(32, bld->vector_width));
>
> - i32_vec_type = lp_build_vec_type(bld->gallivm, i32.type);
> -
> lp_build_extract_image_sizes(bld,
> &bld->int_size_bld,
> bld->int_coord_type,
> @@ -1036,11 +1033,16 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld,
> }
>
> /* convert float to int */
> - s = LLVMBuildFPToSI(builder, s, i32_vec_type, "");
> + /* For correct rounding, need round to nearest, not truncation here.
> + * Note that in some cases (clamp to edge, no texel offsets) we
> + * could use a non-signed build context which would help archs which
> + * don't have fptosi intrinsic with nearest rounding implemented.
> + */
> + s_ipart = lp_build_iround(&bld->coord_bld, s);
> if (dims >= 2)
> - t = LLVMBuildFPToSI(builder, t, i32_vec_type, "");
> + t_ipart = lp_build_iround(&bld->coord_bld, t);
> if (dims >= 3)
> - r = LLVMBuildFPToSI(builder, r, i32_vec_type, "");
> + r_ipart = lp_build_iround(&bld->coord_bld, r);
>
> /* subtract 0.5 (add -128) */
> i32_c128 = lp_build_const_int_vec(bld->gallivm, i32.type, -128);
>
Oops this series is quite a disaster, sorry. That should have been
s_ipart/t_ipart/r_ipart above of course, my typo... And 2/3 is quite
fail too with some nice texel shift, bad math there... 3/3 may be ok...
Roland
More information about the mesa-dev
mailing list