static void decrement_dependencies(struct pair_state *s, int ip) { struct pair_state_instruction *pairinst = s->Instructions + ip; ASSERT(pairinst->NumDependencies > 0); if (!--pairinst->NumDependencies) instruction_ready(s, ip); }
static void decrease_dependencies(struct schedule_state * s, struct schedule_instruction * sinst) { assert(sinst->NumDependencies > 0); sinst->NumDependencies--; if (!sinst->NumDependencies) instruction_ready(s, sinst); }
static void schedule_block(struct r300_fragment_program_compiler * c, struct rc_instruction * begin, struct rc_instruction * end) { struct schedule_state s; unsigned int ip; memset(&s, 0, sizeof(s)); s.C = &c->Base; /* Scan instructions for data dependencies */ ip = 0; for(struct rc_instruction * inst = begin; inst != end; inst = inst->Next) { s.Current = memory_pool_malloc(&c->Base.Pool, sizeof(*s.Current)); memset(s.Current, 0, sizeof(struct schedule_instruction)); s.Current->Instruction = inst; inst->IP = ip++; DBG("%i: Scanning\n", inst->IP); /* The order of things here is subtle and maybe slightly * counter-intuitive, to account for the case where an * instruction writes to the same register as it reads * from. */ rc_for_all_writes_chan(inst, &scan_write, &s); rc_for_all_reads_chan(inst, &scan_read, &s); DBG("%i: Has %i dependencies\n", inst->IP, s.Current->NumDependencies); if (!s.Current->NumDependencies) instruction_ready(&s, s.Current); /* Get global readers for possible RGB->Alpha conversion. */ rc_get_readers(s.C, inst, &s.Current->GlobalReaders, is_rgb_to_alpha_possible_normal, is_rgb_to_alpha_possible, NULL); } /* Temporarily unlink all instructions */ begin->Prev->Next = end; end->Prev = begin->Prev; /* Schedule instructions back */ while(!s.C->Error && (s.ReadyTEX || s.ReadyRGB || s.ReadyAlpha || s.ReadyFullALU)) { if (s.ReadyTEX) emit_all_tex(&s, end); while(!s.C->Error && (s.ReadyFullALU || s.ReadyRGB || s.ReadyAlpha)) emit_one_alu(&s, end); } }
/** * 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; } }
static void schedule_block(struct schedule_state * s, struct rc_instruction * begin, struct rc_instruction * end) { unsigned int ip; /* Scan instructions for data dependencies */ ip = 0; for(struct rc_instruction * inst = begin; inst != end; inst = inst->Next) { s->Current = memory_pool_malloc(&s->C->Pool, sizeof(*s->Current)); memset(s->Current, 0, sizeof(struct schedule_instruction)); if (inst->Type == RC_INSTRUCTION_NORMAL) { const struct rc_opcode_info * info = rc_get_opcode_info(inst->U.I.Opcode); if (info->HasTexture) { s->TEXCount++; } } /* XXX: This causes SemWait to be set for all instructions in * a block if the previous block contained a TEX instruction. * We can do better here, but it will take a lot of work. */ if (s->PrevBlockHasTex) { s->Current->TexReadCount = 1; } s->Current->Instruction = inst; inst->IP = ip++; DBG("%i: Scanning\n", inst->IP); /* The order of things here is subtle and maybe slightly * counter-intuitive, to account for the case where an * instruction writes to the same register as it reads * from. */ rc_for_all_writes_chan(inst, &scan_write, s); rc_for_all_reads_chan(inst, &scan_read, s); DBG("%i: Has %i dependencies\n", inst->IP, s->Current->NumDependencies); if (!s->Current->NumDependencies) { instruction_ready(s, s->Current); } /* Get global readers for possible RGB->Alpha conversion. */ s->Current->GlobalReaders.ExitOnAbort = 1; rc_get_readers(s->C, inst, &s->Current->GlobalReaders, is_rgb_to_alpha_possible_normal, is_rgb_to_alpha_possible, NULL); } /* Temporarily unlink all instructions */ begin->Prev->Next = end; end->Prev = begin->Prev; /* Schedule instructions back */ while(!s->C->Error && (s->ReadyTEX || s->ReadyRGB || s->ReadyAlpha || s->ReadyFullALU)) { emit_instruction(s, end); } }