Add the ability to generate programs that doesn't use condition codes.
authorBrian <brian@yutani.localnet.net>
Fri, 23 Mar 2007 20:47:46 +0000 (14:47 -0600)
committerBrian <brian@yutani.localnet.net>
Fri, 23 Mar 2007 20:47:46 +0000 (14:47 -0600)
ctx->Shader.EmitCondCodes determines if we use condition codes.
If not, IF statement uses first operand's X component as the condition.
Added OPCODE_BRK0, OPCODE_BRK1, OPCODE_CONT0, OPCODE_CONT1 to handle
the common cases of conditional break/continue.

src/mesa/main/mtypes.h
src/mesa/shader/prog_execute.c
src/mesa/shader/prog_instruction.c
src/mesa/shader/prog_instruction.h
src/mesa/shader/prog_print.c
src/mesa/shader/shader_api.c
src/mesa/shader/slang/slang_emit.c
src/mesa/tnl/t_vb_arbprogram.c

index 0c9bf200d8c5eff777a55ac130f0788d007c6177..828b0f2384e009b7bba3e8a0db56964dc55196ed 100644 (file)
@@ -2127,8 +2127,10 @@ struct gl_shader_program
 struct gl_shader_state
 {
    struct gl_shader_program *CurrentProgram; /**< The user-bound program */
-   GLboolean EmitHighLevelInstructions; /**< Driver-selectable */
-   GLboolean EmitComments;              /**< Driver-selectable */
+   /** Driver-selectable options: */
+   GLboolean EmitHighLevelInstructions; /**< IF/ELSE/ENDIF vs. BRA, etc. */
+   GLboolean EmitCondCodes;             /**< Use condition codes? */
+   GLboolean EmitComments;              /**< Annotated instructions */
 };
 
 
index 092c07f7b65a4fd7c18eeb65960f08f0599a7bb6..f881d477caa58e08e554cfb4c5a4540d98abbe14 100644 (file)
@@ -720,6 +720,32 @@ _mesa_execute_program(GLcontext * ctx,
             pc = inst->BranchTarget - 1;
          }
          break;
+      case OPCODE_BRK0:   /* Break if zero */
+         /* fall-through */
+      case OPCODE_CONT0:  /* Continue if zero */
+         {
+            GLfloat a[4];
+            fetch_vector1(&inst->SrcReg[0], machine, a);
+            if (a[0] == 0.0) {
+               /* take branch */
+               /* Subtract 1 here since we'll do pc++ at end of for-loop */
+               pc = inst->BranchTarget - 1;
+            }
+         }
+         break;
+      case OPCODE_BRK1:   /* Break if non-zero */
+         /* fall-through */
+      case OPCODE_CONT1:  /* Continue if non-zero */
+         {
+            GLfloat a[4];
+            fetch_vector1(&inst->SrcReg[0], machine, a);
+            if (a[0] != 0.0) {
+               /* take branch */
+               /* Subtract 1 here since we'll do pc++ at end of for-loop */
+               pc = inst->BranchTarget - 1;
+            }
+         }
+         break;
       case OPCODE_CAL:         /* Call subroutine (conditional) */
          if (eval_condition(machine, inst)) {
             /* call the subroutine */
@@ -914,13 +940,26 @@ _mesa_execute_program(GLcontext * ctx,
          }
          break;
       case OPCODE_IF:
-         if (eval_condition(machine, inst)) {
-            /* do if-clause (just continue execution) */
-         }
-         else {
-            /* go to the instruction after ELSE or ENDIF */
-            assert(inst->BranchTarget >= 0);
-            pc = inst->BranchTarget - 1;
+         {
+            GLboolean cond;
+            /* eval condition */
+            if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
+               GLfloat a[4];
+               fetch_vector1(&inst->SrcReg[0], machine, a);
+               cond = (a[0] != 0.0);
+            }
+            else {
+               cond = eval_condition(machine, inst);
+            }
+            /* do if/else */
+            if (cond) {
+               /* do if-clause (just continue execution) */
+            }
+            else {
+               /* go to the instruction after ELSE or ENDIF */
+               assert(inst->BranchTarget >= 0);
+               pc = inst->BranchTarget - 1;
+            }
          }
          break;
       case OPCODE_ELSE:
index ed479a7f614b29432c9e799fce685e5f6520f783..272caf6c746f8ce97d3462a4a5f085bd39f95056 100644 (file)
@@ -138,9 +138,13 @@ static const struct instruction_info InstInfo[MAX_OPCODE] = {
    { OPCODE_BGNSUB, "BGNSUB", 0 },
    { OPCODE_BRA,    "BRA",   0 },
    { OPCODE_BRK,    "BRK",   0 },
+   { OPCODE_BRK0,   "BRK0",  1 },
+   { OPCODE_BRK1,   "BRK1",  1 },
    { OPCODE_CAL,    "CAL",   0 },
    { OPCODE_CMP,    "CMP",   3 },
-   { OPCODE_CONT,   "CONT",  1 },
+   { OPCODE_CONT,   "CONT",  0 },
+   { OPCODE_CONT0,  "CONT0", 1 },
+   { OPCODE_CONT1,  "CONT1", 1 },
    { OPCODE_COS,    "COS",   1 },
    { OPCODE_DDX,    "DDX",   1 },
    { OPCODE_DDY,    "DDY",   1 },
index c800757aa0f6c993fa0d0e32e508e966aa5ff22a..dc2d2dc29b42c16f809d96b1b43a8518a89ad35f 100644 (file)
@@ -153,9 +153,13 @@ typedef enum prog_opcode {
    OPCODE_BGNSUB,    /*                                     opt  */
    OPCODE_BRA,       /*                    2                 X   */
    OPCODE_BRK,       /*                    2                opt  */
+   OPCODE_BRK0,      /*                                     opt  */
+   OPCODE_BRK1,      /*                                     opt  */
    OPCODE_CAL,       /*                    2       2             */
    OPCODE_CMP,       /*            X                             */
    OPCODE_CONT,      /*                                     opt  */
+   OPCODE_CONT0,     /*                                     opt  */
+   OPCODE_CONT1,     /*                                     opt  */
    OPCODE_COS,       /*            X       2       X         X   */
    OPCODE_DDX,       /*                            X         X   */
    OPCODE_DDY,       /*                            X         X   */
index d290ce0a2a5e892ea1ac898f6202b430a3dba5be..39d2a07812e932f24c1bc9e854d183826962b02c 100644 (file)
@@ -572,10 +572,20 @@ _mesa_print_instruction_opt(const struct prog_instruction *inst, GLint indent,
       print_comment(inst);
       break;
    case OPCODE_IF:
-      _mesa_printf("IF (%s%s); # (if false, goto %d)",
-                   condcode_string(inst->DstReg.CondMask),
-                   _mesa_swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE),
-                   inst->BranchTarget);
+      if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
+         /* Use ordinary register */
+         _mesa_printf("IF ");
+         print_src_reg(&inst->SrcReg[0], mode, prog);
+         _mesa_printf("; ");
+      }
+      else {
+         /* Use cond codes */
+         _mesa_printf("IF (%s%s);",
+                      condcode_string(inst->DstReg.CondMask),
+                      _mesa_swizzle_string(inst->DstReg.CondSwizzle,
+                                           0, GL_FALSE));
+      }
+      _mesa_printf(" # (if false, goto %d)", inst->BranchTarget);
       print_comment(inst);
       return indent + 3;
    case OPCODE_ELSE:
@@ -604,6 +614,18 @@ _mesa_print_instruction_opt(const struct prog_instruction *inst, GLint indent,
                    inst->BranchTarget);
       print_comment(inst);
       break;
+
+   case OPCODE_BRK0:
+   case OPCODE_BRK1:
+   case OPCODE_CONT0:
+   case OPCODE_CONT1:
+      _mesa_printf("%s ", _mesa_opcode_string(inst->Opcode));
+      print_src_reg(&inst->SrcReg[0], mode, prog);
+      _mesa_printf("; ");
+      _mesa_printf(" # (goto %d)", inst->BranchTarget);
+      print_comment(inst);
+      break;
+
    case OPCODE_BGNSUB:
       _mesa_printf("SUB");
       print_comment(inst);
index aab522e292cfad91135b0dfd3815281b796d6dbc..88aa8c50f5bf39e4a5684aaa489c9a0514d2a33a 100644 (file)
@@ -206,6 +206,7 @@ _mesa_init_shader_state(GLcontext * ctx)
     * are generated by the GLSL compiler.
     */
    ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
+   ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */
    ctx->Shader.EmitComments = GL_FALSE;
 }
 
index 16a054b35e5b0649efbf8c9fcfa4b99b5153f950..9e476b8a0fae89bef69c42104f4df519085ed3c9 100644 (file)
@@ -61,6 +61,7 @@ typedef struct
    struct gl_program *prog;
    /* code-gen options */
    GLboolean EmitHighLevelInstructions;
+   GLboolean EmitCondCodes;
    GLboolean EmitComments;
 } slang_emit_info;
 
@@ -1155,10 +1156,6 @@ emit_move(slang_emit_info *emitInfo, slang_ir_node *n)
 static struct prog_instruction *
 emit_cond(slang_emit_info *emitInfo, slang_ir_node *n)
 {
-   /* Conditional expression (in if/while/for stmts).
-    * Need to update condition code register.
-    * Next instruction is typically an IR_IF.
-    */
    struct prog_instruction *inst;
 
    if (!n->Children[0])
@@ -1166,28 +1163,39 @@ emit_cond(slang_emit_info *emitInfo, slang_ir_node *n)
 
    inst = emit(emitInfo, n->Children[0]);
 
-   if (inst) {
-      /* set inst's CondUpdate flag */
-      inst->CondUpdate = GL_TRUE;
-      n->Store = n->Children[0]->Store;
-      return inst; /* XXX or null? */
+   if (emitInfo->EmitCondCodes) {
+      /* Conditional expression (in if/while/for stmts).
+       * Need to update condition code register.
+       * Next instruction is typically an IR_IF.
+       */
+      if (inst) {
+         /* set inst's CondUpdate flag */
+         inst->CondUpdate = GL_TRUE;
+         n->Store = n->Children[0]->Store;
+         return inst; /* XXX or null? */
+      }
+      else {
+         /* This'll happen for things like "if (i) ..." where no code
+          * is normally generated for the expression "i".
+          * Generate a move instruction just to set condition codes.
+          * Note: must use full 4-component vector since all four
+          * condition codes must be set identically.
+          */
+         if (!alloc_temp_storage(emitInfo, n, 4))
+            return NULL;
+         inst = new_instruction(emitInfo, OPCODE_MOV);
+         inst->CondUpdate = GL_TRUE;
+         storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
+         storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store);
+         _slang_free_temp(emitInfo->vt, n->Store);
+         inst->Comment = _mesa_strdup("COND expr");
+         return inst; /* XXX or null? */
+      }
    }
    else {
-      /* This'll happen for things like "if (i) ..." where no code
-       * is normally generated for the expression "i".
-       * Generate a move instruction just to set condition codes.
-       * Note: must use full 4-component vector since all four
-       * condition codes must be set identically.
-       */
-      if (!alloc_temp_storage(emitInfo, n, 4))
-         return NULL;
-      inst = new_instruction(emitInfo, OPCODE_MOV);
-      inst->CondUpdate = GL_TRUE;
-      storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
-      storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store);
-      _slang_free_temp(emitInfo->vt, n->Store);
-      inst->Comment = _mesa_strdup("COND expr");
-      return inst; /* XXX or null? */
+      /* No-op */
+      n->Store = n->Children[0]->Store;
+      return NULL;
    }
 }
 
@@ -1244,7 +1252,13 @@ emit_if(slang_emit_info *emitInfo, slang_ir_node *n)
    ifInstLoc = prog->NumInstructions;
    if (emitInfo->EmitHighLevelInstructions) {
       ifInst = new_instruction(emitInfo, OPCODE_IF);
-      ifInst->DstReg.CondMask = COND_NE;  /* if cond is non-zero */
+      if (emitInfo->EmitCondCodes) {
+         ifInst->DstReg.CondMask = COND_NE;  /* if cond is non-zero */
+      }
+      else {
+         /* test reg.x */
+         storage_to_src_reg(&ifInst->SrcReg[0], n->Children[0]->Store);
+      }
    }
    else {
       /* conditional jump to else, or endif */
@@ -1252,8 +1266,10 @@ emit_if(slang_emit_info *emitInfo, slang_ir_node *n)
       ifInst->DstReg.CondMask = COND_EQ;  /* BRA if cond is zero */
       ifInst->Comment = _mesa_strdup("if zero");
    }
-   /* which condition code to use: */
-   ifInst->DstReg.CondSwizzle = n->Children[0]->Store->Swizzle;
+   if (emitInfo->EmitCondCodes) {
+      /* which condition code to use: */
+      ifInst->DstReg.CondSwizzle = n->Children[0]->Store->Swizzle;
+   }
 
    /* if body */
    emit(emitInfo, n->Children[1]);
@@ -1342,6 +1358,8 @@ emit_loop(slang_emit_info *emitInfo, slang_ir_node *n)
           ir->Opcode == IR_BREAK_IF_FALSE ||
           ir->Opcode == IR_BREAK_IF_TRUE) {
          assert(inst->Opcode == OPCODE_BRK ||
+                inst->Opcode == OPCODE_BRK0 ||
+                inst->Opcode == OPCODE_BRK1 ||
                 inst->Opcode == OPCODE_BRA);
          /* go to instruction after end of loop */
          inst->BranchTarget = endInstLoc + 1;
@@ -1351,6 +1369,8 @@ emit_loop(slang_emit_info *emitInfo, slang_ir_node *n)
                 ir->Opcode == IR_CONT_IF_FALSE ||
                 ir->Opcode == IR_CONT_IF_TRUE);
          assert(inst->Opcode == OPCODE_CONT ||
+                inst->Opcode == OPCODE_CONT0 ||
+                inst->Opcode == OPCODE_CONT1 ||
                 inst->Opcode == OPCODE_BRA);
          /* to go instruction at top of loop */
          inst->BranchTarget = beginInstLoc;
@@ -1361,7 +1381,7 @@ emit_loop(slang_emit_info *emitInfo, slang_ir_node *n)
 
 
 /**
- * "Continue" or "break" statement.
+ * Unconditional "continue" or "break" statement.
  * Either OPCODE_CONT, OPCODE_BRK or OPCODE_BRA will be emitted.
  */
 static struct prog_instruction *
@@ -1393,24 +1413,52 @@ emit_cont_break_if(slang_emit_info *emitInfo, slang_ir_node *n,
    gl_inst_opcode opcode;
    struct prog_instruction *inst;
 
+   assert(n->Opcode == IR_CONT_IF_TRUE ||
+          n->Opcode == IR_CONT_IF_FALSE ||
+          n->Opcode == IR_BREAK_IF_TRUE ||
+          n->Opcode == IR_BREAK_IF_FALSE);
+
    /* evaluate condition expr, setting cond codes */
    inst = emit(emitInfo, n->Children[0]);
-   assert(inst);
-   inst->CondUpdate = GL_TRUE;
+   if (emitInfo->EmitCondCodes) {
+      assert(inst);
+      inst->CondUpdate = GL_TRUE;
+   }
 
    n->InstLocation = emitInfo->prog->NumInstructions;
+
+   /* opcode selection */
    if (emitInfo->EmitHighLevelInstructions) {
-      if (n->Opcode == IR_CONT_IF_TRUE ||
-          n->Opcode == IR_CONT_IF_FALSE)
-         opcode = OPCODE_CONT;
-      else
-         opcode = OPCODE_BRK;
+      if (emitInfo->EmitCondCodes) {
+         if (n->Opcode == IR_CONT_IF_TRUE ||
+             n->Opcode == IR_CONT_IF_FALSE)
+            opcode = OPCODE_CONT;
+         else
+            opcode = OPCODE_BRK;
+      }
+      else {
+         if (n->Opcode == IR_CONT_IF_TRUE)
+            opcode = OPCODE_CONT1;
+         else if (n->Opcode == IR_CONT_IF_FALSE)
+            opcode = OPCODE_CONT0;
+         else if (n->Opcode == IR_BREAK_IF_TRUE)
+            opcode = OPCODE_BRK1;
+         else if (n->Opcode == IR_BREAK_IF_FALSE)
+            opcode = OPCODE_BRK0;
+      }
    }
    else {
       opcode = OPCODE_BRA;
    }
+
    inst = new_instruction(emitInfo, opcode);
-   inst->DstReg.CondMask = breakTrue ? COND_NE : COND_EQ;
+   if (emitInfo->EmitCondCodes) {
+      inst->DstReg.CondMask = breakTrue ? COND_NE : COND_EQ;
+   }
+   else {
+      /* BRK0, BRK1, CONT0, CONT1 */
+      storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store);
+   }
    return inst;
 }
 
@@ -1779,7 +1827,8 @@ _slang_emit_code(slang_ir_node *n, slang_var_table *vt,
    emitInfo.prog = prog;
 
    emitInfo.EmitHighLevelInstructions = ctx->Shader.EmitHighLevelInstructions;
-   emitInfo.EmitComments = 1+ctx->Shader.EmitComments;
+   emitInfo.EmitCondCodes = 0; /* XXX temporary! */
+   emitInfo.EmitComments = ctx->Shader.EmitComments;
 
    (void) emit(&emitInfo, n);
 
index b322d48b231dfd835e5701ece940a4e91fd6c517..425a8669948b114f0466a0bbb4277329ecdfa00a 100644 (file)
@@ -741,9 +741,13 @@ static gpu_function opcode_func[MAX_OPCODE+3] =
    do_NOP,/*BGNSUB*/
    do_NOP,/*BRA*/
    do_NOP,/*BRK*/
+   do_NOP,/*BRK0*/
+   do_NOP,/*BRK1*/
    do_NOP,/*CAL*/
    do_NOP,/*CMP*/
    do_NOP,/*CONT*/
+   do_NOP,/*CONT0*/
+   do_NOP,/*CONT1*/
    do_NOP,/*COS*/
    do_NOP,/*DDX*/
    do_NOP,/*DDY*/