[Mesa-dev] [PATCH] draw/llvmpipe: fix transform feedback position + enable other extensions

Dave Airlie airlied at gmail.com
Thu Dec 13 02:26:21 PST 2012


From: Dave Airlie <airlied at 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 <airlied at 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;
-- 
1.8.0.1



More information about the mesa-dev mailing list