Overhaul emit_compare() function.
authorBrian <brian@yutani.localnet.net>
Thu, 22 Mar 2007 22:07:14 +0000 (16:07 -0600)
committerBrian <brian@yutani.localnet.net>
Thu, 22 Mar 2007 22:07:14 +0000 (16:07 -0600)
Previously, comparing vec2, vec3, vec4 was broken.
Added IR_EQUAL, IR_NOTEQUAL nodes/operators to compute boolean
equality/inequality vs. IR_SEQUAL/IR_SNEQUAL which work component-wise.
Use IR_EQUAL/IR_NOTEQUAL for the == and != operators.
To compute vec4 equality, use SNE, DP4, SEQ instruction sequence.

src/mesa/shader/slang/slang_codegen.c
src/mesa/shader/slang/slang_emit.c
src/mesa/shader/slang/slang_ir.h

index 89a891562eaa77000d456d81e17a628680e05aa0..f1be713c05bcc967a9b9d76ba435433298e797e6 100644 (file)
@@ -2369,11 +2369,11 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
       return new_node0(IR_KILL);
 
    case SLANG_OPER_EQUAL:
-      return new_node2(IR_SEQUAL,
+      return new_node2(IR_EQUAL,
                       _slang_gen_operation(A, &oper->children[0]),
                       _slang_gen_operation(A, &oper->children[1]));
    case SLANG_OPER_NOTEQUAL:
-      return new_node2(IR_SNEQUAL,
+      return new_node2(IR_NOTEQUAL,
                       _slang_gen_operation(A, &oper->children[0]),
                       _slang_gen_operation(A, &oper->children[1]));
    case SLANG_OPER_GREATER:
index bc08104ada5653862a3562ba3880e9bd2dae48e1..6442a023634f3560ec5e8646c534fec60293b52b 100644 (file)
@@ -462,6 +462,12 @@ storage_to_dst_reg(struct prog_dst_register *dst, const slang_ir_storage *st,
       GLuint comp = GET_SWZ(st->Swizzle, 0);
       assert(comp < 4);
       assert(writemask & WRITEMASK_X);
+      /*
+      assert((writemask == WRITEMASK_X) ||
+             (writemask == WRITEMASK_Y) ||
+             (writemask == WRITEMASK_Z) ||
+             (writemask == WRITEMASK_W));
+      */
       dst->WriteMask = WRITEMASK_X << comp;
    }
    else {
@@ -778,27 +784,100 @@ static struct prog_instruction *
 emit_compare(slang_emit_info *emitInfo, slang_ir_node *n)
 {
    struct prog_instruction *inst;
-   gl_inst_opcode opcode;
-
-   assert(n->Opcode == IR_SEQUAL || n->Opcode == IR_SNEQUAL);
+   GLint size;
 
-   opcode = n->Opcode == IR_SEQUAL ? OPCODE_SEQ : OPCODE_SNE;
+   assert(n->Opcode == IR_EQUAL || n->Opcode == IR_NOTEQUAL);
 
    /* gen code for children */
    emit(emitInfo, n->Children[0]);
    emit(emitInfo, n->Children[1]);
 
+#if 0
    assert(n->Children[0]->Store->Size == n->Children[1]->Store->Size);
+   size = n->Children[0]->Store->Size;
+#else
+   /* XXX kind of a hack for now... */
+   size = MIN2(n->Children[0]->Store->Size, n->Children[1]->Store->Size);
+#endif
+   if (size == 1) {
+      gl_inst_opcode opcode;
 
-   if (!n->Store) {
-      if (!alloc_temp_storage(emitInfo, n, 1))  /* 1 bool */
-         return NULL;
+      if (!n->Store) {
+         if (!alloc_temp_storage(emitInfo, n, 1))  /* 1 bool */
+            return NULL;
+      }
+
+      opcode = n->Opcode == IR_EQUAL ? OPCODE_SEQ : OPCODE_SNE;
+      inst = new_instruction(emitInfo, opcode);
+      storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store);
+      ASSERT(inst->SrcReg[0].Swizzle != SWIZZLE_XYZW);
+      storage_to_src_reg(&inst->SrcReg[1], n->Children[1]->Store);
+      ASSERT(inst->SrcReg[1].Swizzle != SWIZZLE_XYZW);
+      storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
    }
+   else if (size <= 4) {
+      static const GLfloat zero[4] = { 0, 0, 0, 0 };
+      GLuint zeroSwizzle, swizzle;
+      GLint zeroReg = _mesa_add_unnamed_constant(emitInfo->prog->Parameters,
+                                                 zero, 4, &zeroSwizzle);
+      gl_inst_opcode dotOp;
+      
+      assert(zeroReg >= 0);
 
-   if (n->Children[0]->Store->Size > 4) {
-      /* struct compare */
-      GLint i, num = (n->Children[0]->Store->Size + 3) / 4;
+      if (!n->Store) {
+         if (!alloc_temp_storage(emitInfo, n, 4))  /* 4 bools */
+            return NULL;
+      }
+
+      if (size == 4) {
+         dotOp = OPCODE_DP4;
+         swizzle = SWIZZLE_XYZW;
+      }
+      else if (size == 3) {
+         dotOp = OPCODE_DP3;
+         swizzle = SWIZZLE_XYZW;
+      }
+      else {
+         assert(size == 2);
+         dotOp = OPCODE_DP3;
+         swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y);
+      }
 
+      /* Compute equality, inequality */
+      inst = new_instruction(emitInfo, OPCODE_SNE);
+      storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store);
+      storage_to_src_reg(&inst->SrcReg[1], n->Children[1]->Store);
+      storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
+      inst->Comment = _mesa_strdup("Compare values");
+      /* compute D = DP4(D, D)  (reduction) */
+      inst = new_instruction(emitInfo, dotOp);
+      inst->SrcReg[0].File = PROGRAM_TEMPORARY;
+      inst->SrcReg[0].Index = n->Store->Index;
+      inst->SrcReg[0].Swizzle = swizzle;
+      inst->SrcReg[1].File = PROGRAM_TEMPORARY;
+      inst->SrcReg[1].Index = n->Store->Index;
+      inst->SrcReg[1].Swizzle = swizzle;
+      inst->DstReg.File = PROGRAM_TEMPORARY;
+      inst->DstReg.Index = n->Store->Index;
+      inst->Comment = _mesa_strdup("Reduce vec to bool");
+      /* compute D = (D == 0)  actually: D.x = (D.x = 0) */
+      if (n->Opcode == IR_EQUAL) {
+         inst = new_instruction(emitInfo, OPCODE_SEQ);
+         inst->SrcReg[0].File = PROGRAM_TEMPORARY;
+         inst->SrcReg[0].Index = n->Store->Index;
+         inst->SrcReg[1].File = PROGRAM_CONSTANT;
+         inst->SrcReg[1].Index = zeroReg;
+         inst->SrcReg[1].Swizzle = zeroSwizzle;
+         inst->DstReg.File = PROGRAM_TEMPORARY;
+         inst->DstReg.Index = n->Store->Index;
+         inst->DstReg.WriteMask = WRITEMASK_X;
+         inst->Comment = _mesa_strdup("Invert true/false");
+      }
+   }
+   else {
+      /* size > 4, struct compare */
+#if 0
+      GLint i, num = (n->Children[0]->Store->Size + 3) / 4;
       /*printf("BEGIN COMPARE size %d\n", num);*/
       for (i = 0; i < num; i++) {
          inst = new_instruction(emitInfo, opcode);
@@ -808,29 +887,23 @@ emit_compare(slang_emit_info *emitInfo, slang_ir_node *n)
          inst->SrcReg[1].Index = n->Children[1]->Store->Index + i;
          inst->DstReg.File = n->Store->File;
          inst->DstReg.Index = n->Store->Index;
-         if (i == 0) {
-            inst->CondUpdate = 1; /* update cond code */
-         }
-         else {
+
+         inst->CondUpdate = 1; /* update cond code */
+         if (i > 0) {
             inst->DstReg.CondMask = COND_NE; /* update if !=0 */
          }
          /*_mesa_print_instruction(inst);*/
       }
-   }
-   else {
-      /* small/simple types */
-      inst = new_instruction(emitInfo, opcode);
-      storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store);
-      storage_to_src_reg(&inst->SrcReg[1], n->Children[1]->Store);
+      storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
+#endif
+      _mesa_problem(NULL, "struct comparison not implemented yet");
+      inst = NULL;
    }
 
    /* free temps */
    free_temp_storage(emitInfo->vt, n->Children[0]);
    free_temp_storage(emitInfo->vt, n->Children[1]);
 
-   /* result storage */
-   storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
-
    return inst;
 }
 
@@ -1092,9 +1165,11 @@ emit_cond(slang_emit_info *emitInfo, slang_ir_node *n)
       return NULL;
 
    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? */
    }
    else {
@@ -1161,19 +1236,24 @@ emit_if(slang_emit_info *emitInfo, slang_ir_node *n)
    GLuint ifInstLoc, elseInstLoc = 0;
 
    emit(emitInfo, n->Children[0]);  /* the condition */
+
+#if 0
+   assert(n->Children[0]->Store->Size == 1); /* a bool! */
+#endif
+
    ifInstLoc = prog->NumInstructions;
    if (emitInfo->EmitHighLevelInstructions) {
       ifInst = new_instruction(emitInfo, OPCODE_IF);
       ifInst->DstReg.CondMask = COND_NE;  /* if cond is non-zero */
-      ifInst->DstReg.CondSwizzle = SWIZZLE_X;
    }
    else {
       /* conditional jump to else, or endif */
       ifInst = new_instruction(emitInfo, OPCODE_BRA);
       ifInst->DstReg.CondMask = COND_EQ;  /* BRA if cond is zero */
-      ifInst->DstReg.CondSwizzle = SWIZZLE_X;
       ifInst->Comment = _mesa_strdup("if zero");
    }
+   /* which condition code to use: */
+   ifInst->DstReg.CondSwizzle = n->Children[0]->Store->Swizzle;
 
    /* if body */
    emit(emitInfo, n->Children[1]);
@@ -1354,6 +1434,20 @@ fix_swizzle(GLuint swizzle)
 }
 
 
+#if 0
+static GLuint
+swizzle_size(GLuint swizzle)
+{
+   GLuint size = 0, i;
+   for (i = 0; i < 4; i++) {
+      GLuint swz = GET_SWZ(swizzle, i);
+      size += (swz >= 0 && swz <= 3);
+   }
+   return size;
+}
+#endif
+
+
 static struct prog_instruction *
 emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n)
 {
@@ -1380,6 +1474,12 @@ emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n)
    }
 #endif
 
+#if 0
+   n->Store->Size = swizzle_size(n->Store->Swizzle);
+   printf("Emit Swizzle reg %d  chSize %d  size %d\n",
+          n->Store->Index, n->Children[0]->Store->Size,
+          n->Store->Size);
+#endif
    /* apply this swizzle to child's swizzle to get composed swizzle */
    n->Store->Swizzle = swizzle_swizzle(n->Children[0]->Store->Swizzle,
                                        swizzle);
@@ -1577,6 +1677,8 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n)
    case IR_CROSS:
    case IR_MIN:
    case IR_MAX:
+   case IR_SEQUAL:
+   case IR_SNEQUAL:
    case IR_SGE:
    case IR_SGT:
    case IR_SLE:
@@ -1588,8 +1690,8 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n)
    case IR_LRP:
       return emit_arith(emitInfo, n);
 
-   case IR_SEQUAL:
-   case IR_SNEQUAL:
+   case IR_EQUAL:
+   case IR_NOTEQUAL:
       return emit_compare(emitInfo, n);
 
    case IR_CLAMP:
index 3c5526e3c547ad2c5a8e1b4175c15c042c064e45..cc9df69e722edf5ad5ffbdc4a78cc6b0fe4b232a 100644 (file)
@@ -69,6 +69,8 @@ typedef enum
    IR_CONT_IF_FALSE,
 
    IR_MOVE,
+
+   /* vector ops: */
    IR_ADD,
    IR_SUB,
    IR_MUL,
@@ -80,12 +82,12 @@ typedef enum
    IR_CLAMP,
    IR_MIN,
    IR_MAX,
-   IR_SEQUAL,  /* Set if args are equal */
-   IR_SNEQUAL, /* Set if args are not equal */
-   IR_SGE,     /* Set if greater or equal */
-   IR_SGT,     /* Set if greater than */
-   IR_SLE,     /* Set if less or equal */
-   IR_SLT,     /* Set if less than */
+   IR_SEQUAL,  /* Set if args are equal (vector) */
+   IR_SNEQUAL, /* Set if args are not equal (vector) */
+   IR_SGE,     /* Set if greater or equal (vector) */
+   IR_SGT,     /* Set if greater than (vector) */
+   IR_SLE,     /* Set if less or equal (vector) */
+   IR_SLT,     /* Set if less than (vector) */
    IR_POW,     /* x^y */
    IR_EXP,     /* e^x */
    IR_EXP2,    /* 2^x */
@@ -104,7 +106,10 @@ typedef enum
    IR_NOISE2,  /* noise(x, y) */
    IR_NOISE3,  /* noise(x, y, z) */
    IR_NOISE4,  /* noise(x, y, z, w) */
-   IR_NOT,     /* logical not */
+
+   IR_EQUAL,   /* boolean equality */
+   IR_NOTEQUAL,/* boolean inequality */
+   IR_NOT,     /* boolean not */
 
    IR_VAR,     /* variable reference */
    IR_VAR_DECL,/* var declaration */