Mesa (master): llvmpipe: Use struct lp_shader_input in the interpolator.

Jose Fonseca jrfonseca at kemper.freedesktop.org
Tue Jun 1 13:31:06 PDT 2010


Module: Mesa
Branch: master
Commit: 6ce68ad3ca242076bbb93fdd99bb448f87a31d15
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=6ce68ad3ca242076bbb93fdd99bb448f87a31d15

Author: José Fonseca <jfonseca at vmware.com>
Date:   Tue Jun  1 21:27:18 2010 +0100

llvmpipe: Use struct lp_shader_input in the interpolator.

Eliminates all this identical yet slightly different code to decide how
shader inputs should be interpolated.

As bonus, don't interpolate the position twice when it is listed in the
TGSI shader inputs.

---

 src/gallium/drivers/llvmpipe/lp_bld_interp.c    |  165 ++++++++++++----------
 src/gallium/drivers/llvmpipe/lp_bld_interp.h    |   11 +-
 src/gallium/drivers/llvmpipe/lp_context.h       |    5 +
 src/gallium/drivers/llvmpipe/lp_setup_tri.c     |   77 +++++++----
 src/gallium/drivers/llvmpipe/lp_state_derived.c |    3 +-
 src/gallium/drivers/llvmpipe/lp_state_fs.c      |    9 +-
 6 files changed, 160 insertions(+), 110 deletions(-)

diff --git a/src/gallium/drivers/llvmpipe/lp_bld_interp.c b/src/gallium/drivers/llvmpipe/lp_bld_interp.c
index 07c9e64..d1f0185 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_interp.c
+++ b/src/gallium/drivers/llvmpipe/lp_bld_interp.c
@@ -105,15 +105,15 @@ coeffs_init(struct lp_build_interp_soa_context *bld,
       for(chan = 0; chan < NUM_CHANNELS; ++chan) {
          if(mask & (1 << chan)) {
             LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), attrib*NUM_CHANNELS + chan, 0);
-            LLVMValueRef a0 = NULL;
-            LLVMValueRef dadx = NULL;
-            LLVMValueRef dady = NULL;
+            LLVMValueRef a0 = bld->base.undef;
+            LLVMValueRef dadx = bld->base.undef;
+            LLVMValueRef dady = bld->base.undef;
 
             switch( interp ) {
-            case TGSI_INTERPOLATE_PERSPECTIVE:
+            case LP_INTERP_PERSPECTIVE:
                /* fall-through */
 
-            case TGSI_INTERPOLATE_LINEAR:
+            case LP_INTERP_LINEAR:
                dadx = LLVMBuildLoad(builder, LLVMBuildGEP(builder, dadx_ptr, &index, 1, ""), "");
                dady = LLVMBuildLoad(builder, LLVMBuildGEP(builder, dady_ptr, &index, 1, ""), "");
                dadx = lp_build_broadcast_scalar(&bld->base, dadx);
@@ -122,12 +122,17 @@ coeffs_init(struct lp_build_interp_soa_context *bld,
                attrib_name(dady, attrib, chan, ".dady");
                /* fall-through */
 
-            case TGSI_INTERPOLATE_CONSTANT:
+            case LP_INTERP_CONSTANT:
+            case LP_INTERP_FACING:
                a0 = LLVMBuildLoad(builder, LLVMBuildGEP(builder, a0_ptr, &index, 1, ""), "");
                a0 = lp_build_broadcast_scalar(&bld->base, a0);
                attrib_name(a0, attrib, chan, ".a0");
                break;
 
+            case LP_INTERP_POSITION:
+               /* Nothing to do as the position coeffs are already setup in slot 0 */
+               break;
+
             default:
                assert(0);
                break;
@@ -163,36 +168,44 @@ attribs_init(struct lp_build_interp_soa_context *bld)
       const unsigned interp = bld->interp[attrib];
       for(chan = 0; chan < NUM_CHANNELS; ++chan) {
          if(mask & (1 << chan)) {
-            LLVMValueRef a0   = bld->a0  [attrib][chan];
-            LLVMValueRef dadx = bld->dadx[attrib][chan];
-            LLVMValueRef dady = bld->dady[attrib][chan];
-            LLVMValueRef res;
-
-            res = a0;
-
-            if (interp != TGSI_INTERPOLATE_CONSTANT) {
-               /* res = res + x * dadx */
-               res = lp_build_add(&bld->base, res, lp_build_mul(&bld->base, x, dadx));
-               /* res = res + y * dady */
-               res = lp_build_add(&bld->base, res, lp_build_mul(&bld->base, y, dady));
+            if (interp == LP_INTERP_POSITION) {
+               assert(attrib > 0);
+               bld->attribs[attrib][chan] = bld->attribs[0][chan];
             }
+            else {
+               LLVMValueRef a0   = bld->a0  [attrib][chan];
+               LLVMValueRef dadx = bld->dadx[attrib][chan];
+               LLVMValueRef dady = bld->dady[attrib][chan];
+               LLVMValueRef res;
 
-            /* Keep the value of the attribute before perspective divide
-             * for faster updates.
-             */
-            bld->attribs_pre[attrib][chan] = res;
-
-            if (interp == TGSI_INTERPOLATE_PERSPECTIVE) {
-               LLVMValueRef w = bld->pos[3];
-               assert(attrib != 0);
-               if(!oow)
-                  oow = lp_build_rcp(&bld->base, w);
-               res = lp_build_mul(&bld->base, res, oow);
-            }
+               res = a0;
+
+               if (interp != LP_INTERP_CONSTANT &&
+                   interp != LP_INTERP_FACING) {
+                  /* res = res + x * dadx */
+                  res = lp_build_add(&bld->base, res, lp_build_mul(&bld->base, x, dadx));
+                  /* res = res + y * dady */
+                  res = lp_build_add(&bld->base, res, lp_build_mul(&bld->base, y, dady));
+               }
 
-            attrib_name(res, attrib, chan, "");
+               /* Keep the value of the attribute before perspective divide
+                * for faster updates.
+                */
+               bld->attribs_pre[attrib][chan] = res;
 
-            bld->attribs[attrib][chan] = res;
+               if (interp == LP_INTERP_PERSPECTIVE) {
+                  LLVMValueRef w = bld->pos[3];
+                  assert(attrib != 0);
+                  assert(bld->mask[0] & TGSI_WRITEMASK_W);
+                  if(!oow)
+                     oow = lp_build_rcp(&bld->base, w);
+                  res = lp_build_mul(&bld->base, res, oow);
+               }
+
+               attrib_name(res, attrib, chan, "");
+
+               bld->attribs[attrib][chan] = res;
+            }
          }
       }
    }
@@ -216,40 +229,48 @@ attribs_update(struct lp_build_interp_soa_context *bld, int quad_index)
       const unsigned mask = bld->mask[attrib];
       const unsigned interp = bld->interp[attrib];
 
-      if (interp != TGSI_INTERPOLATE_CONSTANT) {
+      if (interp != LP_INTERP_CONSTANT &&
+          interp != LP_INTERP_FACING) {
          for(chan = 0; chan < NUM_CHANNELS; ++chan) {
             if(mask & (1 << chan)) {
-               LLVMValueRef dadx = bld->dadx[attrib][chan];
-               LLVMValueRef dady = bld->dady[attrib][chan];
-               LLVMValueRef res;
-
-               res = bld->attribs_pre[attrib][chan];
-
-               if (quad_index == 1 || quad_index == 3) {
-                  /* top-right or bottom-right quad */
-                  /* build res = res + dadx + dadx */
-                  res = lp_build_add(&bld->base, res, dadx);
-                  res = lp_build_add(&bld->base, res, dadx);
+               if (interp == LP_INTERP_POSITION) {
+                  assert(attrib > 0);
+                  bld->attribs[attrib][chan] = bld->attribs[0][chan];
                }
-
-               if (quad_index == 2 || quad_index == 3) {
-                  /* bottom-left or bottom-right quad */
-                  /* build res = res + dady + dady */
-                  res = lp_build_add(&bld->base, res, dady);
-                  res = lp_build_add(&bld->base, res, dady);
+               else {
+                  LLVMValueRef dadx = bld->dadx[attrib][chan];
+                  LLVMValueRef dady = bld->dady[attrib][chan];
+                  LLVMValueRef res;
+
+                  res = bld->attribs_pre[attrib][chan];
+
+                  if (quad_index == 1 || quad_index == 3) {
+                     /* top-right or bottom-right quad */
+                     /* build res = res + dadx + dadx */
+                     res = lp_build_add(&bld->base, res, dadx);
+                     res = lp_build_add(&bld->base, res, dadx);
+                  }
+
+                  if (quad_index == 2 || quad_index == 3) {
+                     /* bottom-left or bottom-right quad */
+                     /* build res = res + dady + dady */
+                     res = lp_build_add(&bld->base, res, dady);
+                     res = lp_build_add(&bld->base, res, dady);
+                  }
+
+                  if (interp == LP_INTERP_PERSPECTIVE) {
+                     LLVMValueRef w = bld->pos[3];
+                     assert(attrib != 0);
+                     assert(bld->mask[0] & TGSI_WRITEMASK_W);
+                     if(!oow)
+                        oow = lp_build_rcp(&bld->base, w);
+                     res = lp_build_mul(&bld->base, res, oow);
+                  }
+
+                  attrib_name(res, attrib, chan, "");
+
+                  bld->attribs[attrib][chan] = res;
                }
-
-               if (interp == TGSI_INTERPOLATE_PERSPECTIVE) {
-                  LLVMValueRef w = bld->pos[3];
-                  assert(attrib != 0);
-                  if(!oow)
-                     oow = lp_build_rcp(&bld->base, w);
-                  res = lp_build_mul(&bld->base, res, oow);
-               }
-
-               attrib_name(res, attrib, chan, "");
-
-               bld->attribs[attrib][chan] = res;
             }
          }
       }
@@ -315,8 +336,8 @@ pos_update(struct lp_build_interp_soa_context *bld, int quad_index)
  */
 void
 lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld,
-                         const struct tgsi_shader_info *info,
-                         boolean flatshade,
+                         unsigned num_inputs,
+                         const struct lp_shader_input *inputs,
                          LLVMBuilderRef builder,
                          struct lp_type type,
                          LLVMValueRef a0_ptr,
@@ -339,20 +360,14 @@ lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld,
    /* Position */
    bld->num_attribs = 1;
    bld->mask[0] = TGSI_WRITEMASK_ZW;
-   bld->interp[0] = TGSI_INTERPOLATE_LINEAR;
+   bld->interp[0] = LP_INTERP_LINEAR;
 
    /* Inputs */
-   for (attrib = 0; attrib < info->num_inputs; ++attrib) {
-      bld->mask[1 + attrib] = info->input_usage_mask[attrib];
-
-      if (info->input_semantic_name[attrib] == TGSI_SEMANTIC_COLOR &&
-          flatshade)
-         bld->interp[1 + attrib] = TGSI_INTERPOLATE_CONSTANT;
-      else
-         bld->interp[1 + attrib] = info->input_interpolate[attrib];
-
+   for (attrib = 0; attrib < num_inputs; ++attrib) {
+      bld->mask[1 + attrib] = inputs[attrib].usage_mask;
+      bld->interp[1 + attrib] = inputs[attrib].interp;
    }
-   bld->num_attribs = 1 + info->num_inputs;
+   bld->num_attribs = 1 + num_inputs;
 
    /* Ensure all masked out input channels have a valid value */
    for (attrib = 0; attrib < bld->num_attribs; ++attrib) {
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_interp.h b/src/gallium/drivers/llvmpipe/lp_bld_interp.h
index 2d41fef..79d1e51 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_interp.h
+++ b/src/gallium/drivers/llvmpipe/lp_bld_interp.h
@@ -46,10 +46,7 @@
 
 #include "tgsi/tgsi_exec.h"
 
-
-
-struct tgsi_token;
-struct tgsi_shader_info;
+#include "lp_setup.h"
 
 
 struct lp_build_interp_soa_context
@@ -58,7 +55,7 @@ struct lp_build_interp_soa_context
 
    unsigned num_attribs;
    unsigned mask[1 + PIPE_MAX_SHADER_INPUTS]; /**< TGSI_WRITE_MASK_x */
-   unsigned interp[1 + PIPE_MAX_SHADER_INPUTS]; /**< TGSI_INTERPOLATE_x */
+   enum lp_interp interp[1 + PIPE_MAX_SHADER_INPUTS];
 
    LLVMValueRef a0  [1 + PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS];
    LLVMValueRef dadx[1 + PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS];
@@ -79,8 +76,8 @@ struct lp_build_interp_soa_context
 
 void
 lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld,
-                         const struct tgsi_shader_info *info,
-                         boolean flatshade,
+                         unsigned num_inputs,
+                         const struct lp_shader_input *inputs,
                          LLVMBuilderRef builder,
                          struct lp_type type,
                          LLVMValueRef a0_ptr,
diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h
index de7fe7a..689265f 100644
--- a/src/gallium/drivers/llvmpipe/lp_context.h
+++ b/src/gallium/drivers/llvmpipe/lp_context.h
@@ -37,6 +37,7 @@
 
 #include "lp_tex_sample.h"
 #include "lp_jit.h"
+#include "lp_setup.h"
 
 
 struct llvmpipe_vbuf_render;
@@ -90,6 +91,10 @@ struct llvmpipe_context {
    /** Vertex format */
    struct vertex_info vertex_info;
 
+   /** Fragment shader input interpolation info */
+   unsigned num_inputs;
+   struct lp_shader_input inputs[PIPE_MAX_SHADER_INPUTS];
+
    /** The tiling engine */
    struct lp_setup_context *setup;
 
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c
index b560061..0557d35 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c
@@ -147,20 +147,32 @@ setup_fragcoord_coef(struct lp_setup_context *setup,
                      unsigned slot,
                      const float (*v1)[4],
                      const float (*v2)[4],
-                     const float (*v3)[4])
+                     const float (*v3)[4],
+                     unsigned usage_mask)
 {
    /*X*/
-   tri->inputs.a0[slot][0] = 0.0;
-   tri->inputs.dadx[slot][0] = 1.0;
-   tri->inputs.dady[slot][0] = 0.0;
+   if (usage_mask & TGSI_WRITEMASK_X) {
+      tri->inputs.a0[slot][0] = 0.0;
+      tri->inputs.dadx[slot][0] = 1.0;
+      tri->inputs.dady[slot][0] = 0.0;
+   }
+
    /*Y*/
-   tri->inputs.a0[slot][1] = 0.0;
-   tri->inputs.dadx[slot][1] = 0.0;
-   tri->inputs.dady[slot][1] = 1.0;
+   if (usage_mask & TGSI_WRITEMASK_Y) {
+      tri->inputs.a0[slot][1] = 0.0;
+      tri->inputs.dadx[slot][1] = 0.0;
+      tri->inputs.dady[slot][1] = 1.0;
+   }
+
    /*Z*/
-   linear_coef(setup, tri, oneoverarea, slot, v1, v2, v3, 0, 2);
+   if (usage_mask & TGSI_WRITEMASK_Z) {
+      linear_coef(setup, tri, oneoverarea, slot, v1, v2, v3, 0, 2);
+   }
+
    /*W*/
-   linear_coef(setup, tri, oneoverarea, slot, v1, v2, v3, 0, 3);
+   if (usage_mask & TGSI_WRITEMASK_W) {
+      linear_coef(setup, tri, oneoverarea, slot, v1, v2, v3, 0, 3);
+   }
 }
 
 
@@ -171,13 +183,21 @@ setup_fragcoord_coef(struct lp_setup_context *setup,
 static void setup_facing_coef( struct lp_setup_context *setup,
                                struct lp_rast_triangle *tri,
                                unsigned slot,
-                               boolean frontface )
+                               boolean frontface,
+                               unsigned usage_mask)
 {
    /* convert TRUE to 1.0 and FALSE to -1.0 */
-   constant_coef( setup, tri, slot, 2.0f * frontface - 1.0f, 0 );
-   constant_coef( setup, tri, slot, 0.0f, 1 ); /* wasted */
-   constant_coef( setup, tri, slot, 0.0f, 2 ); /* wasted */
-   constant_coef( setup, tri, slot, 0.0f, 3 ); /* wasted */
+   if (usage_mask & TGSI_WRITEMASK_X)
+      constant_coef( setup, tri, slot, 2.0f * frontface - 1.0f, 0 );
+
+   if (usage_mask & TGSI_WRITEMASK_Y)
+      constant_coef( setup, tri, slot, 0.0f, 1 ); /* wasted */
+
+   if (usage_mask & TGSI_WRITEMASK_Z)
+      constant_coef( setup, tri, slot, 0.0f, 2 ); /* wasted */
+
+   if (usage_mask & TGSI_WRITEMASK_W)
+      constant_coef( setup, tri, slot, 0.0f, 3 ); /* wasted */
 }
 
 
@@ -192,58 +212,65 @@ static void setup_tri_coefficients( struct lp_setup_context *setup,
 				    const float (*v3)[4],
 				    boolean frontface)
 {
+   unsigned fragcoord_usage_mask = TGSI_WRITEMASK_XYZ;
    unsigned slot;
 
-   /* The internal position input is in slot zero:
-    */
-   setup_fragcoord_coef(setup, tri, oneoverarea, 0, v1, v2, v3);
-
    /* setup interpolation for all the remaining attributes:
     */
    for (slot = 0; slot < setup->fs.nr_inputs; slot++) {
       unsigned vert_attr = setup->fs.input[slot].src_index;
+      unsigned usage_mask = setup->fs.input[slot].usage_mask;
       unsigned i;
 
       switch (setup->fs.input[slot].interp) {
       case LP_INTERP_CONSTANT:
          if (setup->flatshade_first) {
             for (i = 0; i < NUM_CHANNELS; i++)
-               if (setup->fs.input[slot].usage_mask & (1 << i))
+               if (usage_mask & (1 << i))
                   constant_coef(setup, tri, slot+1, v1[vert_attr][i], i);
          }
          else {
             for (i = 0; i < NUM_CHANNELS; i++)
-               if (setup->fs.input[slot].usage_mask & (1 << i))
+               if (usage_mask & (1 << i))
                   constant_coef(setup, tri, slot+1, v3[vert_attr][i], i);
          }
          break;
 
       case LP_INTERP_LINEAR:
          for (i = 0; i < NUM_CHANNELS; i++)
-            if (setup->fs.input[slot].usage_mask & (1 << i))
+            if (usage_mask & (1 << i))
                linear_coef(setup, tri, oneoverarea, slot+1, v1, v2, v3, vert_attr, i);
          break;
 
       case LP_INTERP_PERSPECTIVE:
          for (i = 0; i < NUM_CHANNELS; i++)
-            if (setup->fs.input[slot].usage_mask & (1 << i))
+            if (usage_mask & (1 << i))
                perspective_coef(setup, tri, oneoverarea, slot+1, v1, v2, v3, vert_attr, i);
+         fragcoord_usage_mask |= TGSI_WRITEMASK_W;
          break;
 
       case LP_INTERP_POSITION:
-         /* XXX: fix me - duplicates the values in slot zero.
+         /*
+          * The generated pixel interpolators will pick up the coeffs from
+          * slot 0, so all need to ensure that the usage mask is covers all
+          * usages.
           */
-         setup_fragcoord_coef(setup, tri, oneoverarea, slot+1, v1, v2, v3);
+         fragcoord_usage_mask |= usage_mask;
          break;
 
       case LP_INTERP_FACING:
-         setup_facing_coef(setup, tri, slot+1, frontface);
+         setup_facing_coef(setup, tri, slot+1, frontface, usage_mask);
          break;
 
       default:
          assert(0);
       }
    }
+
+   /* The internal position input is in slot zero:
+    */
+   setup_fragcoord_coef(setup, tri, oneoverarea, 0, v1, v2, v3,
+                        fragcoord_usage_mask);
 }
 
 
diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c
index 773aadc..46a9653 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_derived.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c
@@ -50,7 +50,7 @@ compute_vertex_info(struct llvmpipe_context *llvmpipe)
 {
    const struct lp_fragment_shader *lpfs = llvmpipe->fs;
    struct vertex_info *vinfo = &llvmpipe->vertex_info;
-   struct lp_shader_input inputs[1 + PIPE_MAX_SHADER_INPUTS];
+   struct lp_shader_input *inputs = llvmpipe->inputs;
    unsigned vs_index;
    uint i;
 
@@ -124,6 +124,7 @@ compute_vertex_info(struct llvmpipe_context *llvmpipe)
       inputs[i].src_index = vinfo->num_attribs;
       draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index);
    }
+   llvmpipe->num_inputs = lpfs->info.num_inputs;
 
    draw_compute_vertex_size(vinfo);
 
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
index d3f2eb2..835175d 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -759,9 +759,14 @@ generate_fragment(struct llvmpipe_context *lp,
 
    generate_pos0(builder, x, y, &x0, &y0);
 
+   /*
+    * The shader input interpolation info is not explicitely baked in the
+    * shader key, but everything it derives from (TGSI, and flatshade) is
+    * already included in the shader key.
+    */
    lp_build_interp_soa_init(&interp, 
-                            &shader->info,
-                            key->flatshade,
+                            lp->num_inputs,
+                            lp->inputs,
                             builder, fs_type,
                             a0_ptr, dadx_ptr, dady_ptr,
                             x0, y0);



More information about the mesa-commit mailing list