draw: stop crashing with extra shader outputs
authorZack Rusin <zackr@vmware.com>
Fri, 2 Aug 2013 05:39:35 +0000 (01:39 -0400)
committerZack Rusin <zackr@vmware.com>
Sat, 3 Aug 2013 00:11:18 +0000 (20:11 -0400)
Draw sometimes injects extra shader outputs (aa points, lines or
front face), unfortunately most of the pipeline and llvm code
didn't handle them at all. It only worked if number of inputs
happened to be bigger or equal to the number of shader outputs
plus the extra injected outputs. In particular when running
the pipeline which depends on the vertex_id in the vertex_header
things were completely broken. The patch adjust the code to
correctly use the total number of shader outputs (the standard
ones plus the injected ones) to make it all stop crashing and
work.

Signed-off-by: Zack Rusin <zackr@vmware.com>
Reviewed-by: Roland Scheidegger <sroland@vmware.com>
Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
src/gallium/auxiliary/draw/draw_context.c
src/gallium/auxiliary/draw/draw_context.h
src/gallium/auxiliary/draw/draw_gs.c
src/gallium/auxiliary/draw/draw_llvm.c
src/gallium/auxiliary/draw/draw_llvm.h
src/gallium/auxiliary/draw/draw_pipe.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_vs_variant.c

index 4a6ba1ac426d0c40733c0fbcc0c70b9de90bd74a..29bbc94d0ab4279bddd5227d9cc597d658e42b65 100644 (file)
@@ -604,6 +604,40 @@ draw_num_shader_outputs(const struct draw_context *draw)
 }
 
 
+/**
+ * Return total number of the vertex shader outputs.  This function
+ * also counts any extra vertex output attributes that may
+ * be filled in by some draw stages (such as AA point, AA line,
+ * front face).
+ */
+uint
+draw_total_vs_outputs(const struct draw_context *draw)
+{
+   const struct tgsi_shader_info *info = &draw->vs.vertex_shader->info;
+
+   return info->num_outputs + draw->extra_shader_outputs.num;;
+}
+
+/**
+ * Return total number of the geometry shader outputs. This function
+ * also counts any extra geometry output attributes that may
+ * be filled in by some draw stages (such as AA point, AA line, front
+ * face).
+ */
+uint
+draw_total_gs_outputs(const struct draw_context *draw)
+{   
+   const struct tgsi_shader_info *info;
+
+   if (!draw->gs.geometry_shader)
+      return 0;
+
+   info = &draw->gs.geometry_shader->info;
+
+   return info->num_outputs + draw->extra_shader_outputs.num;
+}
+
+
 /**
  * Provide TGSI sampler objects for vertex/geometry shaders that use
  * texture fetches.  This state only needs to be set once per context.
index 4a1b27ee41494cebd8254a7f1c6cbdef2dc70e10..c720806feca75cb51934d640bef3422b17e80e31 100644 (file)
@@ -133,6 +133,11 @@ draw_find_shader_output(const struct draw_context *draw,
 uint
 draw_num_shader_outputs(const struct draw_context *draw);
 
+uint
+draw_total_vs_outputs(const struct draw_context *draw);
+
+uint
+draw_total_gs_outputs(const struct draw_context *draw);
 
 void
 draw_texture_sampler(struct draw_context *draw,
index cd63e2bf9e38d6321cf7e52b75ab14ac856d5ade..13d3d3b7b9520fd2130a99e9c5a3925900c8d7ca 100644 (file)
@@ -534,7 +534,7 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
 {
    const float (*input)[4] = (const float (*)[4])input_verts->verts->data;
    unsigned input_stride = input_verts->vertex_size;
-   unsigned num_outputs = shader->info.num_outputs;
+   unsigned num_outputs = draw_total_gs_outputs(shader->draw);
    unsigned vertex_size = sizeof(struct vertex_header) + num_outputs * 4 * sizeof(float);
    unsigned num_input_verts = input_prim->linear ?
       input_verts->count :
index cf71a5d6bdfa42aea13457cf9021b6a946f15a30..03f863178bcc49384a988e058b4623036d570896 100644 (file)
@@ -1833,6 +1833,7 @@ draw_llvm_make_variant_key(struct draw_llvm *llvm, char *store)
    key->need_edgeflags = (llvm->draw->vs.edgeflag_output ? TRUE : FALSE);
    key->ucp_enable = llvm->draw->rasterizer->clip_plane_enable;
    key->has_gs = llvm->draw->gs.geometry_shader != NULL;
+   key->num_outputs = draw_total_vs_outputs(llvm->draw);
    key->pad1 = 0;
 
    /* All variants of this shader will have the same value for
@@ -2270,6 +2271,8 @@ draw_gs_llvm_make_variant_key(struct draw_llvm *llvm, char *store)
 
    key = (struct draw_gs_llvm_variant_key *)store;
 
+   key->num_outputs = draw_total_gs_outputs(llvm->draw);
+
    /* All variants of this shader will have the same value for
     * nr_samplers.  Not yet trying to compact away holes in the
     * sampler array.
index 0675e3bf17b6386fc2e344e3dfce668378de5ecc..1d238a2a9c2a75c90dcba803d4503c1d4b84f78d 100644 (file)
@@ -301,12 +301,13 @@ struct draw_llvm_variant_key
    unsigned bypass_viewport:1;
    unsigned need_edgeflags:1;
    unsigned has_gs:1;
+   unsigned num_outputs:8;
    /*
     * it is important there are no holes in this struct
     * (and all padding gets zeroed).
     */
    unsigned ucp_enable:PIPE_MAX_CLIP_PLANES;
-   unsigned pad1:32-PIPE_MAX_CLIP_PLANES;
+   unsigned pad1:24-PIPE_MAX_CLIP_PLANES;
 
    /* Variable number of vertex elements:
     */
@@ -321,6 +322,7 @@ struct draw_gs_llvm_variant_key
 {
    unsigned nr_samplers:8;
    unsigned nr_sampler_views:8;
+   unsigned num_outputs:8;
 
    struct draw_sampler_static_state samplers[1];
 };
index 479250729ff7ac350a38d3c2e87056a7df033d29..547e4bf4d058527ef3bad7cdc4b8b884d82ee4c0 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "pipe/p_compiler.h"
 #include "draw_private.h"       /* for sizeof(vertex_header) */
+#include "draw_context.h"
 
 
 /**
@@ -117,7 +118,7 @@ dup_vert( struct draw_stage *stage,
 {   
    struct vertex_header *tmp = stage->tmp[idx];
    const uint vsize = sizeof(struct vertex_header)
-      + stage->draw->vs.num_vs_outputs * 4 * sizeof(float);
+      + draw_num_shader_outputs(stage->draw) * 4 * sizeof(float);
    memcpy(tmp, vert, vsize);
    tmp->vertex_id = UNDEFINED_VERTEX_ID;
    return tmp;
index 84f86ae75ee6118e42a7f3dbd96d755d5e55a797..8fcc17048d239d3c27c2db99d9e9fb3be5d81535 100644 (file)
@@ -72,12 +72,8 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
 
    const unsigned gs_out_prim = (gs ? gs->output_primitive :
                                  u_assembled_prim(prim));
-
-   /* Add one to num_outputs because the pipeline occasionally tags on
-    * an additional texcoord, eg for AA lines.
-    */
    unsigned nr = MAX2( vs->info.num_inputs,
-                      vs->info.num_outputs + 1 );
+                      draw_total_vs_outputs(draw) );
 
    if (gs) {
       nr = MAX2(nr, gs->info.num_outputs + 1);
index 17b948a7652ba433c3369bc9ecd661d4ef882526..9f172418544c6f1911ae4d1a0ea48e21c15d898f 100644 (file)
@@ -141,12 +141,8 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
    struct draw_geometry_shader *gs = draw->gs.geometry_shader;
    const unsigned out_prim = gs ? gs->output_primitive :
       u_assembled_prim(in_prim);
-
-   /* Add one to num_outputs because the pipeline occasionally tags on
-    * an additional texcoord, eg for AA lines.
-    */
-   const unsigned nr = MAX2( vs->info.num_inputs,
-                             vs->info.num_outputs + 1 );
+   const unsigned nr = MAX2(vs->info.num_inputs,
+                            draw_total_vs_outputs(draw));
 
    fpme->input_prim = in_prim;
    fpme->opt = opt;
index 37500c7db8d249970f56f4d37fa0ad572ced0f4e..9045b63844498745b64df60040279e9710957b1f 100644 (file)
@@ -315,7 +315,7 @@ draw_vs_create_variant_generic( struct draw_vertex_shader *vs,
    vsvg->draw = vs->draw;
 
    vsvg->temp_vertex_stride = MAX2(key->nr_inputs,
-                                   vsvg->base.vs->info.num_outputs) * 4 * sizeof(float);
+                                   draw_total_vs_outputs(vs->draw)) * 4 * sizeof(float);
 
    /* Build free-standing fetch and emit functions:
     */