Exemplo n.º 1
0
/**
 * Allocate an extra vertex/geometry shader vertex attribute, if it doesn't
 * exist already.
 *
 * This is used by some of the optional draw module stages such
 * as wide_point which may need to allocate additional generic/texcoord
 * attributes.
 */
int
draw_alloc_extra_vertex_attrib(struct draw_context *draw,
                               uint semantic_name, uint semantic_index)
{
   int slot;
   uint num_outputs;
   uint n;

   slot = draw_find_shader_output(draw, semantic_name, semantic_index);
   if (slot > 0) {
      return slot;
   }

   num_outputs = draw_current_shader_outputs(draw);
   n = draw->extra_shader_outputs.num;

   assert(n < Elements(draw->extra_shader_outputs.semantic_name));

   draw->extra_shader_outputs.semantic_name[n] = semantic_name;
   draw->extra_shader_outputs.semantic_index[n] = semantic_index;
   draw->extra_shader_outputs.slot[n] = num_outputs + n;
   draw->extra_shader_outputs.num++;

   return draw->extra_shader_outputs.slot[n];
}
Exemplo n.º 2
0
/**
 * The vertex info describes how to convert the post-transformed vertices
 * (simple float[][4]) used by the 'draw' module into vertices for
 * rasterization.
 *
 * This function validates the vertex layout.
 */
static void
compute_vertex_info(struct llvmpipe_context *llvmpipe)
{
   const struct tgsi_shader_info *fsInfo = &llvmpipe->fs->info.base;
   struct vertex_info *vinfo = &llvmpipe->vertex_info;
   int vs_index;
   uint i;

   draw_prepare_shader_outputs(llvmpipe->draw);

   /*
    * Those can't actually be 0 (because pos is always at 0).
    * But use ints anyway to avoid confusion (in vs outputs, they
    * can very well be at pos 0).
    */
   llvmpipe->color_slot[0] = -1;
   llvmpipe->color_slot[1] = -1;
   llvmpipe->bcolor_slot[0] = -1;
   llvmpipe->bcolor_slot[1] = -1;
   llvmpipe->viewport_index_slot = -1;
   llvmpipe->layer_slot = -1;
   llvmpipe->face_slot = -1;
   llvmpipe->psize_slot = -1;

   /*
    * Match FS inputs against VS outputs, emitting the necessary
    * attributes.  Could cache these structs and look them up with a
    * combination of fragment shader, vertex shader ids.
    */

   vinfo->num_attribs = 0;

   vs_index = draw_find_shader_output(llvmpipe->draw,
                                      TGSI_SEMANTIC_POSITION, 0);

   draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);

   for (i = 0; i < fsInfo->num_inputs; i++) {
      /*
       * Search for each input in current vs output:
       */
      vs_index = draw_find_shader_output(llvmpipe->draw,
                                         fsInfo->input_semantic_name[i],
                                         fsInfo->input_semantic_index[i]);

      if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR &&
          fsInfo->input_semantic_index[i] < 2) {
         int idx = fsInfo->input_semantic_index[i];
         llvmpipe->color_slot[idx] = (int)vinfo->num_attribs;
      }

      if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_FACE) {
         llvmpipe->face_slot = (int)vinfo->num_attribs;
         draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);
      /*
       * For vp index and layer, if the fs requires them but the vs doesn't
       * provide them, draw (vbuf) will give us the required 0 (slot -1).
       * (This means in this case we'll also use those slots in setup, which
       * isn't necessary but they'll contain the correct (0) value.)
       */
      } else if (fsInfo->input_semantic_name[i] ==
                 TGSI_SEMANTIC_VIEWPORT_INDEX) {
         llvmpipe->viewport_index_slot = (int)vinfo->num_attribs;
         draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);
      } else if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_LAYER) {
         llvmpipe->layer_slot = (int)vinfo->num_attribs;
         draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);
      } else {
         /*
          * Note that we'd actually want to skip position (as we won't use
          * the attribute in the fs) but can't. The reason is that we don't
          * actually have a input/output map for setup (even though it looks
          * like we do...). Could adjust for this though even without a map
          * (in llvmpipe_create_fs_state()).
          */
         draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);
      }
   }

   /* Figure out if we need bcolor as well.
    */
   for (i = 0; i < 2; i++) {
      vs_index = draw_find_shader_output(llvmpipe->draw,
                                         TGSI_SEMANTIC_BCOLOR, i);

      if (vs_index >= 0) {
         llvmpipe->bcolor_slot[i] = (int)vinfo->num_attribs;
         draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);
      }
   }

   /* Figure out if we need pointsize as well.
    */
   vs_index = draw_find_shader_output(llvmpipe->draw,
                                      TGSI_SEMANTIC_PSIZE, 0);

   if (vs_index >= 0) {
      llvmpipe->psize_slot = (int)vinfo->num_attribs;
      draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);
   }

   /* Figure out if we need viewport index (if it wasn't already in fs input) */
   if (llvmpipe->viewport_index_slot < 0) {
      vs_index = draw_find_shader_output(llvmpipe->draw,
                                         TGSI_SEMANTIC_VIEWPORT_INDEX,
                                         0);
      if (vs_index >= 0) {
         llvmpipe->viewport_index_slot =(int)vinfo->num_attribs;
         draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);
      }
   }

   /* Figure out if we need layer (if it wasn't already in fs input) */
   if (llvmpipe->layer_slot < 0) {
      vs_index = draw_find_shader_output(llvmpipe->draw,
                                         TGSI_SEMANTIC_LAYER,
                                         0);
      if (vs_index >= 0) {
         llvmpipe->layer_slot = (int)vinfo->num_attribs;
         draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);
      }
   }

   draw_compute_vertex_size(vinfo);
   lp_setup_set_vertex_info(llvmpipe->setup, vinfo);
}
Exemplo n.º 3
0
/**
 * The vertex info describes how to convert the post-transformed vertices
 * (simple float[][4]) used by the 'draw' module into vertices for
 * rasterization.
 *
 * This function validates the vertex layout and returns a pointer to a
 * vertex_info object.
 */
struct vertex_info *
softpipe_get_vertex_info(struct softpipe_context *softpipe)
{
    struct vertex_info *vinfo = &softpipe->vertex_info;

    if (vinfo->num_attribs == 0) {
        /* compute vertex layout now */
        const struct tgsi_shader_info *fsInfo = &softpipe->fs_variant->info;
        struct vertex_info *vinfo_vbuf = &softpipe->vertex_info_vbuf;
        const uint num = draw_num_shader_outputs(softpipe->draw);
        uint i;

        /* Tell draw_vbuf to simply emit the whole post-xform vertex
         * as-is.  No longer any need to try and emit draw vertex_header
         * info.
         */
        vinfo_vbuf->num_attribs = 0;
        for (i = 0; i < num; i++) {
            draw_emit_vertex_attr(vinfo_vbuf, EMIT_4F, INTERP_PERSPECTIVE, i);
        }
        draw_compute_vertex_size(vinfo_vbuf);

        /*
         * Loop over fragment shader inputs, searching for the matching output
         * from the vertex shader.
         */
        vinfo->num_attribs = 0;
        for (i = 0; i < fsInfo->num_inputs; i++) {
            int src;
            enum interp_mode interp = INTERP_LINEAR;

            switch (fsInfo->input_interpolate[i]) {
            case TGSI_INTERPOLATE_CONSTANT:
                interp = INTERP_CONSTANT;
                break;
            case TGSI_INTERPOLATE_LINEAR:
                interp = INTERP_LINEAR;
                break;
            case TGSI_INTERPOLATE_PERSPECTIVE:
                interp = INTERP_PERSPECTIVE;
                break;
            case TGSI_INTERPOLATE_COLOR:
                assert(fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR);
                break;
            default:
                assert(0);
            }

            switch (fsInfo->input_semantic_name[i]) {
            case TGSI_SEMANTIC_POSITION:
                interp = INTERP_POS;
                break;

            case TGSI_SEMANTIC_COLOR:
                if (fsInfo->input_interpolate[i] == TGSI_INTERPOLATE_COLOR) {
                    if (softpipe->rasterizer->flatshade)
                        interp = INTERP_CONSTANT;
                    else
                        interp = INTERP_PERSPECTIVE;
                }
                break;
            }

            /* this includes texcoords and varying vars */
            src = draw_find_shader_output(softpipe->draw,
                                          fsInfo->input_semantic_name[i],
                                          fsInfo->input_semantic_index[i]);
            if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR && src == 0)
                /* try and find a bcolor */
                src = draw_find_shader_output(softpipe->draw,
                                              TGSI_SEMANTIC_BCOLOR, fsInfo->input_semantic_index[i]);

            draw_emit_vertex_attr(vinfo, EMIT_4F, interp, src);
        }

        softpipe->psize_slot = draw_find_shader_output(softpipe->draw,
                               TGSI_SEMANTIC_PSIZE, 0);
        if (softpipe->psize_slot > 0) {
            draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT,
                                  softpipe->psize_slot);
        }

        draw_compute_vertex_size(vinfo);
    }

    return vinfo;
}
Exemplo n.º 4
0
/**
 * The vertex info describes how to convert the post-transformed vertices
 * (simple float[][4]) used by the 'draw' module into vertices for
 * rasterization.
 *
 * This function validates the vertex layout.
 */
static void
compute_vertex_info(struct llvmpipe_context *llvmpipe)
{
   const struct lp_fragment_shader *lpfs = llvmpipe->fs;
   struct vertex_info *vinfo = &llvmpipe->vertex_info;
   int vs_index;
   uint i;

   llvmpipe->color_slot[0] = -1;
   llvmpipe->color_slot[1] = -1;
   llvmpipe->bcolor_slot[0] = -1;
   llvmpipe->bcolor_slot[1] = -1;

   /*
    * Match FS inputs against VS outputs, emitting the necessary
    * attributes.  Could cache these structs and look them up with a
    * combination of fragment shader, vertex shader ids.
    */

   vinfo->num_attribs = 0;

   vs_index = draw_find_shader_output(llvmpipe->draw,
                                       TGSI_SEMANTIC_POSITION,
                                       0);

   draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index);

   for (i = 0; i < lpfs->info.base.num_inputs; i++) {
      /*
       * Search for each input in current vs output:
       */

      vs_index = draw_find_shader_output(llvmpipe->draw,
                                         lpfs->info.base.input_semantic_name[i],
                                         lpfs->info.base.input_semantic_index[i]);

      if (lpfs->info.base.input_semantic_name[i] == TGSI_SEMANTIC_COLOR &&
          lpfs->info.base.input_semantic_index[i] < 2) {
         int idx = lpfs->info.base.input_semantic_index[i];
         llvmpipe->color_slot[idx] = (int)vinfo->num_attribs;
      }

      /*
       * Emit the requested fs attribute for all but position.
       */
      draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index);
   }

   /* Figure out if we need bcolor as well.
    */
   for (i = 0; i < 2; i++) {
      vs_index = draw_find_shader_output(llvmpipe->draw,
                                         TGSI_SEMANTIC_BCOLOR, i);

      if (vs_index >= 0) {
         llvmpipe->bcolor_slot[i] = (int)vinfo->num_attribs;
         draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index);
      }
   }


   /* Figure out if we need pointsize as well.
    */
   vs_index = draw_find_shader_output(llvmpipe->draw,
                                      TGSI_SEMANTIC_PSIZE, 0);

   if (vs_index >= 0) {
      llvmpipe->psize_slot = vinfo->num_attribs;
      draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index);
   }

   /* Figure out if we need viewport index */
   vs_index = draw_find_shader_output(llvmpipe->draw,
                                      TGSI_SEMANTIC_VIEWPORT_INDEX,
                                      0);
   if (vs_index >= 0) {
      llvmpipe->viewport_index_slot = vinfo->num_attribs;
      draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index);
   } else {
      llvmpipe->viewport_index_slot = 0;
   }

   /* Figure out if we need layer */
   vs_index = draw_find_shader_output(llvmpipe->draw,
                                      TGSI_SEMANTIC_LAYER,
                                      0);
   if (vs_index >= 0) {
      llvmpipe->layer_slot = vinfo->num_attribs;
      draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index);
   } else {
      llvmpipe->layer_slot = 0;
   }


   draw_compute_vertex_size(vinfo);
   lp_setup_set_vertex_info(llvmpipe->setup, vinfo);
}
Exemplo n.º 5
0
/**
 * The vertex info describes how to convert the post-transformed vertices
 * (simple float[][4]) used by the 'draw' module into vertices for
 * rasterization.
 *
 * This function validates the vertex layout.
 */
static void
compute_vertex_info(struct llvmpipe_context *llvmpipe)
{
   const struct lp_fragment_shader *lpfs = llvmpipe->fs;
   struct vertex_info *vinfo = &llvmpipe->vertex_info;
   int vs_index;
   uint i;

   draw_prepare_shader_outputs(llvmpipe->draw);

   llvmpipe->color_slot[0] = 0;
   llvmpipe->color_slot[1] = 0;
   llvmpipe->bcolor_slot[0] = 0;
   llvmpipe->bcolor_slot[1] = 0;
   llvmpipe->viewport_index_slot = 0;
   llvmpipe->layer_slot = 0;
   llvmpipe->face_slot = 0;
   llvmpipe->psize_slot = 0;

   /*
    * Match FS inputs against VS outputs, emitting the necessary
    * attributes.  Could cache these structs and look them up with a
    * combination of fragment shader, vertex shader ids.
    */

   vinfo->num_attribs = 0;

   vs_index = draw_find_shader_output(llvmpipe->draw,
                                      TGSI_SEMANTIC_POSITION,
                                      0);

   draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index);

   for (i = 0; i < lpfs->info.base.num_inputs; i++) {
      /*
       * Search for each input in current vs output:
       */

      vs_index = draw_find_shader_output(llvmpipe->draw,
                                         lpfs->info.base.input_semantic_name[i],
                                         lpfs->info.base.input_semantic_index[i]);

      if (lpfs->info.base.input_semantic_name[i] == TGSI_SEMANTIC_COLOR &&
          lpfs->info.base.input_semantic_index[i] < 2) {
         int idx = lpfs->info.base.input_semantic_index[i];
         llvmpipe->color_slot[idx] = vinfo->num_attribs;
      }

      if (lpfs->info.base.input_semantic_name[i] == TGSI_SEMANTIC_FACE) {
         llvmpipe->face_slot = vinfo->num_attribs;
         draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index);
      } else if (lpfs->info.base.input_semantic_name[i] == TGSI_SEMANTIC_PRIMID) {
         draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index);
      /*
       * For vp index and layer, if the fs requires them but the vs doesn't
       * provide them, store the slot - we'll later replace the data directly
       * with zero (as required by ARB_fragment_layer_viewport). This is
       * because draw itself just redirects them to whatever was at output 0.
       * We'll also store the real vpindex/layer slot for setup use.
       */
      } else if (lpfs->info.base.input_semantic_name[i] ==
                 TGSI_SEMANTIC_VIEWPORT_INDEX) {
         if (vs_index >= 0) {
            llvmpipe->viewport_index_slot = vinfo->num_attribs;
         }
         else {
            llvmpipe->fake_vpindex_slot = vinfo->num_attribs;
         }
         draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index);
      } else if (lpfs->info.base.input_semantic_name[i] == TGSI_SEMANTIC_LAYER) {
         if (vs_index >= 0) {
            llvmpipe->layer_slot = vinfo->num_attribs;
         }
         else {
            llvmpipe->fake_layer_slot = vinfo->num_attribs;
         }
         draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index);
      } else {
         /*
          * Emit the requested fs attribute for all but position.
          */
         draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index);
      }
   }

   /* Figure out if we need bcolor as well.
    */
   for (i = 0; i < 2; i++) {
      vs_index = draw_find_shader_output(llvmpipe->draw,
                                         TGSI_SEMANTIC_BCOLOR, i);

      if (vs_index >= 0) {
         llvmpipe->bcolor_slot[i] = vinfo->num_attribs;
         draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index);
      }
   }

   /* Figure out if we need pointsize as well.
    */
   vs_index = draw_find_shader_output(llvmpipe->draw,
                                      TGSI_SEMANTIC_PSIZE, 0);

   if (vs_index >= 0) {
      llvmpipe->psize_slot = vinfo->num_attribs;
      draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index);
   }

   /* Figure out if we need viewport index (if it wasn't already in fs input) */
   if (llvmpipe->viewport_index_slot == 0) {
      vs_index = draw_find_shader_output(llvmpipe->draw,
                                         TGSI_SEMANTIC_VIEWPORT_INDEX,
                                         0);
      if (vs_index >= 0) {
         llvmpipe->viewport_index_slot = vinfo->num_attribs;
         draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index);
      }
   }

   /* Figure out if we need layer (if it wasn't already in fs input) */
   if (llvmpipe->layer_slot == 0) {
      vs_index = draw_find_shader_output(llvmpipe->draw,
                                         TGSI_SEMANTIC_LAYER,
                                         0);
      if (vs_index >= 0) {
         llvmpipe->layer_slot = vinfo->num_attribs;
         draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index);
      }
   }

   draw_compute_vertex_size(vinfo);
   lp_setup_set_vertex_info(llvmpipe->setup, vinfo);
}
Exemplo n.º 6
0
enum pipe_error
svga_swtnl_update_vdecl( struct svga_context *svga )
{
   struct svga_vbuf_render *svga_render = svga_vbuf_render(svga->swtnl.backend);
   struct draw_context *draw = svga->swtnl.draw;
   struct vertex_info *vinfo = &svga_render->vertex_info;
   SVGA3dVertexDecl vdecl[PIPE_MAX_ATTRIBS];
   const enum interp_mode colorInterp =
      svga->curr.rast->templ.flatshade ? INTERP_CONSTANT : INTERP_LINEAR;
   struct svga_fragment_shader *fs = svga->curr.fs;
   int offset = 0;
   int nr_decls = 0;
   int src;
   unsigned i;

   memset(vinfo, 0, sizeof(*vinfo));
   memset(vdecl, 0, sizeof(vdecl));

   /* always add position */
   src = draw_find_shader_output(draw, TGSI_SEMANTIC_POSITION, 0);
   draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_LINEAR, src);
   vinfo->attrib[0].emit = EMIT_4F;
   vdecl[0].array.offset = offset;
   vdecl[0].identity.type = SVGA3D_DECLTYPE_FLOAT4;
   vdecl[0].identity.usage = SVGA3D_DECLUSAGE_POSITIONT;
   vdecl[0].identity.usageIndex = 0;
   offset += 16;
   nr_decls++;

   for (i = 0; i < fs->base.info.num_inputs; i++) {
      const unsigned sem_name = fs->base.info.input_semantic_name[i];
      const unsigned sem_index = fs->base.info.input_semantic_index[i];

      src = draw_find_shader_output(draw, sem_name, sem_index);

      vdecl[nr_decls].array.offset = offset;
      vdecl[nr_decls].identity.usageIndex = sem_index;

      switch (sem_name) {
      case TGSI_SEMANTIC_COLOR:
         draw_emit_vertex_attr(vinfo, EMIT_4F, colorInterp, src);
         vdecl[nr_decls].identity.usage = SVGA3D_DECLUSAGE_COLOR;
         vdecl[nr_decls].identity.type = SVGA3D_DECLTYPE_FLOAT4;
         offset += 16;
         nr_decls++;
         break;
      case TGSI_SEMANTIC_GENERIC:
         draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);
         vdecl[nr_decls].identity.usage = SVGA3D_DECLUSAGE_TEXCOORD;
         vdecl[nr_decls].identity.type = SVGA3D_DECLTYPE_FLOAT4;
         vdecl[nr_decls].identity.usageIndex =
            svga_remap_generic_index(fs->generic_remap_table, sem_index);
         offset += 16;
         nr_decls++;
         break;
      case TGSI_SEMANTIC_FOG:
         draw_emit_vertex_attr(vinfo, EMIT_1F, INTERP_PERSPECTIVE, src);
         vdecl[nr_decls].identity.usage = SVGA3D_DECLUSAGE_TEXCOORD;
         vdecl[nr_decls].identity.type = SVGA3D_DECLTYPE_FLOAT1;
         assert(vdecl[nr_decls].identity.usageIndex == 0);
         offset += 4;
         nr_decls++;
         break;
      case TGSI_SEMANTIC_POSITION:
         /* generated internally, not a vertex shader output */
         break;
      default:
         assert(0);
      }
   }

   draw_compute_vertex_size(vinfo);

   svga_render->vdecl_count = nr_decls;
   for (i = 0; i < svga_render->vdecl_count; i++)
      vdecl[i].array.stride = offset;

   if (memcmp(svga_render->vdecl, vdecl, sizeof(vdecl)) == 0)
      return 0;

   memcpy(svga_render->vdecl, vdecl, sizeof(vdecl));
   svga->swtnl.new_vdecl = TRUE;

   return 0;
}
Exemplo n.º 7
0
/**
 * The vertex info describes how to convert the post-transformed vertices
 * (simple float[][4]) used by the 'draw' module into vertices for
 * rasterization.
 *
 * This function validates the vertex layout.
 */
static void
softpipe_compute_vertex_info(struct softpipe_context *softpipe)
{
   struct sp_setup_info *sinfo = &softpipe->setup_info;

   if (sinfo->valid == 0) {
      const struct tgsi_shader_info *fsInfo = &softpipe->fs_variant->info;
      struct vertex_info *vinfo = &softpipe->vertex_info;
      uint i;
      int vs_index;
      /*
       * This doesn't quite work right (wrt face injection, prim id,
       * wide points) - hit a couple assertions, misrenderings plus
       * memory corruption. Albeit could fix (the former two) by calling
       * this "more often" (rasterizer changes etc.). (The latter would
       * need to be included in draw_prepare_shader_outputs, but it looks
       * like that would potentially allocate quite some unused additional
       * vertex outputs.)
       * draw_prepare_shader_outputs(softpipe->draw);
       */

      /*
       * Those can't actually be 0 (because pos is always at 0).
       * But use ints anyway to avoid confusion (in vs outputs, they
       * can very well be at pos 0).
       */
      softpipe->viewport_index_slot = -1;
      softpipe->layer_slot = -1;
      softpipe->psize_slot = -1;

      vinfo->num_attribs = 0;

      /*
       * Put position always first (setup needs it there).
       */
      vs_index = draw_find_shader_output(softpipe->draw,
                                         TGSI_SEMANTIC_POSITION, 0);

      draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);

      /*
       * Match FS inputs against VS outputs, emitting the necessary
       * attributes.
       */
      for (i = 0; i < fsInfo->num_inputs; i++) {
         enum sp_interp_mode interp = SP_INTERP_LINEAR;

         switch (fsInfo->input_interpolate[i]) {
         case TGSI_INTERPOLATE_CONSTANT:
            interp = SP_INTERP_CONSTANT;
            break;
         case TGSI_INTERPOLATE_LINEAR:
            interp = SP_INTERP_LINEAR;
            break;
         case TGSI_INTERPOLATE_PERSPECTIVE:
            interp = SP_INTERP_PERSPECTIVE;
            break;
         case TGSI_INTERPOLATE_COLOR:
            assert(fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR);
            break;
         default:
            assert(0);
         }

         switch (fsInfo->input_semantic_name[i]) {
         case TGSI_SEMANTIC_POSITION:
            interp = SP_INTERP_POS;
            break;

         case TGSI_SEMANTIC_COLOR:
            if (fsInfo->input_interpolate[i] == TGSI_INTERPOLATE_COLOR) {
               if (softpipe->rasterizer->flatshade)
                  interp = SP_INTERP_CONSTANT;
               else
                  interp = SP_INTERP_PERSPECTIVE;
            }
            break;
         }

         /*
          * Search for each input in current vs output:
          */
         vs_index = draw_find_shader_output(softpipe->draw,
                                            fsInfo->input_semantic_name[i],
                                            fsInfo->input_semantic_index[i]);

         if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR &&
             vs_index == -1) {
            /*
             * try and find a bcolor.
             * Note that if there's both front and back color, draw will
             * have copied back to front color already.
             */
            vs_index = draw_find_shader_output(softpipe->draw,
                                               TGSI_SEMANTIC_BCOLOR,
                                               fsInfo->input_semantic_index[i]);
         }

         sinfo->attrib[i].interp = interp;
         /* extremely pointless index map */
         sinfo->attrib[i].src_index = i + 1;
         /*
          * For vp index and layer, if the fs requires them but the vs doesn't
          * provide them, draw (vbuf) will give us the required 0 (slot -1).
          * (This means in this case we'll also use those slots in setup, which
          * isn't necessary but they'll contain the correct (0) value.)
          */
         if (fsInfo->input_semantic_name[i] ==
                    TGSI_SEMANTIC_VIEWPORT_INDEX) {
            softpipe->viewport_index_slot = (int)vinfo->num_attribs;
            draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);
         } else if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_LAYER) {
            softpipe->layer_slot = (int)vinfo->num_attribs;
            draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);
            /*
             * Note that we'd actually want to skip position (as we won't use
             * the attribute in the fs) but can't. The reason is that we don't
             * actually have an input/output map for setup (even though it looks
             * like we do...). Could adjust for this though even without a map.
             */
         } else {
            /*
             * Note that we'd actually want to skip position (as we won't use
             * the attribute in the fs) but can't. The reason is that we don't
             * actually have an input/output map for setup (even though it looks
             * like we do...). Could adjust for this though even without a map.
             */
            draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);
         }
      }

      /* Figure out if we need pointsize as well.
       */
      vs_index = draw_find_shader_output(softpipe->draw,
                                         TGSI_SEMANTIC_PSIZE, 0);

      if (vs_index >= 0) {
         softpipe->psize_slot = (int)vinfo->num_attribs;
         draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);
      }

      /* Figure out if we need viewport index (if it wasn't already in fs input) */
      if (softpipe->viewport_index_slot < 0) {
         vs_index = draw_find_shader_output(softpipe->draw,
                                            TGSI_SEMANTIC_VIEWPORT_INDEX,
                                            0);
         if (vs_index >= 0) {
            softpipe->viewport_index_slot =(int)vinfo->num_attribs;
            draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);
         }
      }

      /* Figure out if we need layer (if it wasn't already in fs input) */
      if (softpipe->layer_slot < 0) {
         vs_index = draw_find_shader_output(softpipe->draw,
                                            TGSI_SEMANTIC_LAYER,
                                            0);
         if (vs_index >= 0) {
            softpipe->layer_slot = (int)vinfo->num_attribs;
            draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);
         }
      }

      draw_compute_vertex_size(vinfo);
      softpipe->setup_info.valid = 1;
   }
   return;
}
/**
 * The vertex info describes how to convert the post-transformed vertices
 * (simple float[][4]) used by the 'draw' module into vertices for
 * rasterization.
 *
 * This function validates the vertex layout.
 */
static void
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 = llvmpipe->inputs;
   unsigned vs_index;
   uint i;

   /*
    * Match FS inputs against VS outputs, emitting the necessary attributes.
    */

   vinfo->num_attribs = 0;

   vs_index = draw_find_shader_output(llvmpipe->draw,
                                       TGSI_SEMANTIC_POSITION,
                                       0);

   draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index);

   for (i = 0; i < lpfs->info.num_inputs; i++) {
      /*
       * Search for each input in current vs output:
       */

      vs_index = draw_find_shader_output(llvmpipe->draw,
                                         lpfs->info.input_semantic_name[i],
                                         lpfs->info.input_semantic_index[i]);
      if (vs_index < 0) {
         /*
          * This can happen with sprite coordinates - the vertex
          * shader doesn't need to provide an output as we generate
          * them internally.  However, lets keep pretending that there
          * is something there to not confuse other code.
          */
         vs_index = 0;
      }

      /* This can be pre-computed, except for flatshade:
       */
      inputs[i].usage_mask = lpfs->info.input_usage_mask[i];

      switch (lpfs->info.input_interpolate[i]) {
      case TGSI_INTERPOLATE_CONSTANT:
         inputs[i].interp = LP_INTERP_CONSTANT;
         break;
      case TGSI_INTERPOLATE_LINEAR:
         inputs[i].interp = LP_INTERP_LINEAR;
         break;
      case TGSI_INTERPOLATE_PERSPECTIVE:
         inputs[i].interp = LP_INTERP_PERSPECTIVE;
         break;
      default:
         assert(0);
         break;
      }

      switch (lpfs->info.input_semantic_name[i]) {
      case TGSI_SEMANTIC_FACE:
         inputs[i].interp = LP_INTERP_FACING;
         break;
      case TGSI_SEMANTIC_POSITION:
         /* Position was already emitted above
          */
         inputs[i].interp = LP_INTERP_POSITION;
         inputs[i].src_index = 0;
         continue;
      case TGSI_SEMANTIC_COLOR:
         /* Colors are linearly inputs[i].interpolated in the fragment shader
          * even when flatshading is active.  This just tells the
          * setup module to use coefficients with ddx==0 and
          * ddy==0.
          */
         if (llvmpipe->rasterizer->flatshade)
            inputs[i].interp = LP_INTERP_CONSTANT;
         break;

      default:
         break;
      }

      /*
       * Emit the requested fs attribute for all but position.
       */

      inputs[i].src_index = vinfo->num_attribs;
      draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index);
   }

   /* Figure out if we need pointsize as well.
    */
   vs_index = draw_find_shader_output(llvmpipe->draw,
                                      TGSI_SEMANTIC_PSIZE, 0);

   if (vs_index > 0) {
      llvmpipe->psize_slot = vinfo->num_attribs;
      draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index);
   }

   llvmpipe->num_inputs = lpfs->info.num_inputs;

   draw_compute_vertex_size(vinfo);

   lp_setup_set_vertex_info(llvmpipe->setup, vinfo);

   lp_setup_set_fs_inputs(llvmpipe->setup,
                          inputs,
                          lpfs->info.num_inputs);
}