/** * 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; }
/** * 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; }