gallium: basic and initial implementation of the stream output interface
authorZack Rusin <zack@kde.org>
Fri, 28 May 2010 17:14:07 +0000 (13:14 -0400)
committerZack Rusin <zackr@vmware.com>
Tue, 8 Jun 2010 10:28:10 +0000 (06:28 -0400)
aka transform feedback

src/gallium/auxiliary/draw/draw_context.c
src/gallium/auxiliary/draw/draw_context.h
src/gallium/auxiliary/draw/draw_private.h
src/gallium/auxiliary/draw/draw_pt_emit.c
src/gallium/drivers/softpipe/SConscript
src/gallium/drivers/softpipe/sp_context.c
src/gallium/drivers/softpipe/sp_context.h
src/gallium/drivers/softpipe/sp_state.h
src/gallium/include/pipe/p_context.h
src/gallium/include/pipe/p_defines.h
src/gallium/include/pipe/p_state.h

index 61980c3e4f54901a9a67eb2337bd32baca09abf8..7c7702549e09d0fe1a06cacf1eea034fb50d82fd 100644 (file)
@@ -574,3 +574,25 @@ draw_get_rasterizer_no_cull( struct draw_context *draw,
    }
    return draw->rasterizer_no_cull[scissor][flatshade];
 }
+
+void
+draw_set_mapped_so_buffers(struct draw_context *draw,
+                           void *buffers[PIPE_MAX_SO_BUFFERS],
+                           unsigned num_buffers)
+{
+   int i;
+
+   for (i = 0; i < num_buffers; ++i) {
+      draw->so.buffers[i] = buffers[i];
+   }
+   draw->so.num_buffers = num_buffers;
+}
+
+void
+draw_set_so_state(struct draw_context *draw,
+                  struct pipe_stream_output_state *state)
+{
+   memcpy(&draw->so.state,
+          state,
+          sizeof(struct pipe_stream_output_state));
+}
index b905c2f2da6c91146053b8613c769da8c195342f..103d6538b8156ae3b50a36b7f8d3da19ab96d5e3 100644 (file)
@@ -162,6 +162,14 @@ draw_set_mapped_constant_buffer(struct draw_context *draw,
                                 const void *buffer,
                                 unsigned size);
 
+void
+draw_set_mapped_so_buffers(struct draw_context *draw,
+                           void *buffers[PIPE_MAX_SO_BUFFERS],
+                           unsigned num_buffers);
+void
+draw_set_so_state(struct draw_context *draw,
+                  struct pipe_stream_output_state *state);
+
 
 /***********************************************************************
  * draw_prim.c 
index a2bfb693c098c615a521da2c3e08183c0ae674a8..ca8f9cfab1eb13bff4138330efaa8603ba666492 100644 (file)
@@ -235,6 +235,12 @@ struct draw_context
       struct tgsi_sampler **samplers;
    } gs;
 
+   struct {
+      struct pipe_stream_output_state state;
+      void *buffers[PIPE_MAX_SO_BUFFERS];
+      uint num_buffers;
+   } so;
+
    /* Clip derived state:
     */
    float plane[12][4];
index f623c0743da17160c342ef3ca885c5042758e956..3b4237245e6fe97439a24983948c69bc652312b0 100644 (file)
 #include "draw/draw_pt.h"
 #include "translate/translate.h"
 #include "translate/translate_cache.h"
+#include "util/u_format.h"
 
 struct pt_emit {
    struct draw_context *draw;
 
    struct translate *translate;
+   struct translate *so_translate;
 
    struct translate_cache *cache;
    unsigned prim;
@@ -45,6 +47,51 @@ struct pt_emit {
    const struct vertex_info *vinfo;
 };
 
+static void
+prepare_so_emit( struct pt_emit *emit,
+                 const struct vertex_info *vinfo )
+{
+   struct draw_context *draw = emit->draw;
+   unsigned i;
+   struct translate_key hw_key;
+   unsigned dst_offset = 0;
+   unsigned output_stride = 0;
+   boolean has_so = (draw->so.state.num_outputs > 0);
+
+   if (has_so) {
+
+      for (i = 0; i < draw->so.state.num_outputs; ++i) {
+         unsigned src_offset = (vinfo->attrib[i].src_index * 4 * sizeof(float) );
+         unsigned output_format = draw->so.state.format[i];
+         unsigned output_bytes = util_format_get_blocksize(output_format);
+
+         hw_key.element[i].type = TRANSLATE_ELEMENT_NORMAL;
+         hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+         hw_key.element[i].input_buffer = 0;
+         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 += output_bytes;
+         output_stride += output_bytes;
+      }
+      hw_key.nr_elements = draw->so.state.num_outputs;
+      hw_key.output_stride = output_stride;
+
+      if (!emit->so_translate ||
+          translate_key_compare(&emit->so_translate->key, &hw_key) != 0)
+      {
+         translate_key_sanitize(&hw_key);
+         emit->so_translate = translate_cache_find(emit->cache, &hw_key);
+      }
+   } else {
+      /* no stream output */
+      emit->so_translate = NULL;
+   }
+}
+
+
 void draw_pt_emit_prepare( struct pt_emit *emit,
                           unsigned prim,
                            unsigned *max_vertices )
@@ -121,6 +168,8 @@ void draw_pt_emit_prepare( struct pt_emit *emit,
    *max_vertices = (draw->render->max_vertex_buffer_bytes / 
                     (vinfo->size * 4));
 
+   prepare_so_emit( emit, vinfo );
+
    /* even number */
    *max_vertices = *max_vertices & ~1;
 }
@@ -135,6 +184,7 @@ void draw_pt_emit( struct pt_emit *emit,
 {
    struct draw_context *draw = emit->draw;
    struct translate *translate = emit->translate;
+   struct translate *so_translate = emit->so_translate;
    struct vbuf_render *render = draw->render;
    void *hw_verts;
 
@@ -186,6 +236,18 @@ void draw_pt_emit( struct pt_emit *emit,
                    draw->instance_id,
                   hw_verts );
 
+   if (so_translate) {
+      void *so_buffer = draw->so.buffers[0];
+
+      /* XXX we only support single output buffer right now */
+      debug_assert(draw->so.num_buffers >= 0);
+
+      so_translate->set_buffer(translate, 0, vertex_data,
+                               stride, ~0);
+      so_translate->run(translate, 0, vertex_count,
+                        draw->instance_id, so_buffer);
+   }
+
    render->unmap_vertices( render, 
                            0, 
                            vertex_count - 1 );
@@ -205,6 +267,7 @@ void draw_pt_emit_linear(struct pt_emit *emit,
 {
    struct draw_context *draw = emit->draw;
    struct translate *translate = emit->translate;
+   struct translate *so_translate = emit->so_translate;
    struct vbuf_render *render = draw->render;
    void *hw_verts;
 
@@ -246,6 +309,18 @@ void draw_pt_emit_linear(struct pt_emit *emit,
                   draw->instance_id,
                   hw_verts);
 
+   if (so_translate) {
+      void *so_buffer = draw->so.buffers[0];
+
+      /* XXX we only support single output buffer right now */
+      debug_assert(draw->so.num_buffers >= 0);
+
+      so_translate->set_buffer(translate, 0,
+                               vertex_data, stride, count - 1);
+      so_translate->run(translate, 0, count,
+                        draw->instance_id, so_buffer);
+   }
+
    if (0) {
       unsigned i;
       for (i = 0; i < count; i++) {
index b80c6dea93a9d9bf1f29d624944eeca402534a1f..be5917a688648ab8a0841ed92c63646fbb680258 100644 (file)
@@ -27,6 +27,7 @@ softpipe = env.ConvenienceLibrary(
                'sp_state_fs.c',
                'sp_state_rasterizer.c',
                'sp_state_sampler.c',
+               'sp_state_so.c',
                'sp_state_surface.c',
                'sp_state_vertex.c',
                'sp_surface.c',
index 2f10b46e9898e3c916646a894aa4f044f2f7e964..b1970140d5037e2b1c80b49305e2d9635959f567 100644 (file)
@@ -251,6 +251,10 @@ softpipe_create_context( struct pipe_screen *screen,
    softpipe->pipe.bind_vertex_elements_state = softpipe_bind_vertex_elements_state;
    softpipe->pipe.delete_vertex_elements_state = softpipe_delete_vertex_elements_state;
 
+   softpipe->pipe.create_stream_output_state = softpipe_create_stream_output_state;
+   softpipe->pipe.bind_stream_output_state = softpipe_bind_stream_output_state;
+   softpipe->pipe.delete_stream_output_state = softpipe_delete_stream_output_state;
+
    softpipe->pipe.set_blend_color = softpipe_set_blend_color;
    softpipe->pipe.set_stencil_ref = softpipe_set_stencil_ref;
    softpipe->pipe.set_clip_state = softpipe_set_clip_state;
@@ -264,7 +268,7 @@ softpipe_create_context( struct pipe_screen *screen,
    softpipe->pipe.create_sampler_view = softpipe_create_sampler_view;
    softpipe->pipe.sampler_view_destroy = softpipe_sampler_view_destroy;
    softpipe->pipe.set_viewport_state = softpipe_set_viewport_state;
-
+   softpipe->pipe.set_stream_output_buffers = softpipe_set_stream_output_buffers;
    softpipe->pipe.set_vertex_buffers = softpipe_set_vertex_buffers;
 
    softpipe->pipe.draw_arrays = softpipe_draw_arrays;
index b3d3fe620fd794ab2160f330ecbfab651199b924..f8ffc5787d365f2e949182bd6861605be01ff338 100644 (file)
@@ -50,6 +50,7 @@ struct softpipe_tex_tile_cache;
 struct sp_fragment_shader;
 struct sp_vertex_shader;
 struct sp_velems_state;
+struct sp_so_state;
 
 
 struct softpipe_context {
@@ -65,6 +66,7 @@ struct softpipe_context {
    struct sp_vertex_shader *vs;
    struct sp_geometry_shader *gs;
    struct sp_velems_state *velems;
+   struct sp_so_state *so;
 
    /** Other rendering state */
    struct pipe_blend_color blend_color;
index 5b0faabeaef48d2db2ff542da11ccb86ebd20723..dd958ebb53ed14881301d4f140098e2aee344e7a 100644 (file)
@@ -51,6 +51,8 @@
 #define SP_NEW_VS            0x2000
 #define SP_NEW_QUERY         0x4000
 #define SP_NEW_GS            0x8000
+#define SP_NEW_SO            0x10000
+#define SP_NEW_SO_BUFFERS    0x20000
 
 
 struct tgsi_sampler;
@@ -105,6 +107,10 @@ struct sp_velems_state {
    struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS];
 };
 
+struct sp_so_state {
+   struct pipe_stream_output_state base;
+};
+
 
 void *
 softpipe_create_blend_state(struct pipe_context *,
@@ -263,5 +269,20 @@ softpipe_get_vertex_info(struct softpipe_context *softpipe);
 struct vertex_info *
 softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe);
 
+void *
+softpipe_create_stream_output_state(
+   struct pipe_context *pipe,
+   const struct pipe_stream_output_state *templ);
+void
+softpipe_bind_stream_output_state(struct pipe_context *pipe,
+                                  void *so);
+void
+softpipe_delete_stream_output_state(struct pipe_context *pipe, void *so);
+
+void
+softpipe_set_stream_output_buffers(struct pipe_context *pipe,
+                                   struct pipe_resource **buffers,
+                                   int *offsets,
+                                   int num_buffers);
 
 #endif
index 3e082bef2ffefc6734045b28de6d6849faaf2438..0267ed8fa4a8fd19f10af2aa3baa5371618a3f73 100644 (file)
@@ -186,6 +186,11 @@ struct pipe_context {
    void   (*bind_vertex_elements_state)(struct pipe_context *, void *);
    void   (*delete_vertex_elements_state)(struct pipe_context *, void *);
 
+   void * (*create_stream_output_state)(struct pipe_context *,
+                                        const struct pipe_stream_output_state *);
+   void   (*bind_stream_output_state)(struct pipe_context *, void *);
+   void   (*delete_stream_output_state)(struct pipe_context*, void*);
+
    /*@}*/
 
    /**
@@ -232,6 +237,13 @@ struct pipe_context {
                                unsigned num_buffers,
                                const struct pipe_vertex_buffer * );
 
+   void (*set_stream_output_buffers)(struct pipe_context *,
+                                     struct pipe_resource **buffers,
+                                     int *offsets, /*array of offsets
+                                                     from the start of each
+                                                     of the buffers */
+                                     int num_buffers);
+
    /*@}*/
 
 
index b00677425ce20b110ac227acb76552fcb29a95ca..be42c2722212fc3ebeee12340418cddcfadf5a18 100644 (file)
@@ -288,6 +288,7 @@ enum pipe_transfer_usage {
 #define PIPE_BIND_DISPLAY_TARGET       (1 << 8) /* flush_front_buffer */
 #define PIPE_BIND_TRANSFER_WRITE       (1 << 9) /* get_transfer */
 #define PIPE_BIND_TRANSFER_READ        (1 << 10) /* get_transfer */
+#define PIPE_BIND_STREAM_OUTPUT        (1 << 11) /* set_stream_output_buffers */
 #define PIPE_BIND_CUSTOM               (1 << 16) /* state-tracker/winsys usages */
 
 /* The first two flags above were previously part of the amorphous
@@ -322,6 +323,7 @@ enum pipe_transfer_usage {
 #define PIPE_USAGE_STATIC         2 /* same as immutable?? */
 #define PIPE_USAGE_IMMUTABLE      3 /* no change after first upload */
 #define PIPE_USAGE_STREAM         4 /* upload, draw, upload, draw */
+#define PIPE_USAGE_STAGING        5 /* supports data transfers from the GPU to the CPU */
 
 
 /* These are intended to be used in calls to is_format_supported, but
index 5255b2003f8d5b0d823af80bcffb31467058b65d..33ee066c0c95851028c919f7457cee7ec68931ed 100644 (file)
@@ -63,6 +63,7 @@ extern "C" {
 #define PIPE_MAX_SHADER_INPUTS    16
 #define PIPE_MAX_SHADER_OUTPUTS   16
 #define PIPE_MAX_TEXTURE_LEVELS   16
+#define PIPE_MAX_SO_BUFFERS        4
 
 
 struct pipe_reference
@@ -345,6 +346,12 @@ struct pipe_resource
    unsigned flags;          /**< bitmask of PIPE_RESOURCE_FLAG_x */
 };
 
+struct pipe_stream_output_state
+{
+   /**< format for each output */
+   enum pipe_format format[PIPE_MAX_SHADER_OUTPUTS];
+   int num_outputs;
+};
 
 /**
  * Extra indexing info for (cube) texture resources.