Mesa (master): i965: Add support for ir_loop counters to the new FS backend .

Eric Anholt anholt at kemper.freedesktop.org
Tue Sep 28 20:44:34 UTC 2010


Module: Mesa
Branch: master
Commit: 701c5f11c9102047c8962f053843469ada3b3a1a
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=701c5f11c9102047c8962f053843469ada3b3a1a

Author: Eric Anholt <eric at anholt.net>
Date:   Tue Sep 28 13:00:46 2010 -0700

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 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 f351b75..c1e6206 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));
 }
 




More information about the mesa-commit mailing list