summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosé Fonseca <jfonseca@vmware.com>2011-11-30 17:12:00 +0000
committerJosé Fonseca <jfonseca@vmware.com>2011-12-08 17:59:33 +0000
commit6cf7245f6938e27c9b8a1742f27659aec017bbdc (patch)
tree79397228a7f7408efd756f6e58298ff9977204f7
parentf32c7232a8a16887af710a11f025381bc73640f0 (diff)
llvmpipe: Trim the fragment shader cached based on LLVM IR instruction count.
Number of fragment shader variants is not very representative of the memory used by LLVM, neither is number of shader instructions, as often texture sampling constitutes most of the generated code. This change adds an additional trim criteria: least recently used fragment shader variants will be freed until the total number of LLVM IR instruction falls below a specified threshold. Reviewed-by: Brian Paul <brianp@vmware.com>
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_type.c25
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_type.h4
-rw-r--r--src/gallium/drivers/llvmpipe/lp_context.h1
-rw-r--r--src/gallium/drivers/llvmpipe/lp_limits.h6
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_fs.c34
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_fs.h3
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 efd159f886..413e69beda 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 5007e83ac5..f11a190e7c 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 70fba21309..438fc88708 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 2538164ffa..43b00c56a5 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 26f8d7ff76..5af74fe792 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 98410c6935..273d241d8f 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;