From f87ad0cdc41af88f134475ab50b0d604004d9cdc Mon Sep 17 00:00:00 2001 From: marha Date: Mon, 1 Aug 2011 09:05:15 +0200 Subject: mesa xserver pixman xkeyboard-config git update 1 aug 2011 --- mesalib/src/glsl/ast_function.cpp | 12 +++- mesalib/src/glsl/glsl_types.cpp | 16 +++++ mesalib/src/glsl/glsl_types.h | 35 ++++++++++ mesalib/src/glsl/ir_function.cpp | 140 ++++++++++++++------------------------ 4 files changed, 113 insertions(+), 90 deletions(-) (limited to 'mesalib/src/glsl') diff --git a/mesalib/src/glsl/ast_function.cpp b/mesalib/src/glsl/ast_function.cpp index bdb73f487..8bcf48dfd 100644 --- a/mesalib/src/glsl/ast_function.cpp +++ b/mesalib/src/glsl/ast_function.cpp @@ -442,13 +442,21 @@ process_array_constructor(exec_list *instructions, ir_rvalue *ir = (ir_rvalue *) n; ir_rvalue *result = ir; - /* Apply implicit conversions (not the scalar constructor rules!) */ + /* Apply implicit conversions (not the scalar constructor rules!). See + * the spec quote above. */ if (constructor_type->element_type()->is_float()) { const glsl_type *desired_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, ir->type->vector_elements, ir->type->matrix_columns); - result = convert_component(ir, desired_type); + if (result->type->can_implicitly_convert_to(desired_type)) { + /* Even though convert_component() implements the constructor + * conversion rules (not the implicit conversion rules), its safe + * to use it here because we already checked that the implicit + * conversion is legal. + */ + result = convert_component(ir, desired_type); + } } if (result->type != constructor_type->element_type()) { diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp index a5e21bbb9..c94aec0d2 100644 --- a/mesalib/src/glsl/glsl_types.cpp +++ b/mesalib/src/glsl/glsl_types.cpp @@ -523,3 +523,19 @@ glsl_type::component_slots() const return 0; } } + +bool +glsl_type::can_implicitly_convert_to(const glsl_type *desired) const +{ + if (this == desired) + return true; + + /* There is no conversion among matrix types. */ + if (this->matrix_columns > 1 || desired->matrix_columns > 1) + return false; + + /* int and uint can be converted to float. */ + return desired->is_float() + && this->is_integer() + && this->vector_elements == desired->vector_elements; +} diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h index 87f57e7c7..048696693 100644 --- a/mesalib/src/glsl/glsl_types.h +++ b/mesalib/src/glsl/glsl_types.h @@ -224,6 +224,41 @@ struct glsl_type { */ unsigned component_slots() const; + /** + * \brief Can this type be implicitly converted to another? + * + * \return True if the types are identical or if this type can be converted + * to \c desired according to Section 4.1.10 of the GLSL spec. + * + * \verbatim + * From page 25 (31 of the pdf) of the GLSL 1.50 spec, Section 4.1.10 + * Implicit Conversions: + * + * In some situations, an expression and its type will be implicitly + * converted to a different type. The following table shows all allowed + * implicit conversions: + * + * Type of expression | Can be implicitly converted to + * -------------------------------------------------- + * int float + * uint + * + * ivec2 vec2 + * uvec2 + * + * ivec3 vec3 + * uvec3 + * + * ivec4 vec4 + * uvec4 + * + * There are no implicit array or structure conversions. For example, + * an array of int cannot be implicitly converted to an array of float. + * There are no implicit conversions between signed and unsigned + * integers. + * \endverbatim + */ + bool can_implicitly_convert_to(const glsl_type *desired) const; /** * Query whether or not a type is a scalar (non-vector and non-matrix). diff --git a/mesalib/src/glsl/ir_function.cpp b/mesalib/src/glsl/ir_function.cpp index 0f2f1a0ee..6cfc32cc2 100644 --- a/mesalib/src/glsl/ir_function.cpp +++ b/mesalib/src/glsl/ir_function.cpp @@ -24,73 +24,36 @@ #include "glsl_types.h" #include "ir.h" -int -type_compare(const glsl_type *a, const glsl_type *b) -{ - /* If the types are the same, they trivially match. - */ - if (a == b) - return 0; - - switch (a->base_type) { - case GLSL_TYPE_UINT: - case GLSL_TYPE_INT: - case GLSL_TYPE_BOOL: - /* There is no implicit conversion to or from integer types or bool. - */ - if ((a->is_integer() != b->is_integer()) - || (a->is_boolean() != b->is_boolean())) - return -1; - - /* FALLTHROUGH */ - - case GLSL_TYPE_FLOAT: - if ((a->vector_elements != b->vector_elements) - || (a->matrix_columns != b->matrix_columns)) - return -1; - - return 1; - - case GLSL_TYPE_SAMPLER: - case GLSL_TYPE_STRUCT: - /* Samplers and structures must match exactly. - */ - return -1; - - case GLSL_TYPE_ARRAY: - if ((b->base_type != GLSL_TYPE_ARRAY) - || (a->length != b->length)) - return -1; - - /* From GLSL 1.50 spec, page 27 (page 33 of the PDF): - * "There are no implicit array or structure conversions." - * - * If the comparison of the array element types detects that a conversion - * would be required, the array types do not match. - */ - return (type_compare(a->fields.array, b->fields.array) == 0) ? 0 : -1; - - case GLSL_TYPE_VOID: - case GLSL_TYPE_ERROR: - default: - /* These are all error conditions. It is invalid for a parameter to - * a function to be declared as error, void, or a function. - */ - return -1; - } - - /* This point should be unreachable. - */ - assert(0); -} - +typedef enum { + PARAMETER_LIST_NO_MATCH, + PARAMETER_LIST_EXACT_MATCH, + PARAMETER_LIST_INEXACT_MATCH, /*< Match requires implicit conversion. */ +} parameter_list_match_t; + +/** + * \brief Check if two parameter lists match. + * + * \param list_a Parameters of the function definition. + * \param list_b Actual parameters passed to the function. + * \see matching_signature() + */ -static int +/** + * \brief Check if two parameter lists match. + * + * \param list_a Parameters of the function definition. + * \param list_b Actual parameters passed to the function. + * \see matching_signature() + */ +static parameter_list_match_t parameter_lists_match(const exec_list *list_a, const exec_list *list_b) { const exec_node *node_a = list_a->head; const exec_node *node_b = list_b->head; - int total_score = 0; + + /* This is set to true if there is an inexact match requiring an implicit + * conversion. */ + bool inexact_match = false; for (/* empty */ ; !node_a->is_tail_sentinel() @@ -100,18 +63,17 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b) * do not match. */ if (node_b->is_tail_sentinel()) - return -1; + return PARAMETER_LIST_NO_MATCH; const ir_variable *const param = (ir_variable *) node_a; const ir_instruction *const actual = (ir_instruction *) node_b; - /* Determine whether or not the types match. If the types are an - * exact match, the match score is zero. If the types don't match - * but the actual parameter can be coerced to the type of the declared - * parameter, the match score is one. - */ - int score; + if (param->type == actual->type) + continue; + + /* Try to find an implicit conversion from actual to param. */ + inexact_match = true; switch ((enum ir_variable_mode)(param->mode)) { case ir_var_auto: case ir_var_uniform: @@ -121,15 +83,17 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b) * as uniform. */ assert(0); - return -1; + return PARAMETER_LIST_NO_MATCH; case ir_var_const_in: case ir_var_in: - score = type_compare(param->type, actual->type); + if (!actual->type->can_implicitly_convert_to(param->type)) + return PARAMETER_LIST_NO_MATCH; break; case ir_var_out: - score = type_compare(actual->type, param->type); + if (!param->type->can_implicitly_convert_to(actual->type)) + return PARAMETER_LIST_NO_MATCH; break; case ir_var_inout: @@ -137,17 +101,12 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b) * there is int -> float but no float -> int), inout parameters must * be exact matches. */ - score = (type_compare(actual->type, param->type) == 0) ? 0 : -1; - break; + return PARAMETER_LIST_NO_MATCH; default: assert(false); + return PARAMETER_LIST_NO_MATCH; } - - if (score < 0) - return -1; - - total_score += score; } /* If all of the parameters from the other parameter list have been @@ -155,9 +114,12 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b) * match. */ if (!node_b->is_tail_sentinel()) - return -1; + return PARAMETER_LIST_NO_MATCH; - return total_score; + if (inexact_match) + return PARAMETER_LIST_INEXACT_MATCH; + else + return PARAMETER_LIST_EXACT_MATCH; } @@ -181,18 +143,20 @@ ir_function::matching_signature(const exec_list *actual_parameters) ir_function_signature *const sig = (ir_function_signature *) iter.get(); - const int score = parameter_lists_match(& sig->parameters, - actual_parameters); - - /* If we found an exact match, simply return it */ - if (score == 0) + switch (parameter_lists_match(& sig->parameters, actual_parameters)) { + case PARAMETER_LIST_EXACT_MATCH: return sig; - - if (score > 0) { + case PARAMETER_LIST_INEXACT_MATCH: if (match == NULL) match = sig; else multiple_inexact_matches = true; + continue; + case PARAMETER_LIST_NO_MATCH: + continue; + default: + assert(false); + return NULL; } } -- cgit v1.2.3