diff options
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_type.c | 25 | ||||
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_type.h | 4 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_context.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_limits.h | 6 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_state_fs.c | 34 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_state_fs.h | 3 |
6 files changed, 62 insertions, 11 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_type.c b/src/gallium/auxiliary/gallivm/lp_bld_type.c index efd159f8869..413e69bedac 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_type.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_type.c @@ -411,3 +411,28 @@ lp_build_context_init(struct lp_build_context *bld, bld->zero = LLVMConstNull(bld->vec_type); bld->one = lp_build_one(gallivm, type); } + + +/** + * Count the number of instructions in a function. + */ +unsigned +lp_build_count_instructions(LLVMValueRef function) +{ + unsigned num_instrs = 0; + LLVMBasicBlockRef block; + + block = LLVMGetFirstBasicBlock(function); + while (block) { + LLVMValueRef instr; + instr = LLVMGetFirstInstruction(block); + while (instr) { + ++num_instrs; + + instr = LLVMGetNextInstruction(instr); + } + block = LLVMGetNextBasicBlock(block); + } + + return num_instrs; +} diff --git a/src/gallium/auxiliary/gallivm/lp_bld_type.h b/src/gallium/auxiliary/gallivm/lp_bld_type.h index 5007e83ac5f..f11a190e7cc 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_type.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_type.h @@ -398,4 +398,8 @@ lp_build_context_init(struct lp_build_context *bld, struct lp_type type); +unsigned +lp_build_count_instructions(LLVMValueRef function); + + #endif /* !LP_BLD_TYPE_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h index 70fba213095..438fc887083 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.h +++ b/src/gallium/drivers/llvmpipe/lp_context.h @@ -129,6 +129,7 @@ struct llvmpipe_context { /** List of all fragment shader variants */ struct lp_fs_variant_list_item fs_variants_list; unsigned nr_fs_variants; + unsigned nr_fs_instrs; /** JIT code generation */ struct gallivm_state *gallivm; diff --git a/src/gallium/drivers/llvmpipe/lp_limits.h b/src/gallium/drivers/llvmpipe/lp_limits.h index 2538164ffaa..43b00c56a5f 100644 --- a/src/gallium/drivers/llvmpipe/lp_limits.h +++ b/src/gallium/drivers/llvmpipe/lp_limits.h @@ -73,6 +73,12 @@ #define LP_MAX_SHADER_VARIANTS 1024 /** + * Max number of instructions (for all fragment shaders combined per context) + * that will be kept around. + */ +#define LP_MAX_SHADER_INSTRUCTIONS (128*1024) + +/** * Max number of setup variants that will be kept around. * * These are determined by the combination of the fragment shader diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index 26f8d7ff765..5af74fe7925 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -804,6 +804,7 @@ generate_fragment(struct llvmpipe_context *lp, LLVMWriteBitcodeToFile(gallivm->module, "llvmpipe.bc"); } + variant->nr_instrs += lp_build_count_instructions(function); /* * Translate the LLVM IR into machine code. */ @@ -1129,6 +1130,7 @@ llvmpipe_remove_shader_variant(struct llvmpipe_context *lp, /* remove from context's list */ remove_from_list(&variant->list_item_global); lp->nr_fs_variants--; + lp->nr_fs_instrs -= variant->nr_instrs; FREE(variant); } @@ -1350,11 +1352,22 @@ llvmpipe_update_fs(struct llvmpipe_context *lp) /* variant not found, create it now */ int64_t t0, t1, dt; unsigned i; + unsigned variants_to_cull; + + if (0) { + debug_printf("%u variants,\t%u instrs,\t%u instrs/variant\n", + lp->nr_fs_variants, + lp->nr_fs_instrs, + lp->nr_fs_variants ? lp->nr_fs_instrs / lp->nr_fs_variants : 0); + } /* First, check if we've exceeded the max number of shader variants. * If so, free 25% of them (the least recently used ones). */ - if (lp->nr_fs_variants >= LP_MAX_SHADER_VARIANTS) { + variants_to_cull = lp->nr_fs_variants >= LP_MAX_SHADER_VARIANTS ? LP_MAX_SHADER_VARIANTS / 4 : 0; + + if (variants_to_cull || + lp->nr_fs_instrs >= LP_MAX_SHADER_INSTRUCTIONS) { struct pipe_context *pipe = &lp->pipe; /* @@ -1370,17 +1383,15 @@ llvmpipe_update_fs(struct llvmpipe_context *lp) * pending for destruction on flush. */ - if (lp->nr_fs_variants >= LP_MAX_SHADER_VARIANTS) { - for (i = 0; i < LP_MAX_SHADER_VARIANTS / 4; i++) { - struct lp_fs_variant_list_item *item; - if (is_empty_list(&lp->fs_variants_list)) { - break; - } - item = last_elem(&lp->fs_variants_list); - assert(item); - assert(item->base); - llvmpipe_remove_shader_variant(lp, item->base); + for (i = 0; i < variants_to_cull || lp->nr_fs_instrs >= LP_MAX_SHADER_INSTRUCTIONS; i++) { + struct lp_fs_variant_list_item *item; + if (is_empty_list(&lp->fs_variants_list)) { + break; } + item = last_elem(&lp->fs_variants_list); + assert(item); + assert(item->base); + llvmpipe_remove_shader_variant(lp, item->base); } } @@ -1401,6 +1412,7 @@ llvmpipe_update_fs(struct llvmpipe_context *lp) insert_at_head(&shader->variants, &variant->list_item_local); insert_at_head(&lp->fs_variants_list, &variant->list_item_global); lp->nr_fs_variants++; + lp->nr_fs_instrs += variant->nr_instrs; shader->variants_cached++; } } diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.h b/src/gallium/drivers/llvmpipe/lp_state_fs.h index 98410c69359..273d241d8fc 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.h +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.h @@ -88,6 +88,9 @@ struct lp_fragment_shader_variant lp_jit_frag_func jit_function[2]; + /* Total number of LLVM instructions generated */ + unsigned nr_instrs; + struct lp_fs_variant_list_item list_item_global, list_item_local; struct lp_fragment_shader *shader; |