[Mesa-dev] [PATCH 4/8] glsl: Evaluate constant pack/unpack 4x8 expressions

Paul Berry stereotype441 at gmail.com
Fri Jan 25 07:29:20 PST 2013


On 24 January 2013 19:47, Matt Turner <mattst88 at gmail.com> wrote:

> That is, evaluate constant expressions for the following functions:
>   packSnorm4x8, unpackSnorm4x8
>   packUnorm4x8, unpackUnorm4x8
> ---
>  src/glsl/ir_constant_expression.cpp |  162
> +++++++++++++++++++++++++++++++++++
>  1 files changed, 162 insertions(+), 0 deletions(-)
>
> diff --git a/src/glsl/ir_constant_expression.cpp
> b/src/glsl/ir_constant_expression.cpp
> index b34c6e8..4796f6f 100644
> --- a/src/glsl/ir_constant_expression.cpp
> +++ b/src/glsl/ir_constant_expression.cpp
> @@ -76,12 +76,24 @@ bitcast_f2u(float f)
>  }
>
>  /**
> + * Evaluate one component of a floating-point 4x8 unpacking function.
> + */
> +typedef uint8_t
> +(*pack_1x8_func_t)(float);
> +
> +/**
>   * Evaluate one component of a floating-point 2x16 unpacking function.
>   */
>  typedef uint16_t
>  (*pack_1x16_func_t)(float);
>
>  /**
> + * Evaluate one component of a floating-point 4x8 unpacking function.
> + */
> +typedef float
> +(*unpack_1x8_func_t)(uint8_t);
> +
> +/**
>   * Evaluate one component of a floating-point 2x16 unpacking function.
>   */
>  typedef float
> @@ -112,6 +124,32 @@ pack_2x16(pack_1x16_func_t pack_1x16,
>  }
>
>  /**
> + * Evaluate a 4x8 floating-point packing function.
> + */
> +static uint32_t
> +pack_4x8(pack_1x8_func_t pack_1x8,
> +         float x, float y, float z, float w)
> +{
> +   /* From section 8.4 of the GLSL 4.30 spec:
> +    *
> +    *    packSnorm4x8
> +    *    ------------
> +    *    The first component of the vector will be written to the least
> +    *    significant bits of the output; the last component will be
> written to
> +    *    the most significant bits.
> +    *
> +    * The specifications for the other packing functions contain similar
> +    * language.
> +    */
> +   uint32_t u = 0;
> +   u |= ((uint32_t) pack_1x8(x) << 0);
> +   u |= ((uint32_t) pack_1x8(y) << 8);
> +   u |= ((uint32_t) pack_1x8(z) << 16);
> +   u |= ((uint32_t) pack_1x8(w) << 24);
> +   return u;
> +}
> +
> +/**
>   * Evaluate a 2x16 floating-point unpacking function.
>   */
>  static void
> @@ -135,6 +173,48 @@ unpack_2x16(unpack_1x16_func_t unpack_1x16,
>  }
>
>  /**
> + * Evaluate a 4x8 floating-point unpacking function.
> + */
> +static void
> +unpack_4x8(unpack_1x8_func_t unpack_1x8, uint32_t u,
> +           float *x, float *y, float *z, float *w)
> +{
> +    /* From section 8.4 of the GLSL 4.30 spec:
> +     *
> +     *    unpackSnorm4x8
> +     *    --------------
> +     *    The first component of the returned vector will be extracted
> from
> +     *    the least significant bits of the input; the last component
> will be
> +     *    extracted from the most significant bits.
> +     *
> +     * The specifications for the other unpacking functions contain
> similar
> +     * language.
> +     */
> +   *x = unpack_1x8((uint8_t) (u & 0xff));
> +   *y = unpack_1x8((uint8_t) (u >> 8));
> +   *z = unpack_1x8((uint8_t) (u >> 16));
> +   *w = unpack_1x8((uint8_t) (u >> 24));
> +}
> +
> +/**
> + * Evaluate one component of packSnorm4x8.
> + */
> +static uint8_t
> +pack_snorm_1x8(float x)
> +{
> +    /* From section 8.4 of the GLSL 4.30 spec:
> +     *
> +     *    packSnorm4x8
> +     *    ------------
> +     *    The conversion for component c of v to fixed point is done as
> +     *    follows:
> +     *
> +     *      packSnorm4x8: round(clamp(c, -1, +1) * 127.0)
> +     */
> +   return (uint8_t) _mesa_round_to_even(CLAMP(x, -1.0f, +1.0f) * 127.0f);
> +}
>

IIRC, Brian Paul has a patch out on the list that changes the return type
of _mesa_round_to_even() to float.  If & when that patch lands, this
conversion will result in undefined behaviour, since casing from a negative
float to an unsigned value is undefined by the C standard.

I recommend changing this to "return (uint8_t) (int8_t)
_mesa_round_to_even(...)" and adding a sentence to the comment to explain
why this is necessary.  See the existing pack_snorm_1x16() function, which
used to have the same issue.

With that change, this patch is:

Reviewed-by: Paul Berry <stereotype441 at gmail.com>


> +
> +/**
>   * Evaluate one component of packSnorm2x16.
>   */
>  static uint16_t
> @@ -153,6 +233,24 @@ pack_snorm_1x16(float x)
>  }
>
>  /**
> + * Evaluate one component of unpackSnorm4x8.
> + */
> +static float
> +unpack_snorm_1x8(uint8_t u)
> +{
> +    /* From section 8.4 of the GLSL 4.30 spec:
> +     *
> +     *    unpackSnorm4x8
> +     *    --------------
> +     *    The conversion for unpacked fixed-point value f to floating
> point is
> +     *    done as follows:
> +     *
> +     *       unpackSnorm4x8: clamp(f / 127.0, -1, +1)
> +     */
> +   return CLAMP((int8_t) u / 127.0f, -1.0f, +1.0f);
> +}
> +
> +/**
>   * Evaluate one component of unpackSnorm2x16.
>   */
>  static float
> @@ -171,6 +269,24 @@ unpack_snorm_1x16(uint16_t u)
>  }
>
>  /**
> + * Evaluate one component packUnorm4x8.
> + */
> +static uint8_t
> +pack_unorm_1x8(float x)
> +{
> +    /* From section 8.4 of the GLSL 4.30 spec:
> +     *
> +     *    packUnorm4x8
> +     *    ------------
> +     *    The conversion for component c of v to fixed point is done as
> +     *    follows:
> +     *
> +     *       packUnorm4x8: round(clamp(c, 0, +1) * 255.0)
> +     */
> +   return (uint8_t) _mesa_round_to_even(CLAMP(x, 0.0f, 1.0f) * 255.0f);
> +}
> +
> +/**
>   * Evaluate one component packUnorm2x16.
>   */
>  static uint16_t
> @@ -188,6 +304,24 @@ pack_unorm_1x16(float x)
>     return (uint16_t) _mesa_round_to_even(CLAMP(x, 0.0f, 1.0f) * 65535.0f);
>  }
>
> +/**
> + * Evaluate one component of unpackUnorm4x8.
> + */
> +static float
> +unpack_unorm_1x8(uint8_t u)
> +{
> +    /* From section 8.4 of the GLSL 4.30 spec:
> +     *
> +     *    unpackUnorm4x8
> +     *    --------------
> +     *    The conversion for unpacked fixed-point value f to floating
> point is
> +     *    done as follows:
> +     *
> +     *       unpackUnorm4x8: f / 255.0
> +     */
> +   return (float) u / 255.0f;
> +}
> +
>
>  /**
>   * Evaluate one component of unpackUnorm2x16.
> @@ -597,24 +731,52 @@ ir_expression::constant_expression_value(struct
> hash_table *variable_context)
>                              op[0]->value.f[0],
>                              op[0]->value.f[1]);
>        break;
> +   case ir_unop_pack_snorm_4x8:
> +      assert(op[0]->type == glsl_type::vec4_type);
> +      data.u[0] = pack_4x8(pack_snorm_1x8,
> +                           op[0]->value.f[0],
> +                           op[0]->value.f[1],
> +                           op[0]->value.f[2],
> +                           op[0]->value.f[3]);
> +      break;
>     case ir_unop_unpack_snorm_2x16:
>        assert(op[0]->type == glsl_type::uint_type);
>        unpack_2x16(unpack_snorm_1x16,
>                    op[0]->value.u[0],
>                    &data.f[0], &data.f[1]);
>        break;
> +   case ir_unop_unpack_snorm_4x8:
> +      assert(op[0]->type == glsl_type::uint_type);
> +      unpack_4x8(unpack_snorm_1x8,
> +                 op[0]->value.u[0],
> +                 &data.f[0], &data.f[1], &data.f[2], &data.f[3]);
> +      break;
>     case ir_unop_pack_unorm_2x16:
>        assert(op[0]->type == glsl_type::vec2_type);
>        data.u[0] = pack_2x16(pack_unorm_1x16,
>                              op[0]->value.f[0],
>                              op[0]->value.f[1]);
>        break;
> +   case ir_unop_pack_unorm_4x8:
> +      assert(op[0]->type == glsl_type::vec4_type);
> +      data.u[0] = pack_4x8(pack_unorm_1x8,
> +                           op[0]->value.f[0],
> +                           op[0]->value.f[1],
> +                           op[0]->value.f[2],
> +                           op[0]->value.f[3]);
> +      break;
>     case ir_unop_unpack_unorm_2x16:
>        assert(op[0]->type == glsl_type::uint_type);
>        unpack_2x16(unpack_unorm_1x16,
>                    op[0]->value.u[0],
>                    &data.f[0], &data.f[1]);
>        break;
> +   case ir_unop_unpack_unorm_4x8:
> +      assert(op[0]->type == glsl_type::uint_type);
> +      unpack_4x8(unpack_unorm_1x8,
> +                 op[0]->value.u[0],
> +                 &data.f[0], &data.f[1], &data.f[2], &data.f[3]);
> +      break;
>     case ir_unop_pack_half_2x16:
>        assert(op[0]->type == glsl_type::vec2_type);
>        data.u[0] = pack_2x16(pack_half_1x16,
> --
> 1.7.8.6
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20130125/a93999c9/attachment-0001.html>


More information about the mesa-dev mailing list