From 701c5f11c9102047c8962f053843469ada3b3a1a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 28 Sep 2010 13:00:46 -0700 Subject: i965: Add support for ir_loop counters to the new FS backend. Fixes: glsl1-discard statement in for loop glsl-fs-loop-two-counter-02 glsl-fs-loop-two-counter-04 --- src/mesa/drivers/dri/i965/brw_fs.cpp | 64 +++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 5 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp index f351b75081..c1e6206231 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp @@ -612,6 +612,9 @@ fs_visitor::visit(ir_variable *ir) { fs_reg *reg = NULL; + if (variable_storage(ir)) + return; + if (strcmp(ir->name, "gl_FragColor") == 0) { this->frag_color = ir; } else if (strcmp(ir->name, "gl_FragData") == 0) { @@ -1175,12 +1178,20 @@ fs_visitor::visit(ir_if *ir) void fs_visitor::visit(ir_loop *ir) { - assert(!ir->from); - assert(!ir->to); - assert(!ir->increment); - assert(!ir->counter); + fs_reg counter = reg_undef; - emit(fs_inst(BRW_OPCODE_DO)); + if (ir->counter) { + this->base_ir = ir->counter; + ir->counter->accept(this); + counter = *(variable_storage(ir->counter)); + + if (ir->from) { + this->base_ir = ir->from; + ir->from->accept(this); + + emit(fs_inst(BRW_OPCODE_MOV, counter, this->result)); + } + } /* Start a safety counter. If the user messed up their loop * counting, we don't want to hang the GPU. @@ -1188,6 +1199,43 @@ fs_visitor::visit(ir_loop *ir) fs_reg max_iter = fs_reg(this, glsl_type::int_type); emit(fs_inst(BRW_OPCODE_MOV, max_iter, fs_reg(10000))); + emit(fs_inst(BRW_OPCODE_DO)); + + if (ir->to) { + this->base_ir = ir->to; + ir->to->accept(this); + + fs_inst *inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null, + counter, this->result)); + switch (ir->cmp) { + case ir_binop_equal: + inst->conditional_mod = BRW_CONDITIONAL_Z; + break; + case ir_binop_nequal: + inst->conditional_mod = BRW_CONDITIONAL_NZ; + break; + case ir_binop_gequal: + inst->conditional_mod = BRW_CONDITIONAL_GE; + break; + case ir_binop_lequal: + inst->conditional_mod = BRW_CONDITIONAL_LE; + break; + case ir_binop_greater: + inst->conditional_mod = BRW_CONDITIONAL_G; + break; + case ir_binop_less: + inst->conditional_mod = BRW_CONDITIONAL_L; + break; + default: + assert(!"not reached: unknown loop condition"); + this->fail = true; + break; + } + + inst = emit(fs_inst(BRW_OPCODE_BREAK)); + inst->predicated = true; + } + foreach_iter(exec_list_iterator, iter, ir->body_instructions) { ir_instruction *ir = (ir_instruction *)iter.get(); fs_inst *inst; @@ -1203,6 +1251,12 @@ fs_visitor::visit(ir_loop *ir) inst->predicated = true; } + if (ir->increment) { + this->base_ir = ir->increment; + ir->increment->accept(this); + emit(fs_inst(BRW_OPCODE_ADD, counter, counter, this->result)); + } + emit(fs_inst(BRW_OPCODE_WHILE)); } -- cgit v1.2.3