diff options
author | Brian Paul <brianp@vmware.com> | 2009-02-13 17:17:52 -0700 |
---|---|---|
committer | Brian Paul <brianp@vmware.com> | 2009-02-13 17:18:36 -0700 |
commit | c51c822ee02cb47ddba46da668577d51b7c02831 (patch) | |
tree | 905cafdc5a02f07aa67fc04e66a7fb1734abec20 /src/mesa/drivers/dri/i965/brw_vs_emit.c | |
parent | 74b6d55864b9264323a09856781f655e453b182b (diff) |
i965: rewrite the code for handling shader subroutine calls
Previously, the prog_instruction::Data field was used to map original Mesa
instructions to brw instructions in order to resolve subroutine calls. This
was a rather tangled mess. Plus it's an obstacle to implementing dynamic
allocation/growing of the instruction buffer (it's still a fixed size).
Mesa's GLSL compiler emits a label for each subroutine and CAL instruction.
Now we use those labels to patch the subroutine calls after code generation
has been done. We just keep a list of all CAL instructions that needs patching
and a list of all subroutine labels. It's a simple matter to resolve them.
This also consolidates some redundant post-emit code between brw_vs_emit.c and
brw_wm_glsl.c and removes some loops that cleared the prog_instruction::Data
fields at the end.
Plus, a bunch of new comments.
Diffstat (limited to 'src/mesa/drivers/dri/i965/brw_vs_emit.c')
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_vs_emit.c | 71 |
1 files changed, 36 insertions, 35 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_vs_emit.c b/src/mesa/drivers/dri/i965/brw_vs_emit.c index a1328f6967..235f826812 100644 --- a/src/mesa/drivers/dri/i965/brw_vs_emit.c +++ b/src/mesa/drivers/dri/i965/brw_vs_emit.c @@ -954,36 +954,27 @@ static void emit_vertex_write( struct brw_vs_compile *c) } +/** + * Called after code generation to resolve subroutine calls and the + * END instruction. + * \param end_inst points to brw code for END instruction + * \param last_inst points to last instruction emitted before vertex write + */ static void -post_vs_emit( struct brw_vs_compile *c, struct brw_instruction *end_inst ) +post_vs_emit( struct brw_vs_compile *c, + struct brw_instruction *end_inst, + struct brw_instruction *last_inst ) { - GLuint nr_insns = c->vp->program.Base.NumInstructions; - GLuint insn, target_insn; - struct prog_instruction *inst1, *inst2; - struct brw_instruction *brw_inst1, *brw_inst2; - int offset; - for (insn = 0; insn < nr_insns; insn++) { - inst1 = &c->vp->program.Base.Instructions[insn]; - brw_inst1 = inst1->Data; - switch (inst1->Opcode) { - case OPCODE_CAL: - case OPCODE_BRA: - target_insn = inst1->BranchTarget; - inst2 = &c->vp->program.Base.Instructions[target_insn]; - brw_inst2 = inst2->Data; - offset = brw_inst2 - brw_inst1; - brw_set_src1(brw_inst1, brw_imm_d(offset*16)); - break; - case OPCODE_END: - offset = end_inst - brw_inst1; - brw_set_src1(brw_inst1, brw_imm_d(offset*16)); - break; - default: - break; - } - } + GLint offset; + + brw_resolve_cals(&c->func); + + /* patch up the END code to jump past subroutines, etc */ + offset = last_inst - end_inst; + brw_set_src1(end_inst, brw_imm_d(offset * 16)); } + /* Emit the fragment program instructions here. */ void brw_vs_emit(struct brw_vs_compile *c ) @@ -992,7 +983,8 @@ void brw_vs_emit(struct brw_vs_compile *c ) struct brw_compile *p = &c->func; GLuint nr_insns = c->vp->program.Base.NumInstructions; GLuint insn, if_insn = 0; - struct brw_instruction *end_inst; + GLuint end_offset = 0; + struct brw_instruction *end_inst, *last_inst; struct brw_instruction *if_inst[MAX_IFSN]; struct brw_indirect stack_index = brw_indirect(0, 0); @@ -1035,7 +1027,6 @@ void brw_vs_emit(struct brw_vs_compile *c ) /* Get argument regs. SWZ is special and does this itself. */ - inst->Data = &p->store[p->nr_insn]; if (inst->Opcode != OPCODE_SWZ) for (i = 0; i < 3; i++) { struct prog_src_register *src = &inst->SrcReg[i]; @@ -1203,7 +1194,7 @@ void brw_vs_emit(struct brw_vs_compile *c ) brw_set_access_mode(p, BRW_ALIGN_16); brw_ADD(p, get_addr_reg(stack_index), get_addr_reg(stack_index), brw_imm_d(4)); - inst->Data = &p->store[p->nr_insn]; + brw_save_call(p, inst->Comment, p->nr_insn); brw_ADD(p, brw_ip_reg(), brw_ip_reg(), brw_imm_d(1*16)); break; case OPCODE_RET: @@ -1214,13 +1205,21 @@ void brw_vs_emit(struct brw_vs_compile *c ) brw_set_access_mode(p, BRW_ALIGN_16); break; case OPCODE_END: + end_offset = p->nr_insn; + /* this instruction will get patched later to jump past subroutine + * code, etc. + */ brw_ADD(p, brw_ip_reg(), brw_ip_reg(), brw_imm_d(1*16)); break; case OPCODE_PRINT: + /* no-op */ + break; case OPCODE_BGNSUB: + brw_save_label(p, inst->Comment, p->nr_insn); + break; case OPCODE_ENDSUB: - /* no-op instructions */ - break; + /* no-op */ + break; default: _mesa_problem(NULL, "Unsupported opcode %i (%s) in vertex shader", inst->Opcode, inst->Opcode < MAX_OPCODE ? @@ -1258,9 +1257,11 @@ void brw_vs_emit(struct brw_vs_compile *c ) release_tmps(c); } - end_inst = &p->store[p->nr_insn]; + end_inst = &p->store[end_offset]; + last_inst = &p->store[p->nr_insn]; + + /* The END instruction will be patched to jump to this code */ emit_vertex_write(c); - post_vs_emit(c, end_inst); - for (insn = 0; insn < nr_insns; insn++) - c->vp->program.Base.Instructions[insn].Data = NULL; + + post_vs_emit(c, end_inst, last_inst); } |