summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2010-08-18 21:21:05 -0700
committerEric Anholt <eric@anholt.net>2010-08-18 21:31:56 -0700
commit8de8c97275e9555183a7e8f2238143657bbe60b2 (patch)
tree69a426182b45075678ca2b7a64f20e6c49846615
parentbad29dc6dad7ed1bff46c67e61dab01f8d82b557 (diff)
i965: Set the if stack pop count when breaking out of a loop inside an if.
Otherwise, we might end up with the if stack pointing at the wrong place. Fixes GPU hang with glsl-vs-if-loop.
-rw-r--r--src/mesa/drivers/dri/i965/brw_vs_emit.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_vs_emit.c b/src/mesa/drivers/dri/i965/brw_vs_emit.c
index 7cbf22f2da..18eb845ed8 100644
--- a/src/mesa/drivers/dri/i965/brw_vs_emit.c
+++ b/src/mesa/drivers/dri/i965/brw_vs_emit.c
@@ -1562,6 +1562,7 @@ void brw_vs_emit(struct brw_vs_compile *c )
const GLuint nr_insns = c->vp->program.Base.NumInstructions;
GLuint insn, if_depth = 0, loop_depth = 0;
struct brw_instruction *if_inst[MAX_IF_DEPTH], *loop_inst[MAX_LOOP_DEPTH] = { 0 };
+ int if_depth_in_loop[MAX_LOOP_DEPTH];
const struct brw_indirect stack_index = brw_indirect(0, 0);
GLuint index;
GLuint file;
@@ -1575,6 +1576,7 @@ void brw_vs_emit(struct brw_vs_compile *c )
brw_set_compression_control(p, BRW_COMPRESSION_NONE);
brw_set_access_mode(p, BRW_ALIGN_16);
+ if_depth_in_loop[loop_depth] = 0;
for (insn = 0; insn < nr_insns; insn++) {
GLuint i;
@@ -1613,7 +1615,8 @@ void brw_vs_emit(struct brw_vs_compile *c )
const struct prog_instruction *inst = &c->vp->program.Base.Instructions[insn];
struct brw_reg args[3], dst;
GLuint i;
-
+ struct brw_instruction *temp;
+
#if 0
printf("%d: ", insn);
_mesa_print_instruction(inst);
@@ -1781,6 +1784,7 @@ void brw_vs_emit(struct brw_vs_compile *c )
if_inst[if_depth] = brw_IF(p, BRW_EXECUTE_8);
/* Note that brw_IF smashes the predicate_control field. */
if_inst[if_depth]->header.predicate_control = get_predicate(inst);
+ if_depth_in_loop[loop_depth]++;
if_depth++;
break;
case OPCODE_ELSE:
@@ -1790,18 +1794,22 @@ void brw_vs_emit(struct brw_vs_compile *c )
case OPCODE_ENDIF:
assert(if_depth > 0);
brw_ENDIF(p, if_inst[--if_depth]);
+ if_depth_in_loop[loop_depth]--;
break;
case OPCODE_BGNLOOP:
loop_inst[loop_depth++] = brw_DO(p, BRW_EXECUTE_8);
+ if_depth_in_loop[loop_depth] = 0;
break;
case OPCODE_BRK:
brw_set_predicate_control(p, get_predicate(inst));
- brw_BREAK(p);
+ temp = brw_BREAK(p);
+ temp->bits3.if_else.pop_count = if_depth_in_loop[loop_depth];
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
break;
case OPCODE_CONT:
brw_set_predicate_control(p, get_predicate(inst));
- brw_CONT(p);
+ temp = brw_CONT(p);
+ temp->bits3.if_else.pop_count = if_depth_in_loop[loop_depth];
brw_set_predicate_control(p, BRW_PREDICATE_NONE);
break;
case OPCODE_ENDLOOP:
@@ -1821,12 +1829,10 @@ void brw_vs_emit(struct brw_vs_compile *c )
if (inst0->header.opcode == BRW_OPCODE_BREAK &&
inst0->bits3.if_else.jump_count == 0) {
inst0->bits3.if_else.jump_count = br * (inst1 - inst0 + 1);
- inst0->bits3.if_else.pop_count = 0;
}
else if (inst0->header.opcode == BRW_OPCODE_CONTINUE &&
inst0->bits3.if_else.jump_count == 0) {
inst0->bits3.if_else.jump_count = br * (inst1 - inst0);
- inst0->bits3.if_else.pop_count = 0;
}
}
}