Am 13.12.2012 11:26, schrieb Dave Airlie: > From: Dave Airlie <airl...@redhat.com> > > This builds on the previous draw/softpipe patch. > > So llvmpipe does streamout calls after clip/viewport stages, > but we have the pre-clip position stored for later use, so > when we are doing transform feedback, and its the position vertex > grab the vertex from the stored pre clip position. > > The perfect fix is too probably add a codegen transform feedback > stage in between shader and clip stages, but this is good enough > for now. > > Signed-off-by: Dave Airlie <airl...@redhat.com> > --- > src/gallium/auxiliary/draw/draw_pt.h | 2 +- > .../auxiliary/draw/draw_pt_fetch_shade_pipeline.c | 2 +- > .../draw/draw_pt_fetch_shade_pipeline_llvm.c | 2 +- > src/gallium/auxiliary/draw/draw_pt_so_emit.c | 26 > ++++++++++++++++++---- > src/gallium/auxiliary/draw/draw_vs.c | 1 + > src/gallium/drivers/llvmpipe/lp_screen.c | 2 +- > 6 files changed, 27 insertions(+), 8 deletions(-) > > diff --git a/src/gallium/auxiliary/draw/draw_pt.h > b/src/gallium/auxiliary/draw/draw_pt.h > index 7d07363..764d311 100644 > --- a/src/gallium/auxiliary/draw/draw_pt.h > +++ b/src/gallium/auxiliary/draw/draw_pt.h > @@ -185,7 +185,7 @@ struct pt_emit *draw_pt_emit_create( struct draw_context > *draw ); > */ > struct pt_so_emit; > > -void draw_pt_so_emit_prepare( struct pt_so_emit *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, > const struct draw_vertex_info *vert_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 d1b76b1..2fc8220 100644 > --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c > +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c > @@ -117,7 +117,7 @@ static void fetch_pipeline_prepare( struct > draw_pt_middle_end *middle, > (boolean)draw->rasterizer->gl_rasterization_rules, > (draw->vs.edgeflag_output ? TRUE : FALSE) ); > > - draw_pt_so_emit_prepare( fpme->so_emit ); > + draw_pt_so_emit_prepare( fpme->so_emit, FALSE ); > > if (!(opt & PT_PIPELINE)) { > draw_pt_emit_prepare( fpme->emit, > 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 bfad54b..b0c18ed 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 > @@ -102,7 +102,7 @@ llvm_middle_end_prepare( struct draw_pt_middle_end > *middle, > (boolean)draw->rasterizer->gl_rasterization_rules, > (draw->vs.edgeflag_output ? TRUE : FALSE) ); > > - draw_pt_so_emit_prepare( fpme->so_emit ); > + draw_pt_so_emit_prepare( fpme->so_emit, TRUE ); > > if (!(opt & PT_PIPELINE)) { > draw_pt_emit_prepare( fpme->emit, > diff --git a/src/gallium/auxiliary/draw/draw_pt_so_emit.c > b/src/gallium/auxiliary/draw/draw_pt_so_emit.c > index 80a164a..13d8470 100644 > --- a/src/gallium/auxiliary/draw/draw_pt_so_emit.c > +++ b/src/gallium/auxiliary/draw/draw_pt_so_emit.c > @@ -42,20 +42,24 @@ struct pt_so_emit { > > unsigned input_vertex_stride; > const float (*inputs)[4]; > - > + const float (*pre_clip_pos)[4]; > boolean has_so; > - > + boolean use_pre_clip_pos; > + int pos_idx; > unsigned emitted_primitives; > unsigned emitted_vertices; > unsigned generated_primitives; > }; > > > -void draw_pt_so_emit_prepare(struct pt_so_emit *emit) > +void draw_pt_so_emit_prepare(struct pt_so_emit *emit, boolean > use_pre_clip_pos) > { > struct draw_context *draw = emit->draw; > > + emit->use_pre_clip_pos = use_pre_clip_pos; > emit->has_so = (draw->vs.vertex_shader->state.stream_output.num_outputs > > 0); > + if (use_pre_clip_pos) > + emit->pos_idx = draw_current_shader_position_output(draw); > > /* if we have a state with outputs make sure we have > * buffers to output to */ > @@ -87,12 +91,15 @@ static void so_emit_prim(struct pt_so_emit *so, > unsigned input_vertex_stride = so->input_vertex_stride; > struct draw_context *draw = so->draw; > const float (*input_ptr)[4]; > + const float (*pcp_ptr)[4] = NULL; > const struct pipe_stream_output_info *state = > &draw->vs.vertex_shader->state.stream_output; > float *buffer; > int buffer_total_bytes[PIPE_MAX_SO_BUFFERS]; > > input_ptr = so->inputs; > + if (so->use_pre_clip_pos) > + pcp_ptr = so->pre_clip_pos; > > ++so->generated_primitives; > > @@ -117,12 +124,17 @@ static void so_emit_prim(struct pt_so_emit *so, > > for (i = 0; i < num_vertices; ++i) { > const float (*input)[4]; > + const float (*pre_clip_pos)[4]; > unsigned total_written_compos = 0; > int ob; > /*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)); > > + if (pcp_ptr) > + pre_clip_pos = (const float (*)[4])( > + (const char *)pcp_ptr + (indices[i] * input_vertex_stride)); > + > for (slot = 0; slot < state->num_outputs; ++slot) { > unsigned idx = state->output[slot].register_index; > unsigned start_comp = state->output[slot].start_component; > @@ -133,7 +145,10 @@ static void so_emit_prim(struct pt_so_emit *so, > buffer = (float *)((char *)draw->so.targets[ob]->mapping + > draw->so.targets[ob]->target.buffer_offset + > draw->so.targets[ob]->internal_offset) + > state->output[slot].dst_offset; > - memcpy(buffer, &input[idx][start_comp], num_comps * sizeof(float)); > + if (idx == so->pos_idx && pcp_ptr) > + memcpy(buffer, &pre_clip_pos[start_comp], num_comps * > sizeof(float)); > + else > + memcpy(buffer, &input[idx][start_comp], num_comps * > sizeof(float)); > total_written_compos += num_comps; > } > for (ob = 0; ob < draw->so.num_targets; ++ob) > @@ -203,6 +218,9 @@ void draw_pt_so_emit( struct pt_so_emit *emit, > 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 = (const float > (*)[4])input_verts->verts->pre_clip_pos; > + > emit->inputs = (const float (*)[4])input_verts->verts->data; > > /* XXX: need to flush to get prim_vbuf.c to release its allocation??*/ > diff --git a/src/gallium/auxiliary/draw/draw_vs.c > b/src/gallium/auxiliary/draw/draw_vs.c > index 785a903..266cca7 100644 > --- a/src/gallium/auxiliary/draw/draw_vs.c > +++ b/src/gallium/auxiliary/draw/draw_vs.c > @@ -80,6 +80,7 @@ draw_create_vertex_shader(struct draw_context *draw, > { > uint i; > bool found_clipvertex = FALSE; > + vs->position_output = -1; > for (i = 0; i < vs->info.num_outputs; i++) { > if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_POSITION && > vs->info.output_semantic_index[i] == 0) > diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c > b/src/gallium/drivers/llvmpipe/lp_screen.c > index ab5a55b..25027e1 100644 > --- a/src/gallium/drivers/llvmpipe/lp_screen.c > +++ b/src/gallium/drivers/llvmpipe/lp_screen.c > @@ -188,7 +188,7 @@ llvmpipe_get_param(struct pipe_screen *screen, enum > pipe_cap param) > case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS: > return 16*4; > case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME: > - return 0; > + return 1; > case PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS: > case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS: > return 0; >
This looks slightly confusing to me, as you've got a "use_pre_clip_pos" boolean somehow indicating you'd use a post-clip position in the non-llvm case (which of course isn't the case). I'm not sure though how to make it less confusing easily (maybe split it into a separate path for the llvm case?), but anyway this is just a minor nitpick. Reviewed-by: Roland Scheidegger <srol...@vmware.com> _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev