diff options
author | Brian <[email protected]> | 2006-12-18 10:05:24 -0700 |
---|---|---|
committer | Brian <[email protected]> | 2006-12-18 10:05:24 -0700 |
commit | 1aee657b0f0fb34a0d6717e47f3bdfd67de8bfc2 (patch) | |
tree | a963e0a23653cb87240994c90cd7500e6e112e73 /src/mesa/shader | |
parent | 34ae99d6049b10115ca64daecdd1d879d3b5140d (diff) |
Implement if-conditionals and while loops, added temporary resolve-branches function in linker.
Diffstat (limited to 'src/mesa/shader')
-rw-r--r-- | src/mesa/shader/slang/slang_codegen.c | 149 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_emit.c | 26 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_link2.c | 44 |
3 files changed, 167 insertions, 52 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index 2f2b2b2a4e0..9cfcfd45d30 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -122,10 +122,10 @@ new_seq(slang_ir_node *left, slang_ir_node *right) } static slang_ir_node * -new_label(const char *name) +new_label(slang_atom labName) { slang_ir_node *n = new_node(IR_LABEL, NULL, NULL); - n->Target = _mesa_strdup(name); + n->Target = (char *) labName; /*_mesa_strdup(name);*/ return n; } @@ -141,20 +141,20 @@ new_float_literal(float x, float y, float z, float w) } static slang_ir_node * -new_cjump(slang_ir_node *cond, const char *target) +new_cjump(slang_atom target) { - slang_ir_node *n = new_node(IR_CJUMP, cond, NULL); - n->Target = _mesa_strdup(target); + slang_ir_node *n = new_node(IR_CJUMP, NULL, NULL); + if (n) + n->Target = (char *) target; return n; } static slang_ir_node * -new_jump(const char *target) +new_jump(slang_atom target) { slang_ir_node *n = new_node(IR_JUMP, NULL, NULL); - if (n) { - n->Target = _mesa_strdup(target); - } + if (n) + n->Target = (char *) target; return n; } @@ -893,6 +893,16 @@ slang_assemble_asm(slang_assemble_ctx *A, slang_operation *oper, +static GLboolean +_slang_is_noop(const slang_operation *oper) +{ + if (!oper || + oper->type == slang_oper_void || + (oper->num_children == 1 && oper->children[0].type == slang_oper_void)) + return GL_TRUE; + else + return GL_FALSE; +} /** @@ -923,6 +933,88 @@ slang_assemble_function_call_name(slang_assemble_ctx *A, const char *name, static slang_ir_node * +_slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper) +{ + /* + * label "__whileStart" + * eval expr (child[0]), updating condcodes + * branch if false to "__endWhile" + * code body + * jump "__whileStart" + * label "__endWhile" + */ + slang_atom startAtom = slang_atom_pool_gen(A->atoms, "__startWhile"); + slang_atom endAtom = slang_atom_pool_gen(A->atoms, "__endWhile"); + slang_ir_node *startLab, *cond, *bra, *body, *jump, *endLab, *tree; + + startLab = new_label(startAtom); + cond = slang_assemble_operation(A, &oper->children[0]); + tree = new_seq(startLab, cond); + + bra = new_cjump(endAtom); + tree = new_seq(tree, bra); + + body = slang_assemble_operation(A, &oper->children[1]); + tree = new_seq(tree, body); + + jump = new_jump(startAtom); + tree = new_seq(tree, jump); + + endLab = new_label(endAtom); + tree = new_seq(tree, endLab); + + return tree; +} + + +static slang_ir_node * +_slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper) +{ + /* + * eval expr (child[0]), updating condcodes + * branch if false to _else or _endif + * "true" code block + * if haveElseClause clause: + * jump "__endif" + * label "__else" + * "false" code block + * label "__endif" + */ + const GLboolean haveElseClause = !_slang_is_noop(&oper->children[2]); + slang_ir_node *cond, *bra, *trueBody, *endifLab, *tree; + slang_atom elseAtom = slang_atom_pool_gen(A->atoms, "__else"); + slang_atom endifAtom = slang_atom_pool_gen(A->atoms, "__endif"); + + cond = slang_assemble_operation(A, &oper->children[0]); + /*assert(cond->Store);*/ + bra = new_cjump(haveElseClause ? elseAtom : endifAtom); + tree = new_seq(cond, bra); + + trueBody = slang_assemble_operation(A, &oper->children[1]); + tree = new_seq(tree, trueBody); + + if (haveElseClause) { + /* else clause */ + slang_ir_node *jump, *elseLab, *falseBody; + jump = new_jump(endifAtom); + tree = new_seq(tree, jump); + + elseLab = new_label(elseAtom); + tree = new_seq(tree, elseLab); + + falseBody = slang_assemble_operation(A, &oper->children[2]); + tree = new_seq(tree, falseBody); + } + + endifLab = new_label(endifAtom); + tree = new_seq(tree, endifLab); + + return tree; +} + + + +static slang_ir_node * slang_assemble_operation(slang_assemble_ctx * A, slang_operation *oper) { switch (oper->type) { @@ -944,25 +1036,7 @@ slang_assemble_operation(slang_assemble_ctx * A, slang_operation *oper) return slang_assemble_operation(A, &oper->children[0]); break; case slang_oper_while: - { - slang_ir_node *tree; - slang_ir_node *nStartLabel = new_label("while-start"); - slang_ir_node *nCond = slang_assemble_operation(A, &oper->children[0]); - slang_ir_node *nNotCond = new_node(IR_NOT, nCond, NULL); - slang_ir_node *nBody = slang_assemble_operation(A, &oper->children[1]); - slang_ir_node *nEndLabel = new_label("while-end"); - slang_ir_node *nCJump = new_cjump(nNotCond, "while-end"); - slang_ir_node *nJump = new_jump("while-start"); - - tree = new_seq(nStartLabel, nCond); - tree = new_seq(tree, nNotCond); - tree = new_seq(tree, nBody); - tree = new_seq(tree, nEndLabel); - tree = new_seq(tree, nCJump); - tree = new_seq(tree, nJump); - return tree; - } - break; + return _slang_gen_while(A, oper); case slang_oper_equal: return new_node(IR_SEQUAL, slang_assemble_operation(A, &oper->children[0]), @@ -1145,24 +1219,7 @@ slang_assemble_operation(slang_assemble_ctx * A, slang_operation *oper) } break; case slang_oper_if: - { - slang_ir_node *cond, *bra, *body, *endif, *tree; - - cond = slang_assemble_operation(A, &oper->children[0]); - /*assert(cond->Store);*/ - bra = new_node(IR_CJUMP, NULL, NULL); - bra->Target = _mesa_strdup("__endif"); - - body = slang_assemble_operation(A, &oper->children[1]); - - endif = new_label("__endif"); - - tree = new_seq(cond, bra); - tree = new_seq(tree, body); - tree = new_seq(tree, endif); - return tree; - } - break; + return _slang_gen_if(A, oper); case slang_oper_field: { slang_assembly_typeinfo ti; diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index fbee314d242..ba1290b45e4 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -897,6 +897,12 @@ 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; } @@ -951,6 +957,18 @@ emit_cjump(const char *target, struct gl_program *prog) } +static struct prog_instruction * +emit_jump(const char *target, struct gl_program *prog) +{ + struct prog_instruction *inst; + inst = new_instruction(prog, OPCODE_BRA); + inst->DstReg.CondMask = COND_TR; /* always branch */ + /*inst->DstReg.CondSwizzle = SWIZZLE_X;*/ + inst->Comment = _mesa_strdup(target); + return inst; +} + + static struct prog_instruction * emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog) @@ -1069,15 +1087,11 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog) break; case IR_LABEL: return emit_label(n->Target, prog); - case IR_JUMP: -#if 0 - inst = new_instruction(prog, OPCODE_BRA); - inst->Comment = _mesa_strdup(n->Target); -#endif - break; case IR_FLOAT: n->Store = alloc_constant(n->Value, 4, prog); /*XXX fix size */ break; + case IR_JUMP: + return emit_jump(n->Target, prog); case IR_CJUMP: return emit_cjump(n->Target, prog); default: diff --git a/src/mesa/shader/slang/slang_link2.c b/src/mesa/shader/slang/slang_link2.c index 6a276d69ac0..c170b3e053f 100644 --- a/src/mesa/shader/slang/slang_link2.c +++ b/src/mesa/shader/slang/slang_link2.c @@ -230,6 +230,47 @@ link_uniform_vars(struct gl_linked_program *linked, struct gl_program *prog) /** + * XXX Temporary + */ +static void +slang_resolve_branches(struct gl_program *prog) +{ + struct target { + const char *Name; + GLuint Pos; + }; + struct target targets[500]; + GLuint numTargets = 0; + GLuint i, j; + + for (i = 0; i < prog->NumInstructions; i++) { + struct prog_instruction *inst = prog->Instructions + i; + if (inst->Opcode == OPCODE_NOP && inst->Comment) { + targets[numTargets].Name = inst->Comment; + targets[numTargets].Pos = i; + numTargets++; + } + } + + for (i = 0; i < prog->NumInstructions; i++) { + struct prog_instruction *inst = prog->Instructions + i; + if (inst->Opcode == OPCODE_BRA) { + for (j = 0; j < numTargets; j++) { + if (!strcmp(inst->Comment, targets[j].Name)) { + inst->BranchTarget = targets[j].Pos; + break; + } + } + if (j == numTargets) { + abort(); + } + } + } +} + + + +/** * Shader linker. Currently: * * 1. The last attached vertex shader and fragment shader are linked. @@ -298,6 +339,9 @@ _slang_link2(GLcontext *ctx, linked->VertexProgram->Base.Parameters = linked->Uniforms; linked->FragmentProgram->Base.Parameters = linked->Uniforms; + slang_resolve_branches(&linked->VertexProgram->Base); + slang_resolve_branches(&linked->FragmentProgram->Base); + #if 1 printf("************** original fragment program\n"); _mesa_print_program(&fragProg->Base); |