draw: account for separate shader objects in geometry shader code
authorBryan Cain <bryancain3@gmail.com>
Fri, 15 Feb 2013 16:05:36 +0000 (10:05 -0600)
committerZack Rusin <zackr@vmware.com>
Wed, 6 Mar 2013 04:13:08 +0000 (20:13 -0800)
The geometry shader code seems to have been originally written with the
assumptions that there are the same number of VS outputs as GS outputs and
that VS outputs are in the same order as their corresponding GS inputs. Since
TGSI uses separate shader objects, these are both wrong assumptions. This
was causing several valid vertex/geometry shader combinations to either render
incorrectly or trigger an assertion.

Conflicts:
src/gallium/auxiliary/draw/draw_gs.c

Reviewed-by: Zack Rusin <zackr@vmware.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: José Fonseca <jfonseca@vmware.com>
src/gallium/auxiliary/draw/draw_gs.c
src/gallium/auxiliary/draw/draw_gs.h
src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c

index 25c117bafae12ed39fffff697cc8ae36dce03887..99335af12d31d424449ccf36999b5ad263828d6e 100644 (file)
@@ -148,6 +148,22 @@ void draw_delete_geometry_shader(struct draw_context *draw,
    FREE(dgs);
 }
 
+static INLINE int
+draw_gs_get_input_index(int semantic, int index,
+                        const struct tgsi_shader_info *input_info)
+{
+   int i;
+   const ubyte *input_semantic_names = input_info->output_semantic_name;
+   const ubyte *input_semantic_indices = input_info->output_semantic_index;
+   for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) {
+      if (input_semantic_names[i] == semantic &&
+          input_semantic_indices[i] == index)
+         return i;
+   }
+   debug_assert(0);
+   return -1;
+}
+
 /*#define DEBUG_OUTPUTS 1*/
 static INLINE void
 draw_geometry_fetch_outputs(struct draw_geometry_shader *shader,
@@ -228,6 +244,10 @@ static void draw_fetch_gs_input(struct draw_geometry_shader *shader,
             machine->Inputs[idx].xyzw[3].f[prim_idx] =
                (float)shader->in_prim_idx;
          } else {
+            vs_slot = draw_gs_get_input_index(
+                        shader->info.input_semantic_name[slot],
+                        shader->info.input_semantic_index[slot],
+                        shader->input_info);
 #if DEBUG_INPUTS
             debug_printf("\tSlot = %d, vs_slot = %d, idx = %d:\n",
                          slot, vs_slot, idx);
@@ -381,12 +401,14 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
                              const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS], 
                              const struct draw_vertex_info *input_verts,
                              const struct draw_prim_info *input_prim,
+                             const struct tgsi_shader_info *input_info,
                              struct draw_vertex_info *output_verts,
                              struct draw_prim_info *output_prims )
 {
    const float (*input)[4] = (const float (*)[4])input_verts->verts->data;
    unsigned input_stride = input_verts->vertex_size;
-   unsigned vertex_size = input_verts->vertex_size;
+   unsigned num_outputs = shader->info.num_outputs;
+   unsigned vertex_size = sizeof(struct vertex_header) + num_outputs * 4 * sizeof(float);
    struct tgsi_exec_machine *machine = shader->machine;
    unsigned num_input_verts = input_prim->linear ?
                               input_verts->count :
@@ -398,10 +420,10 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
                                                     shader->max_output_vertices)
                             * num_in_primitives;
 
-   output_verts->vertex_size = input_verts->vertex_size;
-   output_verts->stride = input_verts->vertex_size;
+   output_verts->vertex_size = vertex_size;
+   output_verts->stride = output_verts->vertex_size;
    output_verts->verts =
-      (struct vertex_header *)MALLOC(input_verts->vertex_size *
+      (struct vertex_header *)MALLOC(output_verts->vertex_size *
                                      num_in_primitives *
                                      shader->max_output_vertices);
 
@@ -425,6 +447,7 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
    shader->in_prim_idx = 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));
 
index bfac02c6635490bbd784cb82654bae97900102cd..5d10d0dcd411fce151b1255b6dfcd4ad725edba4 100644 (file)
@@ -64,6 +64,7 @@ struct draw_geometry_shader {
    unsigned in_prim_idx;
    unsigned input_vertex_stride;
    const float (*input)[4];
+   const struct tgsi_shader_info *input_info;
 };
 
 /*
@@ -76,6 +77,7 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
                              const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS], 
                              const struct draw_vertex_info *input_verts,
                              const struct draw_prim_info *input_prim,
+                             const struct tgsi_shader_info *input_info,
                              struct draw_vertex_info *output_verts,
                              struct draw_prim_info *output_prims );
 
index 45d964da4fa92c0b654b343116581a19cebd1609..72d391257aa5ffdf5f0dc6c6d21a6b90f0690853 100644 (file)
@@ -270,6 +270,7 @@ static void fetch_pipeline_generic( struct draw_pt_middle_end *middle,
                                draw->pt.user.gs_constants_size,
                                vert_info,
                                prim_info,
+                               &vshader->info,
                                &gs_vert_info,
                                &gs_prim_info);
 
index 687dfa404597d63c357c61913602d1f0270d3c3b..5fc94364b4ee1b351c2d3c9eed13ff7271909a51 100644 (file)
@@ -289,11 +289,13 @@ llvm_pipeline_generic( struct draw_pt_middle_end *middle,
 
 
    if ((opt & PT_SHADE) && gshader) {
+      struct draw_vertex_shader *vshader = draw->vs.vertex_shader;
       draw_geometry_shader_run(gshader,
                                draw->pt.user.gs_constants,
                                draw->pt.user.gs_constants_size,
                                vert_info,
                                prim_info,
+                               &vshader->info,
                                &gs_vert_info,
                                &gs_prim_info);