diff options
author | Roland Scheidegger <[email protected]> | 2016-04-26 04:53:01 +0200 |
---|---|---|
committer | Roland Scheidegger <[email protected]> | 2016-04-26 04:55:37 +0200 |
commit | bd07e20d208268382a34dca23ff71a8192bb1525 (patch) | |
tree | dff2bbedc39d7187f562c8971449c56085cbef1f /src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c | |
parent | d8edc3e97cfc9ff36c5f6009dc98bc78e2f76389 (diff) |
gallivm: make sampling more robust against bogus coordinates
Some cases (especially these using fract for coord wrapping) did not handle
NaNs (or Infs) correctly - the following code assumed the fract result
could not be outside [0,1], but if the input is a NaN (or +-Inf) the fract
result was NaN - which then could produce out-of-bound offsets.
(Note that the explicit NaN behavior changes for min/max on x86 sse don't
result in actual changes in the generated jit code, but may on other
architectures. Found by looking through all the wrap functions.)
This fixes https://bugs.freedesktop.org/show_bug.cgi?id=94955
No piglit changes.
(v2: fix min/max typo in coord_mirror, add comment)
Cc: "11.1 11.2" <[email protected]>
Tested-by: Bruce Cherniak <[email protected]>
Reviewed-by: Jose Fonseca <[email protected]>
Diffstat (limited to 'src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c')
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c index 729c5b8f6ef..6bf92c87c49 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c @@ -246,6 +246,12 @@ lp_build_coord_repeat_npot_linear_int(struct lp_build_sample_context *bld, mask = lp_build_compare(int_coord_bld->gallivm, int_coord_bld->type, PIPE_FUNC_LESS, *coord0_i, int_coord_bld->zero); *coord0_i = lp_build_select(int_coord_bld, mask, length_minus_one, *coord0_i); + /* + * We should never get values too large - except if coord was nan or inf, + * in which case things go terribly wrong... + * Alternatively, could use fract_safe above... + */ + *coord0_i = lp_build_min(int_coord_bld, *coord0_i, length_minus_one); } @@ -490,6 +496,10 @@ lp_build_sample_wrap_linear_float(struct lp_build_sample_context *bld, *coord1 = lp_build_add(coord_bld, coord, half); coord = lp_build_sub(coord_bld, coord, half); *weight = lp_build_fract(coord_bld, coord); + /* + * It is important for this comparison to be unordered + * (or need fract_safe above). + */ mask = lp_build_compare(coord_bld->gallivm, coord_bld->type, PIPE_FUNC_LESS, coord, coord_bld->zero); *coord0 = lp_build_select(coord_bld, mask, length_minus_one, coord); @@ -514,7 +524,8 @@ lp_build_sample_wrap_linear_float(struct lp_build_sample_context *bld, coord = lp_build_sub(coord_bld, coord, half); } /* clamp to [0, length - 1] */ - coord = lp_build_min(coord_bld, coord, length_minus_one); + coord = lp_build_min_ext(coord_bld, coord, length_minus_one, + GALLIVM_NAN_RETURN_OTHER_SECOND_NONNAN); coord = lp_build_max(coord_bld, coord, coord_bld->zero); *coord1 = lp_build_add(coord_bld, coord, coord_bld->one); /* convert to int, compute lerp weight */ |