diff options
| author | Brian <brian@yutani.localnet.net> | 2007-03-28 11:06:34 -0600 | 
|---|---|---|
| committer | Brian <brian@yutani.localnet.net> | 2007-03-28 11:06:34 -0600 | 
| commit | dad97b4688ea25caf15cae66194db6ddbb98e936 (patch) | |
| tree | c285c5d3b7d6fa43247e649739b8a14fbe9fc294 /src | |
| parent | a01616eed52aa4dfe3b6850b76a4cd8de119a3f3 (diff) | |
Fix, clean-up code related to comparisons, condition codes, etc.
Diffstat (limited to 'src')
| -rw-r--r-- | src/mesa/shader/slang/slang_emit.c | 125 | 
1 files changed, 78 insertions, 47 deletions
| diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index 64163c4959..cbc71f36f6 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -86,6 +86,25 @@ new_subroutine(slang_emit_info *emitInfo, GLuint *id)  } +/** + * Convert a writemask to a swizzle.  Used for testing cond codes because + * we only want to test the cond code component(s) that was set by the + * previous instruction. + */ +static GLuint +writemask_to_swizzle(GLuint writemask) +{ +   if (writemask == WRITEMASK_X) +      return SWIZZLE_XXXX; +   if (writemask == WRITEMASK_Y) +      return SWIZZLE_YYYY; +   if (writemask == WRITEMASK_Z) +      return SWIZZLE_ZZZZ; +   if (writemask == WRITEMASK_W) +      return SWIZZLE_WWWW; +   return SWIZZLE_XYZW;  /* shouldn't be hit */ +} +  /**   * Swizzle a swizzle.  That is, return swz2(swz1) @@ -152,6 +171,8 @@ free_temp_storage(slang_var_table *vt, slang_ir_node *n)           _slang_free_temp(vt, n->Store);           n->Store->Index = -1;           n->Store->Size = -1; +         _mesa_free(n->Store); +         n->Store = NULL;        }     }  } @@ -485,6 +506,7 @@ emit_arith(slang_emit_info *emitInfo, slang_ir_node *n)     /* result storage */     if (!n->Store) { +      /* XXX this size isn't correct, it depends on the operands */        if (!alloc_temp_storage(emitInfo, n, info->ResultSize))           return NULL;     } @@ -542,8 +564,9 @@ emit_compare(slang_emit_info *emitInfo, slang_ir_node *n)        assert(zeroReg >= 0); +      assert(!n->Store);        if (!n->Store) { -         if (!alloc_temp_storage(emitInfo, n, 4))  /* 4 bools */ +         if (!alloc_temp_storage(emitInfo, n, size))  /* 'size' bools */              return NULL;        } @@ -561,34 +584,32 @@ emit_compare(slang_emit_info *emitInfo, slang_ir_node *n)           swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y);        } -      /* Compute equality, inequality */ +      /* Compute equality, inequality (tmp1 = (A ?= B)) */        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) */ + +      /* Compute tmp2 = DOT(tmp1, tmp1)  (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; +      storage_to_src_reg(&inst->SrcReg[0], n->Store); +      storage_to_src_reg(&inst->SrcReg[1], n->Store); +      inst->SrcReg[0].Swizzle = inst->SrcReg[1].Swizzle = swizzle; /*override*/ +      free_temp_storage(emitInfo->vt, n); /* free tmp1 */ +      if (!alloc_temp_storage(emitInfo, n, 1))  /* alloc tmp2 */ +         return NULL; +      storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);        inst->Comment = _mesa_strdup("Reduce vec to bool"); +        if (n->Opcode == IR_EQUAL) { -         /* compute D.x = !D.x  via D.x = (D.x == 0) */ +         /* compute tmp2.x = !tmp2.x  via tmp2.x = (tmp2.x == 0) */           inst = new_instruction(emitInfo, OPCODE_SEQ); -         inst->SrcReg[0].File = PROGRAM_TEMPORARY; -         inst->SrcReg[0].Index = n->Store->Index; +         storage_to_src_reg(&inst->SrcReg[0], n->Store);           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; +         storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);           inst->Comment = _mesa_strdup("Invert true/false");        }     } @@ -757,6 +778,11 @@ emit_func(slang_emit_info *emitInfo, slang_ir_node *n)                               emitInfo->prog);     if (emitInfo->EmitBeginEndSub) { +      /* BGNSUB isn't a real instruction. +       * We require a label (i.e. "foobar:") though, if we're going to +       * print the program in the NV format.  The BNGSUB instruction is +       * really just a NOP to attach the label to. +       */        inst = new_instruction(emitInfo, OPCODE_BGNSUB);        inst->Comment = _mesa_strdup(n->Label->Name);     } @@ -800,17 +826,8 @@ emit_return(slang_emit_info *emitInfo, slang_ir_node *n)     assert(n);     assert(n->Opcode == IR_RETURN);     assert(n->Label); -   inst = new_instruction(emitInfo, OPCODE_RET/*BRA*/); /*XXX TEMPORARY*/ -   inst->DstReg.CondMask = COND_TR;  /* always return/branch */ - -   if (inst->Opcode == OPCODE_BRA) { -      inst->BranchTarget = _slang_label_get_location(n->Label); -      if (inst->BranchTarget < 0) { -         _slang_label_add_reference(n->Label, -                                    emitInfo->prog->NumInstructions - 1); -      } -   } - +   inst = new_instruction(emitInfo, OPCODE_RET); +   inst->DstReg.CondMask = COND_TR;  /* always return */     return inst;  } @@ -949,28 +966,34 @@ emit_move(slang_emit_info *emitInfo, slang_ir_node *n)  } +/** + * An IR_COND node wraps a boolean expression which is used by an + * IF or WHILE test.  This is where we'll set condition codes, if needed. + */  static struct prog_instruction *  emit_cond(slang_emit_info *emitInfo, slang_ir_node *n)  {     struct prog_instruction *inst; +   assert(n->Opcode == IR_COND); +     if (!n->Children[0])        return NULL; +   /* emit code for the expression */     inst = emit(emitInfo, n->Children[0]); +   assert(n->Children[0]->Store); +   /*assert(n->Children[0]->Store->Size == 1);*/ +     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 &&            n->Children[0]->Store &&            inst->DstReg.File == n->Children[0]->Store->File &&            inst->DstReg.Index == n->Children[0]->Store->Index) {           /* The previous instruction wrote to the register who's value -          * we're testing.  Just update that instruction so that the -          * condition codes are updated. +          * we're testing.  Just fix that instruction so that the +          * condition codes are computed.            */           inst->CondUpdate = GL_TRUE;           n->Store = n->Children[0]->Store; @@ -980,10 +1003,8 @@ emit_cond(slang_emit_info *emitInfo, slang_ir_node *n)           /* 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)) +         if (!alloc_temp_storage(emitInfo, n, 1))              return NULL;           inst = new_instruction(emitInfo, OPCODE_MOV);           inst->CondUpdate = GL_TRUE; @@ -991,13 +1012,13 @@ emit_cond(slang_emit_info *emitInfo, slang_ir_node *n)           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? */ +         return inst;        }     }     else { -      /* No-op */ +      /* No-op: the boolean result of the expression is in a regular reg */        n->Store = n->Children[0]->Store; -      return NULL; +      return inst;     }  } @@ -1042,10 +1063,15 @@ static struct prog_instruction *  emit_if(slang_emit_info *emitInfo, slang_ir_node *n)  {     struct gl_program *prog = emitInfo->prog; -   struct prog_instruction *ifInst; +   struct prog_instruction *ifInst, *inst;     GLuint ifInstLoc, elseInstLoc = 0; +   GLuint condWritemask = 0; -   emit(emitInfo, n->Children[0]);  /* the condition */ +   inst = emit(emitInfo, n->Children[0]);  /* the condition */ +   if (emitInfo->EmitCondCodes) { +      assert(inst); +      condWritemask = inst->DstReg.WriteMask; +   }  #if 0     assert(n->Children[0]->Store->Size == 1); /* a bool! */ @@ -1056,6 +1082,10 @@ emit_if(slang_emit_info *emitInfo, slang_ir_node *n)        ifInst = new_instruction(emitInfo, OPCODE_IF);        if (emitInfo->EmitCondCodes) {           ifInst->DstReg.CondMask = COND_NE;  /* if cond is non-zero */ +         /* only test the cond code (1 of 4) that was updated by the +          * previous instruction. +          */ +         ifInst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);        }        else {           /* test reg.x */ @@ -1067,10 +1097,7 @@ emit_if(slang_emit_info *emitInfo, slang_ir_node *n)        ifInst = new_instruction(emitInfo, OPCODE_BRA);        ifInst->DstReg.CondMask = COND_EQ;  /* BRA if cond is zero */        ifInst->Comment = _mesa_strdup("if zero"); -   } -   if (emitInfo->EmitCondCodes) { -      /* which condition code to use: */ -      ifInst->DstReg.CondSwizzle = n->Children[0]->Store->Swizzle; +      ifInst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);     }     /* if body */ @@ -1097,7 +1124,7 @@ emit_if(slang_emit_info *emitInfo, slang_ir_node *n)     else {        /* no else body */        ifInst = prog->Instructions + ifInstLoc; -      ifInst->BranchTarget = prog->NumInstructions + 1; +      ifInst->BranchTarget = prog->NumInstructions /*+ 1*/;     }     if (emitInfo->EmitHighLevelInstructions) { @@ -1736,6 +1763,10 @@ _slang_emit_code(slang_ir_node *n, slang_var_table *vt,     emitInfo.EmitComments = ctx->Shader.EmitComments;     emitInfo.EmitBeginEndSub = 0;  /* XXX for compiler debug only */ +   if (!emitInfo.EmitCondCodes) { +      emitInfo.EmitHighLevelInstructions = GL_TRUE; +   }       +     (void) emit(&emitInfo, n);     /* finish up by adding the END opcode to program */ | 
