Implement instanced indexed draw.
[mesa.git] / src / gallium / auxiliary / draw / draw_pt_fetch.c
index 034e0eccb26e1fb52902eab52ab3da1875d23139..f88a839f61e9fd286ea5c2a0a125c27e7349c57f 100644 (file)
@@ -25,7 +25,8 @@
  *
  **************************************************************************/
 
-#include "pipe/p_util.h"
+#include "util/u_memory.h"
+#include "util/u_math.h"
 #include "draw/draw_context.h"
 #include "draw/draw_private.h"
 #include "draw/draw_vbuf.h"
@@ -41,11 +42,11 @@ struct pt_fetch {
    struct translate *translate;
 
    unsigned vertex_size;
-   boolean need_edgeflags;
 
    struct translate_cache *cache;
 };
 
+
 /* 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.
@@ -56,17 +57,16 @@ struct pt_fetch {
  *
  */
 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;
-   unsigned keysize;
 
    fetch->vertex_size = vertex_size;
-   keysize = (2*4 + 
-              (draw->pt.nr_vertex_elements + 1) * sizeof(key.element[0]));
 
    /* Always emit/leave space for a vertex header.
     *
@@ -81,6 +81,7 @@ void draw_pt_fetch_prepare( struct pt_fetch *fetch,
       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].instance_divisor = 0;
       key.element[nr].output_format = PIPE_FORMAT_R32_FLOAT;
       key.element[nr].output_offset = dst_offset;
       dst_offset += 1 * sizeof(float);
@@ -92,11 +93,15 @@ void draw_pt_fetch_prepare( struct pt_fetch *fetch,
       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 < draw->pt.nr_vertex_elements; i++) {
+   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].instance_divisor = draw->pt.vertex_element[i].instance_divisor;
       key.element[nr].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
       key.element[nr].output_offset = dst_offset;
 
@@ -111,13 +116,18 @@ void draw_pt_fetch_prepare( struct pt_fetch *fetch,
 
 
    if (!fetch->translate ||
-       memcmp(&fetch->translate->key, &key, keysize) != 0)
+       translate_key_compare(&fetch->translate->key, &key) != 0)
    {
-      memset((char *)&key + keysize, 0, sizeof(key) - keysize);
+      translate_key_sanitize(&key);
       fetch->translate = translate_cache_find(fetch->cache, &key);
 
       {
-        static struct vertex_header vh = { 0, 1, 0, 0xffff };
+         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,
@@ -125,9 +135,6 @@ void draw_pt_fetch_prepare( struct pt_fetch *fetch,
       }
    }
 
-   fetch->need_edgeflags = ((draw->rasterizer->fill_cw != PIPE_POLYGON_MODE_FILL ||
-                             draw->rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL) &&
-                            draw->pt.user.edgeflag);
 }
 
 
@@ -147,25 +154,15 @@ void draw_pt_fetch_run( struct pt_fetch *fetch,
                            i, 
                            ((char *)draw->pt.user.vbuffer[i] + 
                             draw->pt.vertex_buffer[i].buffer_offset),
-                           draw->pt.vertex_buffer[i].pitch );
+                           draw->pt.vertex_buffer[i].stride );
    }
 
    translate->run_elts( translate,
                        elts, 
                        count,
+                        draw->instance_id,
                        verts );
 
-   /* Edgeflags are hard to fit into a translate program, populate
-    * them separately if required.  In the setup above they are
-    * defaulted to one, so only need this if there is reason to change
-    * that default:
-    */
-   if (fetch->need_edgeflags) {
-      for (i = 0; i < count; i++) {
-         struct vertex_header *vh = (struct vertex_header *)(verts + i * fetch->vertex_size);
-         vh->edgeflag = draw_pt_get_edgeflag( draw, elts[i] );
-      }
-   }
 }
 
 
@@ -183,25 +180,14 @@ void draw_pt_fetch_run_linear( struct pt_fetch *fetch,
                            i,
                            ((char *)draw->pt.user.vbuffer[i] +
                             draw->pt.vertex_buffer[i].buffer_offset),
-                           draw->pt.vertex_buffer[i].pitch );
+                           draw->pt.vertex_buffer[i].stride );
    }
 
    translate->run( translate,
                    start,
                    count,
+                   draw->instance_id,
                    verts );
-
-   /* Edgeflags are hard to fit into a translate program, populate
-    * them separately if required.  In the setup above they are
-    * defaulted to one, so only need this if there is reason to change
-    * that default:
-    */
-   if (fetch->need_edgeflags) {
-      for (i = 0; i < count; i++) {
-         struct vertex_header *vh = (struct vertex_header *)(verts + i * fetch->vertex_size);
-         vh->edgeflag = draw_pt_get_edgeflag( draw, start + i );
-      }
-   }
 }