/** * Count which (input, temporary) register is read and written how often, * and scan the instruction stream to find dependencies. */ static void scan_instructions(struct pair_state *s) { struct prog_instruction *inst; struct pair_state_instruction *pairinst; GLuint ip; for(inst = s->Program->Instructions, pairinst = s->Instructions, ip = 0; inst->Opcode != OPCODE_END; ++inst, ++pairinst, ++ip) { final_rewrite(s, inst); classify_instruction(s, inst, pairinst); int nsrc = _mesa_num_inst_src_regs(inst->Opcode); int j; for(j = 0; j < nsrc; j++) { struct pair_register_translation *t = get_register(s, inst->SrcReg[j].File, inst->SrcReg[j].Index); if (!t) continue; t->RefCount++; if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) { int i; for(i = 0; i < 4; ++i) { GLuint swz = GET_SWZ(inst->SrcReg[j].Swizzle, i); if (swz >= 4) continue; /* constant or NIL swizzle */ if (!t->Value[swz]) continue; /* this is an undefined read */ /* Do not add a dependency if this instruction * also rewrites the value. The code below adds * a dependency for the DstReg, which is a superset * of the SrcReg dependency. */ if (inst->DstReg.File == PROGRAM_TEMPORARY && inst->DstReg.Index == inst->SrcReg[j].Index && GET_BIT(inst->DstReg.WriteMask, swz)) continue; struct reg_value_reader* r = &s->ReaderPool[s->ReaderPoolUsed++]; pairinst->NumDependencies++; t->Value[swz]->NumReaders++; r->IP = ip; r->Next = t->Value[swz]->Readers; t->Value[swz]->Readers = r; } } } int ndst = _mesa_num_inst_dst_regs(inst->Opcode); if (ndst) { struct pair_register_translation *t = get_register(s, inst->DstReg.File, inst->DstReg.Index); if (t) { t->RefCount++; if (inst->DstReg.File == PROGRAM_TEMPORARY) { int j; for(j = 0; j < 4; ++j) { if (!GET_BIT(inst->DstReg.WriteMask, j)) continue; struct reg_value* v = &s->ValuePool[s->ValuePoolUsed++]; v->IP = ip; if (t->Value[j]) { pairinst->NumDependencies++; t->Value[j]->Next = v; } t->Value[j] = v; pairinst->Values[j] = v; } } } } if (s->Verbose) _mesa_printf("scan(%i): NumDeps = %i\n", ip, pairinst->NumDependencies); if (!pairinst->NumDependencies) instruction_ready(s, ip); } /* Clear the PROGRAM_TEMPORARY state */ int i, j; for(i = 0; i < MAX_PROGRAM_TEMPS; ++i) { for(j = 0; j < 4; ++j) s->Temps[i].Value[j] = 0; } }
/** * Fill the given ALU instruction's opcodes and source operands into the given pair, * if possible. */ static void set_pair_instruction(struct r300_fragment_program_compiler *c, struct rc_pair_instruction * pair, struct rc_sub_instruction * inst) { memset(pair, 0, sizeof(struct rc_pair_instruction)); int needrgb, needalpha, istranscendent; classify_instruction(inst, &needrgb, &needalpha, &istranscendent); if (needrgb) { if (istranscendent) pair->RGB.Opcode = RC_OPCODE_REPL_ALPHA; else pair->RGB.Opcode = inst->Opcode; if (inst->SaturateMode == RC_SATURATE_ZERO_ONE) pair->RGB.Saturate = 1; } if (needalpha) { pair->Alpha.Opcode = inst->Opcode; if (inst->SaturateMode == RC_SATURATE_ZERO_ONE) pair->Alpha.Saturate = 1; } const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->Opcode); int nargs = opcode->NumSrcRegs; int i; /* Special case for DDX/DDY (MDH/MDV). */ if (inst->Opcode == RC_OPCODE_DDX || inst->Opcode == RC_OPCODE_DDY) { nargs++; } for(i = 0; i < opcode->NumSrcRegs; ++i) { int source; if (needrgb && !istranscendent) { unsigned int srcrgb = 0; unsigned int srcalpha = 0; int j; for(j = 0; j < 3; ++j) { unsigned int swz = GET_SWZ(inst->SrcReg[i].Swizzle, j); if (swz < 3) srcrgb = 1; else if (swz < 4) srcalpha = 1; } source = rc_pair_alloc_source(pair, srcrgb, srcalpha, inst->SrcReg[i].File, inst->SrcReg[i].Index); pair->RGB.Arg[i].Source = source; pair->RGB.Arg[i].Swizzle = inst->SrcReg[i].Swizzle & 0x1ff; pair->RGB.Arg[i].Abs = inst->SrcReg[i].Abs; pair->RGB.Arg[i].Negate = !!(inst->SrcReg[i].Negate & (RC_MASK_X | RC_MASK_Y | RC_MASK_Z)); } if (needalpha) { unsigned int srcrgb = 0; unsigned int srcalpha = 0; unsigned int swz = GET_SWZ(inst->SrcReg[i].Swizzle, istranscendent ? 0 : 3); if (swz < 3) srcrgb = 1; else if (swz < 4) srcalpha = 1; source = rc_pair_alloc_source(pair, srcrgb, srcalpha, inst->SrcReg[i].File, inst->SrcReg[i].Index); pair->Alpha.Arg[i].Source = source; pair->Alpha.Arg[i].Swizzle = swz; pair->Alpha.Arg[i].Abs = inst->SrcReg[i].Abs; pair->Alpha.Arg[i].Negate = !!(inst->SrcReg[i].Negate & RC_MASK_W); } } /* Destination handling */ if (inst->DstReg.File == RC_FILE_OUTPUT) { if (inst->DstReg.Index == c->OutputDepth) { pair->Alpha.DepthWriteMask |= GET_BIT(inst->DstReg.WriteMask, 3); } else { for (i = 0; i < 4; i++) { if (inst->DstReg.Index == c->OutputColor[i]) { pair->RGB.Target = i; pair->Alpha.Target = i; pair->RGB.OutputWriteMask |= inst->DstReg.WriteMask & RC_MASK_XYZ; pair->Alpha.OutputWriteMask |= GET_BIT(inst->DstReg.WriteMask, 3); break; } } } } else { if (needrgb) { pair->RGB.DestIndex = inst->DstReg.Index; pair->RGB.WriteMask |= inst->DstReg.WriteMask & RC_MASK_XYZ; } if (needalpha) { pair->Alpha.DestIndex = inst->DstReg.Index; pair->Alpha.WriteMask |= GET_BIT(inst->DstReg.WriteMask, 3); } } if (inst->WriteALUResult) { pair->WriteALUResult = inst->WriteALUResult; pair->ALUResultCompare = inst->ALUResultCompare; } }