draw/llvmpipe: fix transform feedback position + enable other extensions
authorDave Airlie <airlied@redhat.com>
Thu, 13 Dec 2012 10:17:58 +0000 (20:17 +1000)
committerDave Airlie <airlied@redhat.com>
Fri, 14 Dec 2012 01:34:40 +0000 (11:34 +1000)
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 <sroland@vmware.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
src/gallium/auxiliary/draw/draw_pt.h
src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
src/gallium/auxiliary/draw/draw_pt_so_emit.c
src/gallium/auxiliary/draw/draw_vs.c
src/gallium/drivers/llvmpipe/lp_screen.c

index 7d07363068e1f424da542a36a70ce40002fb59e5..764d3111755fc61ff682e11eaeb0bb04db410360 100644 (file)
@@ -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,
index d1b76b12b02c1ebb06d75ee3b6cbdcacd21ca273..2fc8220452831635757c9ab5a8464fef5d0e3a6e 100644 (file)
@@ -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,
index bfad54bb36e3cd2a9d10655d3721e1544ede55ae..b0c18ed14dcbfc2a73ca95ea2e157e9012cf7c3f 100644 (file)
@@ -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,
index 80a164a0d7da1110cf8e4cef8c2771286dc30368..13d8470e4ecb900e093155e6c5f9e86097f87e8d 100644 (file)
@@ -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??*/
index 785a9032fdfa811b1e41ccae1abe81331d2a32c2..266cca713e1591f30f3614955e0237cde107ba85 100644 (file)
@@ -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)
index ab5a55b3ddd75669b467ae0d3ebeef92f15a061a..25027e197f73bf48ca692b5958a649300976b415 100644 (file)
@@ -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;