summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Romanick <[email protected]>2011-07-25 16:41:39 -0700
committerIan Romanick <[email protected]>2011-08-02 08:23:15 -0700
commit3bb2f0dde1cd813a0b5e0b45be376f4d6606aeb8 (patch)
treea29e12ca66186a56412fc45f19cd8b5b4d3bcea9
parent322c3bf9dc4c6edbf5a8793475ce1307e1c0186b (diff)
i915: Fail without crashing if a Mesa IR program uses too many registers
This can only happen in GLSL shaders because assembly shaders that use too many temps are rejected by core Mesa. It is easiest to make this happen with shaders that contain flow-control that could not be lowered. Signed-off-by: Ian Romanick <[email protected]> Reviewed-by: Kenneth Graunke <[email protected]> Reviewed-by: Eric Anholt <[email protected]>
-rw-r--r--src/mesa/drivers/dri/i915/i915_fragprog.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/src/mesa/drivers/dri/i915/i915_fragprog.c b/src/mesa/drivers/dri/i915/i915_fragprog.c
index 6e1d7092237..32050cebf33 100644
--- a/src/mesa/drivers/dri/i915/i915_fragprog.c
+++ b/src/mesa/drivers/dri/i915/i915_fragprog.c
@@ -303,7 +303,7 @@ do { \
/*
* TODO: consider moving this into core
*/
-static void calc_live_regs( struct i915_fragment_program *p )
+static bool calc_live_regs( struct i915_fragment_program *p )
{
const struct gl_fragment_program *program = &p->FragProg;
GLuint regsUsed = 0xffff0000;
@@ -317,6 +317,9 @@ static void calc_live_regs( struct i915_fragment_program *p )
/* Register is written to: unmark as live for this and preceeding ops */
if (inst->DstReg.File == PROGRAM_TEMPORARY) {
+ if (inst->DstReg.Index > 16)
+ return false;
+
live_components[inst->DstReg.Index] &= ~inst->DstReg.WriteMask;
if (live_components[inst->DstReg.Index] == 0)
regsUsed &= ~(1 << inst->DstReg.Index);
@@ -327,6 +330,9 @@ static void calc_live_regs( struct i915_fragment_program *p )
if (inst->SrcReg[a].File == PROGRAM_TEMPORARY) {
unsigned c;
+ if (inst->SrcReg[a].Index > 16)
+ return false;
+
regsUsed |= 1 << inst->SrcReg[a].Index;
for (c = 0; c < 4; c++) {
@@ -340,6 +346,8 @@ static void calc_live_regs( struct i915_fragment_program *p )
p->usedRegs[i] = regsUsed;
}
+
+ return true;
}
static GLuint get_live_regs( struct i915_fragment_program *p,
@@ -394,7 +402,10 @@ upload_program(struct i915_fragment_program *p)
/* Not always needed:
*/
- calc_live_regs(p);
+ if (!calc_live_regs(p)) {
+ i915_program_error(p, "Could not allocate registers");
+ return;
+ }
while (1) {
GLuint src0, src1, src2, flags;