llvmpipe: Don't waste time interpolating unused input channels.
authorJosé Fonseca <jfonseca@vmware.com>
Tue, 1 Jun 2010 15:28:45 +0000 (16:28 +0100)
committerJosé Fonseca <jfonseca@vmware.com>
Tue, 1 Jun 2010 15:39:03 +0000 (16:39 +0100)
src/gallium/drivers/llvmpipe/lp_bld_interp.c
src/gallium/drivers/llvmpipe/lp_bld_interp.h
src/gallium/drivers/llvmpipe/lp_setup.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 838691e14b0fe6105b56186be2c3f2a8193b633d..07c9e646630f9071aecc7245184869435c4a2bd8 100644 (file)
@@ -37,7 +37,7 @@
 #include "util/u_debug.h"
 #include "util/u_memory.h"
 #include "util/u_math.h"
-#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_scan.h"
 #include "gallivm/lp_bld_debug.h"
 #include "gallivm/lp_bld_const.h"
 #include "gallivm/lp_bld_arit.h"
@@ -315,7 +315,7 @@ 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_token *tokens,
+                         const struct tgsi_shader_info *info,
                          boolean flatshade,
                          LLVMBuilderRef builder,
                          struct lp_type type,
@@ -325,8 +325,8 @@ lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld,
                          LLVMValueRef x0,
                          LLVMValueRef y0)
 {
-   struct tgsi_parse_context parse;
-   struct tgsi_full_declaration *decl;
+   unsigned attrib;
+   unsigned chan;
 
    memset(bld, 0, sizeof *bld);
 
@@ -342,48 +342,24 @@ lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld,
    bld->interp[0] = TGSI_INTERPOLATE_LINEAR;
 
    /* Inputs */
-   tgsi_parse_init( &parse, tokens );
-   while( !tgsi_parse_end_of_tokens( &parse ) ) {
-      tgsi_parse_token( &parse );
-
-      switch( parse.FullToken.Token.Type ) {
-      case TGSI_TOKEN_TYPE_DECLARATION:
-         decl = &parse.FullToken.FullDeclaration;
-         if( decl->Declaration.File == TGSI_FILE_INPUT ) {
-            unsigned first, last, mask;
-            unsigned attrib;
-
-            first = decl->Range.First;
-            last = decl->Range.Last;
-            mask = decl->Declaration.UsageMask;
-
-            for( attrib = first; attrib <= last; ++attrib ) {
-               bld->mask[1 + attrib] = mask;
-
-               /* XXX: have mesa set INTERP_CONSTANT in the fragment
-                * shader.
-                */
-               if (decl->Semantic.Name == TGSI_SEMANTIC_COLOR &&
-                   flatshade)
-                  bld->interp[1 + attrib] = TGSI_INTERPOLATE_CONSTANT;
-               else
-                  bld->interp[1 + attrib] = decl->Declaration.Interpolate;
-            }
+   for (attrib = 0; attrib < info->num_inputs; ++attrib) {
+      bld->mask[1 + attrib] = info->input_usage_mask[attrib];
 
-            bld->num_attribs = MAX2(bld->num_attribs, 1 + last + 1);
-         }
-         break;
+      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];
 
-      case TGSI_TOKEN_TYPE_INSTRUCTION:
-      case TGSI_TOKEN_TYPE_IMMEDIATE:
-      case TGSI_TOKEN_TYPE_PROPERTY:
-         break;
+   }
+   bld->num_attribs = 1 + info->num_inputs;
 
-      default:
-         assert( 0 );
+   /* Ensure all masked out input channels have a valid value */
+   for (attrib = 0; attrib < bld->num_attribs; ++attrib) {
+      for (chan = 0; chan < NUM_CHANNELS; ++chan) {
+         bld->attribs[attrib][chan] = bld->base.undef;
       }
    }
-   tgsi_parse_free( &parse );
 
    coeffs_init(bld, a0_ptr, dadx_ptr, dady_ptr);
 
index 99a432957cefab459736b404505c2a49cb0df28a..2d41fefd47b801e2d01b7da5e3e2541682fe1ed3 100644 (file)
@@ -49,6 +49,7 @@
 
 
 struct tgsi_token;
+struct tgsi_shader_info;
 
 
 struct lp_build_interp_soa_context
@@ -78,7 +79,7 @@ struct lp_build_interp_soa_context
 
 void
 lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld,
-                         const struct tgsi_token *tokens,
+                         const struct tgsi_shader_info *info,
                          boolean flatshade,
                          LLVMBuilderRef builder,
                          struct lp_type type,
index 719cf98454f5d308d93c23726cc506e82c3933c9..6a0dc551290ffb4800da7a17850fcc3790a62b55 100644 (file)
@@ -41,8 +41,11 @@ enum lp_interp {
    LP_INTERP_FACING
 };
 
-/* Describes how to generate all the fragment shader inputs from the
- * the vertices passed into our triangle/line/point functions.
+
+/**
+ * Describes how to compute the interpolation coefficients (a0, dadx, dady)
+ * from the vertices passed into our triangle/line/point functions by the
+ * draw module.
  *
  * Vertices are treated as an array of float[4] values, indexed by
  * src_index.
@@ -50,6 +53,7 @@ enum lp_interp {
 struct lp_shader_input {
    enum lp_interp interp;       /* how to interpolate values */
    unsigned src_index;          /* where to find values in incoming vertices */
+   unsigned usage_mask;         /* bitmask of TGSI_WRITEMASK_x flags */
 };
 
 struct pipe_resource;
index 0fc4dd665e89868beb512371f83d7e07db0fd947..b56006154202b9456b832bd517d712d614ccbd32 100644 (file)
@@ -208,22 +208,26 @@ static void setup_tri_coefficients( struct lp_setup_context *setup,
       case LP_INTERP_CONSTANT:
          if (setup->flatshade_first) {
             for (i = 0; i < NUM_CHANNELS; i++)
-               constant_coef(setup, tri, slot+1, v1[vert_attr][i], i);
+               if (setup->fs.input[slot].usage_mask & (1 << i))
+                  constant_coef(setup, tri, slot+1, v1[vert_attr][i], i);
          }
          else {
             for (i = 0; i < NUM_CHANNELS; i++)
-               constant_coef(setup, tri, slot+1, v3[vert_attr][i], i);
+               if (setup->fs.input[slot].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++)
-            linear_coef(setup, tri, oneoverarea, slot+1, v1, v2, v3, vert_attr, i);
+            if (setup->fs.input[slot].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++)
-            perspective_coef(setup, tri, oneoverarea, slot+1, v1, v2, v3, vert_attr, i);
+            if (setup->fs.input[slot].usage_mask & (1 << i))
+               perspective_coef(setup, tri, oneoverarea, slot+1, v1, v2, v3, vert_attr, i);
          break;
 
       case LP_INTERP_POSITION:
index 2edfcb28ce6dafb0baa70426ba5d43256357f369..773aadc92d9cad63e9b5353899a7d878db3d8a96 100644 (file)
@@ -77,6 +77,7 @@ compute_vertex_info(struct llvmpipe_context *llvmpipe)
 
       /* This can be pre-computed, except for flatshade:
        */
+      inputs[i].usage_mask = lpfs->info.input_usage_mask[i];
       switch (lpfs->info.input_semantic_name[i]) {
       case TGSI_SEMANTIC_FACE:
          inputs[i].interp = LP_INTERP_FACING;
index 21e90fe00ec3739c9739c8ab26944ad74a3a5337..d3f2eb2421eab7649dfabcf988c1d8978c76a568 100644 (file)
@@ -760,7 +760,7 @@ generate_fragment(struct llvmpipe_context *lp,
    generate_pos0(builder, x, y, &x0, &y0);
 
    lp_build_interp_soa_init(&interp, 
-                            shader->base.tokens,
+                            &shader->info,
                             key->flatshade,
                             builder, fs_type,
                             a0_ptr, dadx_ptr, dady_ptr,
@@ -1013,8 +1013,20 @@ llvmpipe_create_fs_state(struct pipe_context *pipe,
    shader->base.tokens = tgsi_dup_tokens(templ->tokens);
 
    if (LP_DEBUG & DEBUG_TGSI) {
+      unsigned attrib;
       debug_printf("llvmpipe: Create fragment shader %p:\n", (void *) shader);
       tgsi_dump(templ->tokens, 0);
+      debug_printf("usage masks:\n");
+      for (attrib = 0; attrib < shader->info.num_inputs; ++attrib) {
+         unsigned usage_mask = shader->info.input_usage_mask[attrib];
+         debug_printf("  IN[%u].%s%s%s%s\n",
+                      attrib,
+                      usage_mask & TGSI_WRITEMASK_X ? "x" : "",
+                      usage_mask & TGSI_WRITEMASK_Y ? "y" : "",
+                      usage_mask & TGSI_WRITEMASK_Z ? "z" : "",
+                      usage_mask & TGSI_WRITEMASK_W ? "w" : "");
+      }
+      debug_printf("\n");
    }
 
    return shader;