diff options
author | Eric Anholt <[email protected]> | 2010-08-27 12:54:12 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2010-08-27 13:15:05 -0700 |
commit | 130368f910a806a12287c7561df7dddd0fc8be40 (patch) | |
tree | 2e7e2aaf4c3b2026412da60e4eea9d05ba352f1e /src/mesa/drivers | |
parent | a0ffee2cd79deb5a437784e25de6512d7f8e6bb8 (diff) |
i965: Add support for if instructions in the new FS backend.
20 more piglit tests pass.
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs.cpp | 62 |
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: |