[Mesa-dev] [PATCH] draw/softpipe: EXT_transform_feedback support (v1)
Brian Paul
brianp at vmware.com
Thu Jan 5 08:28:49 PST 2012
This looks pretty good to me, though I haven't been following the xfb
work too closely. Just minor comments below.
-Brian
On 01/05/2012 07:17 AM, Dave Airlie wrote:
> From: Dave Airlie<airlied at redhat.com>
>
> This replaces the current code with an implementation compatible with
> the new gallium interface. I've left some of the remains of the interface
> intact so llvmpipe keeps building correctly, and I'll take a look at fixing
> llvmpipe up later.
>
> This passes 119/134 of the piglit EXT_transform_feedback tests, the alignment tests fail due to an unrelated integer vertex fetching bug, need to look into the others later.
>
> Signed-off-by: Dave Airlie<airlied at redhat.com>
> ---
> src/gallium/auxiliary/draw/draw_context.c | 21 +++--
> src/gallium/auxiliary/draw/draw_context.h | 12 +++-
> src/gallium/auxiliary/draw/draw_private.h | 4 +-
> src/gallium/auxiliary/draw/draw_pt_so_emit.c | 112 ++++++++++++++----------
> src/gallium/auxiliary/draw/draw_vbuf.h | 3 +-
> src/gallium/auxiliary/draw/draw_vs_exec.c | 1 +
> src/gallium/drivers/softpipe/sp_context.c | 1 -
> src/gallium/drivers/softpipe/sp_context.h | 12 +--
> src/gallium/drivers/softpipe/sp_draw_arrays.c | 62 ++-----------
> src/gallium/drivers/softpipe/sp_prim_vbuf.c | 11 +--
> src/gallium/drivers/softpipe/sp_query.c | 25 +++++-
> src/gallium/drivers/softpipe/sp_screen.c | 5 +-
> src/gallium/drivers/softpipe/sp_setup.c | 6 +-
> src/gallium/drivers/softpipe/sp_state.h | 3 -
> src/gallium/drivers/softpipe/sp_state_so.c | 118 +++++++-----------------
> 15 files changed, 179 insertions(+), 217 deletions(-)
>
> diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
> index 9c00687..b4acbe1 100644
> --- a/src/gallium/auxiliary/draw/draw_context.c
> +++ b/src/gallium/auxiliary/draw/draw_context.c
> @@ -708,16 +708,25 @@ draw_get_rasterizer_no_cull( struct draw_context *draw,
> }
>
> void
> +draw_set_mapped_so_targets(struct draw_context *draw,
> + int num_targets,
> + struct draw_so_target *targets[PIPE_MAX_SO_BUFFERS])
> +{
> + int i;
> +
> + for (i = 0; i< num_targets; i++)
> + draw->so.targets[i] = targets[i];
> + for (i = num_targets; i< PIPE_MAX_SO_BUFFERS; i++)
> + draw->so.targets[i] = NULL;
> +
> + draw->so.num_targets = num_targets;
> +}
> +
> +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
> diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h
> index 93577d0..6b20130 100644
> --- a/src/gallium/auxiliary/draw/draw_context.h
> +++ b/src/gallium/auxiliary/draw/draw_context.h
> @@ -50,7 +50,11 @@ struct draw_fragment_shader;
> struct tgsi_sampler;
> struct gallivm_state;
>
> -
> +struct draw_so_target {
> + struct pipe_stream_output_target b;
'b' is kind of a strange name, would 'target' be better?
> + void *mapping;
> + int internal_offset;
Is internal_offset in bytes? Maybe add a comment about that.
> +};
>
> struct draw_context *draw_create( struct pipe_context *pipe );
>
> @@ -200,6 +204,12 @@ void
> draw_set_mapped_so_buffers(struct draw_context *draw,
> void *buffers[PIPE_MAX_SO_BUFFERS],
> unsigned num_buffers);
> +
> +void
> +draw_set_mapped_so_targets(struct draw_context *draw,
> + int num_targets,
> + struct draw_so_target *targets[PIPE_MAX_SO_BUFFERS]);
> +
> void
> draw_set_so_state(struct draw_context *draw,
> struct pipe_stream_output_info *state);
> diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
> index 89653e1..b5de5d2 100644
> --- a/src/gallium/auxiliary/draw/draw_private.h
> +++ b/src/gallium/auxiliary/draw/draw_private.h
> @@ -271,8 +271,8 @@ struct draw_context
> /** Stream output (vertex feedback) state */
> struct {
> struct pipe_stream_output_info state;
> - void *buffers[PIPE_MAX_SO_BUFFERS];
> - uint num_buffers;
> + struct draw_so_target *targets[PIPE_MAX_SO_BUFFERS];
> + uint num_targets;
> } so;
>
> /* Clip derived state:
> diff --git a/src/gallium/auxiliary/draw/draw_pt_so_emit.c b/src/gallium/auxiliary/draw/draw_pt_so_emit.c
> index 2dc9e29..241a4a6 100644
> --- a/src/gallium/auxiliary/draw/draw_pt_so_emit.c
> +++ b/src/gallium/auxiliary/draw/draw_pt_so_emit.c
> @@ -25,29 +25,29 @@
> *
> **************************************************************************/
>
> -#include "draw/draw_context.h"
> #include "draw/draw_private.h"
> +#include "draw/draw_vs.h"
> +#include "draw/draw_context.h"
> #include "draw/draw_vbuf.h"
> #include "draw/draw_vertex.h"
> #include "draw/draw_pt.h"
>
> +#include "pipe/p_state.h"
> +
> #include "util/u_math.h"
> #include "util/u_memory.h"
>
A comment on this struct explaining what it's for would be good.
> struct pt_so_emit {
> struct draw_context *draw;
>
> - void *buffers[PIPE_MAX_SO_BUFFERS];
> -
> unsigned input_vertex_stride;
> const float (*inputs)[4];
>
> boolean has_so;
>
> - boolean single_buffer;
> -
> unsigned emitted_primitives;
> unsigned emitted_vertices;
> + unsigned generated_primitives;
> };
>
>
> @@ -55,15 +55,15 @@ void draw_pt_so_emit_prepare(struct pt_so_emit *emit)
> {
> struct draw_context *draw = emit->draw;
>
> - emit->has_so = (draw->so.state.num_outputs> 0);
> + emit->has_so = (draw->vs.vertex_shader->state.stream_output.num_outputs> 0);
>
> /* if we have a state with outputs make sure we have
> * buffers to output to */
The closing */ should go on the next line.
> if (emit->has_so) {
> boolean has_valid_buffer = FALSE;
> unsigned i;
> - for (i = 0; i< draw->so.num_buffers; ++i) {
> - if (draw->so.buffers[i]) {
> + for (i = 0; i< draw->so.num_targets; ++i) {
> + if (draw->so.targets[i]) {
> has_valid_buffer = TRUE;
> break;
> }
> @@ -122,6 +122,29 @@ is_component_writable(unsigned mask,
> }
> }
>
> +static inline int mask_num_comps(int register_mask)
Gallium is still using INLINE.
> +{
> + int comps = 0;
> + switch (register_mask) {
> + case TGSI_WRITEMASK_XYZW:
> + comps = 4;
> + break;
> + case TGSI_WRITEMASK_XYZ:
> + comps = 3;
> + break;
> + case TGSI_WRITEMASK_XY:
> + comps = 2;
> + break;
> + case TGSI_WRITEMASK_X:
> + comps = 1;
> + break;
> + default:
> + assert(0);
> + break;
> + }
> + return comps;
> +}
> +
> static void so_emit_prim(struct pt_so_emit *so,
> unsigned *indices,
> unsigned num_vertices)
> @@ -131,57 +154,56 @@ static void so_emit_prim(struct pt_so_emit *so,
> struct draw_context *draw = so->draw;
> const float (*input_ptr)[4];
> const struct pipe_stream_output_info *state =
> -&draw->so.state;
> - float **buffer = 0;
> +&draw->vs.vertex_shader->state.stream_output;
> + float *buffer;
> + int buffer_total_bytes[PIPE_MAX_SO_BUFFERS];
>
> input_ptr = so->inputs;
>
> + ++so->generated_primitives;
> +
> + for (i = 0; i< draw->so.num_targets; i++) {
> + struct draw_so_target *target = draw->so.targets[i];
> + buffer_total_bytes[i] = target->internal_offset;
> + }
> +
> + /* check have we space to emit prim first - if not don't do anything */
> + for (i = 0; i< num_vertices; ++i) {
> + for (slot = 0; slot< state->num_outputs; ++slot) {
> + unsigned writemask = state->output[slot].register_mask;
> + int ob = state->output[slot].output_buffer;
> +
> + if ((buffer_total_bytes[ob] + mask_num_comps(writemask) * sizeof(float))>
> + draw->so.targets[ob]->b.buffer_size) {
> + return;
> + }
> + buffer_total_bytes[ob] += mask_num_comps(writemask) * sizeof(float);
> + }
> + }
> +
> for (i = 0; i< num_vertices; ++i) {
> const float (*input)[4];
> unsigned total_written_compos = 0;
> /*debug_printf("%d) vertex index = %d (prim idx = %d)\n", i, indices[i], prim_idx);*/
> input = (const float (*)[4])(
> (const char *)input_ptr + (indices[i] * input_vertex_stride));
> +
> for (slot = 0; slot< state->num_outputs; ++slot) {
> unsigned idx = state->output[slot].register_index;
> unsigned writemask = state->output[slot].register_mask;
> unsigned written_compos = 0;
> unsigned compo;
> + int ob = state->output[slot].output_buffer;
>
> - buffer = (float**)&so->buffers[state->output[slot].output_buffer];
> -
> - /*debug_printf("\tSlot = %d, vs_slot = %d, idx = %d:\n",
> - slot, vs_slot, idx);*/
> -#if 1
> - assert(!util_is_inf_or_nan(input[idx][0]));
> - assert(!util_is_inf_or_nan(input[idx][1]));
> - assert(!util_is_inf_or_nan(input[idx][2]));
> - assert(!util_is_inf_or_nan(input[idx][3]));
> -#endif
> + buffer = (float *)((char *)draw->so.targets[ob]->mapping + draw->so.targets[ob]->b.buffer_offset + draw->so.targets[ob]->internal_offset);
> for (compo = 0; compo< 4; ++compo) {
> if (is_component_writable(writemask, compo)) {
> - float *buf = *buffer;
> - buf[written_compos++] = input[idx][compo];
> + buffer[written_compos++] = input[idx][compo];
> }
> }
> -#if 0
> - debug_printf("\t\t(writemask = %d)%f %f %f %f\n",
> - writemask,
> - input[idx][0],
> - input[idx][1],
> - input[idx][2],
> - input[idx][3]);
> -#endif
> - *buffer += written_compos;
> + draw->so.targets[ob]->internal_offset += written_compos * sizeof(float);
> total_written_compos += written_compos;
> }
> - if (so->single_buffer) {
> - int stride = (int)state->stride -
> - sizeof(float) * total_written_compos;
> -
> - debug_assert(stride>= 0);
> - *buffer = (float*) (((char*)*buffer) + stride);
> - }
> }
> so->emitted_vertices += num_vertices;
> ++so->emitted_primitives;
> @@ -235,23 +257,18 @@ void draw_pt_so_emit( struct pt_so_emit *emit,
> {
> struct draw_context *draw = emit->draw;
> struct vbuf_render *render = draw->render;
> + struct pipe_stream_output_info *so;
> unsigned start, i;
>
> if (!emit->has_so)
> return;
>
> + so =&draw->vs.vertex_shader->state.stream_output;
> emit->emitted_vertices = 0;
> emit->emitted_primitives = 0;
> + emit->generated_primitives = 0;
> emit->input_vertex_stride = input_verts->stride;
> emit->inputs = (const float (*)[4])input_verts->verts->data;
> - for (i = 0; i< draw->so.num_buffers; ++i) {
> - emit->buffers[i] = draw->so.buffers[i];
> - }
> - emit->single_buffer = TRUE;
> - for (i = 0; i< draw->so.state.num_outputs; ++i) {
> - if (draw->so.state.output[i].output_buffer != 0)
> - emit->single_buffer = FALSE;
> - }
>
> /* XXX: need to flush to get prim_vbuf.c to release its allocation??*/
> draw_do_flush( draw, DRAW_FLUSH_BACKEND );
> @@ -272,7 +289,8 @@ void draw_pt_so_emit( struct pt_so_emit *emit,
>
> render->set_stream_output_info(render,
> emit->emitted_primitives,
> - emit->emitted_vertices);
> + emit->emitted_vertices,
> + emit->generated_primitives);
> }
>
>
> diff --git a/src/gallium/auxiliary/draw/draw_vbuf.h b/src/gallium/auxiliary/draw/draw_vbuf.h
> index e32803c..6496fe3 100644
> --- a/src/gallium/auxiliary/draw/draw_vbuf.h
> +++ b/src/gallium/auxiliary/draw/draw_vbuf.h
> @@ -124,7 +124,8 @@ struct vbuf_render {
> */
> void (*set_stream_output_info)( struct vbuf_render *vbufr,
> unsigned primitive_count,
> - unsigned vertices_count );
> + unsigned vertices_count,
> + unsigned primitive_generated );
> };
>
>
> diff --git a/src/gallium/auxiliary/draw/draw_vs_exec.c b/src/gallium/auxiliary/draw/draw_vs_exec.c
> index d9c4209..3f89881 100644
> --- a/src/gallium/auxiliary/draw/draw_vs_exec.c
> +++ b/src/gallium/auxiliary/draw/draw_vs_exec.c
> @@ -217,6 +217,7 @@ draw_create_vs_exec(struct draw_context *draw,
>
> tgsi_scan_shader(state->tokens,&vs->base.info);
>
> + vs->base.state.stream_output = state->stream_output;
> vs->base.draw = draw;
> vs->base.prepare = vs_exec_prepare;
> vs->base.run_linear = vs_exec_run_linear;
> diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c
> index a720600..1299384 100644
> --- a/src/gallium/drivers/softpipe/sp_context.c
> +++ b/src/gallium/drivers/softpipe/sp_context.c
> @@ -257,7 +257,6 @@ softpipe_create_context( struct pipe_screen *screen,
> softpipe->pipe.set_framebuffer_state = softpipe_set_framebuffer_state;
>
> softpipe->pipe.draw_vbo = softpipe_draw_vbo;
> - /* XXX softpipe->pipe.draw_stream_output = softpipe_draw_stream_output; */
>
> softpipe->pipe.clear = softpipe_clear;
> softpipe->pipe.flush = softpipe_flush_wrapped;
> diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h
> index 5442aba..c657bd6 100644
> --- a/src/gallium/drivers/softpipe/sp_context.h
> +++ b/src/gallium/drivers/softpipe/sp_context.h
> @@ -55,7 +55,6 @@ struct sp_vertex_shader;
> struct sp_velems_state;
> struct sp_so_state;
>
> -
> struct softpipe_context {
> struct pipe_context pipe; /**< base class */
>
> @@ -88,13 +87,12 @@ struct softpipe_context {
> struct pipe_viewport_state viewport;
> struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
> struct pipe_index_buffer index_buffer;
> - struct {
> - struct softpipe_resource *buffer[PIPE_MAX_SO_BUFFERS];
> - int offset[PIPE_MAX_SO_BUFFERS];
> - int so_count[PIPE_MAX_SO_BUFFERS];
> - int num_buffers;
> - } so_target;
> +
> + struct draw_so_target *so_targets[PIPE_MAX_SO_BUFFERS];
> + int num_so_targets;
> +
> struct pipe_query_data_so_statistics so_stats;
> + unsigned num_primitives_generated;
>
> unsigned num_fragment_samplers;
> unsigned num_fragment_sampler_views;
> diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c
> index 69b5b96..10b625c 100644
> --- a/src/gallium/drivers/softpipe/sp_draw_arrays.c
> +++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c
> @@ -43,58 +43,6 @@
>
> #include "draw/draw_context.h"
>
> -
> -
> -
> -
> -void
> -softpipe_draw_stream_output(struct pipe_context *pipe, unsigned mode)
> -{
> - struct softpipe_context *sp = softpipe_context(pipe);
> - struct draw_context *draw = sp->draw;
> - const unsigned start = 0;
> - const unsigned count = sp->so_target.so_count[0];
> - void *buf = sp->so_target.buffer[0]->data;
> - int offset = sp->so_target.offset[0];
> -
> - if (!softpipe_check_render_cond(sp) ||
> - sp->so_target.num_buffers != 1)
> - return;
> -
> - sp->reduced_api_prim = u_reduced_prim(mode);
> -
> - if (sp->dirty) {
> - softpipe_update_derived(sp, sp->reduced_api_prim);
> - }
> -
> - softpipe_map_transfers(sp);
> -
> - /* Map so buffers */
> - if (offset< 0) /* we were appending so start from beginning */
> - offset = 0;
> - buf = (void*)((int32_t*)buf + offset);
> - draw_set_mapped_vertex_buffer(draw, 0, buf);
> -
> - draw_set_mapped_index_buffer(draw, NULL);
> -
> - /* draw! */
> - draw_arrays(draw, mode, start, count);
> -
> - /* unmap vertex/index buffers - will cause draw module to flush */
> - draw_set_mapped_vertex_buffer(draw, 0, NULL);
> -
> - /*
> - * TODO: Flush only when a user vertex/index buffer is present
> - * (or even better, modify draw module to do this
> - * internally when this condition is seen?)
> - */
> - draw_flush(draw);
> -
> - /* Note: leave drawing surfaces mapped */
> - sp->dirty_render_cache = TRUE;
> -}
> -
> -
> /**
> * This function handles drawing indexed and non-indexed prims,
> * instanced and non-instanced drawing, with or without min/max element
> @@ -139,6 +87,14 @@ softpipe_draw_vbo(struct pipe_context *pipe,
>
> draw_set_mapped_index_buffer(draw, mapped_indices);
>
> + for (i = 0; i< sp->num_so_targets; i++) {
> + void *buf = softpipe_resource(sp->so_targets[i]->b.buffer)->data;
> + sp->so_targets[i]->mapping = buf;
> + }
> +
> + draw_set_mapped_so_targets(draw, sp->num_so_targets,
> + sp->so_targets);
> +
> /* draw! */
> draw_vbo(draw, info);
>
> @@ -150,6 +106,8 @@ softpipe_draw_vbo(struct pipe_context *pipe,
> draw_set_mapped_index_buffer(draw, NULL);
> }
>
> + draw_set_mapped_so_targets(draw, 0, NULL);
> +
> /*
> * TODO: Flush only when a user vertex/index buffer is present
> * (or even better, modify draw module to do this
> diff --git a/src/gallium/drivers/softpipe/sp_prim_vbuf.c b/src/gallium/drivers/softpipe/sp_prim_vbuf.c
> index c60249d..acc7e45 100644
> --- a/src/gallium/drivers/softpipe/sp_prim_vbuf.c
> +++ b/src/gallium/drivers/softpipe/sp_prim_vbuf.c
> @@ -543,19 +543,16 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
> }
>
> static void
> -sp_vbuf_so_info(struct vbuf_render *vbr, uint primitives, uint vertices)
> +sp_vbuf_so_info(struct vbuf_render *vbr, uint primitives, uint vertices,
> + uint prim_generated)
> {
> struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
> struct softpipe_context *softpipe = cvbr->softpipe;
> - unsigned i;
> -
> - for (i = 0; i< softpipe->so_target.num_buffers; ++i) {
> - softpipe->so_target.so_count[i] += vertices;
> - }
>
> - softpipe->so_stats.num_primitives_written = primitives;
> + softpipe->so_stats.num_primitives_written += primitives;
> softpipe->so_stats.primitives_storage_needed =
> vertices * 4 /*sizeof(float|int32)*/ * 4 /*x,y,z,w*/;
> + softpipe->num_primitives_generated += prim_generated;
> }
>
>
> diff --git a/src/gallium/drivers/softpipe/sp_query.c b/src/gallium/drivers/softpipe/sp_query.c
> index c2c48e8..2e54e02 100644
> --- a/src/gallium/drivers/softpipe/sp_query.c
> +++ b/src/gallium/drivers/softpipe/sp_query.c
> @@ -42,6 +42,7 @@ struct softpipe_query {
> uint64_t start;
> uint64_t end;
> struct pipe_query_data_so_statistics so;
> + unsigned num_primitives_generated;
> };
>
>
> @@ -59,6 +60,8 @@ softpipe_create_query(struct pipe_context *pipe,
> assert(type == PIPE_QUERY_OCCLUSION_COUNTER ||
> type == PIPE_QUERY_TIME_ELAPSED ||
> type == PIPE_QUERY_SO_STATISTICS ||
> + type == PIPE_QUERY_PRIMITIVES_EMITTED ||
> + type == PIPE_QUERY_PRIMITIVES_GENERATED ||
> type == PIPE_QUERY_GPU_FINISHED ||
> type == PIPE_QUERY_TIMESTAMP ||
> type == PIPE_QUERY_TIMESTAMP_DISJOINT);
> @@ -91,8 +94,14 @@ softpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
> sq->start = 1000*os_time_get();
> break;
> case PIPE_QUERY_SO_STATISTICS:
> - sq->so.num_primitives_written = 0;
> sq->so.primitives_storage_needed = 0;
> + case PIPE_QUERY_PRIMITIVES_EMITTED:
> + sq->so.num_primitives_written = 0;
> + softpipe->so_stats.num_primitives_written = 0;
> + break;
> + case PIPE_QUERY_PRIMITIVES_GENERATED:
> + sq->num_primitives_generated = 0;
> + softpipe->num_primitives_generated = 0;
> break;
> case PIPE_QUERY_TIMESTAMP:
> case PIPE_QUERY_GPU_FINISHED:
> @@ -125,10 +134,14 @@ softpipe_end_query(struct pipe_context *pipe, struct pipe_query *q)
> sq->end = 1000*os_time_get();
> break;
> case PIPE_QUERY_SO_STATISTICS:
> - sq->so.num_primitives_written =
> - softpipe->so_stats.num_primitives_written;
> sq->so.primitives_storage_needed =
> softpipe->so_stats.primitives_storage_needed;
> + case PIPE_QUERY_PRIMITIVES_EMITTED:
> + sq->so.num_primitives_written =
> + softpipe->so_stats.num_primitives_written;
> + break;
> + case PIPE_QUERY_PRIMITIVES_GENERATED:
> + sq->num_primitives_generated = softpipe->num_primitives_generated;
> break;
> case PIPE_QUERY_GPU_FINISHED:
> break;
> @@ -166,6 +179,12 @@ softpipe_get_query_result(struct pipe_context *pipe,
> sizeof(struct pipe_query_data_timestamp_disjoint));
> }
> break;
> + case PIPE_QUERY_PRIMITIVES_EMITTED:
> + *result = sq->so.num_primitives_written;
> + break;
> + case PIPE_QUERY_PRIMITIVES_GENERATED:
> + *result = sq->num_primitives_generated;
> + break;
> default:
> *result = sq->end - sq->start;
> break;
> diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c
> index e58a486..8e88bb5 100644
> --- a/src/gallium/drivers/softpipe/sp_screen.c
> +++ b/src/gallium/drivers/softpipe/sp_screen.c
> @@ -106,7 +106,10 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
> case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
> return 1;
> case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
> - return 0;
> + return 4;
s/4/PIPE_MAX_SO_BUFFERS/?
BTW, is PIPE_MAX_SO_BUFFERS enough? I know that's the min required
for GL_EXT_transform_feedback, but I wonder what other GLs advertise
and what hardware typically supports.
> + case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
> + case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
> + return 16*4;
> case PIPE_CAP_PRIMITIVE_RESTART:
> return 1;
> case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE:
> diff --git a/src/gallium/drivers/softpipe/sp_setup.c b/src/gallium/drivers/softpipe/sp_setup.c
> index 656d001..0d67af3 100644
> --- a/src/gallium/drivers/softpipe/sp_setup.c
> +++ b/src/gallium/drivers/softpipe/sp_setup.c
> @@ -807,7 +807,7 @@ sp_setup_tri(struct setup_context *setup,
> print_vertex(setup, v2);
> #endif
>
> - if (setup->softpipe->no_rast)
> + if (setup->softpipe->no_rast || setup->softpipe->rasterizer->rasterizer_discard)
> return;
>
> det = calc_det(v0, v1, v2);
> @@ -1073,7 +1073,7 @@ sp_setup_line(struct setup_context *setup,
> print_vertex(setup, v1);
> #endif
>
> - if (setup->softpipe->no_rast)
> + if (setup->softpipe->no_rast || setup->softpipe->rasterizer->rasterizer_discard)
> return;
>
> if (dx == 0&& dy == 0)
> @@ -1206,7 +1206,7 @@ sp_setup_point(struct setup_context *setup,
> print_vertex(setup, v0);
> #endif
>
> - if (softpipe->no_rast)
> + if (setup->softpipe->no_rast || setup->softpipe->rasterizer->rasterizer_discard)
> return;
>
> assert(setup->softpipe->reduced_prim == PIPE_PRIM_POINTS);
> diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h
> index bdda294..6df40c6 100644
> --- a/src/gallium/drivers/softpipe/sp_state.h
> +++ b/src/gallium/drivers/softpipe/sp_state.h
> @@ -159,9 +159,6 @@ softpipe_draw_vbo(struct pipe_context *pipe,
> const struct pipe_draw_info *info);
>
> void
> -softpipe_draw_stream_output(struct pipe_context *pipe, unsigned mode);
> -
> -void
> softpipe_map_transfers(struct softpipe_context *sp);
>
> void
> diff --git a/src/gallium/drivers/softpipe/sp_state_so.c b/src/gallium/drivers/softpipe/sp_state_so.c
> index 31ef384..7abaa1a 100644
> --- a/src/gallium/drivers/softpipe/sp_state_so.c
> +++ b/src/gallium/drivers/softpipe/sp_state_so.c
> @@ -32,109 +32,61 @@
> #include "util/u_format.h"
> #include "util/u_memory.h"
> #include "draw/draw_context.h"
> +#include "pipebuffer/pb_buffer.h"
>
> -
> -static void *
> -softpipe_create_stream_output_state(struct pipe_context *pipe,
> - const struct pipe_stream_output_info *templ)
> -{
> - struct sp_so_state *so;
> - so = (struct sp_so_state *) CALLOC_STRUCT(sp_so_state);
> -
> - if (so) {
> - so->base.num_outputs = templ->num_outputs;
> - so->base.stride = templ->stride;
> - memcpy(so->base.output, templ->output,
> - templ->num_outputs * sizeof(templ->output[0]));
> - }
> - return so;
> -}
> -
> -
> -static void
> -softpipe_bind_stream_output_state(struct pipe_context *pipe,
> - void *so)
> +static struct pipe_stream_output_target *
> +softpipe_create_so_target(struct pipe_context *pipe,
> + struct pipe_resource *buffer,
> + unsigned buffer_offset,
> + unsigned buffer_size)
> {
> - struct softpipe_context *softpipe = softpipe_context(pipe);
> - struct sp_so_state *sp_so = (struct sp_so_state *) so;
> -
> - softpipe->so = sp_so;
> -
> - softpipe->dirty |= SP_NEW_SO;
> -
> - if (sp_so)
> - draw_set_so_state(softpipe->draw,&sp_so->base);
> + struct draw_so_target *t;
> +
> + t = CALLOC_STRUCT(draw_so_target);
> + t->b.context = pipe;
> + t->b.reference.count = 1;
> + pipe_resource_reference(&t->b.buffer, buffer);
> + t->b.buffer_offset = buffer_offset;
> + t->b.buffer_size = buffer_size;
> + return&t->b;
> }
>
> -
> -static void
> -softpipe_delete_stream_output_state(struct pipe_context *pipe, void *so)
> +static void softpipe_so_target_destroy(struct pipe_context *pipe,
> + struct pipe_stream_output_target *target)
Lets keep the formatting like:
static void
softpipe_so_target_destroy(...)
To be consistent.
> {
> - FREE( so );
> + struct pipe_stream_output_target *b = target;
> + pipe_resource_reference(&b->buffer, NULL);
> + FREE(b);
Why isn't that written as
pipe_resource_reference(&target->buffer, NULL);
FREE(target);
> }
>
> -
> -static void
> -softpipe_set_stream_output_buffers(struct pipe_context *pipe,
> - struct pipe_resource **buffers,
> - int *offsets,
> - int num_buffers)
> +static void softpipe_set_so_targets(struct pipe_context *pipe,
> + unsigned num_targets,
> + struct pipe_stream_output_target **targets,
> + unsigned append_bitmask)
> {
> struct softpipe_context *softpipe = softpipe_context(pipe);
> int i;
> - void *map_buffers[PIPE_MAX_SO_BUFFERS];
> -
> - assert(num_buffers<= PIPE_MAX_SO_BUFFERS);
> - if (num_buffers> PIPE_MAX_SO_BUFFERS)
> - num_buffers = PIPE_MAX_SO_BUFFERS;
> -
> - softpipe->dirty |= SP_NEW_SO_BUFFERS;
>
> - for (i = 0; i< num_buffers; ++i) {
> - void *mapped;
> - struct softpipe_resource *res = softpipe_resource(buffers[i]);
> + if (softpipe->num_so_targets) {
>
> - if (!res) {
> - /* the whole call is invalid, bail out */
> - softpipe->so_target.num_buffers = 0;
> - draw_set_mapped_so_buffers(softpipe->draw, 0, 0);
> - return;
> - }
> + }
Maybe I'm misreading the patch here, but that looks like an empty
conditional.
>
> - softpipe->so_target.buffer[i] = res;
> - softpipe->so_target.offset[i] = offsets[i];
> - softpipe->so_target.so_count[i] = 0;
> + for (i = 0; i< num_targets; i++) {
> + pipe_so_target_reference((struct pipe_stream_output_target **)&softpipe->so_targets[i], targets[i]);
> + }
>
> - mapped = res->data;
> - if (offsets[i]>= 0)
> - map_buffers[i] = ((char*)mapped) + offsets[i];
> - else {
> - /* this is a buffer append */
> - assert(!"appending not implemented");
> - map_buffers[i] = mapped;
> - }
> + for (; i< softpipe->num_so_targets; i++) {
> + pipe_so_target_reference((struct pipe_stream_output_target **)&softpipe->so_targets[i], NULL);
> }
> - softpipe->so_target.num_buffers = num_buffers;
>
> - draw_set_mapped_so_buffers(softpipe->draw, map_buffers, num_buffers);
> + softpipe->num_so_targets = num_targets;
> }
>
> -
> -
> void
> softpipe_init_streamout_funcs(struct pipe_context *pipe)
> {
> -#if 0
> - pipe->create_stream_output_state = softpipe_create_stream_output_state;
> - pipe->bind_stream_output_state = softpipe_bind_stream_output_state;
> - pipe->delete_stream_output_state = softpipe_delete_stream_output_state;
> -
> - pipe->set_stream_output_buffers = softpipe_set_stream_output_buffers;
> -#else
> - (void) softpipe_create_stream_output_state;
> - (void) softpipe_bind_stream_output_state;
> - (void) softpipe_delete_stream_output_state;
> - (void) softpipe_set_stream_output_buffers;
> -#endif
> + pipe->create_stream_output_target = softpipe_create_so_target;
> + pipe->stream_output_target_destroy = softpipe_so_target_destroy;
> + pipe->set_stream_output_targets = softpipe_set_so_targets;
> }
>
More information about the mesa-dev
mailing list