From 9e41b0badbab97c9db03d5825f91533c69e4f9f9 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 13 Dec 2012 20:17:58 +1000 Subject: [PATCH] draw/llvmpipe: fix transform feedback position + enable other extensions 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. Reviewed-by: Roland Scheidegger Signed-off-by: Dave Airlie --- src/gallium/auxiliary/draw/draw_pt.h | 2 +- .../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 7d07363068e..764d3111755 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 d1b76b12b02..2fc82204528 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 bfad54bb36e..b0c18ed14dc 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 80a164a0d7d..13d8470e4ec 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 785a9032fdf..266cca713e1 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 ab5a55b3ddd..25027e197f7 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; -- 2.30.2