static void add_tex_reader( struct schedule_state * s, struct schedule_instruction * writer, struct schedule_instruction * reader) { if (!writer || writer->Instruction->Type != RC_INSTRUCTION_NORMAL) { /*Not a TEX instructions */ return; } reader->TexReadCount++; rc_list_add(&writer->TexReaders, rc_list(&s->C->Pool, reader)); }
void fn_colon(char **args) { char *cmd, *p, *line = NULL; int i; if (args) { cmd = args[0]; args++; } else { line = p = read_string(": ", 1); if (line == NULL || line[0] == '\0') { free(line); disp_status(DISP_STATUS, ""); return; } if ((cmd=rc_token(&p)) == NULL) { disp_status(DISP_STATUS, "no function"); return; } } if ((i=find_function(cmd)) < 0) { disp_status(DISP_STATUS, "unknown function: %s", cmd); if (line) free(line); return; } if (line) { args = rc_list(p); } disp_status(DISP_STATUS, ""); if (functions[i].fn) functions[i].fn(args); if (line) { free(line); if (args) { for (i=0; args[i]; i++) free(args[i]); free(args); } } }
/** * Emit all ready texture instructions in a single block. * * Emit as a single block to (hopefully) sample many textures in parallel, * and to avoid hardware indirections on R300. */ static void emit_all_tex(struct schedule_state * s, struct rc_instruction * before) { struct schedule_instruction *readytex; struct rc_instruction * inst_begin; assert(s->ReadyTEX); notify_sem_wait(s); /* Node marker for R300 */ inst_begin = rc_insert_new_instruction(s->C, before->Prev); inst_begin->U.I.Opcode = RC_OPCODE_BEGIN_TEX; /* Link texture instructions back in */ readytex = s->ReadyTEX; while(readytex) { rc_insert_instruction(before->Prev, readytex->Instruction); DBG("%i: commit TEX reads\n", readytex->Instruction->IP); /* All of the TEX instructions in the same TEX block have * their source registers read from before any of the * instructions in that block write to their destination * registers. This means that when we commit a TEX * instruction, any other TEX instruction that wants to write * to one of the committed instruction's source register can be * marked as ready and should be emitted in the same TEX * block. This prevents the following sequence from being * emitted in two different TEX blocks: * 0: TEX temp[0].xyz, temp[1].xy__, 2D[0]; * 1: TEX temp[1].xyz, temp[2].xy__, 2D[0]; */ commit_update_reads(s, readytex); readytex = readytex->NextReady; } readytex = s->ReadyTEX; s->ReadyTEX = 0; while(readytex){ DBG("%i: commit TEX writes\n", readytex->Instruction->IP); commit_update_writes(s, readytex); /* Set semaphore bits for last TEX instruction in the block */ if (!readytex->NextReady) { readytex->Instruction->U.I.TexSemAcquire = 1; readytex->Instruction->U.I.TexSemWait = 1; } rc_list_add(&s->PendingTEX, rc_list(&s->C->Pool, readytex)); readytex = readytex->NextReady; } }
void fn_bind(char **args) { enum state state, s2; int key, fn, i; char *line = NULL; char *staten, *kname, *cmd, **list, *p; struct binding *b; state = bs_none; if (args) { if ((s2=parse_state(args[0])) != bs_nostate) { staten = args[0]; state = s2; args++; } kname = args[0]; cmd = args[1]; args += 2; } else { if (rc_inrc) { rc_error("bind: no arguments given"); return; } line = p = read_string("bind ", 1); if ((kname=rc_token(&p)) == NULL) { disp_status(DISP_STATUS, "no key"); free(line); return; } if ((s2=parse_state(kname)) != bs_nostate) { staten = kname; state = s2; if ((kname=rc_token(&p)) == NULL) { disp_status(DISP_STATUS, "no key"); free(line); return; } } cmd = rc_token(&p); } if (state == bs_unknown) { if (rc_inrc) rc_error("unknown state: %s", staten); else disp_status(DISP_STATUS, "unknown state: %s", staten); if (line) free(line); return; } if ((key=parse_key(kname)) < 0) { if (rc_inrc) rc_error("unknown key: %s", kname); else disp_status(DISP_STATUS, "unknown key: %s", kname); if (line) free(line); return; } if (cmd) { if ((fn=find_function(cmd)) < 0) { if (rc_inrc) rc_error("unknown function: %s", cmd); else disp_status(DISP_STATUS, "unknown function: %s", cmd); if (line) free(line); return; } } if (!rc_inrc) disp_status(DISP_STATUS, ""); b = get_function(key, state); if (b->state == state) { b->fn = -1; if (b->args) { if (b->args < binding_argpool || (b->args >= binding_argpool+binding_nargpool)) { for (i=0; b->args[i]; i++) free(b->args[i]); free(b->args); b->args = NULL; } } } else { if ((b=(struct binding *)malloc(sizeof(struct binding))) == NULL) return; b->fn = -1; b->args = NULL; b->state = state; b->next = binding[key].next; binding[key].next = b; } if (cmd) { if (line) list = rc_list(p); else { for (i=0; args[i]; i++) ; if (i > 0) { list = (char **)malloc(sizeof(char *)*(i+1)); memcpy(list, args, sizeof(char *)*(i+1)); } else list = NULL; } b->fn = fn; b->args = list; } return; }
int main(int argc, char **argv) { FILE *fin, *fout; char line[4096], *p, *tok, **args; char tmp[128]; struct binding *b; int i, j, off, argoff; int maxkey; prg = argv[0]; rc_inrc = 1; maxkey = max_fnkey + 256; if (argc == 2 && strcmp(argv[1], ".") != 0) srcdir = argv[1]; else srcdir = NULL; initnames(); for (i=0; i<maxkey; i++) { binding[i].next = NULL; binding[i].state = bs_none; binding[i].fn = -1; binding[i].args = NULL; } off = 0; /* processing ``bindings.desc'' */ if ((fin=vpath_open(FNAME ".desc")) == NULL) exit(1); rc_lineno = 0; while (fgets(line, 4096, fin) != NULL) { rc_lineno++; p = line; if ((tok=rc_token(&p)) == NULL || tok[0] == '#') continue; if (strcasecmp(tok, "bind") != 0) { rc_error("non-bind command ignored: %s", tok); continue; } args = rc_list(p); fn_bind(args); } if (ferror(fin)) { fprintf(stderr, "%s: read error in `%s': %s.\n", prg, rc_filename, strerror(errno)); fclose(fin); exit(1); } fclose(fin); free(rc_filename); rc_filename = NULL; /* writing ``bindings.c'' in temp file */ sprintf(tmp, FNAME ".c.%d", getpid()); if ((fout=fopen(tmp, "w")) == NULL) { fprintf(stderr, "%s: can't open output file `%s': %s.\n", prg, tmp, strerror(errno)); exit(1); } fprintf(fout, "%s", header); /* output: bindings */ off = argoff = 0; fprintf(fout, "struct binding " NAME "[] = {\n"); for (i=0; i<maxkey; i++) { fprintf(fout, " { "); if (binding[i].next) { fprintf(fout, "binding_pool+%3d, ", off); for (b=binding[i].next; b; b=b->next) off++; } else fprintf(fout, "NULL , "); if (binding[i].state+1 < nstates) fprintf(fout, "%s, ", states[binding[i].state+1]); else fprintf(fout, "%d, ", binding[i].state); fprintf(fout, "%3d, ", binding[i].fn); if (binding[i].args) { fprintf(fout, "binding_argpool+%d },\n", argoff); for (j=0; binding[i].args[j]; j++) ; argoff += j+1; } else fprintf(fout, "NULL },\n"); } fprintf(fout, "};\n\n"); if (ferror(fout)) { fprintf(stderr, "%s: write error on `%s': %s.\n", prg, FNAME ".c", strerror(errno)); exit(1); fclose(fout); } /* output: bindings_pool */ off = 1; fprintf(fout, "struct binding " NAME "_" POOL "[] = {\n"); for (i=0; i<maxkey; i++) if (binding[i].next) { for (b=binding[i].next; b; b=b->next) { fprintf(fout, " { "); if (b->next) fprintf(fout, "binding_pool+%3d, ", off); else fprintf(fout, "NULL , "); if (b->state+1 < nstates) fprintf(fout, "%s, ", states[b->state+1]); else fprintf(fout, "%d, ", b->state); fprintf(fout, "%3d, ", b->fn); if (b->args) { fprintf(fout, "binding_argpool+%d },\n", argoff); for (j=0; b->args[j]; j++) ; argoff += j+1; } else fprintf(fout, "NULL },\n"); off++; } } fprintf(fout, "};\n\n"); fprintf(fout, "int " NAME "_n" POOL " = sizeof(" NAME "_" POOL ")" " / sizeof(" NAME "_" POOL "[0]);\n\n"); if (ferror(fout)) { fprintf(stderr, "%s: write error on `%s': %s.\n", prg, FNAME ".c", strerror(errno)); exit(1); fclose(fout); } /* output: binding_argpool */ fprintf(fout, "char *" NAME "_" ARGS "[] = {\n "); for (i=0; i<maxkey; i++) if (binding[i].args) print_args(fout, binding[i].args); for (i=0; i<maxkey; i++) if (binding[i].next) for (b=binding[i].next; b; b=b->next) if (b->args) print_args(fout, b->args); fprintf(fout, "\n};\n\n"); fprintf(fout, "int " NAME "_n" ARGS " = sizeof(" NAME "_" ARGS ")" " / sizeof(" NAME "_" ARGS "[0]);\n"); if (ferror(fout)) { fprintf(stderr, "%s: write error on `%s': %s.\n", prg, FNAME ".c", strerror(errno)); fclose(fout); exit(1); } fclose(fout); /* rename tmp file to ``bindings.c'' */ if (rename(tmp, FNAME ".c") < 0) { fprintf(stderr, "%s: cannot rename `%s' to `%s': %s\n", prg, tmp, FNAME ".c", strerror(errno)); exit(1); } exit(0); }