gallium: plug in vertex passthrough code
authorBrian <brian.paul@tungstengraphics.com>
Thu, 13 Mar 2008 23:10:28 +0000 (17:10 -0600)
committerBrian <brian.paul@tungstengraphics.com>
Thu, 13 Mar 2008 23:10:28 +0000 (17:10 -0600)
Based on a patch from Zack.
Basically, implement a new draw_arrays function that copies the incoming
user-vertices to the hardware vertex buffer, doing format/type conversion
as needed.
The vertex fetch/store code is totally temporary for now.

src/gallium/auxiliary/draw/Makefile
src/gallium/auxiliary/draw/SConscript
src/gallium/auxiliary/draw/draw_passthrough.c
src/gallium/auxiliary/draw/draw_prim.c

index 2daa1636f36ec4e3dc1402693d868229b29ea237..21e9f737b77fa7697b45758d155d469ef9932f2b 100644 (file)
@@ -15,6 +15,7 @@ C_SOURCES = \
        draw_debug.c \
        draw_flatshade.c \
        draw_offset.c \
+       draw_passthrough.c \
        draw_prim.c \
        draw_pstipple.c \
        draw_stipple.c \
index 5cb7664c85dbc9f1cd10583be500cb0169035dd6..64b444dbd56aa05b125d2b323390bafbaae1ed6f 100644 (file)
@@ -15,6 +15,7 @@ draw = env.ConvenienceLibrary(
                'draw_flatshade.c',
                'draw_offset.c',
                'draw_prim.c',
+               'draw_passthrough.c',
                'draw_pstipple.c',
                'draw_passthrough.c',
                'draw_stipple.c',
index a51fa0ab23cbcbef0de0f5b922086989d9e9c491..d16f056191cef89fd16e6bc3ab7538a596e660e8 100644 (file)
 #include "draw/draw_vertex.h"
 
 
+/**
+ * General-purpose fetch from user's vertex arrays, emit to driver's
+ * vertex buffer.
+ *
+ * XXX this is totally temporary.
+ */
+static void
+fetch_store_general( struct draw_context *draw,
+                     float *out,
+                     unsigned start,
+                     unsigned count )
+{
+   const struct vertex_info *vinfo = draw->render->get_vertex_info(draw->render);
+   const unsigned nr_attrs = vinfo->num_attribs;
+   uint i, j;
+
+   const unsigned *pitch   = draw->vertex_fetch.pitch;
+   const ubyte **src       = draw->vertex_fetch.src_ptr;
+
+   for (i = start; i < count; i++) {
+      for (j = 0; j < nr_attrs; j++) {
+         const uint jj = vinfo->src_index[j];
+         const enum pipe_format srcFormat  = draw->vertex_element[jj].src_format;
+         const ubyte *from = src[jj] + i * pitch[jj];
+         float attrib[4];
+
+         switch (srcFormat) {
+         case PIPE_FORMAT_R32G32B32A32_FLOAT:
+            {
+               float *f = (float *) from;
+               attrib[0] = f[0];
+               attrib[1] = f[1];
+               attrib[2] = f[2];
+               attrib[3] = f[3];
+            }
+            break;
+         case PIPE_FORMAT_R32G32B32_FLOAT:
+            {
+               float *f = (float *) from;
+               attrib[0] = f[0];
+               attrib[1] = f[1];
+               attrib[2] = f[2];
+               attrib[3] = 1.0;
+            }
+            break;
+         case PIPE_FORMAT_R32G32_FLOAT:
+            {
+               float *f = (float *) from;
+               attrib[0] = f[0];
+               attrib[1] = f[1];
+               attrib[2] = 0.0;
+               attrib[3] = 1.0;
+            }
+            break;
+         case PIPE_FORMAT_R32_FLOAT:
+            {
+               float *f = (float *) from;
+               attrib[0] = f[0];
+               attrib[1] = 0.0;
+               attrib[2] = 0.0;
+               attrib[3] = 1.0;
+            }
+            break;
+         default:
+            abort();
+         }
+
+         /* XXX this will probably only work for softpipe */
+         switch (vinfo->emit[j]) {
+         case EMIT_HEADER:
+            memset(out, 0, sizeof(struct vertex_header));
+            out += sizeof(struct vertex_header) / 4;
+            break;
+         case EMIT_4F:
+            out[0] = attrib[0];
+            out[1] = attrib[1];
+            out[2] = attrib[2];
+            out[3] = attrib[3];
+            out += 4;
+            break;
+         default:
+            abort();
+         }
+
+      }
+   }
+}
+
+
 
 /* Example of a fetch/emit passthrough shader which could be
  * generated when bypass_clipping is enabled on a passthrough vertex
@@ -116,7 +205,6 @@ static void fetch_xyz_rgb_st( struct draw_context *draw,
    }
 }
 
-                              
 static boolean update_shader( struct draw_context *draw )
 {
    const struct vertex_info *vinfo = draw->render->get_vertex_info(draw->render);
@@ -143,11 +231,15 @@ static boolean update_shader( struct draw_context *draw )
 
    /* Just trying to figure out how this would work:
     */
-   if (nr_attrs == 3 &&
-       0 /* some other tests */)
+   if (draw->rasterizer->bypass_vs ||
+       (nr_attrs == 3 && 0 /* some other tests */))
    {
+#if 0
       draw->vertex_fetch.pt_fetch = fetch_xyz_rgb_st;
-      assert(vinfo->size == 10);
+#else
+      draw->vertex_fetch.pt_fetch = fetch_store_general;
+#endif
+      /*assert(vinfo->size == 10);*/
       return TRUE;
    }
    
@@ -175,7 +267,6 @@ static boolean set_prim( struct draw_context *draw,
 }
 
 
-
 boolean
 draw_passthrough_arrays(struct draw_context *draw, 
                         unsigned prim,
@@ -184,10 +275,13 @@ draw_passthrough_arrays(struct draw_context *draw,
 {
    float *hw_verts;
 
+   if (draw_need_pipeline(draw))
+      return FALSE;
+
    if (!set_prim(draw, prim))
       return FALSE;
 
-   if (!update_shader( draw ))
+   if (!update_shader(draw))
       return FALSE;
 
    hw_verts = draw->render->allocate_vertices( draw->render,
index 7d6cd43410cabb852772f921767d2afc9a52c59f..ff71ba9b73c54288bc8d6dd01eeb3069047fa7af 100644 (file)
@@ -31,6 +31,7 @@
   */
 
 #include "pipe/p_debug.h"
+#include "pipe/p_util.h"
 
 #include "draw_private.h"
 #include "draw_context.h"
@@ -118,7 +119,42 @@ static void draw_prim_queue_flush( struct draw_context *draw )
    draw_vertex_cache_unreference( draw );
 }
 
+static INLINE void fetch_and_store(struct draw_context *draw)
+{
+   unsigned i;
+
+   /* run vertex shader on vertex cache entries, four per invokation */
+#if 0
+   {
+      const struct vertex_info *vinfo = draw->render->get_vertex_info(draw->render);
+      memcpy(draw->vs.queue[0].vertex, draw->vs.queue[i + j].elt,
+             count * vinfo->size);
+   }
+#elif 0
+   draw_update_vertex_fetch(draw);
+   for (i = 0; i < draw->vs.queue_nr; i += 4) {
+      struct vertex_header *dests[4];
+      unsigned elts[4];
+      struct tgsi_exec_machine *machine = &draw->machine;
+      int j, n = MIN2(4, draw->vs.queue_nr - i);
+
+      for (j = 0; j < n; j++) {
+         elts[j] = draw->vs.queue[i + j].elt;
+         dests[j] = draw->vs.queue[i + j].vertex;
+      }
 
+      for ( ; j < 4; j++) {
+        elts[j] = elts[0];
+         dests[j] = draw->vs.queue[i + j].vertex;
+      }
+      //fetch directly into dests
+      draw->vertex_fetch.fetch_func(draw, machine, dests, count);
+   }
+#endif
+
+   draw->vs.post_nr = draw->vs.queue_nr;
+   draw->vs.queue_nr = 0;
+}
 
 void draw_do_flush( struct draw_context *draw, unsigned flags )
 {
@@ -134,7 +170,10 @@ void draw_do_flush( struct draw_context *draw, unsigned flags )
 
    if (flags >= DRAW_FLUSH_SHADER_QUEUE) {
       if (draw->vs.queue_nr)
-         (*draw->shader_queue_flush)(draw);
+         if (draw->rasterizer->bypass_vs)
+            fetch_and_store(draw);
+         else
+            (*draw->shader_queue_flush)(draw);
 
       if (flags >= DRAW_FLUSH_PRIM_QUEUE) {
         if (draw->pq.queue_nr)
@@ -485,7 +524,11 @@ draw_arrays(struct draw_context *draw, unsigned prim,
    }
 
    /* drawing done here: */
-   draw_prim(draw, prim, start, count);
+   if (!draw->rasterizer->bypass_vs ||
+       !draw_passthrough_arrays(draw, prim, start, count)) {
+      /* we have to run the whole pipeline */
+      draw_prim(draw, prim, start, count);
+   }
 }