예제 #1
0
파일: draw_gs.c 프로젝트: DirectFB/mesa
/**
 * 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;
}
예제 #2
0
/**
 * Execute geometry shader using TGSI interpreter.
 */
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,
                             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;
   struct tgsi_exec_machine *machine = shader->machine;
   unsigned num_input_verts = input_prim->linear ?
                              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));
   unsigned max_out_prims = u_gs_prims_for_vertices(shader->output_primitive,
                                                    shader->max_output_vertices)
                            * num_in_primitives;

   output_verts->vertex_size = input_verts->vertex_size;
   output_verts->stride = input_verts->vertex_size;
   output_verts->verts =
      (struct vertex_header *)MALLOC(input_verts->vertex_size *
                                     num_in_primitives *
                                     shader->max_output_vertices);


#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("\tprimt pipe = %d, shader in = %d, shader out = %d, max out = %d\n",
                input_prim->prim, shader->input_primitive,
                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->in_prim_idx = 0;
   shader->input_vertex_stride = input_stride;
   shader->input = input;
   if (shader->primitive_lengths) {
      FREE(shader->primitive_lengths);
   }
   shader->primitive_lengths = MALLOC(max_out_prims * sizeof(unsigned));

   tgsi_exec_set_constant_buffers(machine, PIPE_MAX_CONSTANT_BUFFERS,
                                  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);

   /* 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 0
   debug_printf("GS finished, prims = %d, verts = %d\n",
                output_prims->primitive_count,
                output_verts->count);
#endif

   return shader->emitted_vertices;
}