summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/i965/brw_vs_emit.c
diff options
context:
space:
mode:
authorBrian Paul <brianp@vmware.com>2009-02-13 17:17:52 -0700
committerBrian Paul <brianp@vmware.com>2009-02-13 17:18:36 -0700
commitc51c822ee02cb47ddba46da668577d51b7c02831 (patch)
tree905cafdc5a02f07aa67fc04e66a7fb1734abec20 /src/mesa/drivers/dri/i965/brw_vs_emit.c
parent74b6d55864b9264323a09856781f655e453b182b (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.c71
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);
}