Initial implementation work for CAL, RET, and BRA instructions for fragment
authorBrian Paul <brian.paul@tungstengraphics.com>
Thu, 16 Nov 2006 21:28:35 +0000 (21:28 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Thu, 16 Nov 2006 21:28:35 +0000 (21:28 +0000)
programs.

src/mesa/main/config.h
src/mesa/shader/program_instruction.h
src/mesa/swrast/s_nvfragprog.c

index 5a04813..13c6281 100644 (file)
 #define MAX_PROGRAM_LOCAL_PARAMS 128 /* KW: power of two */
 #define MAX_PROGRAM_MATRICES 8
 #define MAX_PROGRAM_MATRIX_STACK_DEPTH 4
+#define MAX_PROGRAM_CALL_DEPTH 8
 /*@}*/
 
 /** For GL_ARB_fragment_shader */
index cdec0ce..ad3a6d4 100644 (file)
@@ -286,7 +286,7 @@ struct prog_instruction
    GLuint CondUpdate:1;
 
    /**
-    * If prog_instruction::cc_update is \c GL_TRUE, this value selects the
+    * If prog_instruction::CondUpdate is \c GL_TRUE, this value selects the
     * condition code register that is to be updated.
     *
     * In GL_NV_fragment_program or GL_NV_vertex_program2 mode, only condition
@@ -339,6 +339,11 @@ struct prog_instruction
     */
    GLuint TexSrcTarget:3;
    /*@}*/
+
+   /**
+    * For BRA and CAL instructions, the location to jump to.
+    */
+   GLuint BranchTarget;
 };
 
 
index 7a6785b..028ddc0 100644 (file)
@@ -57,6 +57,9 @@ struct fp_machine
    GLfloat Inputs[MAX_NV_FRAGMENT_PROGRAM_INPUTS][4];
    GLfloat Outputs[MAX_NV_FRAGMENT_PROGRAM_OUTPUTS][4];
    GLuint CondCodes[4];  /**< COND_* value for x/y/z/w */
+
+   GLuint CallStack[MAX_PROGRAM_CALL_DEPTH]; /**< For CAL/RET instructions */
+   GLuint StackDepth; /**< Index/ptr to top of CallStack[] */
 };
 
 
@@ -697,6 +700,37 @@ execute_program( GLcontext *ctx,
                }
             }
             break;
+         case OPCODE_BRA: /* conditional branch */
+            {
+               /* NOTE: The return is conditional! */
+               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)) {
+                  /* take branch */
+                  pc = inst->BranchTarget;
+               }
+            }
+            break;
+         case OPCODE_CAL: /* Call subroutine */
+            {
+               /* NOTE: The call is conditional! */
+               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)) {
+                  if (machine->StackDepth >= MAX_PROGRAM_CALL_DEPTH) {
+                     return GL_TRUE; /* Per GL_NV_vertex_program2 spec */
+                  }
+                  machine->CallStack[machine->StackDepth++] = pc + 1;
+                  pc = inst->BranchTarget;
+               }
+            }
+            break;
          case OPCODE_CMP:
             {
                GLfloat a[4], b[4], c[4], result[4];
@@ -1093,6 +1127,22 @@ execute_program( GLcontext *ctx,
                store_vector4( inst, machine, result );
             }
             break;
+         case OPCODE_RET: /* return from subroutine */
+            {
+               /* NOTE: The return is conditional! */
+               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)) {
+                  if (machine->StackDepth == 0) {
+                     return GL_TRUE; /* Per GL_NV_vertex_program2 spec */
+                  }
+                  pc = machine->CallStack[--machine->StackDepth];
+               }
+            }
+            break;
          case OPCODE_RFL: /* reflection vector */
             {
                GLfloat axis[4], dir[4], result[4], tmpX, tmpW;
@@ -1539,6 +1589,9 @@ init_machine( GLcontext *ctx, struct fp_machine *machine,
    machine->CondCodes[1] = COND_EQ;
    machine->CondCodes[2] = COND_EQ;
    machine->CondCodes[3] = COND_EQ;
+
+   /* init call stack */
+   machine->StackDepth = 0;
 }