llvmpipe: Use struct lp_shader_input in the interpolator.
authorJosé Fonseca <jfonseca@vmware.com>
Tue, 1 Jun 2010 20:27:18 +0000 (21:27 +0100)
committerJosé Fonseca <jfonseca@vmware.com>
Tue, 1 Jun 2010 20:30:57 +0000 (21:30 +0100)
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
src/gallium/drivers/llvmpipe/lp_bld_interp.h
src/gallium/drivers/llvmpipe/lp_context.h
src/gallium/drivers/llvmpipe/lp_setup_tri.c
src/gallium/drivers/llvmpipe/lp_state_derived.c
src/gallium/drivers/llvmpipe/lp_state_fs.c

index 07c9e646630f9071aecc7245184869435c4a2bd8..d1f0185684d502701daf8ab49ee76b53b74bc7b6 100644 (file)
@@ -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) {
index 2d41fefd47b801e2d01b7da5e3e2541682fe1ed3..79d1e51605a3650831c191127b5acc171d0d0fdc 100644 (file)
 
 #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,
index de7fe7a17968be2de0737a1c02991a895478b563..689265fa30de24057558e804a58c7376aefea7f4 100644 (file)
@@ -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;
 
index b56006154202b9456b832bd517d712d614ccbd32..0557d35f8b152879f65f68365889a615d7f4d275 100644 (file)
@@ -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);
 }
 
 
index 773aadc92d9cad63e9b5353899a7d878db3d8a96..46a96536075de9aa0c646e70a944dc9694db8505 100644 (file)
@@ -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);
 
index d3f2eb2421eab7649dfabcf988c1d8978c76a568..835175db1380df343cb54c4ca3fe3bef1a7c1845 100644 (file)
@@ -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);