On 24 January 2013 19:47, Matt Turner <matts...@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 <stereotype...@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@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-dev >
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev