summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2010-09-28 13:00:46 -0700
committerEric Anholt <[email protected]>2010-09-28 13:31:01 -0700
commit701c5f11c9102047c8962f053843469ada3b3a1a (patch)
tree65f9ed1e351f8019f5d8165ac7621e2d9d68720d /src
parent35f94b1942d9b99463ef9e179ebf70809e3bea69 (diff)
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
Diffstat (limited to 'src')
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.cpp64
1 files 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 f351b75081c..c1e62062310 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));
}