Mesa (glsl2): glsl2: Don't flatten constructor parameters to scalars

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


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

Author: Ian Romanick <ian.d.romanick at intel.com>
Date:   Fri Jun 25 17:36:17 2010 -0700

glsl2: Don't flatten constructor parameters to scalars

Now that all scalar, vector, and matrix constructors are emitted
in-line, the parameters to these constructors should not be flattened
to a pile of scalars.  Instead, the functions that emit the in-line
constructor bodies can directly write the parameters to the correct
locations in the objects being constructed.

---

 src/glsl/ast_function.cpp |  188 ++++++++++++++-------------------------------
 1 files changed, 59 insertions(+), 129 deletions(-)

diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
index 3828d32..e23d789 100644
--- a/src/glsl/ast_function.cpp
+++ b/src/glsl/ast_function.cpp
@@ -903,19 +903,6 @@ ast_function_expression::hir(exec_list *instructions,
        * matching rules as functions.
        */
       if (constructor_type->is_numeric() || constructor_type->is_boolean()) {
-	 /* Constructing a numeric type has a couple steps.  First all values
-	  * passed to the constructor are broken into individual parameters
-	  * and type converted to the base type of the thing being constructed.
-	  *
-	  * At that point we have some number of values that match the base
-	  * type of the thing being constructed.  Now the constructor can be
-	  * treated like a function call.  Each numeric type has a small set
-	  * of constructor functions.  The set of new parameters will either
-	  * match one of those functions or the original constructor is
-	  * invalid.
-	  */
-	 const glsl_type *const base_type = constructor_type->get_base_type();
-
 	 /* Total number of components of the type being constructed.
 	  */
 	 const unsigned type_components = constructor_type->components();
@@ -944,19 +931,6 @@ ast_function_expression::hir(exec_list *instructions,
 	    ast_node *ast = exec_node_data(ast_node, n, link);
 	    ir_rvalue *result =
 	       ast->hir(instructions, state)->as_rvalue();
-	    ir_variable *result_var = NULL;
-
-	    /* Attempt to convert the parameter to a constant valued expression.
-	     * After doing so, track whether or not all the parameters to the
-	     * constructor are trivially constant valued expressions.
-	     */
-	    ir_rvalue *const constant =
-	       result->constant_expression_value();
-
-	    if (constant != NULL)
-	       result = constant;
-	    else
-	       all_parameters_are_constant = false;
 
 	    /* From page 50 (page 56 of the PDF) of the GLSL 1.50 spec:
 	     *
@@ -985,58 +959,28 @@ ast_function_expression::hir(exec_list *instructions,
 	    else
 	       nonmatrix_parameters++;
 
-	    /* We can't use the same instruction node in the multiple
-	     * swizzle dereferences that happen, so assign it to a
-	     * variable and deref that.  Plus it saves computation for
-	     * complicated expressions and handles
-	     * glsl-vs-constructor-call.shader_test.
+	    /* Type cast the parameter and add it to the parameter list for
+	     * the constructor.
 	     */
-	    if (result->type->components() >= 1 && !result->as_constant()) {
-	       result_var = new(ctx) ir_variable(result->type,
-						 "constructor_tmp");
-	       ir_dereference_variable *lhs;
-
-	       lhs = new(ctx) ir_dereference_variable(result_var);
-	       instructions->push_tail(new(ctx) ir_assignment(lhs,
-							      result, NULL));
-	    }
+	    const glsl_type *desired_type =
+	       glsl_type::get_instance(constructor_type->base_type,
+				       result->type->vector_elements,
+				       result->type->matrix_columns);
+	    result = convert_component(result, desired_type);
 
-	    /* Process each of the components of the parameter.  Dereference
-	     * each component individually, perform any type conversions, and
-	     * add it to the parameter list for the constructor.
+	    /* Attempt to convert the parameter to a constant valued expression.
+	     * After doing so, track whether or not all the parameters to the
+	     * constructor are trivially constant valued expressions.
 	     */
-	    for (unsigned i = 0; i < result->type->components(); i++) {
-	       if (components_used >= type_components)
-		  break;
-
-	       ir_rvalue *component;
-
-	       if (result_var) {
-		  ir_dereference *d = new(ctx) ir_dereference_variable(result_var);
-		  component = dereference_component(d, i);
-	       } else {
-		  component = dereference_component(result, i);
-	       }
-	       component = convert_component(component, base_type);
-
-	       /* All cases that could result in component->type being the
-		* error type should have already been caught above.
-		*/
-	       assert(component->type == base_type);
-
-	       if (component->as_constant() == NULL)
-		  all_parameters_are_constant = false;
+	    ir_rvalue *const constant = result->constant_expression_value();
 
-	       /* Don't actually generate constructor calls for scalars.
-		* Instead, do the usual component selection and conversion,
-		* and return the single component.
-		*/
-	       if (constructor_type->is_scalar())
-		  return component;
+	    if (constant != NULL)
+	       result = constant;
+	    else
+	       all_parameters_are_constant = false;
 
-	       actual_parameters.push_tail(component);
-	       components_used++;
-	    }
+	    actual_parameters.push_tail(result);
+	    components_used += result->type->components();
 	 }
 
 	 /* From page 28 (page 34 of the PDF) of the GLSL 1.10 spec:
@@ -1079,65 +1023,51 @@ ast_function_expression::hir(exec_list *instructions,
 	    return ir_call::get_error_instruction(ctx);
 	 }
 
-	 ir_function *f = state->symbols->get_function(constructor_type->name);
-	 if (f == NULL) {
-	    _mesa_glsl_error(& loc, state, "no constructor for type `%s'",
-			     constructor_type->name);
-	    return ir_call::get_error_instruction(ctx);
-	 }
 
-	 const ir_function_signature *sig =
-	    f->matching_signature(& actual_parameters);
-	 if (sig != NULL) {
-	    /* If all of the parameters are trivially constant, create a
-	     * constant representing the complete collection of parameters.
+	 /* If all of the parameters are trivially constant, create a
+	  * constant representing the complete collection of parameters.
+	  */
+	 if (all_parameters_are_constant) {
+	    if (components_used >= type_components)
+	       return new(ctx) ir_constant(constructor_type,
+					   & actual_parameters);
+
+	    /* The above case must handle all scalar constructors.
 	     */
-	    if (all_parameters_are_constant) {
-	       if (components_used >= type_components)
-		  return new(ctx) ir_constant(sig->return_type,
-					      & actual_parameters);
-
-	       assert(sig->return_type->is_vector()
-		      || sig->return_type->is_matrix());
-
-	       /* Constructors with exactly one component are special for
-		* vectors and matrices.  For vectors it causes all elements of
-		* the vector to be filled with the value.  For matrices it
-		* causes the matrix to be filled with 0 and the diagonal to be
-		* filled with the value.
-		*/
-	       ir_constant_data data;
-	       ir_constant *const initializer =
-		  (ir_constant *) actual_parameters.head;
-	       if (sig->return_type->is_matrix())
-		  generate_constructor_matrix(sig->return_type, initializer,
-					      &data);
-	       else
-		  generate_constructor_vector(sig->return_type, initializer,
-					      &data);
-
-	       return new(ctx) ir_constant(sig->return_type, &data);
-	    } else if (constructor_type->is_vector()) {
-	       return emit_inline_vector_constructor(constructor_type,
-						     instructions,
-						     &actual_parameters,
-						     ctx);
-	    } else {
-	       assert(constructor_type->is_matrix());
-	       return emit_inline_matrix_constructor(constructor_type,
-						     instructions,
-						     &actual_parameters,
-						     ctx);
-	    }
-	 } else {
-	    /* FINISHME: Log a better error message here.  G++ will show the
-	     * FINSIHME: types of the actual parameters and the set of
-	     * FINSIHME: candidate functions.  A different error should also be
-	     * FINSIHME: logged when multiple functions match.
+	    assert(constructor_type->is_vector()
+		   || constructor_type->is_matrix());
+
+	    /* Constructors with exactly one component are special for
+	     * vectors and matrices.  For vectors it causes all elements of
+	     * the vector to be filled with the value.  For matrices it
+	     * causes the matrix to be filled with 0 and the diagonal to be
+	     * filled with the value.
 	     */
-	    _mesa_glsl_error(& loc, state, "no matching constructor for `%s'",
-			     constructor_type->name);
-	    return ir_call::get_error_instruction(ctx);
+	    ir_constant_data data;
+	    ir_constant *const initializer =
+	       (ir_constant *) actual_parameters.head;
+	    if (constructor_type->is_matrix())
+	       generate_constructor_matrix(constructor_type, initializer,
+					   &data);
+	    else
+	       generate_constructor_vector(constructor_type, initializer,
+					   &data);
+
+	    return new(ctx) ir_constant(constructor_type, &data);
+	 } else if (constructor_type->is_scalar()) {
+	    return dereference_component((ir_rvalue *) actual_parameters.head,
+					 0);
+	 } else if (constructor_type->is_vector()) {
+	    return emit_inline_vector_constructor(constructor_type,
+						  instructions,
+						  &actual_parameters,
+						  ctx);
+	 } else {
+	    assert(constructor_type->is_matrix());
+	    return emit_inline_matrix_constructor(constructor_type,
+						  instructions,
+						  &actual_parameters,
+						  ctx);
 	 }
       }
 



More information about the mesa-commit mailing list