[Mesa-dev] [PATCH 1/3] softpipe: implement coord clamping for texel fetches (TXF)

Brian Paul brian.e.paul at gmail.com
Tue May 1 07:48:27 PDT 2012


From: Brian Paul <brianp at vmware.com>

The GL spec says out of bounds fetches produce undefined results.
Use clamping to avoid failed assertions or crashes.

Fixes failed assertion in https://bugs.freedesktop.org/show_bug.cgi?id=49125
but the test still fails.
---
 src/gallium/drivers/softpipe/sp_tex_sample.c |   45 ++++++++++++++++++--------
 1 files changed, 31 insertions(+), 14 deletions(-)

diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c
index d54e02e..83d9be8 100644
--- a/src/gallium/drivers/softpipe/sp_tex_sample.c
+++ b/src/gallium/drivers/softpipe/sp_tex_sample.c
@@ -799,7 +799,8 @@ get_texel_2d_array(const struct sp_sampler_variant *samp,
    const struct pipe_resource *texture = samp->view->texture;
    unsigned level = addr.bits.level;
 
-   assert(layer < texture->array_size);
+   assert(layer < (int) texture->array_size);
+   assert(layer >= 0);
 
    if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
        y < 0 || y >= (int) u_minify(texture->height0, level)) {
@@ -2630,8 +2631,12 @@ sample_get_dims(struct tgsi_sampler *tgsi_sampler, int level,
     }
 }
 
-/* this function is only used for unfiltered texel gets
-   via the TGSI TXF opcode. */
+/**
+ * This function is only used for getting unfiltered texels via the
+ * TXF opcode.  The GL spec says that out-of-bounds texel fetches
+ * produce undefined results.  Instead of crashing, lets just clamp
+ * coords to the texture image size.
+ */
 static void
 sample_get_texels(struct tgsi_sampler *tgsi_sampler,
 	   const int v_i[TGSI_QUAD_SIZE],
@@ -2650,15 +2655,22 @@ sample_get_texels(struct tgsi_sampler *tgsi_sampler,
                         samp->key.bits.swizzle_g != PIPE_SWIZZLE_GREEN ||
                         samp->key.bits.swizzle_b != PIPE_SWIZZLE_BLUE ||
                         samp->key.bits.swizzle_a != PIPE_SWIZZLE_ALPHA);
+   int width, height, depth, layers;
 
    addr.value = 0;
    /* TODO write a better test for LOD */
    addr.bits.level = lod[0];
 
+   width = u_minify(texture->width0, addr.bits.level);
+   height = u_minify(texture->height0, addr.bits.level);
+   depth = u_minify(texture->depth0, addr.bits.level);
+   layers = texture->array_size;
+
    switch(texture->target) {
    case PIPE_TEXTURE_1D:
       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
-	 tx = get_texel_2d(samp, addr, v_i[j] + offset[0], 0);
+         int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
+	 tx = get_texel_2d(samp, addr, x, 0);
 	 for (c = 0; c < 4; c++) {
 	    rgba[c][j] = tx[c];
 	 }
@@ -2666,8 +2678,9 @@ sample_get_texels(struct tgsi_sampler *tgsi_sampler,
       break;
    case PIPE_TEXTURE_1D_ARRAY:
       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
-	 tx = get_texel_1d_array(samp, addr, v_i[j] + offset[0],
-				 v_j[j] + offset[1]);
+         int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
+         int y = CLAMP(v_j[j] + offset[1], 0, layers - 1);
+	 tx = get_texel_1d_array(samp, addr, x, y);
 	 for (c = 0; c < 4; c++) {
 	    rgba[c][j] = tx[c];
 	 }
@@ -2676,8 +2689,9 @@ sample_get_texels(struct tgsi_sampler *tgsi_sampler,
    case PIPE_TEXTURE_2D:
    case PIPE_TEXTURE_RECT:
       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
-	 tx = get_texel_2d(samp, addr, v_i[j] + offset[0],
-			   v_j[j] + offset[1]);
+         int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
+         int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
+	 tx = get_texel_2d(samp, addr, x, y);
 	 for (c = 0; c < 4; c++) {
 	    rgba[c][j] = tx[c];
 	 }
@@ -2685,9 +2699,10 @@ sample_get_texels(struct tgsi_sampler *tgsi_sampler,
       break;
    case PIPE_TEXTURE_2D_ARRAY:
       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
-	 tx = get_texel_2d_array(samp, addr, v_i[j] + offset[0],
-				 v_j[j] + offset[1],
-				 v_k[j] + offset[2]);
+         int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
+         int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
+         int layer = CLAMP(v_k[j] + offset[2], 0, layers - 1);
+	 tx = get_texel_2d_array(samp, addr, x, y, layer);
 	 for (c = 0; c < 4; c++) {
 	    rgba[c][j] = tx[c];
 	 }
@@ -2695,9 +2710,11 @@ sample_get_texels(struct tgsi_sampler *tgsi_sampler,
       break;
    case PIPE_TEXTURE_3D:
       for (j = 0; j < TGSI_QUAD_SIZE; j++) {
-	 tx = get_texel_3d(samp, addr, v_i[j] + offset[0], 
-			   v_j[j] + offset[1],
-			   v_k[j] + offset[2]);
+         int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
+         int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
+         int z = CLAMP(v_k[j] + offset[2], 0, depth - 1);
+
+	 tx = get_texel_3d(samp, addr, x, y, z);
 	 for (c = 0; c < 4; c++) {
 	    rgba[c][j] = tx[c];
 	 }
-- 
1.7.4.1



More information about the mesa-dev mailing list