/* Perform the fetch from API vertex elements & vertex buffers, to a
 * contiguous set of float[4] attributes as required for the
 * vertex_shader->run_linear() method.
 *
 * This is used in all cases except pure passthrough
 * (draw_pt_fetch_emit.c) which has its own version to translate
 * directly to hw vertices.
 *
 */
void draw_pt_fetch_prepare( struct pt_fetch *fetch,
                            unsigned vs_input_count,
			    unsigned vertex_size )
{
   struct draw_context *draw = fetch->draw;
   unsigned nr_inputs;
   unsigned i, nr = 0;
   unsigned dst_offset = 0;
   struct translate_key key;

   fetch->vertex_size = vertex_size;

   /* Always emit/leave space for a vertex header.
    *
    * It's worth considering whether the vertex headers should contain
    * a pointer to the 'data', rather than having it inline.
    * Something to look at after we've fully switched over to the pt
    * paths.
    */
   {
      /* Need to set header->vertex_id = 0xffff somehow.
       */
      key.element[nr].input_format = PIPE_FORMAT_R32_FLOAT;
      key.element[nr].input_buffer = draw->pt.nr_vertex_buffers;
      key.element[nr].input_offset = 0;
      key.element[nr].output_format = PIPE_FORMAT_R32_FLOAT;
      key.element[nr].output_offset = dst_offset;
      dst_offset += 1 * sizeof(float);
      nr++;


      /* Just leave the clip[] array untouched.
       */
      dst_offset += 4 * sizeof(float);
   }
      
   assert( draw->pt.nr_vertex_elements >= vs_input_count );

   nr_inputs = MIN2( vs_input_count, draw->pt.nr_vertex_elements );

   for (i = 0; i < nr_inputs; i++) {
      key.element[nr].input_format = draw->pt.vertex_element[i].src_format;
      key.element[nr].input_buffer = draw->pt.vertex_element[i].vertex_buffer_index;
      key.element[nr].input_offset = draw->pt.vertex_element[i].src_offset;
      key.element[nr].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
      key.element[nr].output_offset = dst_offset;

      dst_offset += 4 * sizeof(float);
      nr++;
   }

   assert(dst_offset <= vertex_size);

   key.nr_elements = nr;
   key.output_stride = vertex_size;


   if (!fetch->translate ||
       translate_key_compare(&fetch->translate->key, &key) != 0)
   {
      translate_key_sanitize(&key);
      fetch->translate = translate_cache_find(fetch->cache, &key);

      {
         static struct vertex_header vh = { 0, 1, 0, UNDEFINED_VERTEX_ID, { .0f, .0f, .0f, .0f } };
	 fetch->translate->set_buffer(fetch->translate,
				      draw->pt.nr_vertex_buffers,
				      &vh,
				      0);
      }
   }

   fetch->need_edgeflags = ((draw->rasterizer->fill_cw != PIPE_POLYGON_MODE_FILL ||
                             draw->rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL) &&
                            draw->pt.user.edgeflag);
}
static int update_zero_stride( struct svga_context *svga,
                               unsigned dirty )
{
   unsigned i;

   svga->curr.zero_stride_vertex_elements = 0;
   svga->curr.num_zero_stride_vertex_elements = 0;

   for (i = 0; i < svga->curr.num_vertex_elements; i++) {
      const struct pipe_vertex_element *vel = &svga->curr.ve[i];
      const struct pipe_vertex_buffer *vbuffer = &svga->curr.vb[
         vel->vertex_buffer_index];
      if (vbuffer->stride == 0) {
         unsigned const_idx =
            svga->curr.num_zero_stride_vertex_elements;
         struct translate *translate;
         struct translate_key key;
         void *mapped_buffer;

         svga->curr.zero_stride_vertex_elements |= (1 << i);
         ++svga->curr.num_zero_stride_vertex_elements;

         key.output_stride = 4 * sizeof(float);
         key.nr_elements = 1;
         key.element[0].type = TRANSLATE_ELEMENT_NORMAL;
         key.element[0].input_format = vel->src_format;
         key.element[0].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
         key.element[0].input_buffer = vel->vertex_buffer_index;
         key.element[0].input_offset = vel->src_offset;
         key.element[0].instance_divisor = vel->instance_divisor;
         key.element[0].output_offset = const_idx * 4 * sizeof(float);

         translate_key_sanitize(&key);
         /* translate_generic_create is technically private but
          * we don't want to code-generate, just want generic
          * translation */
         translate = translate_generic_create(&key);

         assert(vel->src_offset == 0);
         
         mapped_buffer = pipe_buffer_map_range(svga->pipe.screen, 
                                               vbuffer->buffer,
                                               vel->src_offset,
                                               util_format_get_blocksize(vel->src_format),
                                               PIPE_BUFFER_USAGE_CPU_READ);
         translate->set_buffer(translate, vel->vertex_buffer_index,
                               mapped_buffer,
                               vbuffer->stride);
         translate->run(translate, 0, 1, 0,
                        svga->curr.zero_stride_constants);

         pipe_buffer_unmap(svga->pipe.screen,
                           vbuffer->buffer);
         translate->release(translate);
      }
   }

   if (svga->curr.num_zero_stride_vertex_elements)
      svga->dirty |= SVGA_NEW_ZERO_STRIDE;

   return 0;
}
void
draw_pt_emit_prepare(struct pt_emit *emit,
                     unsigned prim,
                     unsigned *max_vertices)
{
   struct draw_context *draw = emit->draw;
   const struct vertex_info *vinfo;
   unsigned dst_offset;
   struct translate_key hw_key;
   unsigned i;

   /* XXX: need to flush to get prim_vbuf.c to release its allocation??
    */
   draw_do_flush( draw, DRAW_FLUSH_BACKEND );

   /* XXX: may need to defensively reset this later on as clipping can
    * clobber this state in the render backend.
    */
   emit->prim = prim;

   draw->render->set_primitive(draw->render, emit->prim);

   /* Must do this after set_primitive() above:
    */
   emit->vinfo = vinfo = draw->render->get_vertex_info(draw->render);

   /* Translate from pipeline vertices to hw vertices.
    */
   dst_offset = 0;
   for (i = 0; i < vinfo->num_attribs; i++) {
      unsigned emit_sz = 0;
      unsigned src_buffer = 0;
      unsigned output_format;
      unsigned src_offset = (vinfo->attrib[i].src_index * 4 * sizeof(float) );

      output_format = draw_translate_vinfo_format(vinfo->attrib[i].emit);
      emit_sz = draw_translate_vinfo_size(vinfo->attrib[i].emit);

      /* doesn't handle EMIT_OMIT */
      assert(emit_sz != 0);

      if (vinfo->attrib[i].emit == EMIT_1F_PSIZE) {
	 src_buffer = 1;
	 src_offset = 0;
      }

      hw_key.element[i].type = TRANSLATE_ELEMENT_NORMAL;
      hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
      hw_key.element[i].input_buffer = src_buffer;
      hw_key.element[i].input_offset = src_offset;
      hw_key.element[i].instance_divisor = 0;
      hw_key.element[i].output_format = output_format;
      hw_key.element[i].output_offset = dst_offset;

      dst_offset += emit_sz;
   }

   hw_key.nr_elements = vinfo->num_attribs;
   hw_key.output_stride = vinfo->size * 4;

   if (!emit->translate ||
       translate_key_compare(&emit->translate->key, &hw_key) != 0) {
      translate_key_sanitize(&hw_key);
      emit->translate = translate_cache_find(emit->cache, &hw_key);
   }

   *max_vertices = (draw->render->max_vertex_buffer_bytes /
                    (vinfo->size * 4));
}
static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
                                unsigned prim,
				unsigned opt,
                                unsigned *max_vertices )
{
   struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
   struct draw_context *draw = feme->draw;
   const struct vertex_info *vinfo;
   unsigned i, dst_offset;
   boolean ok;
   struct translate_key key;


   ok = draw->render->set_primitive( draw->render, 
                                     prim );
   if (!ok) {
      assert(0);
      return;
   }
   
   /* Must do this after set_primitive() above:
    */
   vinfo = feme->vinfo = draw->render->get_vertex_info(draw->render);
   
   

   /* Transform from API vertices to HW vertices, skipping the
    * pipeline_vertex intermediate step.
    */
   dst_offset = 0;
   memset(&key, 0, sizeof(key));

   for (i = 0; i < vinfo->num_attribs; i++) {
      const struct pipe_vertex_element *src = &draw->pt.vertex_element[vinfo->attrib[i].src_index];

      unsigned emit_sz = 0;
      unsigned input_format = src->src_format;
      unsigned input_buffer = src->vertex_buffer_index;
      unsigned input_offset = src->src_offset;
      unsigned output_format;

      switch (vinfo->attrib[i].emit) {
      case EMIT_4UB:
	 output_format = PIPE_FORMAT_R8G8B8A8_UNORM;
	 emit_sz = 4 * sizeof(unsigned char);
         break;
      case EMIT_4F:
	 output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
	 emit_sz = 4 * sizeof(float);
         break;
      case EMIT_3F:
	 output_format = PIPE_FORMAT_R32G32B32_FLOAT;
	 emit_sz = 3 * sizeof(float);
         break;
      case EMIT_2F:
	 output_format = PIPE_FORMAT_R32G32_FLOAT;
	 emit_sz = 2 * sizeof(float);
         break;
      case EMIT_1F:
	 output_format = PIPE_FORMAT_R32_FLOAT;
	 emit_sz = 1 * sizeof(float);
         break;
      case EMIT_1F_PSIZE:
	 input_format = PIPE_FORMAT_R32_FLOAT;
	 input_buffer = draw->pt.nr_vertex_buffers;
	 input_offset = 0;
	 output_format = PIPE_FORMAT_R32_FLOAT;
	 emit_sz = 1 * sizeof(float);
         break;
      case EMIT_OMIT:
         continue;
      default:
         assert(0);
	 output_format = PIPE_FORMAT_NONE;
	 emit_sz = 0;
	 continue;
      }

      key.element[i].input_format = input_format;
      key.element[i].input_buffer = input_buffer;
      key.element[i].input_offset = input_offset;
      key.element[i].output_format = output_format;
      key.element[i].output_offset = dst_offset;
      
      dst_offset += emit_sz;
   }

   key.nr_elements = vinfo->num_attribs;
   key.output_stride = vinfo->size * 4;

   /* Don't bother with caching at this stage:
    */
   if (!feme->translate ||
       translate_key_compare(&feme->translate->key, &key) != 0) 
   {
      translate_key_sanitize(&key);
      feme->translate = translate_cache_find(feme->cache,
                                             &key);


      feme->translate->set_buffer(feme->translate, 
				  draw->pt.nr_vertex_buffers, 
				  &feme->point_size,
				  0);
   }
   
   feme->point_size = draw->rasterizer->point_size;

   for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
      feme->translate->set_buffer(feme->translate, 
                                  i, 
                                  ((char *)draw->pt.user.vbuffer[i] + 
                                   draw->pt.vertex_buffer[i].buffer_offset),
                                  draw->pt.vertex_buffer[i].stride );
   }

   *max_vertices = (draw->render->max_vertex_buffer_bytes / 
                    (vinfo->size * 4));

   /* Return an even number of verts.
    * This prevents "parity" errors when splitting long triangle strips which
    * can lead to front/back culling mix-ups.
    * Every other triangle in a strip has an alternate front/back orientation
    * so splitting at an odd position can cause the orientation of subsequent
    * triangles to get reversed.
    */
   *max_vertices = *max_vertices & ~1;
}
Exemple #5
0
static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
                                unsigned prim,
				unsigned opt,
                                unsigned *max_vertices )
{
   struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
   struct draw_context *draw = feme->draw;
   const struct vertex_info *vinfo;
   unsigned i, dst_offset;
   boolean ok;
   struct translate_key key;

   unsigned gs_out_prim = (draw->gs.geometry_shader ? 
                           draw->gs.geometry_shader->output_primitive :
                           prim);



   ok = draw->render->set_primitive( draw->render, 
                                     gs_out_prim );
   if (!ok) {
      assert(0);
      return;
   }
   
   /* Must do this after set_primitive() above:
    */
   vinfo = feme->vinfo = draw->render->get_vertex_info(draw->render);
   
   

   /* Transform from API vertices to HW vertices, skipping the
    * pipeline_vertex intermediate step.
    */
   dst_offset = 0;
   memset(&key, 0, sizeof(key));

   for (i = 0; i < vinfo->num_attribs; i++) {
      const struct pipe_vertex_element *src = &draw->pt.vertex_element[vinfo->attrib[i].src_index];

      unsigned emit_sz = 0;
      unsigned input_format = src->src_format;
      unsigned input_buffer = src->vertex_buffer_index;
      unsigned input_offset = src->src_offset;
      unsigned output_format;

      output_format = draw_translate_vinfo_format(vinfo->attrib[i].emit);
      emit_sz = draw_translate_vinfo_size(vinfo->attrib[i].emit);

      if (vinfo->attrib[i].emit == EMIT_OMIT)
	 continue;

      if (vinfo->attrib[i].emit == EMIT_1F_PSIZE) {
	 input_format = PIPE_FORMAT_R32_FLOAT;
	 input_buffer = draw->pt.nr_vertex_buffers;
	 input_offset = 0;
      }

      key.element[i].type = TRANSLATE_ELEMENT_NORMAL;
      key.element[i].input_format = input_format;
      key.element[i].input_buffer = input_buffer;
      key.element[i].input_offset = input_offset;
      key.element[i].instance_divisor = src->instance_divisor;
      key.element[i].output_format = output_format;
      key.element[i].output_offset = dst_offset;
      
      dst_offset += emit_sz;
   }

   key.nr_elements = vinfo->num_attribs;
   key.output_stride = vinfo->size * 4;

   /* Don't bother with caching at this stage:
    */
   if (!feme->translate ||
       translate_key_compare(&feme->translate->key, &key) != 0) 
   {
      translate_key_sanitize(&key);
      feme->translate = translate_cache_find(feme->cache,
                                             &key);


      feme->translate->set_buffer(feme->translate, 
				  draw->pt.nr_vertex_buffers, 
				  &feme->point_size,
				  0,
				  ~0);
   }
   
   feme->point_size = draw->rasterizer->point_size;

   for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
      feme->translate->set_buffer(feme->translate, 
                                  i, 
                                  ((char *)draw->pt.user.vbuffer[i] + 
                                   draw->pt.vertex_buffer[i].buffer_offset),
                                  draw->pt.vertex_buffer[i].stride,
                                  draw->pt.max_index);
   }

   *max_vertices = (draw->render->max_vertex_buffer_bytes / 
                    (vinfo->size * 4));
}
Exemple #6
0
/**
 * Perform the fetch from API vertex elements & vertex buffers, to a
 * contiguous set of float[4] attributes as required for the
 * vertex_shader->run_linear() method.
 *
 * This is used in all cases except pure passthrough
 * (draw_pt_fetch_emit.c) which has its own version to translate
 * directly to hw vertices.
 *
 */
void
draw_pt_fetch_prepare(struct pt_fetch *fetch,
                      unsigned vs_input_count,
                      unsigned vertex_size,
                      unsigned instance_id_index)
{
   struct draw_context *draw = fetch->draw;
   unsigned nr_inputs;
   unsigned i, nr = 0, ei = 0;
   unsigned dst_offset = 0;
   unsigned num_extra_inputs = 0;
   struct translate_key key;

   fetch->vertex_size = vertex_size;

   /* Leave the clipmask/edgeflags/pad/vertex_id untouched
    */
   dst_offset += 1 * sizeof(float);
   /* Just leave the clip[] and pre_clip_pos[] array untouched.
    */
   dst_offset += 8 * sizeof(float);

   if (instance_id_index != ~0) {
      num_extra_inputs++;
   }

   assert(draw->pt.nr_vertex_elements + num_extra_inputs >= vs_input_count);

   nr_inputs = MIN2(vs_input_count, draw->pt.nr_vertex_elements + num_extra_inputs);

   for (i = 0; i < nr_inputs; i++) {
      if (i == instance_id_index) {
         key.element[nr].type = TRANSLATE_ELEMENT_INSTANCE_ID;
         key.element[nr].input_format = PIPE_FORMAT_R32_USCALED;
         key.element[nr].output_format = PIPE_FORMAT_R32_USCALED;
         key.element[nr].output_offset = dst_offset;

         dst_offset += sizeof(uint);
      } else if (util_format_is_pure_sint(draw->pt.vertex_element[i].src_format)) {
         key.element[nr].type = TRANSLATE_ELEMENT_NORMAL;
         key.element[nr].input_format = draw->pt.vertex_element[ei].src_format;
         key.element[nr].input_buffer = draw->pt.vertex_element[ei].vertex_buffer_index;
         key.element[nr].input_offset = draw->pt.vertex_element[ei].src_offset;
         key.element[nr].instance_divisor = draw->pt.vertex_element[ei].instance_divisor;
         key.element[nr].output_format = PIPE_FORMAT_R32G32B32A32_SINT;
         key.element[nr].output_offset = dst_offset;

         ei++;
         dst_offset += 4 * sizeof(int);
      } else if (util_format_is_pure_uint(draw->pt.vertex_element[i].src_format)) {
         key.element[nr].type = TRANSLATE_ELEMENT_NORMAL;
         key.element[nr].input_format = draw->pt.vertex_element[ei].src_format;
         key.element[nr].input_buffer = draw->pt.vertex_element[ei].vertex_buffer_index;
         key.element[nr].input_offset = draw->pt.vertex_element[ei].src_offset;
         key.element[nr].instance_divisor = draw->pt.vertex_element[ei].instance_divisor;
         key.element[nr].output_format = PIPE_FORMAT_R32G32B32A32_UINT;
         key.element[nr].output_offset = dst_offset;

         ei++;
         dst_offset += 4 * sizeof(unsigned);
      } else {
         key.element[nr].type = TRANSLATE_ELEMENT_NORMAL;
         key.element[nr].input_format = draw->pt.vertex_element[ei].src_format;
         key.element[nr].input_buffer = draw->pt.vertex_element[ei].vertex_buffer_index;
         key.element[nr].input_offset = draw->pt.vertex_element[ei].src_offset;
         key.element[nr].instance_divisor = draw->pt.vertex_element[ei].instance_divisor;
         key.element[nr].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
         key.element[nr].output_offset = dst_offset;

         ei++;
         dst_offset += 4 * sizeof(float);
      }

      nr++;
   }

   assert(dst_offset <= vertex_size);

   key.nr_elements = nr;
   key.output_stride = vertex_size;

   if (!fetch->translate ||
       translate_key_compare(&fetch->translate->key, &key) != 0)
   {
      translate_key_sanitize(&key);
      fetch->translate = translate_cache_find(fetch->cache, &key);
   }
}
Exemple #7
0
/**
 * Set the prim type for subsequent vertices.
 * This may result in a new vertex size.  The existing vbuffer (if any)
 * will be flushed if needed and a new one allocated.
 */
static void
vbuf_start_prim( struct vbuf_stage *vbuf, uint prim )
{
   struct translate_key hw_key;
   unsigned dst_offset;
   unsigned i;

   vbuf->render->set_primitive(vbuf->render, prim);

   /* Must do this after set_primitive() above:
    * 
    * XXX: need some state managment to track when this needs to be
    * recalculated.  The driver should tell us whether there was a
    * state change.
    */
   vbuf->vinfo = vbuf->render->get_vertex_info(vbuf->render);
   vbuf->vertex_size = vbuf->vinfo->size * sizeof(float);

   /* Translate from pipeline vertices to hw vertices.
    */
   dst_offset = 0;

   for (i = 0; i < vbuf->vinfo->num_attribs; i++) {
      unsigned emit_sz = 0;
      unsigned src_buffer = 0;
      unsigned output_format;
      unsigned src_offset = (vbuf->vinfo->attrib[i].src_index * 4 * sizeof(float) );

      switch (vbuf->vinfo->attrib[i].emit) {
      case EMIT_4F:
	 output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
	 emit_sz = 4 * sizeof(float);
	 break;
      case EMIT_3F:
	 output_format = PIPE_FORMAT_R32G32B32_FLOAT;
	 emit_sz = 3 * sizeof(float);
	 break;
      case EMIT_2F:
	 output_format = PIPE_FORMAT_R32G32_FLOAT;
	 emit_sz = 2 * sizeof(float);
	 break;
      case EMIT_1F:
	 output_format = PIPE_FORMAT_R32_FLOAT;
	 emit_sz = 1 * sizeof(float);
	 break;
      case EMIT_1F_PSIZE:
	 output_format = PIPE_FORMAT_R32_FLOAT;
	 emit_sz = 1 * sizeof(float);
	 src_buffer = 1;
	 src_offset = 0;
	 break;
      case EMIT_4UB:
	 output_format = PIPE_FORMAT_B8G8R8A8_UNORM;
	 emit_sz = 4 * sizeof(ubyte);
         break;
      default:
	 assert(0);
	 output_format = PIPE_FORMAT_NONE;
	 emit_sz = 0;
	 break;
      }
      
      hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
      hw_key.element[i].input_buffer = src_buffer;
      hw_key.element[i].input_offset = src_offset;
      hw_key.element[i].output_format = output_format;
      hw_key.element[i].output_offset = dst_offset;

      dst_offset += emit_sz;
   }

   hw_key.nr_elements = vbuf->vinfo->num_attribs;
   hw_key.output_stride = vbuf->vinfo->size * 4;

   /* Don't bother with caching at this stage:
    */
   if (!vbuf->translate ||
       translate_key_compare(&vbuf->translate->key, &hw_key) != 0) 
   {
      translate_key_sanitize(&hw_key);
      vbuf->translate = translate_cache_find(vbuf->cache, &hw_key);

      vbuf->translate->set_buffer(vbuf->translate, 1, &vbuf->point_size, 0);
   }

   vbuf->point_size = vbuf->stage.draw->rasterizer->point_size;

   /* Allocate new buffer?
    */
   assert(vbuf->vertices == NULL);
   vbuf_alloc_vertices(vbuf);
}
/**
 * Set the prim type for subsequent vertices.
 * This may result in a new vertex size.  The existing vbuffer (if any)
 * will be flushed if needed and a new one allocated.
 */
static void
vbuf_start_prim( struct vbuf_stage *vbuf, uint prim )
{
   struct translate_key hw_key;
   unsigned dst_offset;
   unsigned i;
   const struct vertex_info *vinfo;

   vbuf->render->set_primitive(vbuf->render, prim);

   /* Must do this after set_primitive() above:
    * 
    * XXX: need some state managment to track when this needs to be
    * recalculated.  The driver should tell us whether there was a
    * state change.
    */
   vbuf->vinfo = vbuf->render->get_vertex_info(vbuf->render);
   vinfo = vbuf->vinfo;
   vbuf->vertex_size = vinfo->size * sizeof(float);

   /* Translate from pipeline vertices to hw vertices.
    */
   dst_offset = 0;

   for (i = 0; i < vinfo->num_attribs; i++) {
      unsigned emit_sz = 0;
      unsigned src_buffer = 0;
      enum pipe_format output_format;
      unsigned src_offset = (vinfo->attrib[i].src_index * 4 * sizeof(float) );

      output_format = draw_translate_vinfo_format(vinfo->attrib[i].emit);
      emit_sz = draw_translate_vinfo_size(vinfo->attrib[i].emit);

      /* doesn't handle EMIT_OMIT */
      assert(emit_sz != 0);

      if (vinfo->attrib[i].emit == EMIT_1F_PSIZE) {
         src_buffer = 1;
         src_offset = 0;
      }
      else if (vinfo->attrib[i].src_index == DRAW_ATTR_NONEXIST) {
         /* elements which don't exist will get assigned zeros */
         src_buffer = 2;
         src_offset = 0;
      }

      hw_key.element[i].type = TRANSLATE_ELEMENT_NORMAL;
      hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
      hw_key.element[i].input_buffer = src_buffer;
      hw_key.element[i].input_offset = src_offset;
      hw_key.element[i].instance_divisor = 0;
      hw_key.element[i].output_format = output_format;
      hw_key.element[i].output_offset = dst_offset;

      dst_offset += emit_sz;
   }

   hw_key.nr_elements = vinfo->num_attribs;
   hw_key.output_stride = vbuf->vertex_size;

   /* Don't bother with caching at this stage:
    */
   if (!vbuf->translate ||
       translate_key_compare(&vbuf->translate->key, &hw_key) != 0) 
   {
      translate_key_sanitize(&hw_key);
      vbuf->translate = translate_cache_find(vbuf->cache, &hw_key);

      vbuf->translate->set_buffer(vbuf->translate, 1, &vbuf->point_size, 0, ~0);
      vbuf->translate->set_buffer(vbuf->translate, 2, &vbuf->zero4[0], 0, ~0);
   }

   vbuf->point_size = vbuf->stage.draw->rasterizer->point_size;

   /* Allocate new buffer?
    */
   assert(vbuf->vertices == NULL);
   vbuf_alloc_vertices(vbuf);
}