summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2010-08-27 12:54:12 -0700
committerEric Anholt <[email protected]>2010-08-27 13:15:05 -0700
commit130368f910a806a12287c7561df7dddd0fc8be40 (patch)
tree2e7e2aaf4c3b2026412da60e4eea9d05ba352f1e
parenta0ffee2cd79deb5a437784e25de6512d7f8e6bb8 (diff)
i965: Add support for if instructions in the new FS backend.
20 more piglit tests pass.
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.cpp62
1 files changed, 61 insertions, 1 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index 41b8ecd6815..76000609404 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -311,6 +311,14 @@ public:
this->predicated = false;
}
+ fs_inst(int opcode)
+ {
+ this->opcode = opcode;
+ this->saturate = false;
+ this->conditional_mod = BRW_CONDITIONAL_NONE;
+ this->predicated = false;
+ }
+
fs_inst(int opcode, fs_reg dst, fs_reg src0)
{
this->opcode = opcode;
@@ -932,7 +940,40 @@ fs_visitor::visit(ir_constant *ir)
void
fs_visitor::visit(ir_if *ir)
{
- assert(!"FINISHME");
+ fs_inst *inst;
+
+ /* Don't point the annotation at the if statement, because then it plus
+ * the then and else blocks get printed.
+ */
+ this->base_ir = ir->condition;
+
+ /* Generate the condition into the condition code. */
+ ir->condition->accept(this);
+ inst = emit(fs_inst(BRW_OPCODE_MOV, fs_reg(brw_null_reg()), this->result));
+ inst->conditional_mod = BRW_CONDITIONAL_NZ;
+
+ inst = emit(fs_inst(BRW_OPCODE_IF));
+ inst->predicated = true;
+
+ foreach_iter(exec_list_iterator, iter, ir->then_instructions) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+ this->base_ir = ir;
+
+ ir->accept(this);
+ }
+
+ if (!ir->else_instructions.is_empty()) {
+ emit(fs_inst(BRW_OPCODE_ELSE));
+
+ foreach_iter(exec_list_iterator, iter, ir->else_instructions) {
+ ir_instruction *ir = (ir_instruction *)iter.get();
+ this->base_ir = ir;
+
+ ir->accept(this);
+ }
+ }
+
+ emit(fs_inst(BRW_OPCODE_ENDIF));
}
void
@@ -1415,7 +1456,10 @@ fs_visitor::generate_code()
{
unsigned int annotation_len = 0;
int last_native_inst = 0;
+ struct brw_instruction *if_stack[16];
+ int if_stack_depth = 0;
+ memset(&if_stack, 0, sizeof(if_stack));
foreach_iter(exec_list_iterator, iter, this->instructions) {
fs_inst *inst = (fs_inst *)iter.get();
struct brw_reg src[3], dst;
@@ -1438,6 +1482,22 @@ fs_visitor::generate_code()
case BRW_OPCODE_MUL:
brw_MUL(p, dst, src[0], src[1]);
break;
+ case BRW_OPCODE_CMP:
+ brw_CMP(p, dst, inst->conditional_mod, src[0], src[1]);
+ break;
+ case BRW_OPCODE_IF:
+ assert(if_stack_depth < 16);
+ if_stack[if_stack_depth] = brw_IF(p, BRW_EXECUTE_8);
+ if_stack_depth++;
+ break;
+ case BRW_OPCODE_ELSE:
+ if_stack[if_stack_depth - 1] =
+ brw_ELSE(p, if_stack[if_stack_depth - 1]);
+ break;
+ case BRW_OPCODE_ENDIF:
+ if_stack_depth--;
+ brw_ENDIF(p , if_stack[if_stack_depth]);
+ break;
case FS_OPCODE_RCP:
case FS_OPCODE_RSQ:
case FS_OPCODE_SQRT: