summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c58
1 files changed, 48 insertions, 10 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
index cb4660e424d..1539849b2d6 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c
@@ -299,6 +299,7 @@ lp_build_coord_repeat_npot_linear(struct lp_build_sample_context *bld,
*/
static void
lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
+ boolean is_gather,
LLVMValueRef coord,
LLVMValueRef length,
LLVMValueRef length_f,
@@ -388,13 +389,29 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
/* clamp to length max */
coord = lp_build_min_ext(coord_bld, coord, length_f,
GALLIVM_NAN_RETURN_OTHER_SECOND_NONNAN);
- /* subtract 0.5 */
- coord = lp_build_sub(coord_bld, coord, half);
- /* clamp to [0, length - 0.5] */
- coord = lp_build_max(coord_bld, coord, coord_bld->zero);
- /* convert to int, compute lerp weight */
- lp_build_ifloor_fract(&abs_coord_bld, coord, &coord0, &weight);
- coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
+ if (!is_gather) {
+ /* subtract 0.5 */
+ coord = lp_build_sub(coord_bld, coord, half);
+ /* clamp to [0, length - 0.5] */
+ coord = lp_build_max(coord_bld, coord, coord_bld->zero);
+ /* convert to int, compute lerp weight */
+ lp_build_ifloor_fract(&abs_coord_bld, coord, &coord0, &weight);
+ coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
+ } else {
+ /*
+ * The non-gather path will end up with coords 0, 1 if coord was
+ * smaller than 0.5 (with corresponding weight 0.0 so it doesn't
+ * really matter what the second coord is). But for gather, we
+ * really need to end up with coords 0, 0.
+ */
+ coord = lp_build_max(coord_bld, coord, coord_bld->zero);
+ coord0 = lp_build_sub(coord_bld, coord, half);
+ coord1 = lp_build_add(coord_bld, coord, half);
+ /* Values range ([-0.5, length_f - 0.5], [0.5, length_f + 0.5] */
+ coord0 = lp_build_itrunc(coord_bld, coord0);
+ coord1 = lp_build_itrunc(coord_bld, coord1);
+ weight = coord_bld->undef;
+ }
/* coord1 = min(coord1, length-1) */
coord1 = lp_build_min(int_coord_bld, coord1, length_minus_one);
break;
@@ -424,6 +441,13 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
coord = lp_build_add(coord_bld, coord, offset);
}
/* compute mirror function */
+ /*
+ * XXX: This looks incorrect wrt gather. Due to wrap specification,
+ * it is possible the first coord ends up larger than the second one.
+ * However, with our simplifications the coordinates will be swapped
+ * in this case. (Albeit some other api tests don't like it even
+ * with this fixed...)
+ */
coord = lp_build_coord_mirror(bld, coord);
/* scale coord to length */
@@ -474,6 +498,20 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
offset = lp_build_int_to_float(coord_bld, offset);
coord = lp_build_add(coord_bld, coord, offset);
}
+ /*
+ * XXX: This looks incorrect wrt gather. Due to wrap specification,
+ * the first and second texel actually end up with "different order"
+ * for negative coords. For example, if the scaled coord would
+ * be -0.6, then the first coord should end up as 1
+ * (floor(-0.6 - 0.5) == -2, mirror makes that 1), the second as 0
+ * (floor(-0.6 - 0.5) + 1 == -1, mirror makes that 0).
+ * But with our simplifications the second coord will always be the
+ * larger one. The other two mirror_clamp modes have the same problem.
+ * Moreover, for coords close to zero we should end up with both
+ * coords being 0, but we will end up with coord1 being 1 instead
+ * (with bilinear filtering this is ok as the weight is 0.0) (this
+ * problem is specific to mirror_clamp_to_edge).
+ */
coord = lp_build_abs(coord_bld, coord);
/* clamp to length max */
@@ -929,7 +967,7 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld,
*/
if (!seamless_cube_filter) {
- lp_build_sample_wrap_linear(bld, coords[0], width_vec,
+ lp_build_sample_wrap_linear(bld, is_gather, coords[0], width_vec,
flt_width_vec, offsets[0],
bld->static_texture_state->pot_width,
bld->static_sampler_state->wrap_s,
@@ -940,7 +978,7 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld,
x11 = x01;
if (dims >= 2) {
- lp_build_sample_wrap_linear(bld, coords[1], height_vec,
+ lp_build_sample_wrap_linear(bld, is_gather, coords[1], height_vec,
flt_height_vec, offsets[1],
bld->static_texture_state->pot_height,
bld->static_sampler_state->wrap_t,
@@ -951,7 +989,7 @@ lp_build_sample_image_linear(struct lp_build_sample_context *bld,
y11 = y10;
if (dims == 3) {
- lp_build_sample_wrap_linear(bld, coords[2], depth_vec,
+ lp_build_sample_wrap_linear(bld, is_gather, coords[2], depth_vec,
flt_depth_vec, offsets[2],
bld->static_texture_state->pot_depth,
bld->static_sampler_state->wrap_r,