<div dir="ltr">On 24 January 2013 19:47, Matt Turner <span dir="ltr"><<a href="mailto:mattst88@gmail.com" target="_blank">mattst88@gmail.com</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
That is, evaluate constant expressions for the following functions:<br>
  packSnorm4x8, unpackSnorm4x8<br>
  packUnorm4x8, unpackUnorm4x8<br>
---<br>
 src/glsl/ir_constant_expression.cpp |  162 +++++++++++++++++++++++++++++++++++<br>
 1 files changed, 162 insertions(+), 0 deletions(-)<br>
<br>
diff --git a/src/glsl/ir_constant_expression.cpp b/src/glsl/ir_constant_expression.cpp<br>
index b34c6e8..4796f6f 100644<br>
--- a/src/glsl/ir_constant_expression.cpp<br>
+++ b/src/glsl/ir_constant_expression.cpp<br>
@@ -76,12 +76,24 @@ bitcast_f2u(float f)<br>
 }<br>
<br>
 /**<br>
+ * Evaluate one component of a floating-point 4x8 unpacking function.<br>
+ */<br>
+typedef uint8_t<br>
+(*pack_1x8_func_t)(float);<br>
+<br>
+/**<br>
  * Evaluate one component of a floating-point 2x16 unpacking function.<br>
  */<br>
 typedef uint16_t<br>
 (*pack_1x16_func_t)(float);<br>
<br>
 /**<br>
+ * Evaluate one component of a floating-point 4x8 unpacking function.<br>
+ */<br>
+typedef float<br>
+(*unpack_1x8_func_t)(uint8_t);<br>
+<br>
+/**<br>
  * Evaluate one component of a floating-point 2x16 unpacking function.<br>
  */<br>
 typedef float<br>
@@ -112,6 +124,32 @@ pack_2x16(pack_1x16_func_t pack_1x16,<br>
 }<br>
<br>
 /**<br>
+ * Evaluate a 4x8 floating-point packing function.<br>
+ */<br>
+static uint32_t<br>
+pack_4x8(pack_1x8_func_t pack_1x8,<br>
+         float x, float y, float z, float w)<br>
+{<br>
+   /* From section 8.4 of the GLSL 4.30 spec:<br>
+    *<br>
+    *    packSnorm4x8<br>
+    *    ------------<br>
+    *    The first component of the vector will be written to the least<br>
+    *    significant bits of the output; the last component will be written to<br>
+    *    the most significant bits.<br>
+    *<br>
+    * The specifications for the other packing functions contain similar<br>
+    * language.<br>
+    */<br>
+   uint32_t u = 0;<br>
+   u |= ((uint32_t) pack_1x8(x) << 0);<br>
+   u |= ((uint32_t) pack_1x8(y) << 8);<br>
+   u |= ((uint32_t) pack_1x8(z) << 16);<br>
+   u |= ((uint32_t) pack_1x8(w) << 24);<br>
+   return u;<br>
+}<br>
+<br>
+/**<br>
  * Evaluate a 2x16 floating-point unpacking function.<br>
  */<br>
 static void<br>
@@ -135,6 +173,48 @@ unpack_2x16(unpack_1x16_func_t unpack_1x16,<br>
 }<br>
<br>
 /**<br>
+ * Evaluate a 4x8 floating-point unpacking function.<br>
+ */<br>
+static void<br>
+unpack_4x8(unpack_1x8_func_t unpack_1x8, uint32_t u,<br>
+           float *x, float *y, float *z, float *w)<br>
+{<br>
+    /* From section 8.4 of the GLSL 4.30 spec:<br>
+     *<br>
+     *    unpackSnorm4x8<br>
+     *    --------------<br>
+     *    The first component of the returned vector will be extracted from<br>
+     *    the least significant bits of the input; the last component will be<br>
+     *    extracted from the most significant bits.<br>
+     *<br>
+     * The specifications for the other unpacking functions contain similar<br>
+     * language.<br>
+     */<br>
+   *x = unpack_1x8((uint8_t) (u & 0xff));<br>
+   *y = unpack_1x8((uint8_t) (u >> 8));<br>
+   *z = unpack_1x8((uint8_t) (u >> 16));<br>
+   *w = unpack_1x8((uint8_t) (u >> 24));<br>
+}<br>
+<br>
+/**<br>
+ * Evaluate one component of packSnorm4x8.<br>
+ */<br>
+static uint8_t<br>
+pack_snorm_1x8(float x)<br>
+{<br>
+    /* From section 8.4 of the GLSL 4.30 spec:<br>
+     *<br>
+     *    packSnorm4x8<br>
+     *    ------------<br>
+     *    The conversion for component c of v to fixed point is done as<br>
+     *    follows:<br>
+     *<br>
+     *      packSnorm4x8: round(clamp(c, -1, +1) * 127.0)<br>
+     */<br>
+   return (uint8_t) _mesa_round_to_even(CLAMP(x, -1.0f, +1.0f) * 127.0f);<br>
+}<br></blockquote><div><br></div><div>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.<br>
<br></div><div>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.<br>
<br></div><div>With that change, this patch is:<br><br>Reviewed-by: Paul Berry <<a href="mailto:stereotype441@gmail.com">stereotype441@gmail.com</a>><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

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