summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth Graunke <kenneth@whitecape.org>2011-06-14 16:28:32 -0700
committerKenneth Graunke <kenneth@whitecape.org>2011-06-29 16:07:13 -0700
commit60eb63a855cb89962f2d5bb91e238ff2d1ab8702 (patch)
tree726ddf1d02fd78a4eb504accd088ff8a46659650
parent6b1ba7ccef18232e5586fcda2ff75ef5bd05b57b (diff)
glsl: Find the "closest" signature when there are multiple matches.
Previously, ir_function::matching_signature had a fatal bug: if a function had more than one non-exact match, it would simply return NULL. This occured, for example, when looking for max(uvec3, uvec3): - max(vec3, vec3) -> score 1 (found first) - max(ivec3, ivec3) -> score 1 (found second...used to return NULL here) - max(uvec3, uvec3) -> score 0 (exact match...the right answer) This did not occur for max(ivec3, ivec3) since the second match found was an exact match. The new behavior is to return a match with the lowest score. If there is an exact match, that will be returned. Otherwise, a match with the least number of implicit conversions is chosen. Fixes piglit tests max-uvec3.vert and glsl-inexact-overloads.shader_test. NOTE: This is a candidate for the 7.10 and 7.11 branches. Signed-off-by: Kenneth Graunke <kenneth@whitecape.org> Reviewed-by: Ian Romanick <ian.d.romanick@intel.com> Reviewed-by: Eric Anholt <eric@anholt.net>
-rw-r--r--src/glsl/ir_function.cpp9
1 files changed, 5 insertions, 4 deletions
diff --git a/src/glsl/ir_function.cpp b/src/glsl/ir_function.cpp
index caee9296af9..ef8d4fcfcd4 100644
--- a/src/glsl/ir_function.cpp
+++ b/src/glsl/ir_function.cpp
@@ -165,6 +165,7 @@ ir_function_signature *
ir_function::matching_signature(const exec_list *actual_parameters)
{
ir_function_signature *match = NULL;
+ int matched_score;
foreach_iter(exec_list_iterator, iter, signatures) {
ir_function_signature *const sig =
@@ -173,14 +174,14 @@ ir_function::matching_signature(const exec_list *actual_parameters)
const int score = parameter_lists_match(& sig->parameters,
actual_parameters);
+ /* If we found an exact match, simply return it */
if (score == 0)
return sig;
- if (score > 0) {
- if (match != NULL)
- return NULL;
-
+ /* If we found a match with fewer conversions, use that instead */
+ if (score > 0 && (match == NULL || score < matched_score)) {
match = sig;
+ matched_score = score;
}
}