--- ray/src/hd/rholo3.c 1998/12/15 09:28:18 3.26 +++ ray/src/hd/rholo3.c 2003/02/22 02:07:25 3.34 @@ -1,18 +1,30 @@ -/* Copyright (c) 1998 Silicon Graphics, Inc. */ - #ifndef lint -static char SCCSid[] = "$SunId$ SGI"; +static const char RCSid[] = "$Id: rholo3.c,v 3.34 2003/02/22 02:07:25 greg Exp $"; #endif - /* * Routines for tracking beam compuatations */ #include "rholo.h" +#include "view.h" +#ifndef NFRAG2CHUNK +#define NFRAG2CHUNK 4096 /* number of fragments to start chunking */ +#endif + +#ifndef abs #define abs(x) ((x) > 0 ? (x) : -(x)) +#endif +#ifndef sgn #define sgn(x) ((x) > 0 ? 1 : (x) < 0 ? -1 : 0) +#endif +#define rchunk(n) (((n)+(RPACKSIZ/2))/RPACKSIZ) + +extern time_t time(); + +int chunkycmp = 0; /* clump beams together on disk */ + static PACKHEAD *complist=NULL; /* list of beams to compute */ static int complen=0; /* length of complist */ static int listpos=0; /* current list position for next_packet */ @@ -23,7 +35,32 @@ int beamcmp(b0, b1) /* comparison for compute order */ register PACKHEAD *b0, *b1; { - return( b1->nr*(b0->nc+1) - b0->nr*(b1->nc+1) ); + BEAMI *bip0, *bip1; + register long c; + /* first check desired quantities */ + if (chunkycmp) + c = rchunk(b1->nr)*(rchunk(b0->nc)+1L) - + rchunk(b0->nr)*(rchunk(b1->nc)+1L); + else + c = b1->nr*(b0->nc+1L) - b0->nr*(b1->nc+1L); + if (c > 0) return(1); + if (c < 0) return(-1); + /* only one file, so skip the following: */ +#if 0 + /* next, check file descriptors */ + c = hdlist[b0->hd]->fd - hdlist[b1->hd]->fd; + if (c) return(c); +#endif + /* finally, check file positions */ + bip0 = &hdlist[b0->hd]->bi[b0->bi]; + bip1 = &hdlist[b1->hd]->bi[b1->bi]; + /* put diskless beams last */ + if (!bip0->nrd) + return(bip1->nrd > 0); + if (!bip1->nrd) + return(-1); + c = bip0->fo - bip1->fo; + return(c < 0 ? -1 : c > 0); } @@ -52,8 +89,7 @@ register HDBEAMI *hb; n = b->nrm; if (p == NULL) p = (PACKHEAD *)malloc(packsiz(n)); else p = (PACKHEAD *)realloc((char *)p, packsiz(n)); - if (p == NULL) - error(SYSTEM, "out of memory in dispbeam"); + CHECK(p==NULL, SYSTEM, "out of memory in dispbeam"); } /* assign packet fields */ bcopy((char *)hdbray(b), (char *)packra(p), b->nrm*sizeof(RAYVAL)); @@ -63,6 +99,10 @@ register HDBEAMI *hb; error(CONSISTENCY, "unregistered holodeck in dispbeam"); p->bi = hb->b; disp_packet(p); /* display it */ + if (n >= 1024) { /* free ridiculous packets */ + free((void *)p); + p = NULL; n = 0; + } } @@ -91,6 +131,11 @@ int nents; complist[i].nr += csm->nr; csm->nr = 0; break; + case BS_MAX: /* maximum of counts */ + if (csm->nr > complist[i].nr) + complist[i].nr = csm->nr; + csm->nr = 0; + break; case BS_ADJ: /* reset count */ complist[i].nr = csm->nr; csm->nr = 0; @@ -114,7 +159,7 @@ int nents; case BS_NEW: /* new computation set */ listpos = 0; lastin = -1; if (complen) /* free old list */ - free((char *)complist); + free((void *)complist); complist = NULL; if (!(complen = nents)) return; @@ -124,6 +169,7 @@ int nents; bcopy((char *)clist, (char *)complist, nents*sizeof(PACKHEAD)); break; case BS_ADD: /* add to computation set */ + case BS_MAX: /* maximum of quantities */ case BS_ADJ: /* adjust set quantities */ if (nents <= 0) return; @@ -133,7 +179,7 @@ int nents; for (i = nents, csm = clist; i-- && csm->nr > csm->nc; csm++) ; n = csm - clist; - if (op == BS_ADJ) { /* don't regenerate adjusted beams */ + if (op != BS_ADD) { /* don't regenerate adjusted beams */ for (++i; i-- && csm->nr > 0; csm++) ; nents = csm - clist; @@ -147,7 +193,7 @@ int nents; /* merge lists */ mergeclists(newlist, clist, n, complist, complen); if (complen) - free((char *)complist); + free((void *)complist); complist = newlist; complen += n; } @@ -159,7 +205,7 @@ int nents; default: error(CONSISTENCY, "bundle_set called with unknown operation"); } - if (outdev == NULL) /* nothing to display? */ + if (outdev == NULL || !nents) /* nothing to display? */ return; /* load and display beams we have */ hbarr = (HDBEAMI *)malloc(nents*sizeof(HDBEAMI)); @@ -168,7 +214,11 @@ int nents; hbarr[i].b = clist[i].bi; } hdloadbeams(hbarr, nents, dispbeam); - free((char *)hbarr); + free((void *)hbarr); + if (hdfragflags&FF_READ) { + listpos = 0; + lastin = -1; /* need to re-sort list */ + } return; memerr: error(SYSTEM, "out of memory in bundle_set"); @@ -208,26 +258,20 @@ int bi; } -init_global() /* initialize global ray computation */ +ambient_list() /* compute ambient beam list */ { - long wtotal = 0; + int4 wtotal, minrt; double frac; int i; register int j, k; - /* free old list and empty queue */ - if (complen > 0) { - free((char *)complist); - done_packets(flush_queue()); - } - /* allocate beam list */ + complen = 0; for (j = 0; hdlist[j] != NULL; j++) complen += nbeams(hdlist[j]); complist = (PACKHEAD *)malloc(complen*sizeof(PACKHEAD)); - if (complist == NULL) - error(SYSTEM, "out of memory in init_global"); + CHECK(complist==NULL, SYSTEM, "out of memory in ambient_list"); /* compute beam weights */ - k = 0; + k = 0; wtotal = 0; for (j = 0; hdlist[j] != NULL; j++) { frac = 512. * VLEN(hdlist[j]->wg[0]) * VLEN(hdlist[j]->wg[1]) * @@ -240,15 +284,60 @@ init_global() /* initialize global ray computation * wtotal += complist[k++].nr; } } - /* adjust weights */ + /* adjust sample weights */ if (vdef(DISKSPACE)) frac = 1024.*1024.*vflt(DISKSPACE) / (wtotal*sizeof(RAYVAL)); else - frac = 1024.*1024.*16384. / (wtotal*sizeof(RAYVAL)); - while (k--) - complist[k].nr = frac*complist[k].nr + 0.5; - listpos = 0; lastin = -1; /* perform initial sort */ - sortcomplist(); + frac = 1024.*1024.*2048. / (wtotal*sizeof(RAYVAL)); + minrt = .02*frac*wtotal/complen + .5; /* heuristic mimimum */ + if (minrt > RPACKSIZ) + minrt = RPACKSIZ; + for (k = complen; k--; ) + if ((complist[k].nr = frac*complist[k].nr + 0.5) < minrt) + complist[k].nr = minrt; + listpos = 0; lastin = -1; /* flag initial sort */ +} + + +view_list(fp) /* assign beam priority from view list */ +FILE *fp; +{ + double pa = 1.; + VIEW curview; + int xr, yr; + char *err; + BEAMLIST blist; + + copystruct(&curview, &stdview); + while (nextview(&curview, fp) != EOF) { + if ((err = setview(&curview)) != NULL) { + error(WARNING, err); + continue; + } + xr = yr = 1024; + normaspect(viewaspect(&curview), &pa, &xr, &yr); + viewbeams(&curview, xr, yr, &blist); + bundle_set(BS_MAX, blist.bl, blist.nb); + free((void *)blist.bl); + } +} + + +init_global() /* initialize global ray computation */ +{ + register int k; + /* free old list and empty queue */ + if (complen > 0) { + free((void *)complist); + done_packets(flush_queue()); + } + /* reseed random number generator */ + srandom(time(NULL)); + /* allocate beam list */ + if (readinp) + view_list(stdin); + else + ambient_list(); /* no view vicinity */ myeye.rng = 0; } @@ -280,27 +369,39 @@ int n1, n2; sortcomplist() /* fix our list order */ { PACKHEAD *list2; + int listlen; register int i; if (complen <= 0) /* check to see if there is even a list */ return; + if (!chunkycmp) /* check to see if fragment list is full */ + if (!hdfragOK(hdlist[0]->fd, &listlen, NULL) +#if NFRAG2CHUNK + || listlen >= NFRAG2CHUNK +#endif + ) { + chunkycmp++; /* use "chunky" comparison */ + lastin = -1; /* need to re-sort list */ +#ifdef DEBUG + error(WARNING, "using chunky comparison mode"); +#endif + } if (lastin < 0 || listpos*4 >= complen*3) qsort((char *)complist, complen, sizeof(PACKHEAD), beamcmp); else if (listpos) { /* else sort and merge sublist */ list2 = (PACKHEAD *)malloc(listpos*sizeof(PACKHEAD)); - if (list2 == NULL) - error(SYSTEM, "out of memory in sortcomplist"); + CHECK(list2==NULL, SYSTEM, "out of memory in sortcomplist"); bcopy((char *)complist,(char *)list2,listpos*sizeof(PACKHEAD)); qsort((char *)list2, listpos, sizeof(PACKHEAD), beamcmp); mergeclists(complist, list2, listpos, complist+listpos, complen-listpos); - free((char *)list2); + free((void *)list2); } /* drop satisfied requests */ for (i = complen; i-- && complist[i].nr <= complist[i].nc; ) ; if (i < 0) { - free((char *)complist); + free((void *)complist); complist = NULL; complen = 0; } else if (i < complen-1) { @@ -319,7 +420,7 @@ sortcomplist() /* fix our list order */ * more or less evenly distributed, such that computing a packet causes * a given bundle to move way down in the computation order. We keep * track of where the computed bundle with the highest priority would end - * up, and if we get further in our compute list than this, we resort the + * up, and if we get further in our compute list than this, we re-sort the * list and start again from the beginning. Since * a merge sort is used, the sorting costs are minimal. */ @@ -339,13 +440,13 @@ int n; p->nr = complist[listpos].nr - p->nc; if (p->nr <= 0) return(0); -#ifdef DEBUG - if (n < 1 | n > RPACKSIZ) - error(CONSISTENCY, "next_packet called with bad n value"); -#endif + DCHECK(n < 1 | n > RPACKSIZ, + CONSISTENCY, "next_packet called with bad n value"); if (p->nr > n) p->nr = n; complist[listpos].nc += p->nr; /* find where this one would go */ + if (hdgetbeam(hdlist[p->hd], p->bi) != NULL) + hdfreefrag(hdlist[p->hd], p->bi); while (lastin > listpos && beamcmp(complist+lastin, complist+listpos) > 0) lastin--;