Exemple #1
0
/**
 * Create new draw module context with gallivm state for LLVM JIT.
 */
struct draw_context *
draw_create_gallivm(struct pipe_context *pipe, struct gallivm_state *gallivm)
{
   struct draw_context *draw = CALLOC_STRUCT( draw_context );
   if (draw == NULL)
      goto fail;

#if HAVE_LLVM
   if (draw_get_option_use_llvm()) {
      if (!gallivm) {
         gallivm = gallivm_create();
         draw->own_gallivm = gallivm;
      }

      if (gallivm)
         draw->llvm = draw_llvm_create(draw, gallivm);
   }
#endif

   if (!draw_init(draw))
      goto fail;

   draw->pipe = pipe;

   return draw;

fail:
   draw_destroy( draw );
   return NULL;
}
Exemple #2
0
/**
 * Create new draw module context with gallivm state for LLVM JIT.
 */
static struct draw_context *
draw_create_context(struct pipe_context *pipe, boolean try_llvm)
{
   struct draw_context *draw = CALLOC_STRUCT( draw_context );
   if (draw == NULL)
      goto err_out;

#if HAVE_LLVM
   if (try_llvm && draw_get_option_use_llvm()) {
      draw->llvm = draw_llvm_create(draw);
      if (!draw->llvm)
         goto err_destroy;
   }
#endif

   draw->pipe = pipe;

   if (!draw_init(draw))
      goto err_destroy;

   return draw;

err_destroy:
   draw_destroy( draw );
err_out:
   return NULL;
}
/**
 * Create new draw module context with gallivm state for LLVM JIT.
 */
static struct draw_context *
draw_create_context(struct pipe_context *pipe, void *context,
                    boolean try_llvm)
{
   struct draw_context *draw = CALLOC_STRUCT( draw_context );
   if (!draw)
      goto err_out;

   /* we need correct cpu caps for disabling denorms in draw_vbo() */
   util_cpu_detect();

#if HAVE_LLVM
   if (try_llvm && draw_get_option_use_llvm()) {
      draw->llvm = draw_llvm_create(draw, (LLVMContextRef)context);
   }
#endif

   draw->pipe = pipe;

   if (!draw_init(draw))
      goto err_destroy;

   draw->ia = draw_prim_assembler_create(draw);
   if (!draw->ia)
      goto err_destroy;

   return draw;

err_destroy:
   draw_destroy( draw );
err_out:
   return NULL;
}
Exemple #4
0
void draw_geometry_shader_prepare(struct draw_geometry_shader *shader,
                                  struct draw_context *draw)
{
#ifdef HAVE_LLVM
   boolean use_llvm = draw_get_option_use_llvm();
#else
   boolean use_llvm = FALSE;
#endif
   if (!use_llvm && shader && shader->machine->Tokens != shader->state.tokens) {
      tgsi_exec_machine_bind_shader(shader->machine,
                                    shader->state.tokens,
                                    draw->gs.tgsi.sampler);
   }
}
Exemple #5
0
/**
 * XXX: Results for PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS because there are two
 * different ways of setting textures, and drivers typically only support one.
 */
int
draw_get_shader_param(unsigned shader, enum pipe_shader_cap param)
{

#ifdef HAVE_LLVM
   if (draw_get_option_use_llvm()) {
      switch(shader) {
      case PIPE_SHADER_VERTEX:
      case PIPE_SHADER_GEOMETRY:
         return gallivm_get_shader_param(param);
      default:
         return 0;
      }
   }
#endif

   return draw_get_shader_param_no_llvm(shader, param);
}
Exemple #6
0
void draw_delete_geometry_shader(struct draw_context *draw,
                                 struct draw_geometry_shader *dgs)
{
   if (!dgs) {
      return;
   }
#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->llvm_prim_ids);

      align_free(dgs->gs_input);
   }
#endif

   FREE(dgs->primitive_lengths);
   FREE((void*) dgs->state.tokens);
   FREE(dgs);
}
Exemple #7
0
struct draw_geometry_shader *
draw_create_geometry_shader(struct draw_context *draw,
                            const struct pipe_shader_state *state)
{
#ifdef HAVE_LLVM
   boolean use_llvm = draw_get_option_use_llvm();
   struct llvm_geometry_shader *llvm_gs;
#endif
   struct draw_geometry_shader *gs;
   unsigned i;

#ifdef HAVE_LLVM
   if (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;

   gs->draw = draw;
   gs->state = *state;
   gs->state.tokens = tgsi_dup_tokens(state->tokens);
   if (!gs->state.tokens) {
      FREE(gs);
      return NULL;
   }

   tgsi_scan_shader(state->tokens, &gs->info);

   /* setup the defaults */
   gs->input_primitive = PIPE_PRIM_TRIANGLES;
   gs->output_primitive = PIPE_PRIM_TRIANGLE_STRIP;
   gs->max_output_vertices = 32;
   gs->max_out_prims = 0;

#ifdef HAVE_LLVM
   if (use_llvm) {
      /* TODO: change the input array to handle the following
         vector length, instead of the currently hardcoded
         TGSI_NUM_CHANNELS
      gs->vector_length = lp_native_vector_width / 32;*/
      gs->vector_length = TGSI_NUM_CHANNELS;
   } else
#endif
   {
      gs->vector_length = 1;
   }

   for (i = 0; i < gs->info.num_properties; ++i) {
      if (gs->info.properties[i].name ==
          TGSI_PROPERTY_GS_INPUT_PRIM)
         gs->input_primitive = gs->info.properties[i].data[0];
      else if (gs->info.properties[i].name ==
               TGSI_PROPERTY_GS_OUTPUT_PRIM)
         gs->output_primitive = gs->info.properties[i].data[0];
      else if (gs->info.properties[i].name ==
               TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES)
         gs->max_output_vertices = gs->info.properties[i].data[0];
   }
   /* Primitive boundary is bigger than max_output_vertices by one, because
    * the specification says that the geometry shader should exit if the 
    * number of emitted vertices is bigger or equal to max_output_vertices and
    * we can't do that because we're running in the SoA mode, which means that
    * our storing routines will keep getting called on channels that have
    * overflown.
    * So we need some scratch area where we can keep writing the overflown 
    * vertices without overwriting anything important or crashing.
    */
   gs->primitive_boundary = gs->max_output_vertices + 1;

   for (i = 0; i < gs->info.num_outputs; i++) {
      if (gs->info.output_semantic_name[i] == TGSI_SEMANTIC_POSITION &&
          gs->info.output_semantic_index[i] == 0)
         gs->position_output = i;
      if (gs->info.output_semantic_name[i] == TGSI_SEMANTIC_VIEWPORT_INDEX)
         gs->viewport_index_output = i;
      if (gs->info.output_semantic_name[i] == TGSI_SEMANTIC_CLIPDIST) {
         debug_assert(gs->info.output_semantic_index[i] <
                      PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT);
         gs->clipdistance_output[gs->info.output_semantic_index[i]] = i;
      }
      if (gs->info.output_semantic_name[i] == TGSI_SEMANTIC_CULLDIST) {
         debug_assert(gs->info.output_semantic_index[i] <
                      PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT);
         gs->culldistance_output[gs->info.output_semantic_index[i]] = i;
      }
   }

   gs->machine = draw->gs.tgsi.machine;

#ifdef HAVE_LLVM
   if (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->llvm_prim_ids = 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;
}
Exemple #8
0
/**
 * 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 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 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 :
      input_prim->count;
   unsigned num_in_primitives =
      align(
         MAX2(u_decomposed_prims_for_vertices(input_prim->prim,
                                              num_input_verts),
              u_decomposed_prims_for_vertices(shader->input_primitive,
                                              num_input_verts)),
         shader->vector_length);
   unsigned max_out_prims =
      u_decomposed_prims_for_vertices(shader->output_primitive,
                                      shader->max_output_vertices)
      * 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;
   /* we allocate exactly one extra vertex per primitive to allow the GS to emit
    * overflown vertices into some area where they won't harm anyone */
   output_verts->verts =
      (struct vertex_header *)MALLOC(output_verts->vertex_size *
                                     max_out_prims *
                                     shader->primitive_boundary);

#if 0
   debug_printf("%s count = %d (in prims # = %d)\n",
                __FUNCTION__, num_input_verts, num_in_primitives);
   debug_printf("\tlinear = %d, prim_info->count = %d\n",
                input_prim->linear, input_prim->count);
   debug_printf("\tprim pipe = %s, shader in = %s, shader out = %s, max out = %d\n",
                u_prim_name(input_prim->prim),
                u_prim_name(shader->input_primitive),
                u_prim_name(shader->output_primitive),
                shader->max_output_vertices);
#endif

   shader->emitted_vertices = 0;
   shader->emitted_primitives = 0;
   shader->vertex_size = vertex_size;
   shader->tmp_output = (float (*)[4])output_verts->verts->data;
   shader->fetched_prim_count = 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));


#ifdef HAVE_LLVM
   if (draw_get_option_use_llvm()) {
      shader->gs_output = output_verts->verts;
      if (max_out_prims > shader->max_out_prims) {
         unsigned i;
         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)
      gs_run(shader, input_prim, input_verts,
             output_prims, output_verts);
   else
      gs_run_elts(shader, input_prim, input_verts,
                  output_prims, output_verts);

   /* Flush the remaining primitives. Will happen if
    * num_input_primitives % 4 != 0
    */
   if (shader->fetched_prim_count > 0) {
      gs_flush(shader);
   }

   debug_assert(shader->fetched_prim_count == 0);

   /* Update prim_info:
    */
   output_prims->linear = TRUE;
   output_prims->elts = NULL;
   output_prims->start = 0;
   output_prims->count = shader->emitted_vertices;
   output_prims->prim = shader->output_primitive;
   output_prims->flags = 0x0;
   output_prims->primitive_lengths = shader->primitive_lengths;
   output_prims->primitive_count = shader->emitted_primitives;
   output_verts->count = shader->emitted_vertices;

   if (shader->draw->collect_statistics) {
      unsigned i;
      for (i = 0; i < shader->emitted_primitives; ++i) {
         shader->draw->statistics.gs_primitives +=
            u_decomposed_prims_for_vertices(shader->output_primitive,
                                            shader->primitive_lengths[i]);
      }
   }

#if 0
   debug_printf("GS finished, prims = %d, verts = %d\n",
                output_prims->primitive_count,
                output_verts->count);
#endif

   return shader->emitted_vertices;
}