diff options
-rw-r--r-- | src/mesa/shader/slang/slang_codegen.c | 11 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_emit.c | 42 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_ir.h | 37 |
3 files changed, 64 insertions, 26 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index 51bf26ada86..a2be0435427 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -813,6 +813,14 @@ _slang_is_noop(const slang_operation *oper) } +static slang_ir_node * +_slang_gen_cond(slang_ir_node *n) +{ + slang_ir_node *c = new_node(IR_COND, n, NULL); + return c; +} + + /** * Assemble a function call, given a particular function name. * \param name the function's name (operators like '*' are possible). @@ -866,6 +874,7 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper) startLab = new_label(startAtom); cond = _slang_gen_operation(A, &oper->children[0]); + cond = _slang_gen_cond(cond); tree = new_seq(startLab, cond); bra = new_cjump(endAtom); @@ -922,6 +931,7 @@ _slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper) tree = new_seq(init, startLab); cond = _slang_gen_operation(A, &oper->children[1]); + cond = _slang_gen_cond(cond); tree = new_seq(tree, cond); bra = new_cjump(endAtom); @@ -972,6 +982,7 @@ _slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper) slang_atom endifAtom = slang_atom_pool_gen(A->atoms, "__endif"); cond = _slang_gen_operation(A, &oper->children[0]); + cond = _slang_gen_cond(cond); /*assert(cond->Store);*/ bra = new_cjump(haveElseClause ? elseAtom : endifAtom); tree = new_seq(cond, bra); diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index ba1290b45e4..d7c224541ad 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -85,6 +85,7 @@ static slang_ir_info IrInfo[] = { { IR_LABEL, "IR_LABEL", 0, 0, 0 }, { IR_JUMP, "IR_JUMP", 0, 0, 0 }, { IR_CJUMP, "IR_CJUMP", 0, 0, 0 }, + { IR_COND, "IR_COND", 0, 0, 0 }, { IR_CALL, "IR_CALL", 0, 0, 0 }, { IR_MOVE, "IR_MOVE", 0, 0, 1 }, { IR_NOT, "IR_NOT", 0, 1, 1 }, @@ -300,6 +301,10 @@ slang_print_ir(const slang_ir_node *n, int indent) case IR_LABEL: printf("LABEL: %s\n", n->Target); break; + case IR_COND: + printf("COND\n"); + slang_print_ir(n->Children[0], indent + 3); + break; case IR_JUMP: printf("JUMP %s\n", n->Target); break; @@ -897,12 +902,6 @@ emit_binop(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog) storage_to_src_reg(&inst->SrcReg[1], n->Children[1]->Store, n->Children[1]->Swizzle); inst->Comment = n->Comment; - - if (inst->Opcode == OPCODE_SGT) { - /* update cond codes */ - inst->CondUpdate = GL_TRUE; - } - return inst; } @@ -1075,7 +1074,6 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog) case IR_EXP: case IR_EXP2: return emit_binop(gc, n, prog); - break; case IR_RSQ: case IR_RCP: case IR_FLOOR: @@ -1084,12 +1082,40 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog) case IR_SIN: case IR_COS: return emit_unop(gc, n, prog); - break; case IR_LABEL: return emit_label(n->Target, prog); case IR_FLOAT: n->Store = alloc_constant(n->Value, 4, prog); /*XXX fix size */ break; + case IR_COND: + { + /* Conditional expression (in if/while/for stmts). + * Need to update condition code register. + * Next instruction is typically an IR_CJUMP. + */ + /* last child expr instruction: */ + struct prog_instruction *inst = emit(gc, n->Children[0], prog); + if (inst) { + /* set inst's CondUpdate flag */ + inst->CondUpdate = GL_TRUE; + 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. + */ + slang_alloc_temp_storage(gc, n, 1); + inst = new_instruction(prog, 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, + n->Children[0]->Swizzle); + free_temporary(gc, n->Store->Index, n->Store->Size); + return inst; /* XXX or null? */ + } + } + return NULL; case IR_JUMP: return emit_jump(n->Target, prog); case IR_CJUMP: diff --git a/src/mesa/shader/slang/slang_ir.h b/src/mesa/shader/slang/slang_ir.h index 5c054a56368..188d7d96d34 100644 --- a/src/mesa/shader/slang/slang_ir.h +++ b/src/mesa/shader/slang/slang_ir.h @@ -44,11 +44,12 @@ typedef enum { IR_NOP = 0, - IR_SEQ, + IR_SEQ, /* sequence (eval left, then right) */ IR_LABEL, /* target of a jump or cjump */ IR_JUMP, /* unconditional jump */ IR_CJUMP, /* conditional jump */ - IR_CALL, + IR_COND, /* conditional expression */ + IR_CALL, /* call subroutine */ IR_MOVE, IR_ADD, IR_SUB, @@ -56,27 +57,27 @@ typedef enum IR_DIV, IR_DOT4, IR_DOT3, - IR_CROSS, + IR_CROSS, /* vec3 cross product */ IR_MIN, IR_MAX, - IR_SEQUAL, - IR_SNEQUAL, - IR_SGE, - IR_SGT, - IR_POW, - IR_EXP, - IR_EXP2, - IR_LOG2, - IR_RSQ, - IR_RCP, + IR_SEQUAL, /* Set if not equal */ + IR_SNEQUAL, /* Set if equal */ + IR_SGE, /* Set if greater or equal */ + IR_SGT, /* Set if greater than */ + IR_POW, /* x^y */ + IR_EXP, /* e^x */ + IR_EXP2, /* 2^x */ + IR_LOG2, /* log base 2 */ + IR_RSQ, /* 1/sqrt() */ + IR_RCP, /* recipricol */ IR_FLOOR, IR_FRAC, IR_ABS, - IR_SIN, - IR_COS, - IR_NOT, - IR_VAR, - IR_VAR_DECL, + IR_SIN, /* sine */ + IR_COS, /* cosine */ + IR_NOT, /* logical not */ + IR_VAR, /* variable reference */ + IR_VAR_DECL,/* var declaration */ IR_FLOAT, IR_FIELD, IR_I_TO_F |