ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/pmapcontrib.c
(Generate patch)

Comparing ray/src/rt/pmapcontrib.c (file contents):
Revision 2.13 by greg, Thu Sep 29 21:51:58 2016 UTC vs.
Revision 2.18 by rschregle, Thu Jun 7 19:26:04 2018 UTC

# Line 4 | Line 4 | static const char RCSid[] = "$Id$";
4  
5   /*
6     ======================================================================
7 <   Photon map support for building light source contributions
7 >   Photon map for light source contributions
8  
9     Roland Schregle (roland.schregle@{hslu.ch, gmail.com})
10     (c) Lucerne University of Applied Sciences and Arts,
# Line 23 | Line 23 | static const char RCSid[] = "$Id$";
23   #include "pmapdiag.h"
24   #include "rcontrib.h"
25   #include "otypes.h"
26 < #include <sys/mman.h>
27 < #include <sys/wait.h>
26 > #if NIX
27 >   #include <sys/mman.h>
28 >   #include <sys/wait.h>  
29 > #endif
30  
31  
30
32   static PhotonPrimaryIdx newPhotonPrimary (PhotonMap *pmap,
33                                            const RAY *primRay,
34                                            FILE *primHeap)
# Line 42 | Line 43 | static PhotonPrimaryIdx newPhotonPrimary (PhotonMap *p
43        return 0;
44        
45     /* Check if last primary ray has spawned photons (srcIdx >= 0, see
46 <    * newPhoton()), in which case we write it to the primary heap file
47 <    * before overwriting it */
46 >    * newPhoton()), in which case we save it to the primary heap file
47 >    * before clobbering it */
48     if (pmap -> lastPrimary.srcIdx >= 0) {
49        if (!fwrite(&pmap -> lastPrimary, sizeof(PhotonPrimary), 1, primHeap))
50           error(SYSTEM, "failed writing photon primary in newPhotonPrimary");
# Line 59 | Line 60 | static PhotonPrimaryIdx newPhotonPrimary (PhotonMap *p
60      
61     if (primRay) {
62        FVECT dvec;
63 <      
63 >
64 > #ifdef PMAP_PRIMARYDIR            
65        /* Reverse incident direction to point to light source */
66        dvec [0] = -primRay -> rdir [0];
67        dvec [1] = -primRay -> rdir [1];
68        dvec [2] = -primRay -> rdir [2];
69        pmap -> lastPrimary.dir = encodedir(dvec);
70 + #endif      
71   #ifdef PMAP_PRIMARYPOS      
72        VCOPY(pmap -> lastPrimary.pos, primRay -> rop);
73   #endif      
# Line 75 | Line 78 | static PhotonPrimaryIdx newPhotonPrimary (PhotonMap *p
78  
79  
80  
81 < #ifdef DEBUG_PMAP_CONTRIB
81 > #ifdef DEBUG_PMAP
82   static int checkPrimaryHeap (FILE *file)
83   /* Check heap for ordered primaries */
84   {
# Line 115 | Line 118 | static int checkPrimaryHeap (FILE *file)
118  
119  
120   static PhotonPrimaryIdx buildPrimaries (PhotonMap *pmap, FILE **primaryHeap,
121 +                                        char **primaryHeapFname,
122                                          PhotonPrimaryIdx *primaryOfs,
123                                          unsigned numHeaps)
124   /* Consolidate per-subprocess photon primary heaps into the primary array
# Line 132 | Line 136 | static PhotonPrimaryIdx buildPrimaries (PhotonMap *pma
136     for (heap = 0; heap < numHeaps; heap++) {
137        primaryOfs [heap] = pmap -> numPrimary;
138        
139 <      if (fseek(primaryHeap [heap], 0, SEEK_END))
139 >      if (fseek(primaryHeap [heap], 0, SEEK_END) < 0)
140           error(SYSTEM, "failed photon primary seek in buildPrimaries");
141        pmap -> numPrimary += heapLen = ftell(primaryHeap [heap]) /
142                                        sizeof(PhotonPrimary);      
# Line 148 | Line 152 | static PhotonPrimaryIdx buildPrimaries (PhotonMap *pma
152                  heapLen, primaryHeap [heap]) != heapLen)
153           error(SYSTEM, "failed reading photon primaries in buildPrimaries");
154        
155 <      fclose(primaryHeap [heap]);      
155 >      fclose(primaryHeap [heap]);
156 >      unlink(primaryHeapFname [heap]);
157     }
158    
159     return pmap -> numPrimary;
# Line 167 | Line 172 | typedef  unsigned long  PhotonContribCnt;
172  
173  
174  
175 +
176 +
177 +
178   void distribPhotonContrib (PhotonMap* pm, unsigned numProc)
179   {
180     EmissionMap       emap;
181 <   char              errmsg2 [128], shmFname [255];
181 >   char              errmsg2 [128], shmFname [PMAP_TMPFNLEN];
182     unsigned          srcIdx, proc;
183     int               shmFile, stat, pid;
184     double            *srcFlux,         /* Emitted flux per light source */
185                       srcDistribTarget; /* Target photon count per source */
186     PhotonContribCnt  *photonCnt;       /* Photon emission counter array */
187 <   const unsigned    photonCntSize = sizeof(PhotonContribCnt) *
187 >   unsigned          photonCntSize = sizeof(PhotonContribCnt) *
188                                       PHOTONCNT_NUMEMIT(nsources);
189 <   FILE              *primaryHeap [numProc];
190 <   PhotonPrimaryIdx  primaryOfs [numProc];
189 >   FILE              **primaryHeap = NULL;
190 >   char              **primaryHeapFname = NULL;
191 >   PhotonPrimaryIdx  *primaryOfs = NULL;
192                                      
193     if (!pm)
194        error(USER, "no photon map defined in distribPhotonContrib");
# Line 216 | Line 225 | void distribPhotonContrib (PhotonMap* pm, unsigned num
225    
226     /* Per-subprocess / per-source target counts */
227     pm -> distribTarget /= numProc;
228 <   srcDistribTarget = nsources ? (double)pm -> distribTarget / nsources : 0;
228 >   srcDistribTarget = nsources ? (double)pm -> distribTarget / nsources : 0;  
229    
230 <   /* Get photon ports if specified */
231 <   if (ambincl == 1)
232 <      getPhotonPorts();
230 >   if (!pm -> distribTarget)
231 >      error(INTERNAL, "no photons to distribute in distribPhotonContrib");
232 >  
233 >   /* Get photon ports from modifier list */
234 >   getPhotonPorts(photonPortList);
235        
236     /* Get photon sensor modifiers */
237     getPhotonSensors(photonSensorList);      
238 <  
238 >
239 > #if NIX  
240     /* Set up shared mem for photon counters (zeroed by ftruncate) */
241 < #if 0  
230 <   snprintf(shmFname, 255, PMAP_SHMFNAME, getpid());
231 <   shmFile = shm_open(shmFname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
232 < #else
233 <   strcpy(shmFname, PMAP_SHMFNAME);
241 >   strcpy(shmFname, PMAP_TMPFNAME);
242     shmFile = mkstemp(shmFname);
235 #endif        
243    
244     if (shmFile < 0 || ftruncate(shmFile, photonCntSize) < 0)
245        error(SYSTEM, "failed shared mem init in distribPhotonContrib");
# Line 242 | Line 249 | void distribPhotonContrib (PhotonMap* pm, unsigned num
249                      
250     if (photonCnt == MAP_FAILED)
251        error(SYSTEM, "failed shared mem mapping in distribPhotonContrib");
252 + #else
253 +   /* Allocate photon counters statically on Windoze */
254 +   if (!(photonCnt = malloc(photonCntSize)))
255 +      error(SYSTEM, "failed trivial malloc in distribPhotonContrib");
256 +  
257 +   for (srcIdx = 0; srcIdx < PHOTONCNT_NUMEMIT(nsources); srcIdx++)
258 +      photonCnt [srcIdx] = 0;
259 + #endif /* NIX */
260  
261 +   if (verbose) {
262 +      sprintf(errmsg, "\nIntegrating flux from %d sources", nsources);
263 +
264 +      if (photonPorts) {
265 +         sprintf(errmsg2, " via %d ports", numPhotonPorts);
266 +         strcat(errmsg, errmsg2);
267 +      }
268 +
269 +      strcat(errmsg, "\n");
270 +      eputs(errmsg);
271 +   }
272 +
273     /* =============================================================
274 <    * FLUX INTEGRATION - Get total flux emitted from light source
274 >    * FLUX INTEGRATION - Get total flux emitted from sources/ports
275      * ============================================================= */  
276     for (srcIdx = 0; srcIdx < nsources; srcIdx++) {
277 <      unsigned portCnt = 0;
251 <      
277 >      unsigned portCnt = 0;      
278        srcFlux [srcIdx] = 0;
279        emap.src = source + srcIdx;
280        
255      if (photonRepTime)
256         eputs("\n");
257
281        do {  /* Need at least one iteration if no ports! */      
282           emap.port = emap.src -> sflags & SDISTANT ? photonPorts + portCnt
283                                                     : NULL;
284           photonPartition [emap.src -> so -> otype] (&emap);
285 <        
286 <         if (photonRepTime) {
287 <            sprintf(errmsg, "Integrating flux from source %s (mod %s) ",
288 <                    source [srcIdx].so -> oname,
289 <                    objptr(source [srcIdx].so -> omod) -> oname);
267 <                    
285 >
286 >         if (verbose) {
287 >            sprintf(errmsg, "\tIntegrating flux from source %s ",
288 >                    source [srcIdx].so -> oname);
289 >
290              if (emap.port) {
291                 sprintf(errmsg2, "via port %s ",
292                         photonPorts [portCnt].so -> oname);
293                 strcat(errmsg, errmsg2);
294              }
295 <            
296 <            sprintf(errmsg2, "(%lu partitions)...\n", emap.numPartitions);
295 >
296 >            sprintf(errmsg2, "(%lu partitions)\n", emap.numPartitions);
297              strcat(errmsg, errmsg2);
298              eputs(errmsg);
299 + #if NIX            
300              fflush(stderr);
301 <         }
301 > #endif            
302 >         }                    
303          
304           for (emap.partitionCnt = 0; emap.partitionCnt < emap.numPartitions;
305                emap.partitionCnt++) {
# Line 292 | Line 316 | void distribPhotonContrib (PhotonMap* pm, unsigned num
316           error(WARNING, errmsg);
317        }
318     }  
319 <
320 <   if (photonRepTime)
321 <      eputs("\n");
322 <
323 <   /* Init per-subprocess primary heap files */
324 <   for (proc = 0; proc < numProc; proc++)
325 <      if (!(primaryHeap [proc] = tmpfile()))
319 >  
320 >   /* Allocate & init per-subprocess primary heap files */
321 >   primaryHeap = calloc(numProc, sizeof(FILE*));
322 >   primaryHeapFname = calloc(numProc, sizeof(char*));
323 >   primaryOfs = calloc(numProc, sizeof(PhotonPrimaryIdx));
324 >   if (!primaryHeap || !primaryHeapFname || !primaryOfs)
325 >      error(SYSTEM, "failed primary heap allocation in "
326 >            "distribPhotonContrib");
327 >      
328 >   for (proc = 0; proc < numProc; proc++) {
329 >      primaryHeapFname [proc] = malloc(PMAP_TMPFNLEN);
330 >      if (!primaryHeapFname [proc])
331 >         error(SYSTEM, "failed primary heap file allocation in "
332 >               "distribPhotonContrib");
333 >              
334 >      mktemp(strcpy(primaryHeapFname [proc], PMAP_TMPFNAME));
335 >      if (!(primaryHeap [proc] = fopen(primaryHeapFname [proc], "w+b")))
336           error(SYSTEM, "failed opening primary heap file in "
337                 "distribPhotonContrib");
338 +   }              
339 +
340 +   /* Record start time for progress reports */
341 +   repStartTime = time(NULL);
342 +
343 +   if (verbose) {
344 +      sprintf(errmsg, "\nPhoton distribution @ %d procs\n", numProc);
345 +      eputs(errmsg);
346 +   }
347                
348     /* MAIN LOOP */
349     for (proc = 0; proc < numProc; proc++) {
350 + #if NIX          
351        if (!(pid = fork())) {
352 <         /* SUBPROCESS ENTERS HERE;
353 <          * all opened and memory mapped files are inherited */
354 <          
352 >         /* SUBPROCESS ENTERS HERE; opened and mmapped files inherited */
353 > #else
354 >      if (1) {
355 >         /* No subprocess under Windoze */
356 > #endif  
357           /* Local photon counters for this subprocess */
358           unsigned long  lastNumPhotons = 0, localNumEmitted = 0;
359 <         double         photonFluxSum = 0;   /* Running photon flux sum */
359 >         double         photonFluxSum = 0;   /* Accum. photon flux */
360  
361           /* Seed RNGs from PID for decorellated photon distribution */
362           pmapSeed(randSeed + proc, partState);
363 <         pmapSeed(randSeed + proc, emitState);
364 <         pmapSeed(randSeed + proc, cntState);
365 <         pmapSeed(randSeed + proc, mediumState);
366 <         pmapSeed(randSeed + proc, scatterState);
367 <         pmapSeed(randSeed + proc, rouletteState);
363 >         pmapSeed(randSeed + (proc + 1) % numProc, emitState);
364 >         pmapSeed(randSeed + (proc + 2) % numProc, cntState);
365 >         pmapSeed(randSeed + (proc + 3) % numProc, mediumState);
366 >         pmapSeed(randSeed + (proc + 4) % numProc, scatterState);
367 >         pmapSeed(randSeed + (proc + 5) % numProc, rouletteState);
368 >
369 > #ifdef PMAP_SIGUSR                      
370 >   double partNumEmit;
371 >   unsigned long partEmitCnt;
372 >   double srcPhotonFlux, avgPhotonFlux;
373 >   unsigned       portCnt, passCnt, prePassCnt;
374 >   float          srcPreDistrib;
375 >   double         srcNumEmit;     /* # to emit from source */
376 >   unsigned long  srcNumDistrib;  /* # stored */
377 >
378 >   void sigUsrDiags()
379 >   /* Loop diags via SIGUSR1 */
380 >   {
381 >      sprintf(errmsg,
382 >              "********************* Proc %d Diags *********************\n"
383 >              "srcIdx = %d (%s)\nportCnt = %d (%s)\npassCnt = %d\n"
384 >              "srcFlux = %f\nsrcPhotonFlux = %f\navgPhotonFlux = %f\n"
385 >              "partNumEmit = %f\npartEmitCnt = %lu\n\n",
386 >              proc, srcIdx, findmaterial(source [srcIdx].so) -> oname,
387 >              portCnt, photonPorts [portCnt].so -> oname,
388 >              passCnt, srcFlux [srcIdx], srcPhotonFlux, avgPhotonFlux,
389 >              partNumEmit, partEmitCnt);
390 >      eputs(errmsg);
391 >      fflush(stderr);
392 >   }
393 > #endif
394          
395 + #ifdef PMAP_SIGUSR
396 +         signal(SIGUSR1, sigUsrDiags);
397 + #endif        
398 +
399 + #ifdef DEBUG_PMAP          
400 +         /* Output child process PID after random delay to prevent corrupted
401 +          * console output due to race condition */
402 +         usleep(1e6 * pmapRandom(rouletteState));
403 +         fprintf(stderr, "Proc %d: PID = %d "
404 +                 "(waiting 10 sec to attach debugger...)\n",
405 +                 proc, getpid());
406 +         /* Allow time for debugger to attach to child process */
407 +         sleep(10);
408 + #endif
409 +
410           /* =============================================================
411            * 2-PASS PHOTON DISTRIBUTION
412            * Pass 1 (pre):  emit fraction of target photon count
413            * Pass 2 (main): based on outcome of pass 1, estimate remaining
414            *                number of photons to emit to approximate target
415            *                count
416 <          * ============================================================= */        
416 >          * ============================================================= */
417           for (srcIdx = 0; srcIdx < nsources; srcIdx++) {
418 + #ifndef PMAP_SIGUSR        
419              unsigned       portCnt, passCnt = 0, prePassCnt = 0;
420              float          srcPreDistrib = preDistrib;
421              double         srcNumEmit = 0;       /* # to emit from source */
422              unsigned long  srcNumDistrib = pm -> numPhotons;  /* # stored */
423 + #else
424 +            passCnt = prePassCnt = 0;
425 +            srcPreDistrib = preDistrib;
426 +            srcNumEmit = 0;       /* # to emit from source */
427 +            srcNumDistrib = pm -> numPhotons;  /* # stored */
428 + #endif            
429  
430              if (srcFlux [srcIdx] < FTINY)
431                 continue;
# Line 341 | Line 435 | void distribPhotonContrib (PhotonMap* pm, unsigned num
435                    /* INIT PASS 1 */
436                    if (++prePassCnt > maxPreDistrib) {
437                       /* Warn if no photons contributed after sufficient
438 <                      * iterations */
439 <                     sprintf(errmsg, "proc %d, source %s: "
440 <                             "too many prepasses, skipped",
441 <                             proc, source [srcIdx].so -> oname);
442 <                     error(WARNING, errmsg);
438 >                      * iterations; only output from subprocess 0 to reduce
439 >                      * console clutter */
440 >                     if (!proc) {
441 >                        sprintf(errmsg,
442 >                                "source %s: too many prepasses, skipped",
443 >                                source [srcIdx].so -> oname);
444 >                        error(WARNING, errmsg);
445 >                     }
446 >
447                       break;
448                    }
449                    
# Line 354 | Line 452 | void distribPhotonContrib (PhotonMap* pm, unsigned num
452                 }
453                 else {
454                    /* INIT PASS 2 */
455 + #ifndef PMAP_SIGUSR
456                    double srcPhotonFlux, avgPhotonFlux;
457 + #endif
458                    
459                    /* Based on the outcome of the predistribution we can now
460                     * figure out how many more photons we have to emit from
# Line 376 | Line 476 | void distribPhotonContrib (PhotonMap* pm, unsigned num
476                    srcPhotonFlux = srcFlux [srcIdx] / srcNumEmit;
477                    avgPhotonFlux = photonFluxSum / (srcIdx + 1);
478                    
479 <                  if (avgPhotonFlux > 0 &&
479 >                  if (avgPhotonFlux > FTINY &&
480                        srcPhotonFlux / avgPhotonFlux < FTINY) {
481                       /* Skip source if its photon flux is grossly below the
482 <                      * running average, indicating negligible contribs at
483 <                      * the expense of excessive distribution time */
484 <                     sprintf(errmsg, "proc %d, source %s: "
485 <                             "itsy bitsy photon flux, skipped",
486 <                             proc, source [srcIdx].so -> oname);
487 <                     error(WARNING, errmsg);
488 <                     srcNumEmit = 0;
482 >                      * running average, indicating negligible contributions
483 >                      * at the expense of excessive distribution time; only
484 >                      * output from subproc 0 to reduce console clutter */
485 >                     if (!proc) {
486 >                        sprintf(errmsg,
487 >                                "source %s: itsy bitsy photon flux, skipped",
488 >                                source [srcIdx].so -> oname);                    
489 >                        error(WARNING, errmsg);
490 >                     }
491 >
492 >                     srcNumEmit = 0;   /* Or just break??? */
493                    }
494                          
495                    /* Update sum of photon flux per light source */
496                    photonFluxSum += srcPhotonFlux;
497                 }
498 <              
498 >                              
499                 portCnt = 0;
500                 do {    /* Need at least one iteration if no ports! */
501                    emap.src = source + srcIdx;
502                    emap.port = emap.src -> sflags & SDISTANT
503                                ? photonPorts + portCnt : NULL;
504                    photonPartition [emap.src -> so -> otype] (&emap);
505 <                  
506 <                  if (photonRepTime && !proc) {
505 >
506 >                  if (verbose && !proc) {
507 >                     /* Output from subproc 0 only to avoid race condition
508 >                      * on console I/O */
509                       if (!passCnt)
510 <                        sprintf(errmsg, "PREPASS %d on source %s (mod %s) ",
511 <                                prePassCnt, source [srcIdx].so -> oname,
406 <                                objptr(source[srcIdx].so->omod) -> oname);
510 >                        sprintf(errmsg, "\tPREPASS %d on source %s ",
511 >                                prePassCnt, source [srcIdx].so -> oname);
512                       else
513 <                        sprintf(errmsg, "MAIN PASS on source %s (mod %s) ",
514 <                                source [srcIdx].so -> oname,
515 <                                objptr(source[srcIdx].so->omod) -> oname);
411 <                            
513 >                        sprintf(errmsg, "\tMAIN PASS on source %s ",
514 >                                source [srcIdx].so -> oname);
515 >
516                       if (emap.port) {
517                          sprintf(errmsg2, "via port %s ",
518                                  photonPorts [portCnt].so -> oname);
519                          strcat(errmsg, errmsg2);
520                       }
521 <                    
521 >
522                       sprintf(errmsg2, "(%lu partitions)\n",
523                               emap.numPartitions);
524 <                     strcat(errmsg, errmsg2);
524 >                     strcat(errmsg, errmsg2);                    
525                       eputs(errmsg);
526 + #if NIX                    
527                       fflush(stderr);
528 <                  }
528 > #endif                    
529 >                  }                
530                    
531                    for (emap.partitionCnt = 0; emap.partitionCnt < emap.numPartitions;
532                         emap.partitionCnt++) {
533 + #ifndef PMAP_SIGUSR                      
534                       double partNumEmit;
535                       unsigned long partEmitCnt;
536 + #endif
537                      
538                       /* Get photon origin within current source partishunn
539                        * and build emission map */
# Line 444 | Line 552 | void distribPhotonContrib (PhotonMap* pm, unsigned num
552                          partEmitCnt++;
553                          
554                       /* Update local and shared global emission counter */
447                     localNumEmitted += partEmitCnt;                                    
555                       photonCnt [PHOTONCNT_NUMEMIT(srcIdx)] += partEmitCnt;
556 +                     localNumEmitted += partEmitCnt;                                    
557                      
558 <                     /* Integer counter avoids FP rounding errors */
558 >                     /* Integer counter avoids FP rounding errors during
559 >                      * iteration */
560                       while (partEmitCnt--) {
561                          RAY photonRay;
562                      
# Line 456 | Line 565 | void distribPhotonContrib (PhotonMap* pm, unsigned num
565                           * until absorbed/leaked; emitPhoton() sets the
566                           * emitting light source index in photonRay */
567                          emitPhoton(&emap, &photonRay);
568 + #if 1
569 +                        if (emap.port)
570 +                           /* !!!  PHOTON PORT REJECTION SAMPLING HACK: set
571 +                            * !!!  photon port as fake hit object for
572 +                            * !!!  primary ray to check for intersection in
573 +                            * !!!  tracePhoton() */                        
574 +                           photonRay.ro = emap.port -> so;
575 + #endif
576                          newPhotonPrimary(pm, &photonRay, primaryHeap[proc]);
577                          /* Set subprocess index in photonRay for post-
578                           * distrib primary index linearisation; this is
# Line 469 | Line 586 | void distribPhotonContrib (PhotonMap* pm, unsigned num
586                       photonCnt [PHOTONCNT_NUMPHOT] += pm -> numPhotons -
587                                                        lastNumPhotons;
588                       lastNumPhotons = pm -> numPhotons;
589 + #if !NIX
590 +                     /* Synchronous progress report on Windoze */
591 +                     if (!proc && photonRepTime > 0 &&
592 +                           time(NULL) >= repLastTime + photonRepTime) {
593 +                        unsigned s;                        
594 +                        repComplete = pm -> distribTarget * numProc;
595 +                        repProgress = photonCnt [PHOTONCNT_NUMPHOT];
596 +                        
597 +                        for (repEmitted = 0, s = 0; s < nsources; s++)
598 +                           repEmitted += photonCnt [PHOTONCNT_NUMEMIT(s)];
599 +
600 +                        pmapDistribReport();
601 +                     }
602 + #endif
603                    }
604  
605                    portCnt++;
606                 } while (portCnt < numPhotonPorts);                  
607  
608 <               if (pm -> numPhotons == srcNumDistrib)
608 >               if (pm -> numPhotons == srcNumDistrib) {
609                    /* Double predistrib factor in case no photons were stored
610                     * for this source and redo pass 1 */
611                    srcPreDistrib *= 2;
612 +               }
613                 else {
614                    /* Now do pass 2 */
615                    passCnt++;
484 /*                if (photonRepTime)
485                     eputs("\n"); */
616                 }
617              }
618           }
619                          
620           /* Flush heap buffa one final time to prevent data corruption */
621 <         flushPhotonHeap(pm);
492 <         fclose(pm -> heap);
493 <        
621 >         flushPhotonHeap(pm);        
622           /* Flush final photon primary to primary heap file */
623           newPhotonPrimary(pm, NULL, primaryHeap [proc]);
624 <         fclose(primaryHeap [proc]);
624 >         /* Heap files closed automatically on exit
625 >            fclose(pm -> heap);
626 >            fclose(primaryHeap [proc]); */
627                    
628   #ifdef DEBUG_PMAP
629 <         sprintf(errmsg, "Proc %d exited with total %ld photons\n", proc,
629 >         sprintf(errmsg, "Proc %d total %ld photons\n", proc,
630                   pm -> numPhotons);
631           eputs(errmsg);
632 +         fflush(stderr);
633   #endif
634  
635 + #ifdef PMAP_SIGUSR
636 +         signal(SIGUSR1, SIG_DFL);
637 + #endif
638 +
639 + #if NIX
640 +         /* Terminate subprocess */
641           exit(0);
642 + #endif
643        }
644        else if (pid < 0)
645           error(SYSTEM, "failed to fork subprocess in distribPhotonContrib");
646     }
647  
648 + #if NIX
649     /* PARENT PROCESS CONTINUES HERE */
511   /* Record start time and enable progress report signal handler */
512   repStartTime = time(NULL);
650   #ifdef SIGCONT
651 +   /* Enable progress report signal handler */
652     signal(SIGCONT, pmapDistribReport);
653   #endif
516 /*
517   if (photonRepTime)
518      eputs("\n"); */
519  
654     /* Wait for subprocesses to complete while reporting progress */
655     proc = numProc;
656     while (proc) {
# Line 530 | Line 664 | void distribPhotonContrib (PhotonMap* pm, unsigned num
664        
665        /* Nod off for a bit and update progress  */
666        sleep(1);
667 <      
668 <      /* Update progress report from shared subprocess counters */
667 >
668 >      /* Asynchronous progress report from shared subprocess counters */      
669        repComplete = pm -> distribTarget * numProc;
670 <      repProgress = photonCnt [PHOTONCNT_NUMPHOT];
670 >      repProgress = photonCnt [PHOTONCNT_NUMPHOT];      
671 >      
672        for (repEmitted = 0, srcIdx = 0; srcIdx < nsources; srcIdx++)
673           repEmitted += photonCnt [PHOTONCNT_NUMEMIT(srcIdx)];
674  
# Line 546 | Line 681 | void distribPhotonContrib (PhotonMap* pm, unsigned num
681        else signal(SIGCONT, pmapDistribReport);
682   #endif
683     }
684 + #endif /* NIX */
685  
686     /* ================================================================
687      * POST-DISTRIBUTION - Set photon flux and build kd-tree, etc.
688      * ================================================================ */
689   #ifdef SIGCONT    
690 +   /* Reset signal handler */
691     signal(SIGCONT, SIG_DFL);
692   #endif  
693     free(emap.samples);
694  
695     if (!pm -> numPhotons)
696 <      error(USER, "empty photon map");
696 >      error(USER, "empty contribution photon map");
697  
698     /* Load per-subprocess primary rays into pm -> primary array */
699 <   pm -> numPrimary = buildPrimaries(pm, primaryHeap, primaryOfs, numProc);
699 >   /* Dumb compilers apparently need the char** cast */
700 >   pm -> numPrimary = buildPrimaries(pm, primaryHeap,
701 >                                     (char**)primaryHeapFname,
702 >                                     primaryOfs, numProc);
703     if (!pm -> numPrimary)
704        error(INTERNAL, "no primary rays in contribution photon map");
705    
706     /* Set photon flux per source */
707     for (srcIdx = 0; srcIdx < nsources; srcIdx++)
708        srcFlux [srcIdx] /= photonCnt [PHOTONCNT_NUMEMIT(srcIdx)];
709 <
709 > #if NIX
710     /* Photon counters no longer needed, unmap shared memory */
711     munmap(photonCnt, sizeof(*photonCnt));
712     close(shmFile);
573 #if 0  
574   shm_unlink(shmFname);
575 #else
713     unlink(shmFname);
714 + #else
715 +   free(photonCnt);  
716   #endif      
717    
718 <   if (photonRepTime) {
719 <      eputs("\nBuilding contrib photon map...\n");
718 >   if (verbose) {
719 >      eputs("\nBuilding contribution photon map...\n");
720 > #if NIX      
721        fflush(stderr);
722 + #endif      
723     }
724    
725     /* Build underlying data structure; heap is destroyed */
726 <   buildPhotonMap(pm, srcFlux, primaryOfs, numProc);  
726 >   buildPhotonMap(pm, srcFlux, primaryOfs, numProc);
727 >  
728 >   /* Free per-subprocess primary heap files */
729 >   for (proc = 0; proc < numProc; proc++)
730 >      free(primaryHeapFname [proc]);
731 >      
732 >   free(primaryHeapFname);
733 >   free(primaryHeap);
734 >   free(primaryOfs);
735 >  
736 >   if (verbose)
737 >      eputs("\n");
738   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines