diff options
Diffstat (limited to 'src/mesa/shader/slang/slang_emit.c')
-rw-r--r-- | src/mesa/shader/slang/slang_emit.c | 189 |
1 files changed, 112 insertions, 77 deletions
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index 29588379a2..6e2394f265 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -43,7 +43,7 @@ #define ANNOTATE 1 -static GLboolean EmitHighLevelInstructions = GL_FALSE; +static GLboolean EmitHighLevelInstructions = GL_TRUE; /** @@ -523,9 +523,9 @@ storage_annotation(const slang_ir_node *n, const struct gl_program *prog) if (st->Index >= 0) { const GLfloat *val = prog->Parameters->ParameterValues[st->Index]; if (st->Swizzle == SWIZZLE_NOOP) - sprintf(s, "{%f, %f, %f, %f}", val[0], val[1], val[2], val[3]); + sprintf(s, "{%g, %g, %g, %g}", val[0], val[1], val[2], val[3]); else { - sprintf(s, "%f", val[GET_SWZ(st->Swizzle, 0)]); + sprintf(s, "%g", val[GET_SWZ(st->Swizzle, 0)]); } } break; @@ -1059,28 +1059,50 @@ emit_if(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog) emit(vt, n->Children[0], prog); /* the condition */ ifInstLoc = prog->NumInstructions; - ifInst = new_instruction(prog, OPCODE_IF); - ifInst->DstReg.CondMask = COND_NE; /* if cond is non-zero */ - ifInst->DstReg.CondSwizzle = SWIZZLE_X; + if (EmitHighLevelInstructions) { + ifInst = new_instruction(prog, 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(prog, OPCODE_BRA); + ifInst->DstReg.CondMask = COND_EQ; /* BRA if cond is zero */ + ifInst->DstReg.CondSwizzle = SWIZZLE_X; + ifInst->Comment = _mesa_strdup("if zero"); + } /* if body */ emit(vt, n->Children[1], prog); if (n->Children[2]) { - /* else body */ + /* have else body */ elseInstLoc = prog->NumInstructions; - (void) new_instruction(prog, OPCODE_ELSE); + if (EmitHighLevelInstructions) { + (void) new_instruction(prog, OPCODE_ELSE); + } + else { + /* jump to endif instruction */ + struct prog_instruction *inst; + inst = new_instruction(prog, OPCODE_BRA); + inst->Comment = _mesa_strdup("else"); + inst->DstReg.CondMask = COND_TR; /* always branch */ + } ifInst = prog->Instructions + ifInstLoc; ifInst->BranchTarget = prog->NumInstructions; emit(vt, n->Children[2], prog); } else { + /* no else body */ ifInst = prog->Instructions + ifInstLoc; ifInst->BranchTarget = prog->NumInstructions + 1; } - (void) new_instruction(prog, OPCODE_ENDIF); + if (EmitHighLevelInstructions) { + (void) new_instruction(prog, OPCODE_ENDIF); + } + if (n->Children[2]) { struct prog_instruction *elseInst; elseInst = prog->Instructions + elseInstLoc; @@ -1090,6 +1112,85 @@ emit_if(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog) } +static struct prog_instruction * +emit_loop(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog) +{ + struct prog_instruction *beginInst, *endInst; + GLuint beginInstLoc, endInstLoc; + slang_ir_node *ir; + + /* emit OPCODE_BGNLOOP */ + beginInstLoc = prog->NumInstructions; + if (EmitHighLevelInstructions) { + (void) new_instruction(prog, OPCODE_BGNLOOP); + } + + /* body */ + emit(vt, n->Children[0], prog); + + endInstLoc = prog->NumInstructions; + if (EmitHighLevelInstructions) { + /* emit OPCODE_ENDLOOP */ + endInst = new_instruction(prog, OPCODE_ENDLOOP); + } + else { + /* emit unconditional BRA-nch */ + endInst = new_instruction(prog, OPCODE_BRA); + endInst->DstReg.CondMask = COND_TR; /* always true */ + } + /* end instruction's BranchTarget points to top of loop */ + endInst->BranchTarget = beginInstLoc; + + if (EmitHighLevelInstructions) { + /* BGNLOOP's BranchTarget points to the ENDLOOP inst */ + beginInst = prog->Instructions + beginInstLoc; + beginInst->BranchTarget = prog->NumInstructions - 1; + } + + /* Done emitting loop code. Now walk over the loop's linked list + * of BREAK and CONT nodes, filling in their BranchTarget fields + * (which will point to the ENDLOOP or ENDLOOP+1 instructions). + */ + for (ir = n->BranchNode; ir; ir = ir->BranchNode) { + struct prog_instruction *inst = prog->Instructions + ir->InstLocation; + if (ir->Opcode == IR_BREAK) { + assert(inst->Opcode == OPCODE_BRK || + inst->Opcode == OPCODE_BRA); + inst->BranchTarget = endInstLoc + 1; + } + else { + assert(ir->Opcode == IR_CONT); + assert(inst->Opcode == OPCODE_CONT || + inst->Opcode == OPCODE_BRA); + /* XXX goto top of loop instead! */ + inst->BranchTarget = endInstLoc; + } + } + return NULL; +} + + +/** + * Emit code for IR_CONT or IR_BREAK. + */ +static struct prog_instruction * +emit_cont_break(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog) +{ + gl_inst_opcode opcode; + struct prog_instruction *inst; + n->InstLocation = prog->NumInstructions; + if (EmitHighLevelInstructions) { + opcode = (n->Opcode == IR_CONT) ? OPCODE_CONT : OPCODE_BRK; + } + else { + opcode = OPCODE_BRA; + } + inst = new_instruction(prog, opcode); + inst->DstReg.CondMask = COND_TR; /* always true */ + return inst; +} + + /** * Remove any SWIZZLE_NIL terms from given swizzle mask (smear prev term). * Ex: fix_swizzle("zyNN") -> "zyyy" @@ -1305,77 +1406,11 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog) return emit_if(vt, n, prog); case IR_LOOP: - { - struct prog_instruction *beginInst, *endInst; - GLuint beginInstLoc, endInstLoc; - slang_ir_node *ir; - - /* emit OPCODE_BGNLOOP */ - beginInstLoc = prog->NumInstructions; - if (EmitHighLevelInstructions) { - (void) new_instruction(prog, OPCODE_BGNLOOP); - } - - /* body */ - emit(vt, n->Children[0], prog); - - endInstLoc = prog->NumInstructions; - if (EmitHighLevelInstructions) { - /* emit OPCODE_ENDLOOP */ - endInst = new_instruction(prog, OPCODE_ENDLOOP); - } - else { - /* emit unconditional BRA-nch */ - endInst = new_instruction(prog, OPCODE_BRA); - endInst->DstReg.CondMask = COND_TR; /* always true */ - } - /* end instruction's BranchTarget points to top of loop */ - endInst->BranchTarget = beginInstLoc; - - if (EmitHighLevelInstructions) { - /* BGNLOOP's BranchTarget points to the ENDLOOP inst */ - beginInst = prog->Instructions + beginInstLoc; - beginInst->BranchTarget = prog->NumInstructions - 1; - } - - /* Done emitting loop code. Now walk over the loop's linked list - * of BREAK and CONT nodes, filling in their BranchTarget fields - * (which will point to the ENDLOOP or ENDLOOP+1 instructions). - */ - for (ir = n->BranchNode; ir; ir = ir->BranchNode) { - struct prog_instruction *inst - = prog->Instructions + ir->InstLocation; - if (ir->Opcode == IR_BREAK) { - assert(inst->Opcode == OPCODE_BRK || - inst->Opcode == OPCODE_BRA); - inst->BranchTarget = endInstLoc + 1; - } - else { - assert(ir->Opcode == IR_CONT); - assert(inst->Opcode == OPCODE_CONT || - inst->Opcode == OPCODE_BRA); - inst->BranchTarget = endInstLoc; - } - } - return NULL; - } + return emit_loop(vt, n, prog); case IR_BREAK: /* fall-through */ case IR_CONT: - { - gl_inst_opcode opcode; - struct prog_instruction *inst; - n->InstLocation = prog->NumInstructions; - if (EmitHighLevelInstructions) { - opcode = (n->Opcode == IR_CONT) ? OPCODE_CONT : OPCODE_BRK; - } - else { - opcode = OPCODE_BRA; - } - inst = new_instruction(prog, opcode); - inst->DstReg.CondMask = COND_TR; /* always true */ - return inst; - } + return emit_cont_break(vt, n, prog); case IR_BEGIN_SUB: return new_instruction(prog, OPCODE_BGNSUB); |