summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 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;