From: Dave Airlie Date: Wed, 27 May 2015 07:39:05 +0000 (+1000) Subject: draw: add support to tgsi paths for geometry streams. (v2) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7720ce32a;p=mesa.git draw: add support to tgsi paths for geometry streams. (v2) This hooks up the geometry shader processing to the TGSI support added in the previous commits. It doesn't change the llvm interface other than to keep things building. v2: fix some regressions caused by primitiveoffsets Reviewed-by: Roland Scheidegger Signed-off-by: Dave Airlie --- diff --git a/src/gallium/auxiliary/draw/draw_gs.c b/src/gallium/auxiliary/draw/draw_gs.c index 7664ecf8f3a..1d6040993c6 100644 --- a/src/gallium/auxiliary/draw/draw_gs.c +++ b/src/gallium/auxiliary/draw/draw_gs.c @@ -75,12 +75,12 @@ draw_gs_should_flush(struct draw_geometry_shader *shader) /*#define DEBUG_OUTPUTS 1*/ static void tgsi_fetch_gs_outputs(struct draw_geometry_shader *shader, + unsigned stream, unsigned num_primitives, float (**p_output)[4]) { struct tgsi_exec_machine *machine = shader->machine; unsigned prim_idx, j, slot; - unsigned current_idx = 0; float (*output)[4]; output = *p_output; @@ -89,14 +89,16 @@ tgsi_fetch_gs_outputs(struct draw_geometry_shader *shader, */ for (prim_idx = 0; prim_idx < num_primitives; ++prim_idx) { - unsigned num_verts_per_prim = machine->Primitives[prim_idx][0]; - shader->primitive_lengths[prim_idx + shader->emitted_primitives] = - machine->Primitives[prim_idx][0]; - shader->emitted_vertices += num_verts_per_prim; - for (j = 0; j < num_verts_per_prim; j++, current_idx++) { - int idx = current_idx * shader->info.num_outputs; + unsigned num_verts_per_prim = machine->Primitives[stream][prim_idx]; + unsigned prim_offset = machine->PrimitiveOffsets[stream][prim_idx]; + shader->stream[stream].primitive_lengths[prim_idx + shader->stream[stream].emitted_primitives] = + machine->Primitives[stream][prim_idx]; + shader->stream[stream].emitted_vertices += num_verts_per_prim; + + for (j = 0; j < num_verts_per_prim; j++) { + int idx = prim_offset + j * shader->info.num_outputs; #ifdef DEBUG_OUTPUTS - debug_printf("%d) Output vert:\n", idx / shader->info.num_outputs); + debug_printf("%d/%d) Output vert:\n", stream, idx / shader->info.num_outputs); #endif for (slot = 0; slot < shader->info.num_outputs; slot++) { output[slot][0] = machine->Outputs[idx + slot].xyzw[0].f[0]; @@ -115,7 +117,7 @@ tgsi_fetch_gs_outputs(struct draw_geometry_shader *shader, } } *p_output = output; - shader->emitted_primitives += num_primitives; + shader->stream[stream].emitted_primitives += num_primitives; } /*#define DEBUG_INPUTS 1*/ @@ -201,16 +203,40 @@ static void tgsi_gs_prepare(struct draw_geometry_shader *shader, } } -static unsigned tgsi_gs_run(struct draw_geometry_shader *shader, - unsigned input_primitives) +static void tgsi_gs_run(struct draw_geometry_shader *shader, + unsigned input_primitives, + unsigned *out_prims) { struct tgsi_exec_machine *machine = shader->machine; + int i; /* run interpreter */ tgsi_exec_machine_run(machine, 0); - return - machine->Temps[TGSI_EXEC_TEMP_PRIMITIVE_I].xyzw[TGSI_EXEC_TEMP_PRIMITIVE_C].u[0]; + for (i = 0; i < 4; i++) { + int prim_i; + int prim_c; + switch (i) { + case 0: + prim_i = TGSI_EXEC_TEMP_PRIMITIVE_I; + prim_c = TGSI_EXEC_TEMP_PRIMITIVE_C; + break; + case 1: + prim_i = TGSI_EXEC_TEMP_PRIMITIVE_S1_I; + prim_c = TGSI_EXEC_TEMP_PRIMITIVE_S1_C; + break; + case 2: + prim_i = TGSI_EXEC_TEMP_PRIMITIVE_S2_I; + prim_c = TGSI_EXEC_TEMP_PRIMITIVE_S2_C; + break; + case 3: + prim_i = TGSI_EXEC_TEMP_PRIMITIVE_S3_I; + prim_c = TGSI_EXEC_TEMP_PRIMITIVE_S3_C; + break; + }; + + out_prims[i] = machine->Temps[prim_i].xyzw[prim_c].u[0]; + } } #ifdef HAVE_LLVM @@ -287,6 +313,7 @@ llvm_fetch_gs_input(struct draw_geometry_shader *shader, static void llvm_fetch_gs_outputs(struct draw_geometry_shader *shader, + unsigned stream, unsigned num_primitives, float (**p_output)[4]) { @@ -307,7 +334,7 @@ llvm_fetch_gs_outputs(struct draw_geometry_shader *shader, total_verts += shader->llvm_emitted_vertices[i]; } - output_ptr += shader->emitted_vertices * shader->vertex_size; + output_ptr += shader->stream[0].emitted_vertices * shader->vertex_size; for (i = 0; i < shader->vector_length - 1; ++i) { int current_verts = shader->llvm_emitted_vertices[i]; int next_verts = shader->llvm_emitted_vertices[i + 1]; @@ -354,14 +381,14 @@ llvm_fetch_gs_outputs(struct draw_geometry_shader *shader, for (j = 0; j < num_prims; ++j) { int prim_length = shader->llvm_prim_lengths[j][i]; - shader->primitive_lengths[shader->emitted_primitives + prim_idx] = + shader->stream[0].primitive_lengths[shader->stream[0].emitted_primitives + prim_idx] = prim_length; ++prim_idx; } } - shader->emitted_primitives += total_prims; - shader->emitted_vertices += total_verts; + shader->stream[0].emitted_primitives += total_prims; + shader->stream[0].emitted_vertices += total_verts; } static void @@ -371,14 +398,14 @@ llvm_gs_prepare(struct draw_geometry_shader *shader, { } -static unsigned +static void llvm_gs_run(struct draw_geometry_shader *shader, - unsigned input_primitives) + unsigned input_primitives, unsigned *out_prims) { unsigned ret; char *input = (char*)shader->gs_output; - input += (shader->emitted_vertices * shader->vertex_size); + input += (shader->stream[0].emitted_vertices * shader->vertex_size); ret = shader->current_variant->jit_func( shader->jit_context, shader->gs_input->data, @@ -388,15 +415,15 @@ llvm_gs_run(struct draw_geometry_shader *shader, shader->llvm_prim_ids, shader->invocation_id); - return ret; + *out_prims = ret; } #endif static void gs_flush(struct draw_geometry_shader *shader) { - unsigned out_prim_count; - + unsigned out_prim_count[TGSI_MAX_VERTEX_STREAMS]; + unsigned i; unsigned input_primitives = shader->fetched_prim_count; if (shader->draw->collect_statistics) { @@ -406,14 +433,19 @@ static void gs_flush(struct draw_geometry_shader *shader) debug_assert(input_primitives > 0 && input_primitives <= 4); - out_prim_count = shader->run(shader, input_primitives); - shader->fetch_outputs(shader, out_prim_count, - &shader->tmp_output); + shader->run(shader, input_primitives, out_prim_count); + for (i = 0; i < shader->num_vertex_streams; i++) { + shader->fetch_outputs(shader, i, out_prim_count[i], + &shader->stream[i].tmp_output); + } #if 0 - debug_printf("PRIM emitted prims = %d (verts=%d), cur prim count = %d\n", - shader->emitted_primitives, shader->emitted_vertices, - out_prim_count); + for (i = 0; i < shader->num_vertex_streams; i++) { + debug_printf("stream %d: PRIM emitted prims = %d (verts=%d), cur prim count = %d\n", + i, + shader->stream[i].emitted_primitives, shader->stream[i].emitted_vertices, + out_prim_count[i]); + } #endif shader->fetched_prim_count = 0; @@ -557,16 +589,19 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader, unsigned total_verts_per_buffer = shader->primitive_boundary * num_in_primitives; unsigned invocation; + int i; //Assume at least one primitive max_out_prims = MAX2(max_out_prims, 1); - - output_verts->vertex_size = vertex_size; - output_verts->stride = output_verts->vertex_size; - output_verts->verts = - (struct vertex_header *)MALLOC(output_verts->vertex_size * - total_verts_per_buffer * shader->num_invocations); - debug_assert(output_verts->verts); + for (i = 0; i < shader->num_vertex_streams; i++) { + /* write all the vertex data into all the streams */ + output_verts[i].vertex_size = vertex_size; + output_verts[i].stride = output_verts[i].vertex_size; + output_verts[i].verts = + (struct vertex_header *)MALLOC(output_verts[i].vertex_size * + total_verts_per_buffer * shader->num_invocations); + debug_assert(output_verts[i].verts); + } #if 0 debug_printf("%s count = %d (in prims # = %d)\n", @@ -584,21 +619,22 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader, total_verts_per_buffer); #endif - shader->emitted_vertices = 0; - shader->emitted_primitives = 0; + for (i = 0; i < shader->num_vertex_streams; i++) { + shader->stream[i].emitted_vertices = 0; + shader->stream[i].emitted_primitives = 0; + FREE(shader->stream[i].primitive_lengths); + shader->stream[i].primitive_lengths = MALLOC(max_out_prims * sizeof(unsigned) * shader->num_invocations); + shader->stream[i].tmp_output = (float (*)[4])output_verts[i].verts->data; + } shader->vertex_size = vertex_size; - shader->tmp_output = (float (*)[4])output_verts->verts->data; shader->fetched_prim_count = 0; shader->input_vertex_stride = input_stride; shader->input = input; shader->input_info = input_info; - FREE(shader->primitive_lengths); - shader->primitive_lengths = MALLOC(max_out_prims * sizeof(unsigned) * shader->num_invocations); - #ifdef HAVE_LLVM if (shader->draw->llvm) { - shader->gs_output = output_verts->verts; + shader->gs_output = output_verts[0].verts; if (max_out_prims > shader->max_out_prims) { unsigned i; if (shader->llvm_prim_lengths) { @@ -646,32 +682,34 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader, /* Update prim_info: */ - output_prims->linear = TRUE; - output_prims->elts = NULL; - output_prims->start = 0; - output_prims->count = shader->emitted_vertices; - output_prims->prim = shader->output_primitive; - output_prims->flags = 0x0; - output_prims->primitive_lengths = shader->primitive_lengths; - output_prims->primitive_count = shader->emitted_primitives; - output_verts->count = shader->emitted_vertices; - - if (shader->draw->collect_statistics) { - unsigned i; - for (i = 0; i < shader->emitted_primitives; ++i) { - shader->draw->statistics.gs_primitives += - u_decomposed_prims_for_vertices(shader->output_primitive, - shader->primitive_lengths[i]); + for (i = 0; i < shader->num_vertex_streams; i++) { + output_prims[i].linear = TRUE; + output_prims[i].elts = NULL; + output_prims[i].start = 0; + output_prims[i].count = shader->stream[i].emitted_vertices; + output_prims[i].prim = shader->output_primitive; + output_prims[i].flags = 0x0; + output_prims[i].primitive_lengths = shader->stream[i].primitive_lengths; + output_prims[i].primitive_count = shader->stream[i].emitted_primitives; + output_verts[i].count = shader->stream[i].emitted_vertices; + + if (shader->draw->collect_statistics) { + unsigned j; + for (j = 0; j < shader->stream[i].emitted_primitives; ++j) { + shader->draw->statistics.gs_primitives += + u_decomposed_prims_for_vertices(shader->output_primitive, + shader->stream[i].primitive_lengths[j]); + } } } #if 0 - debug_printf("GS finished, prims = %d, verts = %d\n", - output_prims->primitive_count, - output_verts->count); + debug_printf("GS finished\n"); + for (i = 0; i < 4; i++) + debug_printf("stream %d: prims = %d verts = %d\n", i, output_prims[i].primitive_count, output_verts[i].count); #endif - return shader->emitted_vertices; + return 0; } void draw_geometry_shader_prepare(struct draw_geometry_shader *shader, @@ -693,15 +731,19 @@ draw_gs_init( struct draw_context *draw ) { if (!draw->llvm) { draw->gs.tgsi.machine = tgsi_exec_machine_create(PIPE_SHADER_GEOMETRY); - if (!draw->gs.tgsi.machine) - return FALSE; - draw->gs.tgsi.machine->Primitives[0] = align_malloc( - MAX_PRIMITIVES * sizeof(struct tgsi_exec_vector), 16); - if (!draw->gs.tgsi.machine->Primitives) - return FALSE; - memset(draw->gs.tgsi.machine->Primitives, 0, - MAX_PRIMITIVES * sizeof(struct tgsi_exec_vector)); + for (unsigned i = 0; i < TGSI_MAX_VERTEX_STREAMS; i++) { + draw->gs.tgsi.machine->Primitives[i] = align_malloc( + MAX_PRIMITIVES * sizeof(struct tgsi_exec_vector), 16); + draw->gs.tgsi.machine->PrimitiveOffsets[i] = align_malloc( + MAX_PRIMITIVES * sizeof(struct tgsi_exec_vector), 16); + if (!draw->gs.tgsi.machine->Primitives[i] || !draw->gs.tgsi.machine->PrimitiveOffsets) + return FALSE; + memset(draw->gs.tgsi.machine->Primitives[i], 0, + MAX_PRIMITIVES * sizeof(struct tgsi_exec_vector)); + memset(draw->gs.tgsi.machine->PrimitiveOffsets[i], 0, + MAX_PRIMITIVES * sizeof(struct tgsi_exec_vector)); + } } return TRUE; @@ -709,8 +751,10 @@ draw_gs_init( struct draw_context *draw ) void draw_gs_destroy( struct draw_context *draw ) { + int i; if (draw->gs.tgsi.machine) { - align_free(draw->gs.tgsi.machine->Primitives); + for (i = 0; i < TGSI_MAX_VERTEX_STREAMS; i++) + align_free(draw->gs.tgsi.machine->Primitives[i]); tgsi_exec_machine_destroy(draw->gs.tgsi.machine); } } @@ -809,6 +853,12 @@ draw_create_geometry_shader(struct draw_context *draw, gs->machine = draw->gs.tgsi.machine; + gs->num_vertex_streams = 1; + for (i = 0; i < gs->state.stream_output.num_outputs; i++) { + if (gs->state.stream_output.output[i].stream >= gs->num_vertex_streams) + gs->num_vertex_streams = gs->state.stream_output.output[i].stream + 1; + } + #ifdef HAVE_LLVM if (use_llvm) { int vector_size = gs->vector_length * sizeof(float); @@ -864,6 +914,7 @@ void draw_bind_geometry_shader(struct draw_context *draw, void draw_delete_geometry_shader(struct draw_context *draw, struct draw_geometry_shader *dgs) { + int i; if (!dgs) { return; } @@ -896,7 +947,8 @@ void draw_delete_geometry_shader(struct draw_context *draw, } #endif - FREE(dgs->primitive_lengths); + for (i = 0; i < TGSI_MAX_VERTEX_STREAMS; i++) + FREE(dgs->stream[i].primitive_lengths); FREE((void*) dgs->state.tokens); FREE(dgs); } diff --git a/src/gallium/auxiliary/draw/draw_gs.h b/src/gallium/auxiliary/draw/draw_gs.h index 149278dd080..9a9154969f5 100644 --- a/src/gallium/auxiliary/draw/draw_gs.h +++ b/src/gallium/auxiliary/draw/draw_gs.h @@ -57,6 +57,13 @@ struct draw_gs_inputs { /** * Private version of the compiled geometry shader */ +struct draw_vertex_stream { + unsigned *primitive_lengths; + unsigned emitted_vertices; + unsigned emitted_primitives; + float (*tmp_output)[4]; +}; + struct draw_geometry_shader { struct draw_context *draw; @@ -74,14 +81,11 @@ struct draw_geometry_shader { unsigned primitive_boundary; unsigned input_primitive; unsigned output_primitive; - - unsigned *primitive_lengths; - unsigned emitted_vertices; - unsigned emitted_primitives; - - float (*tmp_output)[4]; unsigned vertex_size; + struct draw_vertex_stream stream[TGSI_MAX_VERTEX_STREAMS]; + unsigned num_vertex_streams; + unsigned in_prim_idx; unsigned input_vertex_stride; unsigned fetched_prim_count; @@ -109,14 +113,15 @@ struct draw_geometry_shader { unsigned num_vertices, unsigned prim_idx); void (*fetch_outputs)(struct draw_geometry_shader *shader, + unsigned vertex_stream, unsigned num_primitives, float (**p_output)[4]); void (*prepare)(struct draw_geometry_shader *shader, const void *constants[PIPE_MAX_CONSTANT_BUFFERS], const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS]); - unsigned (*run)(struct draw_geometry_shader *shader, - unsigned input_primitives); + void (*run)(struct draw_geometry_shader *shader, + unsigned input_primitives, unsigned *out_prims); }; void draw_geometry_shader_new_instance(struct draw_geometry_shader *gs); diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h index cb9a1b30848..00527527fe7 100644 --- a/src/gallium/auxiliary/draw/draw_pt.h +++ b/src/gallium/auxiliary/draw/draw_pt.h @@ -188,6 +188,7 @@ struct pt_so_emit; void draw_pt_so_emit_prepare(struct pt_so_emit *emit, boolean use_pre_clip_pos); void draw_pt_so_emit( struct pt_so_emit *emit, + int num_vertex_streams, const struct draw_vertex_info *vert_info, const struct draw_prim_info *prim_info ); diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c index 3207932c601..07838fb7eda 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c @@ -237,16 +237,17 @@ fetch_pipeline_generic(struct draw_pt_middle_end *middle, struct draw_context *draw = fpme->draw; struct draw_vertex_shader *vshader = draw->vs.vertex_shader; struct draw_geometry_shader *gshader = draw->gs.geometry_shader; - struct draw_prim_info gs_prim_info; + struct draw_prim_info gs_prim_info[TGSI_MAX_VERTEX_STREAMS]; struct draw_vertex_info fetched_vert_info; struct draw_vertex_info vs_vert_info; - struct draw_vertex_info gs_vert_info; + struct draw_vertex_info gs_vert_info[TGSI_MAX_VERTEX_STREAMS]; struct draw_vertex_info *vert_info; struct draw_prim_info ia_prim_info; struct draw_vertex_info ia_vert_info; const struct draw_prim_info *prim_info = in_prim_info; boolean free_prim_info = FALSE; unsigned opt = fpme->opt; + int num_vertex_streams = 1; fetched_vert_info.count = fetch_info->count; fetched_vert_info.vertex_size = fpme->vertex_size; @@ -298,12 +299,13 @@ fetch_pipeline_generic(struct draw_pt_middle_end *middle, vert_info, prim_info, &vshader->info, - &gs_vert_info, - &gs_prim_info); + gs_vert_info, + gs_prim_info); FREE(vert_info->verts); - vert_info = &gs_vert_info; - prim_info = &gs_prim_info; + vert_info = &gs_vert_info[0]; + prim_info = &gs_prim_info[0]; + num_vertex_streams = gshader->num_vertex_streams; /* * pt emit can only handle ushort number of vertices (see @@ -343,7 +345,7 @@ fetch_pipeline_generic(struct draw_pt_middle_end *middle, * XXX: Stream output surely needs to respect the prim_info->elt * lists. */ - draw_pt_so_emit( fpme->so_emit, vert_info, prim_info ); + draw_pt_so_emit( fpme->so_emit, num_vertex_streams, vert_info, prim_info ); draw_stats_clipper_primitives(draw, prim_info); diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c index 91c9360cced..9f4f887dff0 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c @@ -355,9 +355,9 @@ llvm_pipeline_generic(struct draw_pt_middle_end *middle, struct llvm_middle_end *fpme = llvm_middle_end(middle); struct draw_context *draw = fpme->draw; struct draw_geometry_shader *gshader = draw->gs.geometry_shader; - struct draw_prim_info gs_prim_info; + struct draw_prim_info gs_prim_info[TGSI_MAX_VERTEX_STREAMS]; struct draw_vertex_info llvm_vert_info; - struct draw_vertex_info gs_vert_info; + struct draw_vertex_info gs_vert_info[TGSI_MAX_VERTEX_STREAMS]; struct draw_vertex_info *vert_info; struct draw_prim_info ia_prim_info; struct draw_vertex_info ia_vert_info; @@ -422,12 +422,12 @@ llvm_pipeline_generic(struct draw_pt_middle_end *middle, vert_info, prim_info, &vshader->info, - &gs_vert_info, - &gs_prim_info); + gs_vert_info, + gs_prim_info); FREE(vert_info->verts); - vert_info = &gs_vert_info; - prim_info = &gs_prim_info; + vert_info = &gs_vert_info[0]; + prim_info = &gs_prim_info[0]; /* * pt emit can only handle ushort number of vertices (see * render->allocate_vertices). @@ -461,7 +461,7 @@ llvm_pipeline_generic(struct draw_pt_middle_end *middle, } /* stream output needs to be done before clipping */ - draw_pt_so_emit( fpme->so_emit, vert_info, prim_info ); + draw_pt_so_emit( fpme->so_emit, 1, vert_info, prim_info ); draw_stats_clipper_primitives(draw, prim_info); diff --git a/src/gallium/auxiliary/draw/draw_pt_so_emit.c b/src/gallium/auxiliary/draw/draw_pt_so_emit.c index 829543cf615..ea3169f32b1 100644 --- a/src/gallium/auxiliary/draw/draw_pt_so_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_so_emit.c @@ -49,6 +49,7 @@ struct pt_so_emit { int pos_idx; unsigned emitted_primitives; unsigned generated_primitives; + unsigned stream; }; static const struct pipe_stream_output_info * @@ -144,6 +145,9 @@ static void so_emit_prim(struct pt_so_emit *so, int ob = state->output[slot].output_buffer; unsigned dst_offset = state->output[slot].dst_offset * sizeof(float); unsigned write_size = num_comps * sizeof(float); + + if (state->output[slot].stream != so->stream) + continue; /* If a buffer is missing then that's equivalent to * an overflow */ if (!draw->so.targets[ob]) { @@ -175,7 +179,10 @@ static void so_emit_prim(struct pt_so_emit *so, unsigned idx = state->output[slot].register_index; unsigned start_comp = state->output[slot].start_component; unsigned num_comps = state->output[slot].num_components; + unsigned stream = state->output[slot].stream; + if (stream != so->stream) + continue; ob = state->output[slot].output_buffer; buffer_written[ob] = TRUE; @@ -184,7 +191,7 @@ static void so_emit_prim(struct pt_so_emit *so, draw->so.targets[ob]->internal_offset) + state->output[slot].dst_offset; - if (idx == so->pos_idx && pcp_ptr) + if (idx == so->pos_idx && pcp_ptr && so->stream == 0) memcpy(buffer, &pre_clip_pos[start_comp], num_comps * sizeof(float)); else @@ -193,8 +200,8 @@ static void so_emit_prim(struct pt_so_emit *so, #if 0 { int j; - debug_printf("VERT[%d], offset = %d, slot[%d] sc = %d, num_c = %d, idx = %d = [", - i, + debug_printf("VERT[%d], stream = %d, offset = %d, slot[%d] sc = %d, num_c = %d, idx = %d = [", + i, stream, draw->so.targets[ob]->internal_offset, slot, start_comp, num_comps, idx); for (j = 0; j < num_comps; ++j) { @@ -258,12 +265,13 @@ static void so_tri(struct pt_so_emit *so, int i0, int i1, int i2) void draw_pt_so_emit( struct pt_so_emit *emit, + int num_vertex_streams, const struct draw_vertex_info *input_verts, const struct draw_prim_info *input_prims ) { struct draw_context *draw = emit->draw; struct vbuf_render *render = draw->render; - unsigned start, i; + unsigned start, i, stream; if (!emit->has_so) return; @@ -271,34 +279,36 @@ void draw_pt_so_emit( struct pt_so_emit *emit, if (!draw->so.num_targets) return; - emit->emitted_primitives = 0; - emit->generated_primitives = 0; - emit->input_vertex_stride = input_verts->stride; - if (emit->use_pre_clip_pos) - emit->pre_clip_pos = input_verts->verts->clip_pos; - - emit->inputs = (const float (*)[4])input_verts->verts->data; - /* XXX: need to flush to get prim_vbuf.c to release its allocation??*/ draw_do_flush( draw, DRAW_FLUSH_BACKEND ); - for (start = i = 0; i < input_prims->primitive_count; - start += input_prims->primitive_lengths[i], i++) - { - unsigned count = input_prims->primitive_lengths[i]; - - if (input_prims->linear) { - so_run_linear(emit, input_prims, input_verts, - start, count); - } else { - so_run_elts(emit, input_prims, input_verts, - start, count); + for (stream = 0; stream < num_vertex_streams; stream++) { + emit->emitted_primitives = 0; + emit->generated_primitives = 0; + if (emit->use_pre_clip_pos) + emit->pre_clip_pos = input_verts[stream].verts->clip_pos; + + emit->input_vertex_stride = input_verts[stream].stride; + emit->inputs = (const float (*)[4])input_verts[stream].verts->data; + emit->stream = stream; + for (start = i = 0; i < input_prims[stream].primitive_count; + start += input_prims[stream].primitive_lengths[i], i++) + { + unsigned count = input_prims[stream].primitive_lengths[i]; + + if (input_prims->linear) { + so_run_linear(emit, &input_prims[stream], &input_verts[stream], + start, count); + } else { + so_run_elts(emit, &input_prims[stream], &input_verts[stream], + start, count); + } } + render->set_stream_output_info(render, + stream, + emit->emitted_primitives, + emit->generated_primitives); } - - render->set_stream_output_info(render, 0, - emit->emitted_primitives, - emit->generated_primitives); } diff --git a/src/gallium/drivers/softpipe/sp_query.c b/src/gallium/drivers/softpipe/sp_query.c index 7187c562068..6e7626d370e 100644 --- a/src/gallium/drivers/softpipe/sp_query.c +++ b/src/gallium/drivers/softpipe/sp_query.c @@ -107,8 +107,8 @@ softpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q) break; case PIPE_QUERY_SO_OVERFLOW_PREDICATE: case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: - sq->so.num_primitives_written = softpipe->so_stats.num_primitives_written; - sq->so.primitives_storage_needed = softpipe->so_stats.primitives_storage_needed; + sq->so.num_primitives_written = softpipe->so_stats[sq->index].num_primitives_written; + sq->so.primitives_storage_needed = softpipe->so_stats[sq->index].primitives_storage_needed; break; case PIPE_QUERY_PRIMITIVES_EMITTED: sq->so.num_primitives_written = softpipe->so_stats[sq->index].num_primitives_written;