Mesa (master): glsl2: Write vector constructor constants in a single assignment

Ian Romanick idr at kemper.freedesktop.org
Tue Aug 31 21:50:04 UTC 2010


Module: Mesa
Branch: master
Commit: a6c3cd5ca6822da2ec6e869c7bc2b8ac64c177f2
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=a6c3cd5ca6822da2ec6e869c7bc2b8ac64c177f2

Author: Ian Romanick <ian.d.romanick at intel.com>
Date:   Tue Aug 31 14:44:13 2010 -0700

glsl2: Write vector constructor constants in a single assignment

Make two passes over the constructor parameters.  Write all of the
constants in a single write, then write the non-constants one at a
time.  This causes the fragment shader

varying float g;
void main()
{
	gl_FragColor = vec4(0.0, g, 0.0, 1.0);
}

to generate

(function main
  (signature void (parameters )
    (
      (declare (temporary ) vec4 vec_ctor at 0x8580058)
      (assign (constant bool (1)) (xzw) (var_ref vec_ctor at 0x8580058)  (constant vec4 (0.000000 0.000000 0.000000 1.000000)) )
      (assign (constant bool (1)) (y) (var_ref vec_ctor at 0x8580058)  (swiz xxxx (var_ref g at 0x8580218) ))
      (assign (constant bool (1)) (xyzw) (var_ref gl_FragColor at 0x84d32a0)  (var_ref vec_ctor at 0x8580058) )
    ))
)

instead of

(function main
  (signature void (parameters )
    (
      (declare (temporary ) vec4 vec_ctor at 0x8580058)
      (assign (constant bool (1)) (x) (var_ref vec_ctor at 0x8580058)  (constant vec4 (0.000000 0.000000 0.000000 1.000000)) )
      (assign (constant bool (1)) (y) (var_ref vec_ctor at 0x8580058)  (swiz xxxx (var_ref g at 0x8580218) ))
      (assign (constant bool (1)) (z) (var_ref vec_ctor at 0x8580058)  (constant vec4 (0.000000 0.000000 0.000000 1.000000)) )
      (assign (constant bool (1)) (w) (var_ref vec_ctor at 0x8580058)  (constant vec4 (0.000000 0.000000 0.000000 1.000000)) )
      (assign (constant bool (1)) (xyzw) (var_ref gl_FragColor at 0x84d32a0)  (var_ref vec_ctor at 0x8580058) )
    ))
)

A similar optimization could be done for matrix constructors, but it
is a little more complicate there.

---

 src/glsl/ast_function.cpp |   83 +++++++++++++++++++++++++++++++++++++++------
 1 files changed, 72 insertions(+), 11 deletions(-)

diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
index c2e526c..d39c4b1 100644
--- a/src/glsl/ast_function.cpp
+++ b/src/glsl/ast_function.cpp
@@ -621,6 +621,11 @@ emit_inline_vector_constructor(const glsl_type *type,
       instructions->push_tail(inst);
    } else {
       unsigned base_component = 0;
+      ir_constant_data data;
+      unsigned constant_mask = 0;
+
+      memset(&data, 0, sizeof(data));
+
       foreach_list(node, parameters) {
 	 ir_rvalue *param = (ir_rvalue *) node;
 	 unsigned rhs_components = param->type->components();
@@ -631,24 +636,80 @@ emit_inline_vector_constructor(const glsl_type *type,
 	    rhs_components = lhs_components - base_component;
 	 }
 
-	 /* Generate a swizzle that puts the first element of the source at
-	  * the location of the first element of the destination.
-	  */
-	 unsigned swiz[4] = { 0, 0, 0, 0 };
-	 for (unsigned i = 0; i < rhs_components; i++)
-	    swiz[i + base_component] = i;
+	 const ir_constant *const c = param->as_constant();
+	 if (c != NULL) {
+	    for (unsigned i = 0; i < rhs_components; i++) {
+	       switch (c->type->base_type) {
+	       case GLSL_TYPE_UINT:
+		  data.u[i + base_component] = c->get_uint_component(i);
+		  break;
+	       case GLSL_TYPE_INT:
+		  data.i[i + base_component] = c->get_int_component(i);
+		  break;
+	       case GLSL_TYPE_FLOAT:
+		  data.f[i + base_component] = c->get_float_component(i);
+		  break;
+	       case GLSL_TYPE_BOOL:
+		  data.b[i + base_component] = c->get_bool_component(i);
+		  break;
+	       default:
+		  assert(!"Should not get here.");
+		  break;
+	       }
+	    }
 
-	 /* Mask of fields to be written in the assignment.
+	    /* Mask of fields to be written in the assignment.
+	     */
+	    constant_mask |= ((1U << rhs_components) - 1) << base_component;
+	 }
+
+	 /* Advance the component index by the number of components that were
+	  * just assigned.
 	  */
-	 const unsigned write_mask = ((1U << rhs_components) - 1)
-	    << base_component;
+	 base_component += rhs_components;
+      }
 
+      if (constant_mask != 0) {
 	 ir_dereference *lhs = new(ctx) ir_dereference_variable(var);
-	 ir_rvalue *rhs = new(ctx) ir_swizzle(param, swiz, lhs_components);
+	 ir_rvalue *rhs = new(ctx) ir_constant(var->type, &data);
 
 	 ir_instruction *inst =
-	    new(ctx) ir_assignment(lhs, rhs, NULL, write_mask);
+	    new(ctx) ir_assignment(lhs, rhs, NULL, constant_mask);
 	 instructions->push_tail(inst);
+      }
+
+      base_component = 0;
+      foreach_list(node, parameters) {
+	 ir_rvalue *param = (ir_rvalue *) node;
+	 unsigned rhs_components = param->type->components();
+
+	 /* Do not try to assign more components to the vector than it has!
+	  */
+	 if ((rhs_components + base_component) > lhs_components) {
+	    rhs_components = lhs_components - base_component;
+	 }
+
+	 const ir_constant *const c = param->as_constant();
+	 if (c == NULL) {
+	    /* Generate a swizzle that puts the first element of the source at
+	     * the location of the first element of the destination.
+	     */
+	    unsigned swiz[4] = { 0, 0, 0, 0 };
+	    for (unsigned i = 0; i < rhs_components; i++)
+	       swiz[i + base_component] = i;
+
+	    /* Mask of fields to be written in the assignment.
+	     */
+	    const unsigned write_mask = ((1U << rhs_components) - 1)
+	       << base_component;
+
+	    ir_dereference *lhs = new(ctx) ir_dereference_variable(var);
+	    ir_rvalue *rhs = new(ctx) ir_swizzle(param, swiz, lhs_components);
+
+	    ir_instruction *inst =
+	       new(ctx) ir_assignment(lhs, rhs, NULL, write_mask);
+	    instructions->push_tail(inst);
+	 }
 
 	 /* Advance the component index by the number of components that were
 	  * just assigned.




More information about the mesa-commit mailing list