diff options
author | Kenneth Graunke <[email protected]> | 2011-06-14 16:28:32 -0700 |
---|---|---|
committer | Kenneth Graunke <[email protected]> | 2011-06-29 16:07:13 -0700 |
commit | 60eb63a855cb89962f2d5bb91e238ff2d1ab8702 (patch) | |
tree | 726ddf1d02fd78a4eb504accd088ff8a46659650 | |
parent | 6b1ba7ccef18232e5586fcda2ff75ef5bd05b57b (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 <[email protected]>
Reviewed-by: Ian Romanick <[email protected]>
Reviewed-by: Eric Anholt <[email protected]>
-rw-r--r-- | src/glsl/ir_function.cpp | 9 |
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; } } |