[Mesa-dev] [PATCH 3/7] mesa: Replace F_TO_I() with _mesa_lroundevenf().

Roland Scheidegger sroland at vmware.com
Fri Jul 31 17:46:08 PDT 2015


I think that just means "depends on currently set rounding mode". But
well if someone calls into mesa code with different set rounding mode we
have a lot more problems...


Am 01.08.2015 um 01:26 schrieb Matt Turner:
> I'm not sure what the true meaning of "The rounding mode may vary." is,
> but it is the case that the IROUND() path rounds differently than the
> other paths (and does it wrong, at that).
> 
> Like _mesa_roundeven{f,}(), just add an use _mesa_lroundeven{f,}() that
> has known semantics.
> ---
>  src/mesa/main/format_utils.h  |  5 +++--
>  src/mesa/main/imports.h       | 28 ----------------------------
>  src/mesa/main/macros.h        | 11 ++++++-----
>  src/mesa/main/pack.c          |  4 ++--
>  src/mesa/main/pixeltransfer.c | 11 ++++++-----
>  src/util/rounding.h           | 25 +++++++++++++++++++++++++
>  6 files changed, 42 insertions(+), 42 deletions(-)
> 
> diff --git a/src/mesa/main/format_utils.h b/src/mesa/main/format_utils.h
> index 7f500ec..00ec777 100644
> --- a/src/mesa/main/format_utils.h
> +++ b/src/mesa/main/format_utils.h
> @@ -33,6 +33,7 @@
>  
>  #include "imports.h"
>  #include "macros.h"
> +#include "util/rounding.h"
>  
>  extern const mesa_array_format RGBA32_FLOAT;
>  extern const mesa_array_format RGBA8_UBYTE;
> @@ -84,7 +85,7 @@ _mesa_float_to_unorm(float x, unsigned dst_bits)
>     else if (x > 1.0f)
>        return MAX_UINT(dst_bits);
>     else
> -      return F_TO_I(x * MAX_UINT(dst_bits));
> +      return _mesa_lroundevenf(x * MAX_UINT(dst_bits));
>  }
>  
>  static inline unsigned
> @@ -128,7 +129,7 @@ _mesa_float_to_snorm(float x, unsigned dst_bits)
>     else if (x > 1.0f)
>        return MAX_INT(dst_bits);
>     else
> -      return F_TO_I(x * MAX_INT(dst_bits));
> +      return _mesa_lroundevenf(x * MAX_INT(dst_bits));
>  }
>  
>  static inline int
> diff --git a/src/mesa/main/imports.h b/src/mesa/main/imports.h
> index 9ffe3de..d61279a 100644
> --- a/src/mesa/main/imports.h
> +++ b/src/mesa/main/imports.h
> @@ -170,34 +170,6 @@ static inline int IROUND_POS(float f)
>     return (int) (f + 0.5F);
>  }
>  
> -#ifdef __x86_64__
> -#  include <xmmintrin.h>
> -#endif
> -
> -/**
> - * Convert float to int using a fast method.  The rounding mode may vary.
> - */
> -static inline int F_TO_I(float f)
> -{
> -#if defined(USE_X86_ASM) && defined(__GNUC__) && defined(__i386__)
> -   int r;
> -   __asm__ ("fistpl %0" : "=m" (r) : "t" (f) : "st");
> -   return r;
> -#elif defined(USE_X86_ASM) && defined(_MSC_VER)
> -   int r;
> -   _asm {
> -	 fld f
> -	 fistp r
> -	}
> -   return r;
> -#elif defined(__x86_64__)
> -   return _mm_cvt_ss2si(_mm_load_ss(&f));
> -#else
> -   return IROUND(f);
> -#endif
> -}
> -
> -
>  /** Return (as an integer) floor of float */
>  static inline int IFLOOR(float f)
>  {
> diff --git a/src/mesa/main/macros.h b/src/mesa/main/macros.h
> index 07919a6..54df50c 100644
> --- a/src/mesa/main/macros.h
> +++ b/src/mesa/main/macros.h
> @@ -33,6 +33,7 @@
>  
>  #include "util/macros.h"
>  #include "util/u_math.h"
> +#include "util/rounding.h"
>  #include "imports.h"
>  
>  
> @@ -131,12 +132,12 @@ extern GLfloat _mesa_ubyte_to_float_color_tab[256];
>  #define INT_TO_USHORT(i)   ((i) < 0 ? 0 : ((GLushort) ((i) >> 15)))
>  #define UINT_TO_USHORT(i)  ((i) < 0 ? 0 : ((GLushort) ((i) >> 16)))
>  #define UNCLAMPED_FLOAT_TO_USHORT(us, f)  \
> -        us = ( (GLushort) F_TO_I( CLAMP((f), 0.0F, 1.0F) * 65535.0F) )
> +        us = ( (GLushort) _mesa_lroundevenf( CLAMP((f), 0.0F, 1.0F) * 65535.0F) )

I just realized we actually generate undefined results for NaNs with
this and similar clamp->int conversions. May be fine though (d3d10
generally requires you to return 0 for converting floats to ints for
NaN, which you can do if you have a CLAMP anyway without extra effort,
if the result is unsigned, by carefully choosing the comparisons - not
entirely sure if it compiles into the same amount of instructions
though, might be more or less...).

>  #define CLAMPED_FLOAT_TO_USHORT(us, f)  \
> -        us = ( (GLushort) F_TO_I( (f) * 65535.0F) )
> +        us = ( (GLushort) _mesa_lroundevenf( (f) * 65535.0F) )
>  
>  #define UNCLAMPED_FLOAT_TO_SHORT(s, f)  \
> -        s = ( (GLshort) F_TO_I( CLAMP((f), -1.0F, 1.0F) * 32767.0F) )
> +        s = ( (GLshort) _mesa_lroundevenf( CLAMP((f), -1.0F, 1.0F) * 32767.0F) )
>  
>  /***
>   *** UNCLAMPED_FLOAT_TO_UBYTE: clamp float to [0,1] and map to ubyte in [0,255]
> @@ -167,9 +168,9 @@ extern GLfloat _mesa_ubyte_to_float_color_tab[256];
>          } while (0)
>  #else
>  #define UNCLAMPED_FLOAT_TO_UBYTE(ub, f) \
> -	ub = ((GLubyte) F_TO_I(CLAMP((f), 0.0F, 1.0F) * 255.0F))
> +	ub = ((GLubyte) _mesa_lroundevenf(CLAMP((f), 0.0F, 1.0F) * 255.0F))
>  #define CLAMPED_FLOAT_TO_UBYTE(ub, f) \
> -	ub = ((GLubyte) F_TO_I((f) * 255.0F))
> +	ub = ((GLubyte) _mesa_lroundevenf((f) * 255.0F))
>  #endif
>  
>  static fi_type UINT_AS_UNION(GLuint u)
> diff --git a/src/mesa/main/pack.c b/src/mesa/main/pack.c
> index fb642b8..7147fd6 100644
> --- a/src/mesa/main/pack.c
> +++ b/src/mesa/main/pack.c
> @@ -470,7 +470,7 @@ extract_uint_indexes(GLuint n, GLuint indexes[],
>  static inline GLuint
>  clamp_float_to_uint(GLfloat f)
>  {
> -   return f < 0.0F ? 0 : F_TO_I(f);
> +   return f < 0.0F ? 0 : _mesa_lroundevenf(f);
>  }
>  
>  
> @@ -478,7 +478,7 @@ static inline GLuint
>  clamp_half_to_uint(GLhalfARB h)
>  {
>     GLfloat f = _mesa_half_to_float(h);
> -   return f < 0.0F ? 0 : F_TO_I(f);
> +   return f < 0.0F ? 0 : _mesa_lroundevenf(f);
>  }
>  
>  
> diff --git a/src/mesa/main/pixeltransfer.c b/src/mesa/main/pixeltransfer.c
> index 51f2ebf..22eac00 100644
> --- a/src/mesa/main/pixeltransfer.c
> +++ b/src/mesa/main/pixeltransfer.c
> @@ -35,6 +35,7 @@
>  #include "pixeltransfer.h"
>  #include "imports.h"
>  #include "mtypes.h"
> +#include "util/rounding.h"
>  
>  
>  /*
> @@ -94,10 +95,10 @@ _mesa_map_rgba( const struct gl_context *ctx, GLuint n, GLfloat rgba[][4] )
>        GLfloat g = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F);
>        GLfloat b = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F);
>        GLfloat a = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F);
> -      rgba[i][RCOMP] = rMap[F_TO_I(r * rscale)];
> -      rgba[i][GCOMP] = gMap[F_TO_I(g * gscale)];
> -      rgba[i][BCOMP] = bMap[F_TO_I(b * bscale)];
> -      rgba[i][ACOMP] = aMap[F_TO_I(a * ascale)];
> +      rgba[i][RCOMP] = rMap[(int)_mesa_lroundevenf(r * rscale)];
> +      rgba[i][GCOMP] = gMap[(int)_mesa_lroundevenf(g * gscale)];
> +      rgba[i][BCOMP] = bMap[(int)_mesa_lroundevenf(b * bscale)];
> +      rgba[i][ACOMP] = aMap[(int)_mesa_lroundevenf(a * ascale)];
>     }
>  }
>  
> @@ -236,7 +237,7 @@ _mesa_apply_ci_transfer_ops(const struct gl_context *ctx,
>        GLuint i;
>        for (i = 0; i < n; i++) {
>           const GLuint j = indexes[i] & mask;
> -         indexes[i] = F_TO_I(ctx->PixelMaps.ItoI.Map[j]);
> +         indexes[i] = _mesa_lroundevenf(ctx->PixelMaps.ItoI.Map[j]);
>        }
>     }
>  }
> diff --git a/src/util/rounding.h b/src/util/rounding.h
> index 0cbe926..2d00760 100644
> --- a/src/util/rounding.h
> +++ b/src/util/rounding.h
> @@ -21,6 +21,9 @@
>   * IN THE SOFTWARE.
>   */
>  
> +#ifndef _ROUNDING_H
> +#define _ROUNDING_H
> +
>  #include <math.h>
>  
>  #ifdef __SSE4_1__
> @@ -76,3 +79,25 @@ _mesa_roundeven(double x)
>     return rint(x);
>  #endif
>  }
> +
> +/**
> + * \brief Rounds \c x to the nearest integer, with ties to the even integer,
> + * and returns the value as an long int.
an->a


> + */
> +static inline long
> +_mesa_lroundevenf(float x)
> +{
> +   return lrintf(x);
> +}
> +
> +/**
> + * \brief Rounds \c x to the nearest integer, with ties to the even integer,
> + * and returns the value as a long int.
> + */
> +static inline long
> +_mesa_lroundeven(double x)
Is there any need for this one? In any case,
Reviewed-by: Roland Scheidegger <sroland at vmware.com>

> +{
> +   return lrint(x);
> +}
> +
> +#endif
> 



More information about the mesa-dev mailing list