diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c b/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c index a279549..1fdf90f 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_pair_schedule.c @@ -481,9 +481,99 @@ static int is_controlflow(struct rc_instruction * inst) return 0; } +static void rewrite_tex_dst_reg(struct r300_fragment_program_compiler *c) +{ + char used_regs[RC_REGISTER_MAX_INDEX]; + struct rc_instruction * inst; + memset(used_regs, 0, sizeof(used_regs)); + + for(inst = c->Base.Program.Instructions.Next; + inst != &c->Base.Program.Instructions; + inst = inst->Next){ + struct rc_instruction * temp; + int old_index, new_index; + const struct rc_opcode_info * info; + if(inst->Type != RC_INSTRUCTION_NORMAL || is_controlflow(inst)) + continue; + + info = rc_get_opcode_info(inst->U.I.Opcode); + if(!info->HasDstReg){ + continue; + } + old_index = inst->U.I.DstReg.Index; + if(!used_regs[old_index]){ + used_regs[old_index] = 1; + continue; + } + fprintf(stderr, "Rewriting TEX\n"); + new_index = rc_find_free_temporary(&c->Base); + for(temp = inst; temp != &c->Base.Program.Instructions; + temp = temp->Next){ + unsigned int i; + switch(temp->Type){ + case RC_INSTRUCTION_NORMAL: + info = rc_get_opcode_info(temp->U.I.Opcode); + if(info->HasDstReg){ + struct rc_dst_register *dst = &temp->U.I.DstReg; + if(dst->Index == old_index + && dst->File == RC_FILE_TEMPORARY){ + dst->Index = new_index; + } + } + for(i=0; i < info->NumSrcRegs; i++){ + struct rc_src_register *src = + &temp->U.I.SrcReg[i]; + if(src->Index == old_index + && src->File == RC_FILE_TEMPORARY){ + src->Index = new_index; + } + } + break; + case RC_INSTRUCTION_PAIR: + { + struct radeon_pair_instruction_rgb rgb = + temp->U.P.RGB; + struct radeon_pair_instruction_alpha alpha = + temp->U.P.Alpha; + /* RGB */ + info = rc_get_opcode_info(rgb.Opcode); + /* If WriteMask is defined, then the + * destination register is a temporary. */ + if(rgb.DestIndex == old_index + && info->HasDstReg + && rgb.WriteMask){ + rgb.DestIndex = new_index; + } + for(i = 0; i < info->NumSrcRegs; i++){ + if(rgb.Src[i].Index == old_index && rgb.Src[i].File == RC_FILE_TEMPORARY){ + rgb.Src[i].Index = new_index; + } + } + + /* Alpha */ + info = rc_get_opcode_info(alpha.Opcode); + if(alpha.DestIndex == old_index && info->HasDstReg && alpha.WriteMask){ + alpha.DestIndex = new_index; + } + for(i = 0; i < info->NumSrcRegs; i++){ + if(alpha.Src[i].Index == old_index && alpha.Src[i].File == RC_FILE_TEMPORARY){ + alpha.Src[i].Index = new_index; + } + } + break; + } + } + used_regs[new_index] = 1; + } + } +} + void rc_pair_schedule(struct r300_fragment_program_compiler *c) { struct rc_instruction * inst = c->Base.Program.Instructions.Next; + + rewrite_tex_dst_reg(c); + while(inst != &c->Base.Program.Instructions) { if (is_controlflow(inst)) { inst = inst->Next; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program.c b/src/mesa/drivers/dri/r300/compiler/radeon_program.c index a3c41d7..969ef84 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program.c @@ -90,6 +90,56 @@ struct rc_src_register lmul_swizzle(unsigned int swizzle, struct rc_src_register return tmp; } +static void mark_used_registers_pair(struct rc_pair_instruction * pair, + char * used) +{ + const struct rc_opcode_info * info; + unsigned int i; + struct radeon_pair_instruction_rgb rgb = pair->RGB; + struct radeon_pair_instruction_alpha alpha = pair->Alpha; + + /* RGB */ + info = rc_get_opcode_info(rgb.Opcode); + /* If WriteMask is defined, then the destination register is a + * temporary. */ + if(info->HasDstReg && rgb.WriteMask){ + used[rgb.DestIndex] = 1; + } + for(i = 0; i < info->NumSrcRegs; i++){ + if(rgb.Src[i].File == RC_FILE_TEMPORARY){ + used[rgb.Src[i].Index] = 1; + } + } + + /* Alpha */ + info = rc_get_opcode_info(alpha.Opcode); + if(info->HasDstReg && alpha.WriteMask){ + used[alpha.DestIndex] = 1; + } + for(i = 0; i < info->NumSrcRegs; i++){ + if(alpha.Src[i].File == RC_FILE_TEMPORARY){ + used[alpha.Src[i].Index] = 1; + } + } +} + +static void mark_used_registers_normal(struct rc_sub_instruction * inst, + char * used) +{ + const struct rc_opcode_info *opcode = rc_get_opcode_info(inst->Opcode); + unsigned int k; + + for (k = 0; k < opcode->NumSrcRegs; k++) { + if (inst->SrcReg[k].File == RC_FILE_TEMPORARY) + used[inst->SrcReg[k].Index] = 1; + } + if (opcode->HasDstReg) { + if (inst->DstReg.File == RC_FILE_TEMPORARY) + used[inst->DstReg.Index] = 1; + } +} + + unsigned int rc_find_free_temporary(struct radeon_compiler * c) { char used[RC_REGISTER_MAX_INDEX]; @@ -99,18 +149,17 @@ unsigned int rc_find_free_temporary(struct radeon_compiler * c) memset(used, 0, sizeof(used)); for (rcinst = c->Program.Instructions.Next; rcinst != &c->Program.Instructions; rcinst = rcinst->Next) { - const struct rc_sub_instruction *inst = &rcinst->U.I; - const struct rc_opcode_info *opcode = rc_get_opcode_info(inst->Opcode); - unsigned int k; - - for (k = 0; k < opcode->NumSrcRegs; k++) { - if (inst->SrcReg[k].File == RC_FILE_TEMPORARY) - used[inst->SrcReg[k].Index] = 1; - } - - if (opcode->HasDstReg) { - if (inst->DstReg.File == RC_FILE_TEMPORARY) - used[inst->DstReg.Index] = 1; + switch(rcinst->Type){ + case RC_INSTRUCTION_NORMAL: + mark_used_registers_normal(&rcinst->U.I, used); + break; + case RC_INSTRUCTION_PAIR: + mark_used_registers_pair(&rcinst->U.P, used); + break; + default: + rc_error(c, "%s: Unknown instruction type.", + __FUNCTION__); + break; } }