aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl/ir_constant_expression.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/glsl/ir_constant_expression.cpp')
-rw-r--r--mesalib/src/glsl/ir_constant_expression.cpp376
1 files changed, 356 insertions, 20 deletions
diff --git a/mesalib/src/glsl/ir_constant_expression.cpp b/mesalib/src/glsl/ir_constant_expression.cpp
index 17b54b923..86b863f31 100644
--- a/mesalib/src/glsl/ir_constant_expression.cpp
+++ b/mesalib/src/glsl/ir_constant_expression.cpp
@@ -40,25 +40,6 @@
#include "glsl_types.h"
#include "program/hash_table.h"
-/* Using C99 rounding functions for roundToEven() implementation is
- * difficult, because round(), rint, and nearbyint() are affected by
- * fesetenv(), which the application may have done for its own
- * purposes. Mesa's IROUND macro is close to what we want, but it
- * rounds away from 0 on n + 0.5.
- */
-static int
-round_to_even(float val)
-{
- int rounded = IROUND(val);
-
- if (val - floor(val) == 0.5) {
- if (rounded % 2 != 0)
- rounded += val > 0 ? -1 : 1;
- }
-
- return rounded;
-}
-
static float
dot(ir_constant *op0, ir_constant *op1)
{
@@ -94,6 +75,297 @@ bitcast_f2u(float f)
return u;
}
+/**
+ * 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
+(*unpack_1x16_func_t)(uint16_t);
+
+/**
+ * Evaluate a 2x16 floating-point packing function.
+ */
+static uint32_t
+pack_2x16(pack_1x16_func_t pack_1x16,
+ float x, float y)
+{
+ /* From section 8.4 of the GLSL ES 3.00 spec:
+ *
+ * packSnorm2x16
+ * -------------
+ * 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_1x16(x) << 0);
+ u |= ((uint32_t) pack_1x16(y) << 16);
+ return u;
+}
+
+/**
+ * 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
+unpack_2x16(unpack_1x16_func_t unpack_1x16,
+ uint32_t u,
+ float *x, float *y)
+{
+ /* From section 8.4 of the GLSL ES 3.00 spec:
+ *
+ * unpackSnorm2x16
+ * ---------------
+ * 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_1x16((uint16_t) (u & 0xffff));
+ *y = unpack_1x16((uint16_t) (u >> 16));
+}
+
+/**
+ * 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)
+ *
+ * We must first cast the float to an int, because casting a negative
+ * float to a uint is undefined.
+ */
+ return (uint8_t) (int8_t)
+ _mesa_round_to_even(CLAMP(x, -1.0f, +1.0f) * 127.0f);
+}
+
+/**
+ * Evaluate one component of packSnorm2x16.
+ */
+static uint16_t
+pack_snorm_1x16(float x)
+{
+ /* From section 8.4 of the GLSL ES 3.00 spec:
+ *
+ * packSnorm2x16
+ * -------------
+ * The conversion for component c of v to fixed point is done as
+ * follows:
+ *
+ * packSnorm2x16: round(clamp(c, -1, +1) * 32767.0)
+ *
+ * We must first cast the float to an int, because casting a negative
+ * float to a uint is undefined.
+ */
+ return (uint16_t) (int16_t)
+ _mesa_round_to_even(CLAMP(x, -1.0f, +1.0f) * 32767.0f);
+}
+
+/**
+ * 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
+unpack_snorm_1x16(uint16_t u)
+{
+ /* From section 8.4 of the GLSL ES 3.00 spec:
+ *
+ * unpackSnorm2x16
+ * ---------------
+ * The conversion for unpacked fixed-point value f to floating point is
+ * done as follows:
+ *
+ * unpackSnorm2x16: clamp(f / 32767.0, -1, +1)
+ */
+ return CLAMP((int16_t) u / 32767.0f, -1.0f, +1.0f);
+}
+
+/**
+ * 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
+pack_unorm_1x16(float x)
+{
+ /* From section 8.4 of the GLSL ES 3.00 spec:
+ *
+ * packUnorm2x16
+ * -------------
+ * The conversion for component c of v to fixed point is done as
+ * follows:
+ *
+ * packUnorm2x16: round(clamp(c, 0, +1) * 65535.0)
+ */
+ 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.
+ */
+static float
+unpack_unorm_1x16(uint16_t u)
+{
+ /* From section 8.4 of the GLSL ES 3.00 spec:
+ *
+ * unpackUnorm2x16
+ * ---------------
+ * The conversion for unpacked fixed-point value f to floating point is
+ * done as follows:
+ *
+ * unpackUnorm2x16: f / 65535.0
+ */
+ return (float) u / 65535.0f;
+}
+
+/**
+ * Evaluate one component of packHalf2x16.
+ */
+static uint16_t
+pack_half_1x16(float x)
+{
+ return _mesa_float_to_half(x);
+}
+
+/**
+ * Evaluate one component of unpackHalf2x16.
+ */
+static float
+unpack_half_1x16(uint16_t u)
+{
+ return _mesa_half_to_float(u);
+}
+
ir_constant *
ir_rvalue::constant_expression_value(struct hash_table *variable_context)
{
@@ -279,7 +551,7 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
case ir_unop_round_even:
assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
for (unsigned c = 0; c < op[0]->type->components(); c++) {
- data.f[c] = round_to_even(op[0]->value.f[c]);
+ data.f[c] = _mesa_round_to_even(op[0]->value.f[c]);
}
break;
@@ -459,6 +731,70 @@ ir_expression::constant_expression_value(struct hash_table *variable_context)
}
break;
+ case ir_unop_pack_snorm_2x16:
+ assert(op[0]->type == glsl_type::vec2_type);
+ data.u[0] = pack_2x16(pack_snorm_1x16,
+ 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,
+ op[0]->value.f[0],
+ op[0]->value.f[1]);
+ break;
+ case ir_unop_unpack_half_2x16:
+ assert(op[0]->type == glsl_type::uint_type);
+ unpack_2x16(unpack_half_1x16,
+ op[0]->value.u[0],
+ &data.f[0], &data.f[1]);
+ break;
case ir_binop_pow:
assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
for (unsigned c = 0; c < op[0]->type->components(); c++) {