diff options
author | Christoph Bumiller <[email protected]> | 2010-09-07 15:40:34 +0200 |
---|---|---|
committer | Christoph Bumiller <[email protected]> | 2010-09-09 19:21:34 +0200 |
commit | d91b8865ec2bb41f9b58ad5ce2df7f6f48f98281 (patch) | |
tree | bc6ff85f2f891b9b05124cc1f8ec874159a3ace0 /src/gallium/drivers/nv50/nv50_program.c | |
parent | 217542a061ef31150b1b04f1b45b6099bcc153fe (diff) |
nv50: prepare for having multiple functions
At some point we'll want to support real subroutines instead of
just inlining them into the main shader.
Since recursive calls are forbidden, we can just save all used
registers to a fixed local memory region and restore them on a
return, no need for a stack pointer.
Diffstat (limited to 'src/gallium/drivers/nv50/nv50_program.c')
-rw-r--r-- | src/gallium/drivers/nv50/nv50_program.c | 63 |
1 files changed, 60 insertions, 3 deletions
diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c index d7d3030e2f6..925028700cd 100644 --- a/src/gallium/drivers/nv50/nv50_program.c +++ b/src/gallium/drivers/nv50/nv50_program.c @@ -147,10 +147,17 @@ prog_inst(struct nv50_translation_info *ti, int s, c, k; unsigned mask; + if (inst->Instruction.Opcode == TGSI_OPCODE_BGNSUB) { + ti->subr[ti->subr_nr].pos = id - 1; + ti->subr[ti->subr_nr].id = ti->subr_nr + 1; /* id 0 is main program */ + ++ti->subr_nr; + } + if (inst->Dst[0].Register.File == TGSI_FILE_OUTPUT) { + dst = &inst->Dst[0].Register; + for (c = 0; c < 4; ++c) { - dst = &inst->Dst[0].Register; - if (inst->Dst[0].Register.Indirect) + if (dst->Indirect) nv50_indirect_outputs(ti, id); if (!(dst->WriteMask & (1 << c))) continue; @@ -182,6 +189,44 @@ prog_inst(struct nv50_translation_info *ti, } } +/* Probably should introduce something like struct tgsi_function_declaration + * instead of trying to guess inputs/outputs. + */ +static void +prog_subroutine_inst(struct nv50_subroutine *subr, + const struct tgsi_full_instruction *inst) +{ + const struct tgsi_dst_register *dst; + const struct tgsi_src_register *src; + int s, c, k; + unsigned mask; + + for (s = 0; s < inst->Instruction.NumSrcRegs; ++s) { + src = &inst->Src[s].Register; + if (src->File != TGSI_FILE_TEMPORARY) + continue; + mask = nv50_tgsi_src_mask(inst, s); + + assert(!inst->Src[s].Register.Indirect); + + for (c = 0; c < 4; ++c) { + k = tgsi_util_get_full_src_register_swizzle(&inst->Src[s], c); + + if ((mask & (1 << c)) && k < TGSI_SWIZZLE_W) + if (!(subr->retv[src->Index / 32][k] & (1 << (src->Index % 32)))) + subr->argv[src->Index / 32][k] |= 1 << (src->Index % 32); + } + } + + if (inst->Dst[0].Register.File == TGSI_FILE_TEMPORARY) { + dst = &inst->Dst[0].Register; + + for (c = 0; c < 4; ++c) + if (dst->WriteMask & (1 << c)) + subr->retv[dst->Index / 32][c] |= 1 << (dst->Index % 32); + } +} + static void prog_immediate(struct nv50_translation_info *ti, const struct tgsi_full_immediate *imm) @@ -482,7 +527,7 @@ nv50_prog_scan(struct nv50_translation_info *ti) { struct nv50_program *p = ti->p; struct tgsi_parse_context parse; - int ret; + int ret, i; p->vp.edgeflag = 0x40; p->vp.psiz = 0x40; @@ -496,6 +541,9 @@ nv50_prog_scan(struct nv50_translation_info *ti) tgsi_dump(p->pipe.tokens, 0); #endif + ti->subr = + CALLOC(ti->scan.opcode_count[TGSI_OPCODE_BGNSUB], sizeof(ti->subr[0])); + ti->immd32 = (uint32_t *)MALLOC(ti->scan.immediate_count * 16); ti->immd32_ty = (ubyte *)MALLOC(ti->scan.immediate_count * sizeof(ubyte)); @@ -519,6 +567,13 @@ nv50_prog_scan(struct nv50_translation_info *ti) } } + /* Scan to determine which registers are inputs/outputs of a subroutine. */ + for (i = 0; i < ti->subr_nr; ++i) { + int pc = ti->subr[i].id; + while (ti->insns[pc].Instruction.Opcode != TGSI_OPCODE_ENDSUB) + prog_subroutine_inst(&ti->subr[i], &ti->insns[pc++]); + } + p->in_nr = ti->scan.file_max[TGSI_FILE_INPUT] + 1; p->out_nr = ti->scan.file_max[TGSI_FILE_OUTPUT] + 1; @@ -572,6 +627,8 @@ out: FREE(ti->immd32_ty); if (ti->insns) FREE(ti->insns); + if (ti->subr) + FREE(ti->subr); FREE(ti); return ret ? FALSE : TRUE; } |