From e6aeb24b23097024ba60e1c49239a18692f781e1 Mon Sep 17 00:00:00 2001 From: Brian Date: Thu, 22 Mar 2007 16:07:14 -0600 Subject: Overhaul emit_compare() function. 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 | 4 +- src/mesa/shader/slang/slang_emit.c | 156 ++++++++++++++++++++++++++++------ src/mesa/shader/slang/slang_ir.h | 19 +++-- 3 files changed, 143 insertions(+), 36 deletions(-) diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index 89a891562ea..f1be713c05b 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -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: diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index bc08104ada5..6442a023634 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -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: diff --git a/src/mesa/shader/slang/slang_ir.h b/src/mesa/shader/slang/slang_ir.h index 3c5526e3c54..cc9df69e722 100644 --- a/src/mesa/shader/slang/slang_ir.h +++ b/src/mesa/shader/slang/slang_ir.h @@ -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 */ -- cgit v1.2.3