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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines