From a45b7f47ee0e38b288cc8fc4f6a1c013e8c227bc Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Fri, 28 May 2010 13:14:07 -0400 Subject: [PATCH] gallium: basic and initial implementation of the stream output interface aka transform feedback --- src/gallium/auxiliary/draw/draw_context.c | 22 +++++++++ src/gallium/auxiliary/draw/draw_context.h | 8 ++++ src/gallium/auxiliary/draw/draw_private.h | 6 +++ src/gallium/auxiliary/draw/draw_pt_emit.c | 75 +++++++++++++++++++++++++++++++ src/gallium/drivers/softpipe/SConscript | 1 + src/gallium/drivers/softpipe/sp_context.c | 6 ++- src/gallium/drivers/softpipe/sp_context.h | 2 + src/gallium/drivers/softpipe/sp_state.h | 21 +++++++++ src/gallium/include/pipe/p_context.h | 12 +++++ src/gallium/include/pipe/p_defines.h | 2 + src/gallium/include/pipe/p_state.h | 7 +++ 11 files changed, 161 insertions(+), 1 deletion(-) diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c index 61980c3..7c77025 100644 --- a/src/gallium/auxiliary/draw/draw_context.c +++ b/src/gallium/auxiliary/draw/draw_context.c @@ -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)); +} diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h index b905c2f..103d653 100644 --- a/src/gallium/auxiliary/draw/draw_context.h +++ b/src/gallium/auxiliary/draw/draw_context.h @@ -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 diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h index a2bfb69..ca8f9cf 100644 --- a/src/gallium/auxiliary/draw/draw_private.h +++ b/src/gallium/auxiliary/draw/draw_private.h @@ -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]; diff --git a/src/gallium/auxiliary/draw/draw_pt_emit.c b/src/gallium/auxiliary/draw/draw_pt_emit.c index f623c07..3b42372 100644 --- a/src/gallium/auxiliary/draw/draw_pt_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_emit.c @@ -33,11 +33,13 @@ #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++) { diff --git a/src/gallium/drivers/softpipe/SConscript b/src/gallium/drivers/softpipe/SConscript index b80c6de..be5917a 100644 --- a/src/gallium/drivers/softpipe/SConscript +++ b/src/gallium/drivers/softpipe/SConscript @@ -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', diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c index 2f10b46..b197014 100644 --- a/src/gallium/drivers/softpipe/sp_context.c +++ b/src/gallium/drivers/softpipe/sp_context.c @@ -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; diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h index b3d3fe6..f8ffc57 100644 --- a/src/gallium/drivers/softpipe/sp_context.h +++ b/src/gallium/drivers/softpipe/sp_context.h @@ -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; diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h index 5b0faab..dd958eb 100644 --- a/src/gallium/drivers/softpipe/sp_state.h +++ b/src/gallium/drivers/softpipe/sp_state.h @@ -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 diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h index 3e082be..0267ed8 100644 --- a/src/gallium/include/pipe/p_context.h +++ b/src/gallium/include/pipe/p_context.h @@ -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); + /*@}*/ diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index b006774..be42c27 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -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 diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h index 5255b20..33ee066 100644 --- a/src/gallium/include/pipe/p_state.h +++ b/src/gallium/include/pipe/p_state.h @@ -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. -- 2.7.4