[Mesa-dev] [PATCH 5/6] gallium/llvm: implement geometry shaders in the llvm paths

Brian Paul brianp at vmware.com
Wed Mar 27 07:41:05 PDT 2013


On 03/26/2013 10:38 AM, Zack Rusin wrote:
> This commits implements code generation of the geometry shaders in
> the SOA paths. All the code is there but bugs are likely present.
>
> Signed-off-by: Zack Rusin<zackr at vmware.com>
> ---
>   src/gallium/auxiliary/draw/draw_context.c          |   17 +-
>   src/gallium/auxiliary/draw/draw_context.h          |    5 +
>   src/gallium/auxiliary/draw/draw_gs.c               |  297 +++++++++-
>   src/gallium/auxiliary/draw/draw_gs.h               |   26 +-
>   src/gallium/auxiliary/draw/draw_llvm.c             |  567 ++++++++++++++++++--
>   src/gallium/auxiliary/draw/draw_llvm.h             |  161 +++++-
>   .../draw/draw_pt_fetch_shade_pipeline_llvm.c       |   75 +++
>   src/gallium/auxiliary/gallivm/lp_bld_tgsi.h        |   27 +-
>   src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c    |  173 +++++-
>   src/gallium/drivers/llvmpipe/lp_state_fs.c         |    4 +-
>   10 files changed, 1273 insertions(+), 79 deletions(-)
>
> diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
> index 6b70ac8..d64b82b 100644
> --- a/src/gallium/auxiliary/draw/draw_context.c
> +++ b/src/gallium/auxiliary/draw/draw_context.c
> @@ -46,7 +46,7 @@
>   #include "gallivm/lp_bld_limits.h"
>   #include "draw_llvm.h"
>
> -static boolean
> +boolean
>   draw_get_option_use_llvm(void)
>   {
>      static boolean first = TRUE;
> @@ -808,16 +808,15 @@ draw_set_mapped_texture(struct draw_context *draw,
>                           uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS],
>                           uint32_t mip_offsets[PIPE_MAX_TEXTURE_LEVELS])
>   {
> -   if (shader_stage == PIPE_SHADER_VERTEX) {
>   #ifdef HAVE_LLVM
> -      if (draw->llvm)
> -         draw_llvm_set_mapped_texture(draw,
> -                                      sview_idx,
> -                                      width, height, depth, first_level,
> -                                      last_level, base_ptr,
> -                                      row_stride, img_stride, mip_offsets);
> +   if (draw->llvm)
> +      draw_llvm_set_mapped_texture(draw,
> +                                   shader_stage,
> +                                   sview_idx,
> +                                   width, height, depth, first_level,
> +                                   last_level, base_ptr,
> +                                   row_stride, img_stride, mip_offsets);
>   #endif
> -   }
>   }
>
>   /**
> diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h
> index 18c8595..369f6c8 100644
> --- a/src/gallium/auxiliary/draw/draw_context.h
> +++ b/src/gallium/auxiliary/draw/draw_context.h
> @@ -282,4 +282,9 @@ draw_get_shader_param(unsigned shader, enum pipe_shader_cap param);
>   int
>   draw_get_shader_param_no_llvm(unsigned shader, enum pipe_shader_cap param);
>
> +#ifdef HAVE_LLVM
> +boolean
> +draw_get_option_use_llvm(void);
> +#endif
> +
>   #endif /* DRAW_CONTEXT_H */
> diff --git a/src/gallium/auxiliary/draw/draw_gs.c b/src/gallium/auxiliary/draw/draw_gs.c
> index 2b50c9c..c1e1f56 100644
> --- a/src/gallium/auxiliary/draw/draw_gs.c
> +++ b/src/gallium/auxiliary/draw/draw_gs.c
> @@ -29,6 +29,9 @@
>
>   #include "draw_private.h"
>   #include "draw_context.h"
> +#ifdef HAVE_LLVM
> +#include "draw_llvm.h"
> +#endif
>
>   #include "tgsi/tgsi_parse.h"
>   #include "tgsi/tgsi_exec.h"
> @@ -61,7 +64,7 @@ draw_gs_get_input_index(int semantic, int index,
>   static INLINE boolean
>   draw_gs_should_flush(struct draw_geometry_shader *shader)
>   {
> -   return (shader->fetched_prim_count == 4);
> +   return (shader->fetched_prim_count == shader->vector_length);
>   }
>
>   /*#define DEBUG_OUTPUTS 1*/
> @@ -176,7 +179,7 @@ static void tgsi_fetch_gs_input(struct draw_geometry_shader *shader,
>   }
>
>   static void tgsi_gs_prepare(struct draw_geometry_shader *shader,
> -                            const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
> +                            const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
>                               const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS])
>   {
>      struct tgsi_exec_machine *machine = shader->machine;
> @@ -199,10 +202,148 @@ static unsigned tgsi_gs_run(struct draw_geometry_shader *shader,
>      /* run interpreter */
>      tgsi_exec_machine_run(machine);
>
> -   return
> +   return
>         machine->Temps[TGSI_EXEC_TEMP_PRIMITIVE_I].xyzw[TGSI_EXEC_TEMP_PRIMITIVE_C].u[0];
>   }
>
> +#ifdef HAVE_LLVM
> +
> +static void
> +llvm_fetch_gs_input(struct draw_geometry_shader *shader,
> +                    unsigned *indices,
> +                    unsigned num_vertices,
> +                    unsigned prim_idx)
> +{
> +   unsigned slot, vs_slot, i;
> +   unsigned input_vertex_stride = shader->input_vertex_stride;
> +   const float (*input_ptr)[4];
> +   float (*input_data)[6][PIPE_MAX_SHADER_INPUTS][TGSI_NUM_CHANNELS][TGSI_NUM_CHANNELS] =&shader->gs_input->data;
> +
> +   input_ptr = shader->input;
> +
> +   for (i = 0; i<  num_vertices; ++i) {
> +      const float (*input)[4];
> +#if DEBUG_INPUTS
> +      debug_printf("%d) vertex index = %d (prim idx = %d)\n",
> +                   i, indices[i], prim_idx);
> +#endif
> +      input = (const float (*)[4])(
> +         (const char *)input_ptr + (indices[i] * input_vertex_stride));
> +      for (slot = 0, vs_slot = 0; slot<  shader->info.num_inputs; ++slot) {
> +         if (shader->info.input_semantic_name[slot] == TGSI_SEMANTIC_PRIMID) {
> +            (*input_data)[i][slot][0][prim_idx] = (float)shader->in_prim_idx;
> +            (*input_data)[i][slot][1][prim_idx] = (float)shader->in_prim_idx;
> +            (*input_data)[i][slot][2][prim_idx] = (float)shader->in_prim_idx;
> +            (*input_data)[i][slot][3][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);
> +#endif
> +#if 0
> +            assert(!util_is_inf_or_nan(input[vs_slot][0]));
> +            assert(!util_is_inf_or_nan(input[vs_slot][1]));
> +            assert(!util_is_inf_or_nan(input[vs_slot][2]));
> +            assert(!util_is_inf_or_nan(input[vs_slot][3]));
> +#endif
> +            (*input_data)[i][slot][0][prim_idx] = input[vs_slot][0];
> +            (*input_data)[i][slot][1][prim_idx] = input[vs_slot][1];
> +            (*input_data)[i][slot][2][prim_idx] = input[vs_slot][2];
> +            (*input_data)[i][slot][3][prim_idx] = input[vs_slot][3];
> +#if DEBUG_INPUTS
> +            debug_printf("\t\t%f %f %f %f\n",
> +                         (*input_data)[i][slot][0][prim_idx],
> +                         (*input_data)[i][slot][1][prim_idx],
> +                         (*input_data)[i][slot][2][prim_idx],
> +                         (*input_data)[i][slot][3][prim_idx]);
> +#endif
> +            ++vs_slot;
> +         }
> +      }
> +   }
> +}
> +
> +static void
> +llvm_fetch_gs_outputs(struct draw_geometry_shader *shader,
> +                      unsigned num_primitives,
> +                      float (**p_output)[4])
> +{
> +   int total_verts = 0;
> +   int vertex_count = 0;
> +   int total_prims = 0;
> +   int max_prims_per_invocation = 0;
> +   char *output_ptr = (char*)shader->gs_output;
> +   int i, j, prim_idx;
> +
> +   for (i = 0; i<  shader->vector_length; ++i) {
> +      int prims = shader->llvm_emitted_primitives[i];
> +      total_prims += prims;
> +      max_prims_per_invocation = MAX2(max_prims_per_invocation, prims);
> +   }
> +   for (int i = 0; i<  shader->vector_length; ++i) {

remove int decl.


> +      total_verts += shader->llvm_emitted_vertices[i];
> +   }
> +
> +
> +   output_ptr += shader->emitted_vertices * shader->vertex_size;
> +   for (i = 0; i<  shader->vector_length - 1; ++i) {
> +      int current_verts = shader->llvm_emitted_vertices[i];
> +
> +      if (current_verts != shader->max_output_vertices) {
> +         memcpy(output_ptr + (vertex_count + current_verts) * shader->vertex_size,
> +                output_ptr + (vertex_count + shader->max_output_vertices) * shader->vertex_size,
> +                shader->vertex_size * (total_verts - vertex_count - current_verts));
> +      }
> +      vertex_count += current_verts;
> +   }
> +
> +   prim_idx = 0;
> +   for (i = 0; i<  shader->vector_length; ++i) {
> +      int num_prims = shader->llvm_emitted_primitives[i];
> +      for (j = 0; j<  num_prims; ++j) {
> +         int prim_length =
> +            shader->llvm_prim_lengths[j][i];
> +         shader->primitive_lengths[shader->emitted_primitives + prim_idx] =
> +            prim_length;
> +         ++prim_idx;
> +      }
> +   }
> +
> +   shader->emitted_primitives += total_prims;
> +   shader->emitted_vertices += total_verts;
> +}
> +
> +static void
> +llvm_gs_prepare(struct draw_geometry_shader *shader,
> +                const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
> +                const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS])
> +{
> +}
> +
> +static unsigned
> +llvm_gs_run(struct draw_geometry_shader *shader,
> +            unsigned input_primitives)
> +{
> +   unsigned ret;
> +   char *input = (char*)shader->gs_output;
> +
> +   input += (shader->emitted_vertices * shader->vertex_size);
> +
> +   ret = shader->current_variant->jit_func(
> +      shader->jit_context, shader->gs_input->data,
> +      (struct vertex_header*)input,
> +      input_primitives,
> +      shader->draw->instance_id);
> +
> +   return ret;
> +}
> +
> +#endif
> +
>   static void gs_flush(struct draw_geometry_shader *shader)
>   {
>      unsigned out_prim_count;
> @@ -213,13 +354,15 @@ static void gs_flush(struct draw_geometry_shader *shader)
>                   input_primitives<= 4);
>
>      out_prim_count = shader->run(shader, input_primitives);
> +   shader->fetch_outputs(shader, out_prim_count,
> +&shader->tmp_output);
> +
>   #if 0
>      debug_printf("PRIM emitted prims = %d (verts=%d), cur prim count = %d\n",
>                   shader->emitted_primitives, shader->emitted_vertices,
>                   out_prim_count);
>   #endif
> -   shader->fetch_outputs(shader, out_prim_count,
> -&shader->tmp_output);
> +
>      shader->fetched_prim_count = 0;
>   }
>
> @@ -325,8 +468,8 @@ static void gs_tri_adj(struct draw_geometry_shader *shader,
>    * Execute geometry shader.
>    */
>   int draw_geometry_shader_run(struct draw_geometry_shader *shader,
> -                             const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
> -                             const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS],
> +                             const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
> +                             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,
> @@ -338,14 +481,20 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
>      unsigned num_outputs = shader->info.num_outputs;
>      unsigned vertex_size = sizeof(struct vertex_header) + num_outputs * 4 * sizeof(float);
>      unsigned num_input_verts = input_prim->linear ?
> -                              input_verts->count :
> -                              input_prim->count;
> +      input_verts->count :
> +      input_prim->count;
>      unsigned num_in_primitives =
> -      MAX2(u_gs_prims_for_vertices(input_prim->prim, num_input_verts),
> -           u_gs_prims_for_vertices(shader->input_primitive, num_input_verts));
> +      align(
> +         MAX2(u_gs_prims_for_vertices(input_prim->prim, num_input_verts),
> +              u_gs_prims_for_vertices(shader->input_primitive, num_input_verts)),
> +         shader->vector_length);
>      unsigned max_out_prims = u_gs_prims_for_vertices(shader->output_primitive,
>                                                       shader->max_output_vertices)
> -                            * num_in_primitives;
> +      * num_in_primitives;
> +
> +   //Assume at least one primitive
> +   max_out_prims = MAX2(max_out_prims, 1);
> +
>
>      output_verts->vertex_size = vertex_size;
>      output_verts->stride = output_verts->vertex_size;
> @@ -379,6 +528,34 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
>      FREE(shader->primitive_lengths);
>      shader->primitive_lengths = MALLOC(max_out_prims * sizeof(unsigned));
>
> +
> +#ifdef HAVE_LLVM
> +   if (draw_get_option_use_llvm()) {
> +      shader->gs_output = output_verts->verts;
> +      if (max_out_prims>  shader->max_out_prims) {
> +         int i;

'unsigned i' since shader->max_out_prims is unsigned, to avoid MVSC 
warnings.


> +         if (shader->llvm_prim_lengths) {
> +            for (i = 0; i<  shader->max_out_prims; ++i) {
> +               align_free(shader->llvm_prim_lengths[i]);
> +            }
> +            free(shader->llvm_prim_lengths);
> +         }
> +
> +         shader->llvm_prim_lengths = malloc(max_out_prims * sizeof(unsigned*));
> +         for (i = 0; i<  max_out_prims; ++i) {
> +            int vector_size = shader->vector_length * sizeof(unsigned);
> +            shader->llvm_prim_lengths[i] =
> +               align_malloc(vector_size, vector_size);
> +         }
> +
> +         shader->max_out_prims = max_out_prims;
> +      }
> +      shader->jit_context->prim_lengths = shader->llvm_prim_lengths;
> +      shader->jit_context->emitted_vertices = shader->llvm_emitted_vertices;
> +      shader->jit_context->emitted_prims = shader->llvm_emitted_primitives;
> +   }
> +#endif
> +
>      shader->prepare(shader, constants, constants_size);
>
>      if (input_prim->linear)
> @@ -458,10 +635,27 @@ struct draw_geometry_shader *
>   draw_create_geometry_shader(struct draw_context *draw,
>                               const struct pipe_shader_state *state)
>   {
> +#ifdef HAVE_LLVM
> +   struct llvm_geometry_shader *llvm_gs;
> +#endif
>      struct draw_geometry_shader *gs;
>      unsigned i;
>
> -   gs = CALLOC_STRUCT(draw_geometry_shader);
> +#ifdef HAVE_LLVM
> +   if (draw_get_option_use_llvm()) {
> +      llvm_gs = CALLOC_STRUCT(llvm_geometry_shader);
> +
> +      if (llvm_gs == NULL)
> +         return NULL;
> +
> +      gs =&llvm_gs->base;
> +
> +      make_empty_list(&llvm_gs->variants);
> +   } else
> +#endif
> +   {
> +      gs = CALLOC_STRUCT(draw_geometry_shader);
> +   }
>
>      if (!gs)
>         return NULL;
> @@ -480,6 +674,14 @@ draw_create_geometry_shader(struct draw_context *draw,
>      gs->input_primitive = PIPE_PRIM_TRIANGLES;
>      gs->output_primitive = PIPE_PRIM_TRIANGLE_STRIP;
>      gs->max_output_vertices = 32;
> +   gs->max_out_prims = 0;
> +
> +   if (draw_get_option_use_llvm()) {
> +      //gs->vector_length = lp_native_vector_width / 32;
> +      gs->vector_length = TGSI_NUM_CHANNELS;

Is this a "to do" item or something unresolved?



> +   } else {
> +      gs->vector_length = TGSI_NUM_CHANNELS;
> +   }
>
>      for (i = 0; i<  gs->info.num_properties; ++i) {
>         if (gs->info.properties[i].name ==
> @@ -501,10 +703,36 @@ draw_create_geometry_shader(struct draw_context *draw,
>
>      gs->machine = draw->gs.tgsi.machine;
>
> -   gs->fetch_outputs = tgsi_fetch_gs_outputs;
> -   gs->fetch_inputs = tgsi_fetch_gs_input;
> -   gs->prepare = tgsi_gs_prepare;
> -   gs->run = tgsi_gs_run;
> +#ifdef HAVE_LLVM
> +   if (draw_get_option_use_llvm()) {
> +      int vector_size = gs->vector_length * sizeof(float);
> +      gs->gs_input = align_malloc(sizeof(struct draw_gs_inputs), 16);
> +      memset(gs->gs_input, 0, sizeof(struct draw_gs_inputs));
> +      gs->llvm_prim_lengths = 0;
> +
> +      gs->llvm_emitted_primitives = align_malloc(vector_size, vector_size);
> +      gs->llvm_emitted_vertices = align_malloc(vector_size, vector_size);
> +
> +      gs->fetch_outputs = llvm_fetch_gs_outputs;
> +      gs->fetch_inputs = llvm_fetch_gs_input;
> +      gs->prepare = llvm_gs_prepare;
> +      gs->run = llvm_gs_run;
> +
> +      gs->jit_context =&draw->llvm->gs_jit_context;
> +
> +
> +      llvm_gs->variant_key_size =
> +         draw_gs_llvm_variant_key_size(
> +            MAX2(gs->info.file_max[TGSI_FILE_SAMPLER]+1,
> +                 gs->info.file_max[TGSI_FILE_SAMPLER_VIEW]+1));
> +   } else
> +#endif
> +   {
> +      gs->fetch_outputs = tgsi_fetch_gs_outputs;
> +      gs->fetch_inputs = tgsi_fetch_gs_input;
> +      gs->prepare = tgsi_gs_prepare;
> +      gs->run = tgsi_gs_run;
> +   }
>
>      return gs;
>   }
> @@ -529,7 +757,42 @@ void draw_bind_geometry_shader(struct draw_context *draw,
>   void draw_delete_geometry_shader(struct draw_context *draw,
>                                    struct draw_geometry_shader *dgs)
>   {
> +#ifdef HAVE_LLVM
> +   if (draw_get_option_use_llvm()) {
> +      struct llvm_geometry_shader *shader = llvm_geometry_shader(dgs);
> +      struct draw_gs_llvm_variant_list_item *li;
> +
> +      li = first_elem(&shader->variants);
> +      while(!at_end(&shader->variants, li)) {
> +         struct draw_gs_llvm_variant_list_item *next = next_elem(li);
> +         draw_gs_llvm_destroy_variant(li->base);
> +         li = next;
> +      }
> +
> +      assert(shader->variants_cached == 0);
> +
> +      if (dgs->llvm_prim_lengths) {
> +         unsigned i;
> +         for (i = 0; i<  dgs->max_out_prims; ++i) {
> +            align_free(dgs->llvm_prim_lengths[i]);
> +         }
> +         free(dgs->llvm_prim_lengths);
> +      }
> +      align_free(dgs->llvm_emitted_primitives);
> +      align_free(dgs->llvm_emitted_vertices);
> +
> +      align_free(dgs->gs_input);
> +   }
> +#endif
> +
>      FREE(dgs->primitive_lengths);
>      FREE((void*) dgs->state.tokens);
>      FREE(dgs);
>   }
> +
> +
> +void draw_gs_set_current_variant(struct draw_geometry_shader *shader,
> +                                 struct draw_gs_llvm_variant *variant)
> +{
> +   shader->current_variant = variant;
> +}
> diff --git a/src/gallium/auxiliary/draw/draw_gs.h b/src/gallium/auxiliary/draw/draw_gs.h
> index 7ab4f04..62bfcab 100644
> --- a/src/gallium/auxiliary/draw/draw_gs.h
> +++ b/src/gallium/auxiliary/draw/draw_gs.h
> @@ -31,11 +31,19 @@
>   #include "draw_context.h"
>   #include "draw_private.h"
>
> -
>   #define MAX_TGSI_PRIMITIVES 4
>
>   struct draw_context;
>
> +#ifdef HAVE_LLVM
> +struct draw_gs_jit_context;
> +struct draw_gs_llvm_variant;
> +
> +struct draw_gs_inputs {
> +   float data[6][PIPE_MAX_SHADER_INPUTS][TGSI_NUM_CHANNELS][TGSI_NUM_CHANNELS];

Could you add some extra comments explaining all these array 
dimensions?  it's a bit overwhelming.


> +};
> +#endif
> +
>   /**
>    * Private version of the compiled geometry shader
>    */
> @@ -66,6 +74,19 @@ struct draw_geometry_shader {
>      unsigned fetched_prim_count;
>      const float (*input)[4];
>      const struct tgsi_shader_info *input_info;
> +   unsigned vector_length;
> +   unsigned max_out_prims;
> +
> +#ifdef HAVE_LLVM
> +   struct draw_gs_inputs *gs_input;
> +   struct draw_gs_jit_context *jit_context;
> +   struct draw_gs_llvm_variant *current_variant;
> +   struct vertex_header *gs_output;
> +
> +   int **llvm_prim_lengths;
> +   int *llvm_emitted_primitives;
> +   int *llvm_emitted_vertices;

Should any of those be unsigned?



> +#endif
>
>      void (*fetch_inputs)(struct draw_geometry_shader *shader,
>                           unsigned *indices,
> @@ -102,4 +123,7 @@ void draw_geometry_shader_prepare(struct draw_geometry_shader *shader,
>   int draw_gs_max_output_vertices(struct draw_geometry_shader *shader,
>                                   unsigned pipe_prim);
>
> +void draw_gs_set_current_variant(struct draw_geometry_shader *shader,
> +                                 struct draw_gs_llvm_variant *variant);
> +
>   #endif


> +static void
> +draw_gs_llvm_generate(struct draw_llvm *llvm,
> +                      struct draw_gs_llvm_variant *variant)
> +{
> +   struct gallivm_state *gallivm = variant->gallivm;
> +   LLVMContextRef context = gallivm->context;
> +   LLVMTypeRef int32_type = LLVMInt32TypeInContext(context);
> +   LLVMTypeRef arg_types[5];
> +   LLVMTypeRef func_type;
> +   LLVMValueRef variant_func;
> +   LLVMValueRef context_ptr;
> +   LLVMBasicBlockRef block;
> +   LLVMBuilderRef builder;
> +   LLVMValueRef io_ptr, input_array, num_prims, mask_val;
> +   struct lp_build_sampler_soa *sampler = 0;
> +   struct lp_build_context bld;
> +   struct lp_bld_tgsi_system_values system_values;
> +   struct lp_type gs_type;
> +   unsigned i;
> +   struct lp_build_tgsi_gs_args gs_args;
> +   const struct tgsi_token *tokens = variant->shader->base.state.tokens;
> +   LLVMValueRef consts_ptr;
> +   LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][TGSI_NUM_CHANNELS];
> +   struct lp_build_mask_context mask;
> +
> +   memset(&system_values, 0, sizeof(system_values));
> +
> +   assert(variant->vertex_header_ptr_type);
> +
> +   arg_types[0] = get_gs_context_ptr_type(variant);    /* context */
> +   arg_types[1] = variant->input_array_type;           /* input */
> +   arg_types[2] = variant->vertex_header_ptr_type;     /* vertex_header */
> +   arg_types[3] = int32_type;                          /* num_prims */
> +   arg_types[4] = int32_type;                          /* instance_id */
> +
> +   func_type = LLVMFunctionType(int32_type, arg_types, Elements(arg_types), 0);
> +
> +   variant_func = LLVMAddFunction(gallivm->module, "draw_geometry_shader",
> +                                  func_type);
> +   variant->function = variant_func;
> +
> +   LLVMSetFunctionCallConv(variant_func, LLVMCCallConv);
> +
> +   for (i = 0; i<  Elements(arg_types); ++i)
> +      if (LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind)
> +         LLVMAddAttribute(LLVMGetParam(variant_func, i),
> +                          LLVMNoAliasAttribute);
> +
> +   context_ptr               = LLVMGetParam(variant_func, 0);
> +   input_array               = LLVMGetParam(variant_func, 1);
> +   io_ptr                    = LLVMGetParam(variant_func, 2);
> +   num_prims                 = LLVMGetParam(variant_func, 3);
> +   system_values.instance_id = LLVMGetParam(variant_func, 4);
> +
> +   lp_build_name(context_ptr, "context");
> +   lp_build_name(input_array, "input");
> +   lp_build_name(io_ptr, "io");

lp_build_name(num_prims, "num_prims");


> +   lp_build_name(system_values.instance_id, "instance_id");
> +
> +   variant->context_ptr = context_ptr;
> +   variant->io_ptr = io_ptr;
> +   variant->num_prims = num_prims;
> +
> +   gs_args.input = input_array;
> +   gs_args.emit_vertex = draw_gs_llvm_emit_vertex;
> +   gs_args.end_primitive = draw_gs_llvm_end_primitive;
> +   gs_args.gs_epilogue = draw_gs_llvm_epilogue;
> +   gs_args.user_data = variant;
> +
> +   /*
> +    * Function body
> +    */
> +
> +   block = LLVMAppendBasicBlockInContext(gallivm->context, variant_func, "entry");
> +   builder = gallivm->builder;
> +   LLVMPositionBuilderAtEnd(builder, block);
> +
> +   lp_build_context_init(&bld, gallivm, lp_type_int(32));
> +
> +   memset(&gs_type, 0, sizeof gs_type);
> +   gs_type.floating = TRUE; /* floating point values */
> +   gs_type.sign = TRUE;     /* values are signed */
> +   gs_type.norm = FALSE;    /* values are not limited to [0,1] or [-1,1] */
> +   gs_type.width = 32;      /* 32-bit float */
> +   gs_type.length = variant->shader->base.vector_length;
> +
> +   consts_ptr = draw_gs_jit_context_constants(variant->gallivm, context_ptr);
> +
> +   /* code generated texture sampling */
> +   sampler = draw_llvm_sampler_soa_create(variant->key.samplers,
> +                                          context_ptr);
> +
> +   mask_val = generate_mask_value(variant, gs_type);
> +   lp_build_mask_begin(&mask, gallivm, gs_type, mask_val);
> +
> +   lp_build_tgsi_soa(variant->gallivm,
> +                     tokens,
> +                     gs_type,
> +&mask,
> +                     consts_ptr,
> +&system_values,
> +                     NULL /*pos*/,
> +                     NULL,
> +                     outputs,
> +                     sampler,
> +&llvm->draw->gs.geometry_shader->info,
> +&gs_args);
> +
> +   lp_build_mask_end(&mask);
> +
> +   LLVMBuildRet(builder, lp_build_zero(gallivm, lp_type_uint(32)));
> +
> +   gallivm_verify_function(gallivm, variant_func);
> +}
> +
> +
> +struct draw_gs_llvm_variant *
> +draw_gs_llvm_create_variant(struct draw_llvm *llvm,
> +                            unsigned num_outputs,
> +                            const struct draw_gs_llvm_variant_key *key)
> +{
> +   struct draw_gs_llvm_variant *variant;
> +   struct llvm_geometry_shader *shader =
> +      llvm_geometry_shader(llvm->draw->gs.geometry_shader);
> +   LLVMTypeRef vertex_header;
> +
> +   variant = MALLOC(sizeof *variant +
> +                    shader->variant_key_size -
> +                    sizeof variant->key);
> +   if (variant == NULL)
> +      return NULL;
> +
> +   variant->llvm = llvm;
> +   variant->shader = shader;
> +
> +   variant->gallivm = gallivm_create();
> +
> +   create_gs_jit_types(variant);
> +
> +   memcpy(&variant->key, key, shader->variant_key_size);
> +
> +   vertex_header = create_jit_vertex_header(variant->gallivm, num_outputs);
> +
> +   variant->vertex_header_ptr_type = LLVMPointerType(vertex_header, 0);
> +
> +   draw_gs_llvm_generate(llvm, variant);
> +
> +   gallivm_compile_module(variant->gallivm);
> +
> +   variant->jit_func = (draw_gs_jit_func)
> +         gallivm_jit_function(variant->gallivm, variant->function);
> +
> +   variant->list_item_global.base = variant;
> +   variant->list_item_local.base = variant;
> +   /*variant->no = */shader->variants_created++;
> +   variant->list_item_global.base = variant;
> +
> +   return variant;
> +}
> +
> +void
> +draw_gs_llvm_destroy_variant(struct draw_gs_llvm_variant *variant)
> +{
> +   struct draw_llvm *llvm = variant->llvm;
> +
> +   if (variant->function) {
> +      gallivm_free_function(variant->gallivm,
> +                            variant->function, variant->jit_func);
> +   }
> +
> +   gallivm_destroy(variant->gallivm);
> +
> +   remove_from_list(&variant->list_item_local);
> +   variant->shader->variants_cached--;
> +   remove_from_list(&variant->list_item_global);
> +   llvm->nr_gs_variants--;
> +   FREE(variant);
> +}
> +
> +struct draw_gs_llvm_variant_key *
> +draw_gs_llvm_make_variant_key(struct draw_llvm *llvm, char *store)
> +{
> +   unsigned i;
> +   struct draw_gs_llvm_variant_key *key;
> +   struct draw_sampler_static_state *draw_sampler;
> +
> +   key = (struct draw_gs_llvm_variant_key *)store;
> +
> +   /* All variants of this shader will have the same value for
> +    * nr_samplers.  Not yet trying to compact away holes in the
> +    * sampler array.
> +    */
> +   key->nr_samplers = llvm->draw->gs.geometry_shader->info.file_max[TGSI_FILE_SAMPLER] + 1;
> +   if (llvm->draw->gs.geometry_shader->info.file_max[TGSI_FILE_SAMPLER_VIEW] != -1) {
> +      key->nr_sampler_views =
> +         llvm->draw->gs.geometry_shader->info.file_max[TGSI_FILE_SAMPLER_VIEW] + 1;
> +   }
> +   else {
> +      key->nr_sampler_views = key->nr_samplers;
> +   }
> +
> +   draw_sampler = key->samplers;
> +
> +   memset(draw_sampler, 0, MAX2(key->nr_samplers, key->nr_sampler_views) * sizeof *draw_sampler);
> +
> +   for (i = 0 ; i<  key->nr_samplers; i++) {
> +      lp_sampler_static_sampler_state(&draw_sampler[i].sampler_state,
> +                                      llvm->draw->samplers[PIPE_SHADER_GEOMETRY][i]);
> +   }
> +   for (i = 0 ; i<  key->nr_sampler_views; i++) {
> +      lp_sampler_static_texture_state(&draw_sampler[i].texture_state,
> +                                      llvm->draw->sampler_views[PIPE_SHADER_GEOMETRY][i]);
> +   }
> +
> +   return key;
> +}
> +
> +void
> +draw_gs_llvm_dump_variant_key(struct draw_gs_llvm_variant_key *key)
> +{
> +

Remove blank line.


> +   unsigned i;
> +   struct draw_sampler_static_state *sampler = key->samplers;
> +
> +   for (i = 0 ; i<  key->nr_sampler_views; i++) {
> +      debug_printf("sampler[%i].src_format = %s\n", i,
> +                   util_format_name(sampler[i].texture_state.format));
> +   }
> +}



More information about the mesa-dev mailing list