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); }
static void llvm_middle_end_prepare_gs(struct llvm_middle_end *fpme) { struct draw_context *draw = fpme->draw; struct draw_geometry_shader *gs = draw->gs.geometry_shader; struct draw_gs_llvm_variant_key *key; struct draw_gs_llvm_variant *variant = NULL; struct draw_gs_llvm_variant_list_item *li; struct llvm_geometry_shader *shader = llvm_geometry_shader(gs); char store[DRAW_GS_LLVM_MAX_VARIANT_KEY_SIZE]; unsigned i; key = draw_gs_llvm_make_variant_key(fpme->llvm, store); /* Search shader's list of variants for the key */ li = first_elem(&shader->variants); while (!at_end(&shader->variants, li)) { if (memcmp(&li->base->key, key, shader->variant_key_size) == 0) { variant = li->base; break; } li = next_elem(li); } if (variant) { /* found the variant, move to head of global list (for LRU) */ move_to_head(&fpme->llvm->gs_variants_list, &variant->list_item_global); } else { /* Need to create new variant */ /* First check if we've created too many variants. If so, free * 25% of the LRU to avoid using too much memory. */ if (fpme->llvm->nr_gs_variants >= DRAW_MAX_SHADER_VARIANTS) { /* * XXX: should we flush here ? */ for (i = 0; i < DRAW_MAX_SHADER_VARIANTS / 4; i++) { struct draw_gs_llvm_variant_list_item *item; if (is_empty_list(&fpme->llvm->gs_variants_list)) { break; } item = last_elem(&fpme->llvm->gs_variants_list); assert(item); assert(item->base); draw_gs_llvm_destroy_variant(item->base); } } variant = draw_gs_llvm_create_variant(fpme->llvm, gs->info.num_outputs, key); if (variant) { insert_at_head(&shader->variants, &variant->list_item_local); insert_at_head(&fpme->llvm->gs_variants_list, &variant->list_item_global); fpme->llvm->nr_gs_variants++; shader->variants_cached++; } } gs->current_variant = variant; }