ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rholo3.c
Revision: 3.29
Committed: Sat Jan 9 19:48:28 1999 UTC (25 years, 3 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.28: +4 -0 lines
Log Message:
added packet deallocation to dispbeam()

File Contents

# User Rev Content
1 gwlarson 3.23 /* Copyright (c) 1998 Silicon Graphics, Inc. */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ SGI";
5     #endif
6    
7 gregl 3.1 /*
8     * Routines for tracking beam compuatations
9     */
10    
11     #include "rholo.h"
12 gwlarson 3.28 #include <sys/types.h>
13 gregl 3.1
14 gwlarson 3.27 #ifndef NFRAG2CHUNK
15     #define NFRAG2CHUNK 4096 /* number of fragments to start chunking */
16     #endif
17    
18     #ifndef abs
19 gregl 3.1 #define abs(x) ((x) > 0 ? (x) : -(x))
20 gwlarson 3.27 #endif
21     #ifndef sgn
22 gregl 3.1 #define sgn(x) ((x) > 0 ? 1 : (x) < 0 ? -1 : 0)
23 gwlarson 3.27 #endif
24 gregl 3.1
25 gwlarson 3.27 #define rchunk(n) (((n)+(RPACKSIZ/2))/RPACKSIZ)
26    
27 gwlarson 3.28 extern time_t time();
28    
29 gregl 3.4 static PACKHEAD *complist=NULL; /* list of beams to compute */
30     static int complen=0; /* length of complist */
31     static int listpos=0; /* current list position for next_packet */
32     static int lastin= -1; /* last ordered position in list */
33 gwlarson 3.27 static int chunky=0; /* clump beams together on disk */
34 gregl 3.1
35    
36     int
37 gwlarson 3.23 beamcmp(b0, b1) /* comparison for compute order */
38 gregl 3.2 register PACKHEAD *b0, *b1;
39     {
40 gwlarson 3.27 BEAMI *bip0, *bip1;
41     register long c;
42     /* first check desired quantities */
43     if (chunky)
44 gwlarson 3.28 c = rchunk(b1->nr)*(rchunk(b0->nc)+1L) -
45     rchunk(b0->nr)*(rchunk(b1->nc)+1L);
46 gwlarson 3.27 else
47 gwlarson 3.28 c = b1->nr*(b0->nc+1L) - b0->nr*(b1->nc+1L);
48     if (c > 0) return(1);
49     if (c < 0) return(-1);
50 gwlarson 3.27 /* only one file, so skip the following: */
51     #if 0
52     /* next, check file descriptors */
53     c = hdlist[b0->hd]->fd - hdlist[b1->hd]->fd;
54     if (c) return(c);
55     #endif
56     /* finally, check file positions */
57     bip0 = &hdlist[b0->hd]->bi[b0->bi];
58     bip1 = &hdlist[b1->hd]->bi[b1->bi];
59     /* put diskless beams last */
60     if (!bip0->nrd)
61     return(bip1->nrd > 0);
62     if (!bip1->nrd)
63     return(-1);
64     c = bip0->fo - bip1->fo;
65     return(c < 0 ? -1 : c > 0);
66 gregl 3.2 }
67    
68    
69 gregl 3.14 int
70 gwlarson 3.23 beamidcmp(b0, b1) /* comparison for beam searching */
71     register PACKHEAD *b0, *b1;
72     {
73     register int c = b0->hd - b1->hd;
74    
75     if (c) return(c);
76     return(b0->bi - b1->bi);
77     }
78    
79    
80     int
81     dispbeam(b, hb) /* display a holodeck beam */
82 gregl 3.14 register BEAM *b;
83 gwlarson 3.23 register HDBEAMI *hb;
84 gregl 3.14 {
85     static int n = 0;
86     static PACKHEAD *p = NULL;
87    
88     if (b == NULL)
89     return;
90     if (b->nrm > n) { /* (re)allocate packet holder */
91     n = b->nrm;
92     if (p == NULL) p = (PACKHEAD *)malloc(packsiz(n));
93     else p = (PACKHEAD *)realloc((char *)p, packsiz(n));
94     if (p == NULL)
95     error(SYSTEM, "out of memory in dispbeam");
96     }
97     /* assign packet fields */
98     bcopy((char *)hdbray(b), (char *)packra(p), b->nrm*sizeof(RAYVAL));
99     p->nr = p->nc = b->nrm;
100 gwlarson 3.23 for (p->hd = 0; hdlist[p->hd] != hb->h; p->hd++)
101 gregl 3.14 if (hdlist[p->hd] == NULL)
102     error(CONSISTENCY, "unregistered holodeck in dispbeam");
103 gwlarson 3.23 p->bi = hb->b;
104 gregl 3.14 disp_packet(p); /* display it */
105 gwlarson 3.29 if (n >= 1024) { /* free ridiculous packets */
106     free((char *)p);
107     p = NULL; n = 0;
108     }
109 gregl 3.14 }
110    
111    
112 gregl 3.2 bundle_set(op, clist, nents) /* bundle set operation */
113     int op;
114 gwlarson 3.23 PACKHEAD *clist;
115 gregl 3.2 int nents;
116     {
117 gwlarson 3.23 int oldnr, n;
118     HDBEAMI *hbarr;
119     register PACKHEAD *csm;
120     register int i;
121     /* search for common members */
122     for (csm = clist+nents; csm-- > clist; )
123     csm->nc = -1;
124 gwlarson 3.25 qsort((char *)clist, nents, sizeof(PACKHEAD), beamidcmp);
125 gwlarson 3.23 for (i = 0; i < complen; i++) {
126     csm = (PACKHEAD *)bsearch((char *)(complist+i), (char *)clist,
127     nents, sizeof(PACKHEAD), beamidcmp);
128     if (csm == NULL)
129     continue;
130     oldnr = complist[i].nr;
131     csm->nc = complist[i].nc;
132     switch (op) {
133     case BS_ADD: /* add to count */
134     complist[i].nr += csm->nr;
135     csm->nr = 0;
136     break;
137     case BS_ADJ: /* reset count */
138     complist[i].nr = csm->nr;
139     csm->nr = 0;
140     break;
141     case BS_DEL: /* delete count */
142     if (csm->nr == 0 || csm->nr >= complist[i].nr)
143     complist[i].nr = 0;
144     else
145     complist[i].nr -= csm->nr;
146     break;
147     }
148     if (complist[i].nr != oldnr)
149     lastin = -1; /* flag sort */
150 gregl 3.20 }
151 gwlarson 3.24 /* record computed rays for uncommon beams */
152 gwlarson 3.23 for (csm = clist+nents; csm-- > clist; )
153     if (csm->nc < 0)
154     csm->nc = bnrays(hdlist[csm->hd], csm->bi);
155 gregl 3.20 /* complete list operations */
156 gregl 3.2 switch (op) {
157     case BS_NEW: /* new computation set */
158 gwlarson 3.21 listpos = 0; lastin = -1;
159 gregl 3.20 if (complen) /* free old list */
160 gregl 3.2 free((char *)complist);
161 gregl 3.20 complist = NULL;
162     if (!(complen = nents))
163 gregl 3.2 return;
164     complist = (PACKHEAD *)malloc(nents*sizeof(PACKHEAD));
165     if (complist == NULL)
166     goto memerr;
167     bcopy((char *)clist, (char *)complist, nents*sizeof(PACKHEAD));
168     break;
169     case BS_ADD: /* add to computation set */
170 gregl 3.11 case BS_ADJ: /* adjust set quantities */
171 gregl 3.2 if (nents <= 0)
172     return;
173 gregl 3.20 sortcomplist(); /* sort updated list & new entries */
174 gregl 3.2 qsort((char *)clist, nents, sizeof(PACKHEAD), beamcmp);
175     /* what can't we satisfy? */
176 gwlarson 3.23 for (i = nents, csm = clist; i-- && csm->nr > csm->nc; csm++)
177 gregl 3.2 ;
178 gwlarson 3.23 n = csm - clist;
179 gwlarson 3.22 if (op == BS_ADJ) { /* don't regenerate adjusted beams */
180 gwlarson 3.24 for (++i; i-- && csm->nr > 0; csm++)
181 gwlarson 3.22 ;
182 gwlarson 3.24 nents = csm - clist;
183 gwlarson 3.22 }
184 gregl 3.2 if (n) { /* allocate space for merged list */
185     PACKHEAD *newlist;
186     newlist = (PACKHEAD *)malloc(
187     (complen+n)*sizeof(PACKHEAD) );
188     if (newlist == NULL)
189     goto memerr;
190     /* merge lists */
191     mergeclists(newlist, clist, n, complist, complen);
192     if (complen)
193     free((char *)complist);
194     complist = newlist;
195     complen += n;
196     }
197     listpos = 0;
198     lastin = complen-1; /* list is now sorted */
199     break;
200     case BS_DEL: /* delete from computation set */
201 gregl 3.20 return; /* already done */
202 gregl 3.2 default:
203     error(CONSISTENCY, "bundle_set called with unknown operation");
204     }
205 gwlarson 3.27 if (outdev == NULL || !nents) /* nothing to display? */
206 gwlarson 3.22 return;
207     /* load and display beams we have */
208 gwlarson 3.23 hbarr = (HDBEAMI *)malloc(nents*sizeof(HDBEAMI));
209     for (i = nents; i--; ) {
210     hbarr[i].h = hdlist[clist[i].hd];
211     hbarr[i].b = clist[i].bi;
212 gregl 3.11 }
213 gwlarson 3.23 hdloadbeams(hbarr, nents, dispbeam);
214     free((char *)hbarr);
215 gwlarson 3.27 if (hdfragflags&FF_READ) {
216     listpos = 0;
217     lastin = -1; /* need to re-sort list */
218     }
219 gregl 3.2 return;
220     memerr:
221     error(SYSTEM, "out of memory in bundle_set");
222     }
223    
224    
225 gregl 3.13 double
226     beamvolume(hp, bi) /* compute approximate volume of a beam */
227 gregl 3.1 HOLO *hp;
228 gregl 3.13 int bi;
229 gregl 3.1 {
230 gregl 3.13 GCOORD gc[2];
231     FVECT cp[4], edgeA, edgeB, cent[2];
232     FVECT v, crossp[2], diffv;
233     double vol[2];
234     register int i;
235     /* get grid coordinates */
236     if (!hdbcoord(gc, hp, bi))
237     error(CONSISTENCY, "bad beam index in beamvolume");
238     for (i = 0; i < 2; i++) { /* compute cell area vectors */
239     hdcell(cp, hp, gc+i);
240     VSUM(edgeA, cp[1], cp[0], -1.0);
241     VSUM(edgeB, cp[3], cp[1], -1.0);
242     fcross(crossp[i], edgeA, edgeB);
243     /* compute center */
244     cent[i][0] = 0.5*(cp[0][0] + cp[2][0]);
245     cent[i][1] = 0.5*(cp[0][1] + cp[2][1]);
246     cent[i][2] = 0.5*(cp[0][2] + cp[2][2]);
247 gregl 3.1 }
248 gregl 3.13 /* compute difference vector */
249     VSUM(diffv, cent[1], cent[0], -1.0);
250     for (i = 0; i < 2; i++) { /* compute volume contributions */
251 gregl 3.15 vol[i] = 0.5*DOT(crossp[i], diffv);
252 gregl 3.13 if (vol[i] < 0.) vol[i] = -vol[i];
253     }
254     return(vol[0] + vol[1]); /* return total volume */
255 gregl 3.1 }
256    
257    
258     init_global() /* initialize global ray computation */
259     {
260     long wtotal = 0;
261     double frac;
262 gregl 3.13 int i;
263     register int j, k;
264 gregl 3.18 /* free old list and empty queue */
265     if (complen > 0) {
266 gregl 3.3 free((char *)complist);
267 gregl 3.18 done_packets(flush_queue());
268     }
269 gwlarson 3.28 /* reseed random number generator */
270     srandom(time(NULL));
271 gregl 3.1 /* allocate beam list */
272     complen = 0;
273     for (j = 0; hdlist[j] != NULL; j++)
274     complen += nbeams(hdlist[j]);
275     complist = (PACKHEAD *)malloc(complen*sizeof(PACKHEAD));
276     if (complist == NULL)
277     error(SYSTEM, "out of memory in init_global");
278     /* compute beam weights */
279     k = 0;
280 gregl 3.13 for (j = 0; hdlist[j] != NULL; j++) {
281 gregl 3.19 frac = 512. * VLEN(hdlist[j]->wg[0]) *
282     VLEN(hdlist[j]->wg[1]) *
283     VLEN(hdlist[j]->wg[2]);
284 gregl 3.1 for (i = nbeams(hdlist[j]); i > 0; i--) {
285     complist[k].hd = j;
286     complist[k].bi = i;
287 gregl 3.13 complist[k].nr = frac*beamvolume(hdlist[j], i) + 0.5;
288 gregl 3.18 complist[k].nc = bnrays(hdlist[j], i);
289 gregl 3.1 wtotal += complist[k++].nr;
290     }
291 gregl 3.13 }
292 gregl 3.1 /* adjust weights */
293 gregl 3.12 if (vdef(DISKSPACE))
294 gregl 3.1 frac = 1024.*1024.*vflt(DISKSPACE) / (wtotal*sizeof(RAYVAL));
295 gregl 3.12 else
296     frac = 1024.*1024.*16384. / (wtotal*sizeof(RAYVAL));
297     while (k--)
298 gwlarson 3.24 complist[k].nr = frac*complist[k].nr + 0.5;
299 gwlarson 3.21 listpos = 0; lastin = -1; /* perform initial sort */
300     sortcomplist();
301 gwlarson 3.25 /* no view vicinity */
302     myeye.rng = 0;
303 gregl 3.1 }
304    
305    
306     mergeclists(cdest, cl1, n1, cl2, n2) /* merge two sorted lists */
307 gregl 3.16 register PACKHEAD *cdest;
308     register PACKHEAD *cl1, *cl2;
309 gregl 3.1 int n1, n2;
310     {
311 gregl 3.16 register int cmp;
312 gregl 3.1
313     while (n1 | n2) {
314     if (!n1) cmp = 1;
315     else if (!n2) cmp = -1;
316     else cmp = beamcmp(cl1, cl2);
317     if (cmp > 0) {
318     copystruct(cdest, cl2);
319     cl2++; n2--;
320     } else {
321     copystruct(cdest, cl1);
322     cl1++; n1--;
323     }
324     cdest++;
325     }
326     }
327    
328    
329     sortcomplist() /* fix our list order */
330     {
331     PACKHEAD *list2;
332 gwlarson 3.27 int listlen;
333 gregl 3.2 register int i;
334    
335 gregl 3.3 if (complen <= 0) /* check to see if there is even a list */
336 gregl 3.2 return;
337 gwlarson 3.27 if (!chunky) /* check to see if fragment list is full */
338     if (!hdfragOK(hdlist[0]->fd, &listlen, NULL)
339     #if NFRAG2CHUNK
340     || listlen >= NFRAG2CHUNK
341     #endif
342     ) {
343     #ifdef DEBUG
344     error(WARNING, "using chunky comparison mode");
345     #endif
346     chunky++; /* use "chunky" comparison */
347     lastin = -1; /* need to re-sort list */
348     }
349 gwlarson 3.28 #ifdef DEBUG
350     else
351     fprintf(stderr, "sortcomplist: %d fragments\n",
352     listlen);
353     #endif
354 gregl 3.6 if (lastin < 0 || listpos*4 >= complen*3)
355 gregl 3.1 qsort((char *)complist, complen, sizeof(PACKHEAD), beamcmp);
356     else if (listpos) { /* else sort and merge sublist */
357     list2 = (PACKHEAD *)malloc(listpos*sizeof(PACKHEAD));
358     if (list2 == NULL)
359     error(SYSTEM, "out of memory in sortcomplist");
360     bcopy((char *)complist,(char *)list2,listpos*sizeof(PACKHEAD));
361     qsort((char *)list2, listpos, sizeof(PACKHEAD), beamcmp);
362     mergeclists(complist, list2, listpos,
363     complist+listpos, complen-listpos);
364     free((char *)list2);
365     }
366 gregl 3.2 /* drop satisfied requests */
367 gregl 3.11 for (i = complen; i-- && complist[i].nr <= complist[i].nc; )
368 gregl 3.2 ;
369 gregl 3.4 if (i < 0) {
370     free((char *)complist);
371     complist = NULL;
372     complen = 0;
373     } else if (i < complen-1) {
374 gregl 3.2 list2 = (PACKHEAD *)realloc((char *)complist,
375     (i+1)*sizeof(PACKHEAD));
376 gwlarson 3.26 if (list2 != NULL)
377 gregl 3.2 complist = list2;
378 gwlarson 3.26 complen = i+1;
379 gregl 3.2 }
380     listpos = 0; lastin = i;
381 gregl 3.1 }
382    
383    
384     /*
385     * The following routine works on the assumption that the bundle weights are
386     * more or less evenly distributed, such that computing a packet causes
387     * a given bundle to move way down in the computation order. We keep
388     * track of where the computed bundle with the highest priority would end
389 gwlarson 3.27 * up, and if we get further in our compute list than this, we re-sort the
390 gregl 3.11 * list and start again from the beginning. Since
391     * a merge sort is used, the sorting costs are minimal.
392 gregl 3.1 */
393 gregl 3.17 next_packet(p, n) /* prepare packet for computation */
394 gregl 3.1 register PACKET *p;
395 gregl 3.17 int n;
396 gregl 3.1 {
397     register int i;
398    
399 gregl 3.10 if (listpos > lastin) /* time to sort the list */
400     sortcomplist();
401 gregl 3.1 if (complen <= 0)
402     return(0);
403     p->hd = complist[listpos].hd;
404     p->bi = complist[listpos].bi;
405 gregl 3.11 p->nc = complist[listpos].nc;
406     p->nr = complist[listpos].nr - p->nc;
407 gregl 3.1 if (p->nr <= 0)
408     return(0);
409 gwlarson 3.28 DCHECK(n < 1 | n > RPACKSIZ,
410     CONSISTENCY, "next_packet called with bad n value");
411 gregl 3.17 if (p->nr > n)
412     p->nr = n;
413 gregl 3.11 complist[listpos].nc += p->nr; /* find where this one would go */
414 gwlarson 3.27 if (hdgetbeam(hdlist[p->hd], p->bi) != NULL)
415     hdfreefrag(hdlist[p->hd], p->bi);
416 gregl 3.11 while (lastin > listpos &&
417     beamcmp(complist+lastin, complist+listpos) > 0)
418 gregl 3.1 lastin--;
419     listpos++;
420     return(1);
421     }