gallium: improved vertex layout and interpolant setup in softpipe
authorBrian <brian.paul@tungstengraphics.com>
Thu, 24 Jan 2008 06:08:59 +0000 (23:08 -0700)
committerBrian <brian.paul@tungstengraphics.com>
Thu, 24 Jan 2008 06:08:59 +0000 (23:08 -0700)
src/mesa/pipe/draw/draw_vertex.h
src/mesa/pipe/softpipe/sp_context.h
src/mesa/pipe/softpipe/sp_prim_setup.c
src/mesa/pipe/softpipe/sp_prim_vbuf.c
src/mesa/pipe/softpipe/sp_state_derived.c

index e76a17c198bbeae097b8f4d29b14b52abe29a11b..7e9d8abcce10044a568bd2ac0824c6d0d3c3a2c9 100644 (file)
@@ -36,6 +36,7 @@
 
 /**
  * Vertex attribute format
+ * XXX rename to "EMIT"
  */
 enum attrib_format {
    FORMAT_OMIT,      /**< don't emit the attribute */
@@ -54,6 +55,7 @@ enum attrib_format {
  */
 enum interp_mode {
    INTERP_NONE,      /**< never interpolate vertex header info */
+   INTERP_POS,       /**< special case for frag position */
    INTERP_CONSTANT,
    INTERP_LINEAR,
    INTERP_PERSPECTIVE
index daf7dd5acccc4fa3bc5f729e0c6e6e8f227982cc..aff8c2cc5dc58e6d111a67a3f5246d87091fc5a4 100644 (file)
@@ -89,8 +89,8 @@ struct softpipe_context {
 
    /** Vertex format */
    struct vertex_info vertex_info;
-   unsigned attr_mask;
-   unsigned nr_frag_attrs;  /**< number of active fragment attribs */
+   struct vertex_info vertex_info_vbuf;
+
    int psize_slot;
 
 #if 0
index 4b6b7a0fd129a2efa8173f2ed5093674d9445b9e..478ecff2fb5e796dc2ed4da74c6c8370598b3167 100644 (file)
@@ -85,8 +85,6 @@ struct setup_stage {
    struct tgsi_interp_coef posCoef;  /* For Z, W */
    struct quad_header quad; 
 
-   uint firstFpInput;  /** Semantic type of first frag input */
-
    struct {
       int left[2];   /**< [0] = row0, [1] = row1 */
       int right[2];
@@ -515,22 +513,10 @@ setup_fragcoord_coeff(struct setup_stage *setup)
  */
 static void setup_tri_coefficients( struct setup_stage *setup )
 {
-   const enum interp_mode *interp;
-#define USE_INPUT_MAP 01
-#if USE_INPUT_MAP
-   const struct pipe_shader_state *fs = &setup->softpipe->fs->shader;
-#endif
+   const struct softpipe_context *softpipe = setup->softpipe;
+   const struct pipe_shader_state *fs = &softpipe->fs->shader;
    uint fragSlot;
 
-   if (setup->softpipe->vertex_info.format[0] == FORMAT_HEADER) {
-      /* skip header, pos slots */
-      interp = setup->softpipe->vertex_info.interp_mode + 2;
-   }
-   else {
-      /* skip pos slot */
-      interp = setup->softpipe->vertex_info.interp_mode + 1;
-   }
-
    /* z and w are done by linear interpolation:
     */
    tri_linear_coeff(setup, &setup->posCoef, 0, 2);
@@ -538,64 +524,37 @@ static void setup_tri_coefficients( struct setup_stage *setup )
 
    /* setup interpolation for all the remaining attributes:
     */
-   for (fragSlot = 0; fragSlot < setup->quad.nr_attrs; fragSlot++) {
-      /* which vertex output maps to this fragment input: */
-#if !USE_INPUT_MAP
-      uint vertSlot;
-      if (setup->firstFpInput == TGSI_SEMANTIC_POSITION) {
-         if (fragSlot == 0) {
-            setup_fragcoord_coeff(setup);
-            continue;
-         }
-         vertSlot = fragSlot;
-      }
-      else {
-         vertSlot = fragSlot + 1;
-      }
-
-#else
-      uint vertSlot = fs->input_map[fragSlot];
-
-      if (vertSlot == 0) {
-         /* special case: shader is reading gl_FragCoord */
-         /* XXX with a new INTERP_POSITION token, we could just add a
-          * new case to the switch below.
-          */
+   for (fragSlot = 0; fragSlot < fs->num_inputs; fragSlot++) {
+      const uint vertSlot = softpipe->vertex_info.src_index[fragSlot];
+      uint j;
+
+      switch (softpipe->vertex_info.interp_mode[fragSlot]) {
+      case INTERP_CONSTANT:
+         for (j = 0; j < NUM_CHANNELS; j++)
+            const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
+         break;
+      case INTERP_LINEAR:
+         for (j = 0; j < NUM_CHANNELS; j++)
+            tri_linear_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
+         break;
+      case INTERP_PERSPECTIVE:
+         for (j = 0; j < NUM_CHANNELS; j++)
+            tri_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
+         break;
+      case INTERP_POS:
+         assert(fragSlot == 0);
          setup_fragcoord_coeff(setup);
+         break;
+      default:
+         assert(0);
       }
-      else {
-#endif
-         uint j;
-         switch (interp[fragSlot]) {
-         case INTERP_CONSTANT:
-            for (j = 0; j < NUM_CHANNELS; j++)
-               const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
-            break;
-         case INTERP_LINEAR:
-            for (j = 0; j < NUM_CHANNELS; j++)
-               tri_linear_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
-            break;
-         case INTERP_PERSPECTIVE:
-            for (j = 0; j < NUM_CHANNELS; j++)
-               tri_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
-            break;
-         default:
-            /* invalid interp mode */
-            /* assert(0); re-enable this and run demos/fogcoord.c ... */
-            ;
-         }
 
-         if (fs->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FOG) {
-            /* FOG.y = front/back facing  XXX fix this */
-            setup->coef[fragSlot].a0[1] = 1 - setup->quad.facing;
-            setup->coef[fragSlot].dadx[1] = 0.0;
-            setup->coef[fragSlot].dady[1] = 0.0;
-         }
-
-
-#if USE_INPUT_MAP
+      if (fs->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FOG) {
+         /* FOG.y = front/back facing  XXX fix this */
+         setup->coef[fragSlot].a0[1] = 1 - setup->quad.facing;
+         setup->coef[fragSlot].dadx[1] = 0.0;
+         setup->coef[fragSlot].dady[1] = 0.0;
       }
-#endif
    }
 }
 
@@ -797,9 +756,9 @@ line_persp_coeff(struct setup_stage *setup,
 static INLINE void
 setup_line_coefficients(struct setup_stage *setup, struct prim_header *prim)
 {
-   const enum interp_mode *interp = setup->softpipe->vertex_info.interp_mode;
+   const struct softpipe_context *softpipe = setup->softpipe;
    const struct pipe_shader_state *fs = &setup->softpipe->fs->shader;
-   unsigned fragSlot;
+   uint fragSlot;
 
    /* use setup->vmin, vmax to point to vertices */
    setup->vprovoke = prim->v[1];
@@ -819,34 +778,37 @@ setup_line_coefficients(struct setup_stage *setup, struct prim_header *prim)
 
    /* setup interpolation for all the remaining attributes:
     */
-   for (fragSlot = 0; fragSlot < setup->quad.nr_attrs; fragSlot++) {
-      /* which vertex output maps to this fragment input: */
-      uint vertSlot = fs->input_map[fragSlot];
-
-      if (vertSlot == 0) {
-         /* special case: shader is reading gl_FragCoord */
+   for (fragSlot = 0; fragSlot < fs->num_inputs; fragSlot++) {
+      const uint vertSlot = softpipe->vertex_info.src_index[fragSlot];
+      uint j;
+
+      switch (softpipe->vertex_info.interp_mode[fragSlot]) {
+      case INTERP_CONSTANT:
+         for (j = 0; j < NUM_CHANNELS; j++)
+            const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
+         break;
+      case INTERP_LINEAR:
+         for (j = 0; j < NUM_CHANNELS; j++)
+            line_linear_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
+         break;
+      case INTERP_PERSPECTIVE:
+         for (j = 0; j < NUM_CHANNELS; j++)
+            line_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
+         break;
+      case INTERP_POS:
+         assert(fragSlot == 0);
+         assert(0); /* XXX fix this: */
          setup_fragcoord_coeff(setup);
+         break;
+      default:
+         assert(0);
       }
-      else {
-         uint j;
-         switch (interp[vertSlot]) {
-         case INTERP_CONSTANT:
-            for (j = 0; j < NUM_CHANNELS; j++)
-               const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
-            break;
-         case INTERP_LINEAR:
-            for (j = 0; j < NUM_CHANNELS; j++)
-               line_linear_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
-            break;
-         case INTERP_PERSPECTIVE:
-            for (j = 0; j < NUM_CHANNELS; j++)
-               line_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
-            break;
-            
-         default:
-            /* invalid interp mode */
-            assert(0);
-         }
+
+      if (fs->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FOG) {
+         /* FOG.y = front/back facing  XXX fix this */
+         setup->coef[fragSlot].a0[1] = 1 - setup->quad.facing;
+         setup->coef[fragSlot].dadx[1] = 0.0;
+         setup->coef[fragSlot].dady[1] = 0.0;
       }
    }
 }
@@ -1005,8 +967,8 @@ static void
 setup_point(struct draw_stage *stage, struct prim_header *prim)
 {
    struct setup_stage *setup = setup_stage( stage );
-   const struct pipe_shader_state *fs = &setup->softpipe->fs->shader;
-   const enum interp_mode *interp = setup->softpipe->vertex_info.interp_mode;
+   struct softpipe_context *softpipe = setup->softpipe;
+   const struct pipe_shader_state *fs = &softpipe->fs->shader;
    const struct vertex_header *v0 = prim->v[0];
    const int sizeAttr = setup->softpipe->psize_slot;
    const float size
@@ -1040,31 +1002,36 @@ setup_point(struct draw_stage *stage, struct prim_header *prim)
    const_coeff(setup, &setup->posCoef, 0, 2);
    const_coeff(setup, &setup->posCoef, 0, 3);
 
-   for (fragSlot = 0; fragSlot < setup->quad.nr_attrs; fragSlot++) {
-      /* which vertex output maps to this fragment input: */
-      uint vertSlot = fs->input_map[fragSlot];
-
-      if (vertSlot == 0) {
-         /* special case: shader is reading gl_FragCoord */
+   for (fragSlot = 0; fragSlot < fs->num_inputs; fragSlot++) {
+      const uint vertSlot = softpipe->vertex_info.src_index[fragSlot];
+      uint j;
+
+      switch (softpipe->vertex_info.interp_mode[fragSlot]) {
+      case INTERP_CONSTANT:
+         /* fall-through */
+      case INTERP_LINEAR:
+         for (j = 0; j < NUM_CHANNELS; j++)
+            const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
+         break;
+      case INTERP_PERSPECTIVE:
+         for (j = 0; j < NUM_CHANNELS; j++)
+            point_persp_coeff(setup, setup->vprovoke,
+                              &setup->coef[fragSlot], vertSlot, j);
+         break;
+      case INTERP_POS:
+         assert(fragSlot == 0);
+         assert(0); /* XXX fix this: */
          setup_fragcoord_coeff(setup);
+         break;
+      default:
+         assert(0);
       }
-      else {
-         uint j;
-         switch (interp[vertSlot]) {
-         case INTERP_CONSTANT:
-            /* fall-through */
-         case INTERP_LINEAR:
-            for (j = 0; j < NUM_CHANNELS; j++)
-               const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
-            break;
-         case INTERP_PERSPECTIVE:
-            for (j = 0; j < NUM_CHANNELS; j++)
-               point_persp_coeff(setup, setup->vprovoke,
-                                 &setup->coef[fragSlot], vertSlot, j);
-            break;
-         default:
-            assert(0);
-         }
+
+      if (fs->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FOG) {
+         /* FOG.y = front/back facing  XXX fix this */
+         setup->coef[fragSlot].a0[1] = 1 - setup->quad.facing;
+         setup->coef[fragSlot].dadx[1] = 0.0;
+         setup->coef[fragSlot].dady[1] = 0.0;
       }
    }
 
@@ -1200,9 +1167,7 @@ static void setup_begin( struct draw_stage *stage )
    struct softpipe_context *sp = setup->softpipe;
    const struct pipe_shader_state *fs = &setup->softpipe->fs->shader;
 
-   setup->quad.nr_attrs = setup->softpipe->nr_frag_attrs;
-
-   setup->firstFpInput = fs->input_semantic_name[0];
+   setup->quad.nr_attrs = fs->num_inputs;
 
    sp->quad.first->begin(sp->quad.first);
 }
index 0ab8a55d7d4af8a20f87227295d6dc570e808d78..dfabae8302535889584eff189e9c041e5806dfa3 100644 (file)
@@ -75,7 +75,7 @@ sp_vbuf_get_vertex_info(struct vbuf_render *vbr)
    struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
    /* XXX check for state changes? */
    assert(!cvbr->softpipe->dirty );
-   return &cvbr->softpipe->vertex_info;
+   return &cvbr->softpipe->vertex_info_vbuf;
 }
 
 
@@ -140,7 +140,7 @@ sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr_indices)
    struct softpipe_context *softpipe = cvbr->softpipe;
    struct draw_stage *setup = softpipe->setup;
    struct prim_header prim;
-   unsigned vertex_size = softpipe->vertex_info.size * sizeof(float);
+   unsigned vertex_size = softpipe->vertex_info_vbuf.size * sizeof(float);
    unsigned i, j;
    void *vertex_buffer = cvbr->vertex_buffer;
 
index d399868f24446a8eb9c895e141425f7e7b11ada0..4be3641d677ace273e1a17d9575ac5e707066e6c 100644 (file)
@@ -50,9 +50,9 @@ find_vs_output(const struct pipe_shader_state *vs,
 
 
 /**
- * Determine which post-transform / pre-rasterization vertex attributes
- * we need.
- * Derived from:  fs, setup states.
+ * Determine how to map vertex program outputs to fragment program inputs.
+ * Basically, this will be used when computing the triangle interpolation
+ * coefficients from the post-transform vertex attributes.
  */
 static void calculate_vertex_layout( struct softpipe_context *softpipe )
 {
@@ -61,35 +61,33 @@ static void calculate_vertex_layout( struct softpipe_context *softpipe )
    const enum interp_mode colorInterp
       = softpipe->rasterizer->flatshade ? INTERP_CONSTANT : INTERP_LINEAR;
    struct vertex_info *vinfo = &softpipe->vertex_info;
+   struct vertex_info *vinfo_vbuf = &softpipe->vertex_info_vbuf;
    uint i;
    int src;
 
-   memset(vinfo, 0, sizeof(*vinfo));
-
-   softpipe->psize_slot = -1;
-
    if (softpipe->vbuf) {
-      /* softpipe's setup/rasterizer stage expects vertex to have a header */
-      draw_emit_vertex_attr(vinfo, FORMAT_HEADER, INTERP_LINEAR, 0);
+      /* if using the post-transform vertex buffer, tell draw_vbuf to
+       * simply emit the whole post-xform vertex as-is:
+       */
+      vinfo_vbuf->num_attribs = 0;
+      draw_emit_vertex_attr(vinfo_vbuf, FORMAT_HEADER, INTERP_NONE, 0);
+      for (i = 0; i < vs->num_outputs; i++) {
+         draw_emit_vertex_attr(vinfo_vbuf, FORMAT_4F, INTERP_NONE, i);
+      }
+      draw_compute_vertex_size(vinfo_vbuf);
    }
 
-   /* always emit pos for softpipe rasterization */
-   src = find_vs_output(vs, TGSI_SEMANTIC_POSITION, 0);
-   assert(src >= 0);
-   draw_emit_vertex_attr(vinfo, FORMAT_4F, INTERP_LINEAR, src);
-
    /*
-    * XXX I think we need to reconcile the vertex shader outputs with
-    * the fragment shader inputs here to make sure the slots line up.
-    * Might just be getting lucky so far.
-    * Or maybe do that in the state tracker?
+    * Loop over fragment shader inputs, searching for the matching output
+    * from the vertex shader.
     */
-
+   vinfo->num_attribs = 0;
    for (i = 0; i < fs->num_inputs; i++) {
       switch (fs->input_semantic_name[i]) {
-
       case TGSI_SEMANTIC_POSITION:
-         /* handled above */
+         src = find_vs_output(vs, TGSI_SEMANTIC_POSITION, 0);
+         assert(src >= 0);
+         draw_emit_vertex_attr(vinfo, FORMAT_4F, INTERP_POS, src);
          break;
 
       case TGSI_SEMANTIC_COLOR:
@@ -122,16 +120,13 @@ static void calculate_vertex_layout( struct softpipe_context *softpipe )
       }
    }
 
-   src = find_vs_output(vs, TGSI_SEMANTIC_PSIZE, 0);
-   if (src >= 0) {
-      softpipe->psize_slot = src;
-      draw_emit_vertex_attr(vinfo, FORMAT_4F, INTERP_CONSTANT, src);
+   softpipe->psize_slot = find_vs_output(vs, TGSI_SEMANTIC_PSIZE, 0);
+   if (softpipe->psize_slot >= 0) {
+      draw_emit_vertex_attr(vinfo, FORMAT_4F, INTERP_CONSTANT,
+                            softpipe->psize_slot);
    }
 
-
    draw_compute_vertex_size(vinfo);
-
-   softpipe->nr_frag_attrs = fs->num_inputs;
 }
 
 
@@ -175,7 +170,9 @@ compute_cliprect(struct softpipe_context *sp)
  */
 void softpipe_update_derived( struct softpipe_context *softpipe )
 {
-   if (softpipe->dirty & (SP_NEW_RASTERIZER | SP_NEW_FS | SP_NEW_VS))
+   if (softpipe->dirty & (SP_NEW_RASTERIZER |
+                          SP_NEW_FS |
+                          SP_NEW_VS))
       calculate_vertex_layout( softpipe );
 
    if (softpipe->dirty & (SP_NEW_SCISSOR |