Initial implementation of OPCODE_IF/ELSE/ENDIF instructions.
authorBrian <brian@yutani.localnet.net>
Sat, 20 Jan 2007 16:27:40 +0000 (09:27 -0700)
committerBrian <brian@yutani.localnet.net>
Sat, 20 Jan 2007 16:27:40 +0000 (09:27 -0700)
src/mesa/shader/prog_instruction.c
src/mesa/shader/prog_instruction.h
src/mesa/shader/prog_print.c
src/mesa/shader/slang/slang_codegen.c
src/mesa/shader/slang/slang_emit.c
src/mesa/shader/slang/slang_ir.h
src/mesa/swrast/s_fragprog.c
src/mesa/tnl/t_vb_arbprogram.c

index 1379018..3de71b8 100644 (file)
@@ -130,11 +130,14 @@ static const struct instruction_info InstInfo[MAX_OPCODE] = {
    { OPCODE_DP4,    "DP4",   2 },
    { OPCODE_DPH,    "DPH",   2 },
    { OPCODE_DST,    "DST",   2 },
+   { OPCODE_ELSE,   "ELSE",  0 },
    { OPCODE_END,    "END",   0 },
+   { OPCODE_ENDIF,  "ENDIF", 0 },
    { OPCODE_EX2,    "EX2",   1 },
    { OPCODE_EXP,    "EXP",   1 },
    { OPCODE_FLR,    "FLR",   1 },
    { OPCODE_FRC,    "FRC",   1 },
+   { OPCODE_IF,     "IF",    0 },
    { OPCODE_INT,    "INT",   1 },
    { OPCODE_KIL,    "KIL",   1 },
    { OPCODE_KIL_NV, "KIL",   0 },
index b659879..b100188 100644 (file)
@@ -143,11 +143,14 @@ typedef enum prog_opcode {
    OPCODE_DP4,       /*   X        X       X       X    */
    OPCODE_DPH,       /*   X        X       1.1          */
    OPCODE_DST,       /*   X        X       X       X    */
+   OPCODE_ELSE,
    OPCODE_END,       /*   X        X       X       X    */
+   OPCODE_ENDIF,
    OPCODE_EX2,       /*   X        X       2       X    */
    OPCODE_EXP,       /*   X                X            */
    OPCODE_FLR,       /*   X        X       2       X    */
    OPCODE_FRC,       /*   X        X       2       X    */
+   OPCODE_IF,
    OPCODE_INT,       /*                                 */
    OPCODE_KIL,       /*            X                    */
    OPCODE_KIL_NV,    /*                            X    */
index 04b7c7d..78ce752 100644 (file)
@@ -295,7 +295,7 @@ _mesa_print_instruction(const struct prog_instruction *inst)
       print_comment(inst);
       break;
    case OPCODE_BRA:
-      _mesa_printf("BRA %u (%s.%s)",
+      _mesa_printf("BRA %u (%s%s)",
                    inst->BranchTarget,
                    condcode_string(inst->DstReg.CondMask),
                    swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE));
@@ -305,6 +305,18 @@ _mesa_print_instruction(const struct prog_instruction *inst)
       _mesa_printf("CAL %u", inst->BranchTarget);
       print_comment(inst);
       break;
+   case OPCODE_IF:
+      _mesa_printf("  IF (%s%s)",
+                   condcode_string(inst->DstReg.CondMask),
+                   swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE));
+      print_comment(inst);
+      break;
+   case OPCODE_ELSE:
+      _mesa_printf("  ELSE;\n");
+      break;
+   case OPCODE_ENDIF:
+      _mesa_printf("  ENDIF;\n");
+      break;
    case OPCODE_END:
       _mesa_printf("END");
       print_comment(inst);
index 6923c00..aba6813 100644 (file)
@@ -1561,6 +1561,51 @@ _slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper)
 
 
 /**
+ * Use high-level IF/ELSE/ENDIF instructions
+ */
+static slang_ir_node *
+_slang_gen_if2(slang_assemble_ctx * A, const slang_operation *oper)
+{
+   /*
+    * eval expr (child[0]), updating condcodes
+    * branch if false to _else or _endif
+    * "true" code block
+    * if haveElseClause clause:
+    *    jump "__endif"
+    *    label "__else"
+    *    "false" code block
+    * label "__endif"
+    */
+   const GLboolean haveElseClause = !_slang_is_noop(&oper->children[2]);
+   slang_ir_node *ifNode, *cond, *trueBody, *elseNode, *falseBody, *endifNode;
+   slang_ir_node *tree;
+
+   cond = _slang_gen_operation(A, &oper->children[0]);
+   cond = _slang_gen_cond(cond);
+   /*assert(cond->Store);*/
+   ifNode = new_node(IR_IF, cond, NULL);
+
+   trueBody = _slang_gen_operation(A, &oper->children[1]);
+   tree = new_seq(ifNode, trueBody);
+
+   if (haveElseClause) {
+      /* else clause */
+      elseNode = new_node(IR_ELSE, NULL, NULL);
+      tree = new_seq(tree, elseNode);
+
+      falseBody = _slang_gen_operation(A, &oper->children[2]);
+      tree = new_seq(tree, falseBody);
+   }
+
+   endifNode = new_node(IR_ENDIF, NULL, NULL);
+   tree = new_seq(tree, endifNode);
+
+   return tree;
+}
+
+
+
+/**
  * Generate IR node for storage of a temporary of given size.
  */
 static slang_ir_node *
@@ -2314,7 +2359,13 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
    case slang_oper_identifier:
       return _slang_gen_variable(A, oper);
    case slang_oper_if:
-      return _slang_gen_if(A, oper);
+      if (A->program->Target == GL_FRAGMENT_PROGRAM_ARB) {
+         return _slang_gen_if(A, oper);
+      }
+      else {
+         /* XXX update tnl executor */
+         return _slang_gen_if(A, oper);
+      }
    case slang_oper_field:
       return _slang_gen_field(A, oper);
    case slang_oper_subscript:
index 6c31bfc..44fd375 100644 (file)
@@ -91,6 +91,9 @@ static slang_ir_info IrInfo[] = {
    { IR_JUMP, "IR_JUMP", 0, 0, 0 },
    { IR_CJUMP0, "IR_CJUMP0", 0, 0, 0 },
    { IR_CJUMP1, "IR_CJUMP1", 0, 0, 0 },
+   { IR_IF, "IR_IF", 0, 0, 0 },
+   { IR_ELSE, "IR_ELSE", 0, 0, 0 },
+   { IR_ENDIF, "IR_ENDIF", 0, 0, 0 },
    { IR_KILL, "IR_KILL", 0, 0, 0 },
    { IR_COND, "IR_COND", 0, 0, 0 },
    { IR_CALL, "IR_CALL", 0, 0, 0 },
@@ -271,6 +274,18 @@ slang_print_ir(const slang_ir_node *n, int indent)
       printf("CJUMP1 %s\n", n->Target);
       slang_print_ir(n->Children[0], indent+3);
       break;
+
+   case IR_IF:
+      printf("IF \n");
+      slang_print_ir(n->Children[0], indent+3);
+      break;
+   case IR_ELSE:
+      printf("ELSE\n");
+      break;
+   case IR_ENDIF:
+      printf("ENDIF\n");
+      break;
+
    case IR_VAR:
       printf("VAR %s%s at %s  store %p\n",
              (char *) n->Var->a_name, swizzle_string(n->Store->Swizzle),
@@ -862,6 +877,28 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
    case IR_KILL:
       return emit_kill(prog);
 
+   case IR_IF:
+      {
+         struct prog_instruction *inst;
+         emit(vt, n->Children[0], prog);  /* the condition */
+         inst = new_instruction(prog, OPCODE_IF);
+         inst->DstReg.CondMask = COND_NE;  /* if cond is non-zero */
+         inst->DstReg.CondSwizzle = SWIZZLE_X;
+         return inst;
+      }
+   case IR_ELSE:
+      {
+         struct prog_instruction *inst;
+         inst = new_instruction(prog, OPCODE_ELSE);
+         return inst;
+      }
+   case IR_ENDIF:
+      {
+         struct prog_instruction *inst;
+         inst = new_instruction(prog, OPCODE_ENDIF);
+         return inst;
+      }
+
    default:
       _mesa_problem(NULL, "Unexpected IR opcode in emit()\n");
       abort();
index 4072c70..e5a0fa8 100644 (file)
@@ -51,6 +51,9 @@ typedef enum
    IR_CJUMP0,  /* conditional jump if zero */
    IR_CJUMP1,  /* conditional jump if one (or non-zero) */
    IR_COND,    /* conditional expression */
+   IR_IF,      /* high-level IF */
+   IR_ELSE,    /* high-level ELSE */
+   IR_ENDIF,   /* high-level ENDIF */
    IR_CALL,    /* call subroutine */
    IR_MOVE,
    IR_ADD,
index b842b49..813345f 100644 (file)
@@ -888,6 +888,73 @@ execute_program( GLcontext *ctx,
                store_vector4( inst, machine, result );
             }
             break;
+         case OPCODE_IF:
+            {
+               const GLuint swizzle = inst->DstReg.CondSwizzle;
+               const GLuint condMask = inst->DstReg.CondMask;
+               if (test_cc(machine->CondCodes[GET_SWZ(swizzle, 0)], condMask) ||
+                   test_cc(machine->CondCodes[GET_SWZ(swizzle, 1)], condMask) ||
+                   test_cc(machine->CondCodes[GET_SWZ(swizzle, 2)], condMask) ||
+                   test_cc(machine->CondCodes[GET_SWZ(swizzle, 3)], condMask)) {
+                  /* do if-clause (just continue execution) */
+               }
+               else {
+                  /* do else-clause, or go to endif */
+                  GLint ifDepth = 1;
+                  do {
+                     pc++;
+                     inst = program->Base.Instructions + pc;
+                     if (inst->Opcode == OPCODE_END) {
+                        /* mal-formed program! */
+                        abort();
+                     }
+                     else if (inst->Opcode == OPCODE_IF) {
+                        ifDepth++;
+                     }
+                     else if (inst->Opcode == OPCODE_ELSE) {
+                        if (ifDepth == 0) {
+                           /* ok, continue normal execution */
+                           break;
+                        }
+                     }
+                     else if (inst->Opcode == OPCODE_ENDIF) {
+                        ifDepth--;
+                        if (ifDepth == 0) {
+                           /* ok, continue normal execution */
+                           break;
+                        }
+                     }
+                     assert(ifDepth >= 0);
+                  } while (pc < maxInst);
+               }
+            }
+            break;
+         case OPCODE_ELSE:
+            {
+               /* find/goto ENDIF */
+               GLint ifDepth = 1;
+               do {
+                  pc++;
+                  inst = program->Base.Instructions + pc;
+                  if (inst->Opcode == OPCODE_END) {
+                     /* mal-formed program! */
+                     abort();
+                  }
+                  else if (inst->Opcode == OPCODE_IF) {
+                     ifDepth++;
+                  }
+                  else if (inst->Opcode == OPCODE_ENDIF) {
+                     ifDepth--;
+                     if (ifDepth == 0)
+                        break;
+                  }
+                  assert(ifDepth >= 0);
+               } while (pc < maxInst);
+            }
+            break;
+         case OPCODE_ENDIF:
+            /* nothing */
+            break;
          case OPCODE_INT: /* float to int */
             {
                GLfloat a[4], result[4];
index 5773f0f..5726a66 100644 (file)
@@ -746,11 +746,14 @@ static void (* const opcode_func[MAX_OPCODE+3])(struct arb_vp_machine *, union i
    do_DP4,
    do_DPH,
    do_DST,
-   do_NOP,
+   do_NOP,/*ELSE*/
+   do_NOP,/*END*/
+   do_NOP,/*ENDIF*/
    do_EX2,
    do_EXP,
    do_FLR,
    do_FRC,
+   do_NOP,/*IF*/
    do_INT,
    do_NOP,/*KIL*/
    do_NOP,/*KIL_NV*/