<p dir="ltr">Looks good to me.  My initial reaction was that we could simplify it but you're right about the rounding.  This one gets my r-b too.<br>
On Jan 15, 2015 10:52 AM, "Neil Roberts" <<a href="mailto:neil@linux.intel.com">neil@linux.intel.com</a>> wrote:<br>
><br>
> Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>> writes:<br>
><br>
> > This looks fine to me.  We should probably also do this for snorm formats.<br>
> > I don't care if that's part of this or in a separate patch.<br>
> > --Jason<br>
><br>
> The snorm formats are a bit more fiddly because the hardware doesn't<br>
> quite seem to be doing what I'd expect. For example, when converting<br>
> from 16 bits to 8 bits we effectively want to convert from the range<br>
> [-32767,+32767] to [-127,+127]. I think that means we can just use a<br>
> formula like this:<br>
><br>
>  a = 127 * b / 32767<br>
><br>
> This almost works except when the result is close to halfway between two<br>
> integers the hardware seems to round in the wrong direction. For example<br>
> the input value 16642 according to the formula should be 64.5019, which<br>
> you'd hope it would round to 65. However it rounds to 64.<br>
><br>
> We could probably bodge the formula to match what Intel hardware does<br>
> but that seems a bit cheeky considering this is in generic Mesa code. I<br>
> tried to check what NVidia is doing on my old GeForce 9400 with the<br>
> binary driver and it seems to be more or less doing the formula but<br>
> truncating the fractional part instead of rounding. That of course would<br>
> end up with completely different results again so we wouldn't be able to<br>
> match both ways of doing it.<br>
><br>
> I made the patch below which seems to correctly implement the formula at<br>
> least for all values of converting 16-bit to 8-bit. Maybe we could just use<br>
> it and accept that it doesn't match the hardware in a few cases. I don't<br>
> think it will affect any Piglit tests which was the original incentive<br>
> to try and fix this.<br>
><br>
> diff --git a/src/mesa/main/format_utils.h b/src/mesa/main/format_utils.h<br>
> index 2faaf76..c959b57 100644<br>
> --- a/src/mesa/main/format_utils.h<br>
> +++ b/src/mesa/main/format_utils.h<br>
> @@ -150,8 +150,19 @@ _mesa_snorm_to_snorm(int x, unsigned src_bits, unsigned dst_bits)<br>
>        return -MAX_INT(dst_bits);<br>
>     else if (src_bits < dst_bits)<br>
>        return EXTEND_NORMALIZED_INT(x, src_bits - 1, dst_bits - 1);<br>
> -   else<br>
> -      return x >> (src_bits - dst_bits);<br>
> +   else {<br>
> +      /* As an example, when converting from 16 bits to 8 bits, when it gets<br>
> +       * here x will be in the range [-32767,+32767] and we want to map this<br>
> +       * to [-127,+127]. The -32768 case will have been handled in the first<br>
> +       * if-clause above. This just adds 32767 so that it is in the range<br>
> +       * [0,65534], multiplies it by 254 and then divides by 65534. The<br>
> +       * division is done with only positive numbers because dividing a<br>
> +       * negative number has undefined rounding in C < 99. After the division<br>
> +       * it is subtracted by 127 to put in back in the range [-127,127]. */<br>
> +      return (((x + MAX_INT(src_bits)) * (MAX_INT(dst_bits) * 2) +<br>
> +               MAX_INT(src_bits)) /<br>
> +              (MAX_INT(src_bits) * 2) - MAX_INT(dst_bits));<br>
> +   }<br>
>  }<br>
><br>
> - Neil<br>
</p>