Mesa (glsl2): glsl2: Always emit vector constructors inline

Ian Romanick idr at kemper.freedesktop.org
Tue Jun 29 11:54:42 PDT 2010


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

Author: Ian Romanick <ian.d.romanick at intel.com>
Date:   Wed Jun 23 15:19:40 2010 -0700

glsl2: Always emit vector constructors inline

---

 src/glsl/ast_function.cpp |  101 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 100 insertions(+), 1 deletions(-)

diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
index f431d1d..f1ab6f0 100644
--- a/src/glsl/ast_function.cpp
+++ b/src/glsl/ast_function.cpp
@@ -444,6 +444,98 @@ generate_constructor_vector(const glsl_type *type, ir_constant *initializer,
 }
 
 
+/**
+ * Determine if a list consists of a single scalar r-value
+ */
+bool
+single_scalar_parameter(exec_list *parameters)
+{
+   const ir_rvalue *const p = (ir_rvalue *) parameters->head;
+   assert(((ir_rvalue *)p)->as_rvalue() != NULL);
+
+   return (p->type->is_scalar() && p->next->is_tail_sentinal());
+}
+
+
+/**
+ * Generate inline code for a vector constructor
+ *
+ * The generated constructor code will consist of a temporary variable
+ * declaration of the same type as the constructor.  A sequence of assignments
+ * from constructor parameters to the temporary will follow.
+ *
+ * \return
+ * An \c ir_dereference_variable of the temprorary generated in the constructor
+ * body.
+ */
+ir_rvalue *
+emit_inline_vector_constructor(const glsl_type *type,
+			       exec_list *instructions,
+			       exec_list *parameters,
+			       void *ctx)
+{
+   assert(!parameters->is_empty());
+
+   ir_variable *var = new(ctx) ir_variable(type, strdup("vec_ctor"));
+   instructions->push_tail(var);
+
+   /* There are two kinds of vector constructors.
+    *
+    *  - Construct a vector from a single scalar by replicating that scalar to
+    *    all components of the vector.
+    *
+    *  - Construct a vector from an arbirary combination of vectors and
+    *    scalars.  The components of the constructor parameters are assigned
+    *    to the vector in order until the vector is full.
+    */
+   const unsigned lhs_components = type->components();
+   if (single_scalar_parameter(parameters)) {
+      ir_rvalue *first_param = (ir_rvalue *)parameters->head;
+      ir_rvalue *rhs = new(ctx) ir_swizzle(first_param, 0, 0, 0, 0,
+					   lhs_components);
+      ir_dereference_variable *lhs = new(ctx) ir_dereference_variable(var);
+
+      assert(rhs->type == lhs->type);
+
+      ir_instruction *inst = new(ctx) ir_assignment(lhs, rhs, NULL);
+      instructions->push_tail(inst);
+   } else {
+      unsigned base_component = 0;
+      foreach_list(node, parameters) {
+	 ir_rvalue *rhs = (ir_rvalue *) node;
+	 unsigned rhs_components = rhs->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;
+	 }
+
+	 /* Emit an assignment of the constructor parameter to the next set of
+	  * components in the temporary variable.
+	  */
+	 unsigned mask[4] = { 0, 0, 0, 0 };
+	 for (unsigned i = 0; i < rhs_components; i++) {
+	    mask[i] = i + base_component;
+	 }
+
+
+	 ir_rvalue *lhs_ref = new(ctx) ir_dereference_variable(var);
+	 ir_swizzle *lhs = new(ctx) ir_swizzle(lhs_ref, mask, rhs_components);
+
+	 ir_instruction *inst = new(ctx) ir_assignment(lhs, rhs, NULL);
+	 instructions->push_tail(inst);
+
+	 /* Advance the component index by the number of components that were
+	  * just assigned.
+	  */
+	 base_component += rhs_components;
+      }
+   }
+   return new(ctx) ir_dereference_variable(var);
+}
+
+
 ir_rvalue *
 ast_function_expression::hir(exec_list *instructions,
 			     struct _mesa_glsl_parse_state *state)
@@ -708,8 +800,15 @@ ast_function_expression::hir(exec_list *instructions,
 					      &data);
 
 	       return new(ctx) ir_constant(sig->return_type, &data);
-	    } else
+	    } else if (constructor_type->is_vector()) {
+	       return emit_inline_vector_constructor(constructor_type,
+						     instructions,
+						     &actual_parameters,
+						     ctx);
+	    } else {
+	       assert(constructor_type->is_matrix());
 	       return new(ctx) ir_call(sig, & actual_parameters);
+	    }
 	 } else {
 	    /* FINISHME: Log a better error message here.  G++ will show the
 	     * FINSIHME: types of the actual parameters and the set of



More information about the mesa-commit mailing list