static void emit_instruction( struct schedule_state * s, struct rc_instruction * before) { int max_score = -1; struct schedule_instruction * max_inst = NULL; struct schedule_instruction ** max_list = NULL; unsigned tex_count = 0; struct schedule_instruction * tex_ptr; pair_instructions(s); #if VERBOSE fprintf(stderr, "Full:\n"); print_list(s->ReadyFullALU); fprintf(stderr, "RGB:\n"); print_list(s->ReadyRGB); fprintf(stderr, "Alpha:\n"); print_list(s->ReadyAlpha); fprintf(stderr, "TEX:\n"); print_list(s->ReadyTEX); #endif for (tex_ptr = s->ReadyTEX; tex_ptr; tex_ptr = tex_ptr->NextReady) { if (tex_ptr->Instruction->U.I.Opcode == RC_OPCODE_KIL) { emit_all_tex(s, before); return; } tex_count++; } update_max_score(s, &s->ReadyFullALU, &max_score, &max_inst, &max_list); update_max_score(s, &s->ReadyRGB, &max_score, &max_inst, &max_list); update_max_score(s, &s->ReadyAlpha, &max_score, &max_inst, &max_list); if (tex_count >= s->max_tex_group || max_score == -1 || (s->TEXCount > 0 && tex_count == s->TEXCount) || (!s->C->is_r500 && tex_count > 0 && max_score == -1)) { emit_all_tex(s, before); } else { remove_inst_from_list(max_list, max_inst); rc_insert_instruction(before->Prev, max_inst->Instruction); commit_alu_instruction(s, max_inst); presub_nop(before->Prev); } }
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); } }
GLboolean radeonPairProgram(GLcontext *ctx, struct gl_program *program, const struct radeon_pair_handler* handler, void *userdata) { struct pair_state s; _mesa_bzero(&s, sizeof(s)); s.Ctx = ctx; s.Program = program; s.Handler = handler; s.UserData = userdata; s.Debug = (RADEON_DEBUG & DEBUG_PIXEL) ? GL_TRUE : GL_FALSE; s.Verbose = GL_FALSE && s.Debug; s.Instructions = (struct pair_state_instruction*)_mesa_calloc( sizeof(struct pair_state_instruction)*s.Program->NumInstructions); s.ValuePool = (struct reg_value*)_mesa_calloc(sizeof(struct reg_value)*s.Program->NumInstructions*4); s.ReaderPool = (struct reg_value_reader*)_mesa_calloc( sizeof(struct reg_value_reader)*s.Program->NumInstructions*12); if (s.Debug) _mesa_printf("Emit paired program\n"); scan_instructions(&s); allocate_input_registers(&s); while(!s.Error && (s.ReadyTEX || s.ReadyRGB || s.ReadyAlpha || s.ReadyFullALU)) { if (s.ReadyTEX) emit_all_tex(&s); while(s.ReadyFullALU || s.ReadyRGB || s.ReadyAlpha) emit_alu(&s); } if (s.Debug) _mesa_printf(" END\n"); _mesa_free(s.Instructions); _mesa_free(s.ValuePool); _mesa_free(s.ReaderPool); return !s.Error; }