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.12 by rschregle, Tue May 17 17:39:47 2016 UTC vs.
Revision 2.19 by greg, Thu Nov 8 00:54:07 2018 UTC

# Line 4 | Line 4 | static const char RCSid[] = "$Id$";
4  
5   /*
6     ======================================================================
7 <   Photon map support for 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
31 static void setPmapContribParams (PhotonMap *pmap, LUTAB *srcContrib)
32 /* Set parameters for light source contributions */
33 {
34   /* Set light source modifier list and appropriate callback to extract
35    * their contributions from the photon map */
36   if (pmap) {
37      pmap -> srcContrib = srcContrib;
38      pmap -> lookup = photonContrib;
39      /* Ensure we get all requested photon contribs during lookups */
40      pmap -> gatherTolerance = 1.0;
41   }
42 }
43
44
45
46 static void checkPmapContribs (const PhotonMap *pmap, LUTAB *srcContrib)
47 /* Check modifiers for light source contributions */
48 {
49   const PhotonPrimary  *primary = pmap -> primaries;
50   PhotonPrimaryIdx     i, found = 0;
51   OBJREC *srcMod;
52  
53   /* Make sure at least one of the modifiers is actually in the pmap,
54    * otherwise findPhotons() winds up in an infinite loop! */
55   for (i = pmap -> numPrimary; i; --i, ++primary) {
56      if (primary -> srcIdx < 0 || primary -> srcIdx >= nsources)
57         error(INTERNAL, "invalid light source index in photon map");
58        
59      srcMod = findmaterial(source [primary -> srcIdx].so);
60      if ((MODCONT*)lu_find(srcContrib, srcMod -> oname) -> data)
61         ++found;
62   }
63  
64   if (!found)
65      error(USER, "modifiers not in photon map");
66 }
67
68  
69
70 void initPmapContrib (LUTAB *srcContrib, unsigned numSrcContrib)
71 {
72   unsigned t;
73  
74   for (t = 0; t < NUM_PMAP_TYPES; t++)
75      if (photonMaps [t] && t != PMAP_TYPE_CONTRIB) {
76         sprintf(errmsg, "%s photon map does not support contributions",
77                 pmapName [t]);
78         error(USER, errmsg);
79      }
80  
81   /* Get params */
82   setPmapContribParams(contribPmap, srcContrib);
83  
84   if (contribPhotonMapping) {
85      if (contribPmap -> maxGather < numSrcContrib) {
86         /* Adjust density estimate bandwidth if lower than modifier
87          * count, otherwise contributions are missing */
88         error(WARNING, "contrib density estimate bandwidth too low, "
89                        "adjusting to modifier count");
90         contribPmap -> maxGather = numSrcContrib;
91      }
92      
93      /* Sanity check */
94      checkPmapContribs(contribPmap, srcContrib);
95   }
96 }
97
98
99
33   static PhotonPrimaryIdx newPhotonPrimary (PhotonMap *pmap,
34                                            const RAY *primRay,
35                                            FILE *primHeap)
# Line 111 | 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 128 | 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 144 | 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 184 | 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 201 | 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 217 | 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 236 | 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 285 | Line 226 | void distribPhotonContrib (PhotonMap* pm, unsigned num
226    
227     /* Per-subprocess / per-source target counts */
228     pm -> distribTarget /= numProc;
229 <   srcDistribTarget = nsources ? (double)pm -> distribTarget / nsources : 0;
229 >   srcDistribTarget = nsources ? (double)pm -> distribTarget / nsources : 0;  
230    
231 <   /* Get photon ports if specified */
232 <   if (ambincl == 1)
233 <      getPhotonPorts();
231 >   if (!pm -> distribTarget)
232 >      error(INTERNAL, "no photons to distribute in distribPhotonContrib");
233 >  
234 >   /* Get photon ports from modifier list */
235 >   getPhotonPorts(photonPortList);
236        
237     /* Get photon sensor modifiers */
238     getPhotonSensors(photonSensorList);      
239 <  
239 >
240 > #if NIX  
241     /* Set up shared mem for photon counters (zeroed by ftruncate) */
242 < #if 0  
299 <   snprintf(shmFname, 255, PMAP_SHMFNAME, getpid());
300 <   shmFile = shm_open(shmFname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
301 < #else
302 <   strcpy(shmFname, PMAP_SHMFNAME);
242 >   strcpy(shmFname, PMAP_TMPFNAME);
243     shmFile = mkstemp(shmFname);
304 #endif        
244    
245     if (shmFile < 0 || ftruncate(shmFile, photonCntSize) < 0)
246        error(SYSTEM, "failed shared mem init in distribPhotonContrib");
# Line 311 | Line 250 | void distribPhotonContrib (PhotonMap* pm, unsigned num
250                      
251     if (photonCnt == MAP_FAILED)
252        error(SYSTEM, "failed shared mem mapping in distribPhotonContrib");
253 + #else
254 +   /* Allocate photon counters statically on Windoze */
255 +   if (!(photonCnt = malloc(photonCntSize)))
256 +      error(SYSTEM, "failed trivial malloc in distribPhotonContrib");
257 +  
258 +   for (srcIdx = 0; srcIdx < PHOTONCNT_NUMEMIT(nsources); srcIdx++)
259 +      photonCnt [srcIdx] = 0;
260 + #endif /* NIX */
261  
262 +   if (verbose) {
263 +      sprintf(errmsg, "\nIntegrating flux from %d sources", nsources);
264 +
265 +      if (photonPorts) {
266 +         sprintf(errmsg2, " via %d ports", numPhotonPorts);
267 +         strcat(errmsg, errmsg2);
268 +      }
269 +
270 +      strcat(errmsg, "\n");
271 +      eputs(errmsg);
272 +   }
273 +
274     /* =============================================================
275 <    * FLUX INTEGRATION - Get total flux emitted from light source
275 >    * FLUX INTEGRATION - Get total flux emitted from sources/ports
276      * ============================================================= */  
277     for (srcIdx = 0; srcIdx < nsources; srcIdx++) {
278 <      unsigned portCnt = 0;
320 <      
278 >      unsigned portCnt = 0;      
279        srcFlux [srcIdx] = 0;
280        emap.src = source + srcIdx;
281        
324      if (photonRepTime)
325         eputs("\n");
326
282        do {  /* Need at least one iteration if no ports! */      
283           emap.port = emap.src -> sflags & SDISTANT ? photonPorts + portCnt
284                                                     : NULL;
285           photonPartition [emap.src -> so -> otype] (&emap);
286 <        
287 <         if (photonRepTime) {
288 <            sprintf(errmsg, "Integrating flux from source %s (mod %s) ",
289 <                    source [srcIdx].so -> oname,
290 <                    objptr(source [srcIdx].so -> omod) -> oname);
336 <                    
286 >
287 >         if (verbose) {
288 >            sprintf(errmsg, "\tIntegrating flux from source %s ",
289 >                    source [srcIdx].so -> oname);
290 >
291              if (emap.port) {
292                 sprintf(errmsg2, "via port %s ",
293                         photonPorts [portCnt].so -> oname);
294                 strcat(errmsg, errmsg2);
295              }
296 <            
297 <            sprintf(errmsg2, "(%lu partitions)...\n", emap.numPartitions);
296 >
297 >            sprintf(errmsg2, "(%lu partitions)\n", emap.numPartitions);
298              strcat(errmsg, errmsg2);
299              eputs(errmsg);
300 + #if NIX            
301              fflush(stderr);
302 <         }
302 > #endif            
303 >         }                    
304          
305           for (emap.partitionCnt = 0; emap.partitionCnt < emap.numPartitions;
306                emap.partitionCnt++) {
# Line 361 | Line 317 | void distribPhotonContrib (PhotonMap* pm, unsigned num
317           error(WARNING, errmsg);
318        }
319     }  
320 <
321 <   if (photonRepTime)
322 <      eputs("\n");
323 <
324 <   /* Init per-subprocess primary heap files */
325 <   for (proc = 0; proc < numProc; proc++)
326 <      if (!(primaryHeap [proc] = tmpfile()))
320 >  
321 >   /* Allocate & init per-subprocess primary heap files */
322 >   primaryHeap = calloc(numProc, sizeof(FILE*));
323 >   primaryHeapFname = calloc(numProc, sizeof(char*));
324 >   primaryOfs = calloc(numProc, sizeof(PhotonPrimaryIdx));
325 >   if (!primaryHeap || !primaryHeapFname || !primaryOfs)
326 >      error(SYSTEM, "failed primary heap allocation in "
327 >            "distribPhotonContrib");
328 >      
329 >   for (proc = 0; proc < numProc; proc++) {
330 >      primaryHeapFname [proc] = malloc(PMAP_TMPFNLEN);
331 >      if (!primaryHeapFname [proc])
332 >         error(SYSTEM, "failed primary heap file allocation in "
333 >               "distribPhotonContrib");
334 >              
335 >      mktemp(strcpy(primaryHeapFname [proc], PMAP_TMPFNAME));
336 >      if (!(primaryHeap [proc] = fopen(primaryHeapFname [proc], "w+b")))
337           error(SYSTEM, "failed opening primary heap file in "
338                 "distribPhotonContrib");
339 +   }              
340 +
341 +   /* Record start time for progress reports */
342 +   repStartTime = time(NULL);
343 +
344 +   if (verbose) {
345 +      sprintf(errmsg, "\nPhoton distribution @ %d procs\n", numProc);
346 +      eputs(errmsg);
347 +   }
348                
349     /* MAIN LOOP */
350     for (proc = 0; proc < numProc; proc++) {
351 + #if NIX          
352        if (!(pid = fork())) {
353 <         /* SUBPROCESS ENTERS HERE;
354 <          * all opened and memory mapped files are inherited */
355 <          
353 >         /* SUBPROCESS ENTERS HERE; opened and mmapped files inherited */
354 > #else
355 >      if (1) {
356 >         /* No subprocess under Windoze */
357 > #endif  
358           /* Local photon counters for this subprocess */
359           unsigned long  lastNumPhotons = 0, localNumEmitted = 0;
360 <         double         photonFluxSum = 0;   /* Running photon flux sum */
360 >         double         photonFluxSum = 0;   /* Accum. photon flux */
361  
362           /* Seed RNGs from PID for decorellated photon distribution */
363           pmapSeed(randSeed + proc, partState);
364 <         pmapSeed(randSeed + proc, emitState);
365 <         pmapSeed(randSeed + proc, cntState);
366 <         pmapSeed(randSeed + proc, mediumState);
367 <         pmapSeed(randSeed + proc, scatterState);
368 <         pmapSeed(randSeed + proc, rouletteState);
364 >         pmapSeed(randSeed + (proc + 1) % numProc, emitState);
365 >         pmapSeed(randSeed + (proc + 2) % numProc, cntState);
366 >         pmapSeed(randSeed + (proc + 3) % numProc, mediumState);
367 >         pmapSeed(randSeed + (proc + 4) % numProc, scatterState);
368 >         pmapSeed(randSeed + (proc + 5) % numProc, rouletteState);
369 >
370 > #ifdef PMAP_SIGUSR                      
371 >   double partNumEmit;
372 >   unsigned long partEmitCnt;
373 >   double srcPhotonFlux, avgPhotonFlux;
374 >   unsigned       portCnt, passCnt, prePassCnt;
375 >   float          srcPreDistrib;
376 >   double         srcNumEmit;     /* # to emit from source */
377 >   unsigned long  srcNumDistrib;  /* # stored */
378 >
379 >   void sigUsrDiags()
380 >   /* Loop diags via SIGUSR1 */
381 >   {
382 >      sprintf(errmsg,
383 >              "********************* Proc %d Diags *********************\n"
384 >              "srcIdx = %d (%s)\nportCnt = %d (%s)\npassCnt = %d\n"
385 >              "srcFlux = %f\nsrcPhotonFlux = %f\navgPhotonFlux = %f\n"
386 >              "partNumEmit = %f\npartEmitCnt = %lu\n\n",
387 >              proc, srcIdx, findmaterial(source [srcIdx].so) -> oname,
388 >              portCnt, photonPorts [portCnt].so -> oname,
389 >              passCnt, srcFlux [srcIdx], srcPhotonFlux, avgPhotonFlux,
390 >              partNumEmit, partEmitCnt);
391 >      eputs(errmsg);
392 >      fflush(stderr);
393 >   }
394 > #endif
395          
396 + #ifdef PMAP_SIGUSR
397 +         signal(SIGUSR1, sigUsrDiags);
398 + #endif        
399 +
400 + #ifdef DEBUG_PMAP          
401 +         /* Output child process PID after random delay to prevent corrupted
402 +          * console output due to race condition */
403 +         usleep(1e6 * pmapRandom(rouletteState));
404 +         fprintf(stderr, "Proc %d: PID = %d "
405 +                 "(waiting 10 sec to attach debugger...)\n",
406 +                 proc, getpid());
407 +         /* Allow time for debugger to attach to child process */
408 +         sleep(10);
409 + #endif
410 +
411           /* =============================================================
412            * 2-PASS PHOTON DISTRIBUTION
413            * Pass 1 (pre):  emit fraction of target photon count
414            * Pass 2 (main): based on outcome of pass 1, estimate remaining
415            *                number of photons to emit to approximate target
416            *                count
417 <          * ============================================================= */        
417 >          * ============================================================= */
418           for (srcIdx = 0; srcIdx < nsources; srcIdx++) {
419 + #ifndef PMAP_SIGUSR        
420              unsigned       portCnt, passCnt = 0, prePassCnt = 0;
421              float          srcPreDistrib = preDistrib;
422              double         srcNumEmit = 0;       /* # to emit from source */
423              unsigned long  srcNumDistrib = pm -> numPhotons;  /* # stored */
424 + #else
425 +            passCnt = prePassCnt = 0;
426 +            srcPreDistrib = preDistrib;
427 +            srcNumEmit = 0;       /* # to emit from source */
428 +            srcNumDistrib = pm -> numPhotons;  /* # stored */
429 + #endif            
430  
431              if (srcFlux [srcIdx] < FTINY)
432                 continue;
# Line 410 | Line 436 | void distribPhotonContrib (PhotonMap* pm, unsigned num
436                    /* INIT PASS 1 */
437                    if (++prePassCnt > maxPreDistrib) {
438                       /* Warn if no photons contributed after sufficient
439 <                      * iterations */
440 <                     sprintf(errmsg, "proc %d, source %s: "
441 <                             "too many prepasses, skipped",
442 <                             proc, source [srcIdx].so -> oname);
443 <                     error(WARNING, errmsg);
439 >                      * iterations; only output from subprocess 0 to reduce
440 >                      * console clutter */
441 >                     if (!proc) {
442 >                        sprintf(errmsg,
443 >                                "source %s: too many prepasses, skipped",
444 >                                source [srcIdx].so -> oname);
445 >                        error(WARNING, errmsg);
446 >                     }
447 >
448                       break;
449                    }
450                    
# Line 423 | Line 453 | void distribPhotonContrib (PhotonMap* pm, unsigned num
453                 }
454                 else {
455                    /* INIT PASS 2 */
456 + #ifndef PMAP_SIGUSR
457                    double srcPhotonFlux, avgPhotonFlux;
458 + #endif
459                    
460                    /* Based on the outcome of the predistribution we can now
461                     * figure out how many more photons we have to emit from
# Line 445 | Line 477 | void distribPhotonContrib (PhotonMap* pm, unsigned num
477                    srcPhotonFlux = srcFlux [srcIdx] / srcNumEmit;
478                    avgPhotonFlux = photonFluxSum / (srcIdx + 1);
479                    
480 <                  if (avgPhotonFlux > 0 &&
480 >                  if (avgPhotonFlux > FTINY &&
481                        srcPhotonFlux / avgPhotonFlux < FTINY) {
482                       /* Skip source if its photon flux is grossly below the
483 <                      * running average, indicating negligible contribs at
484 <                      * the expense of excessive distribution time */
485 <                     sprintf(errmsg, "proc %d, source %s: "
486 <                             "itsy bitsy photon flux, skipped",
487 <                             proc, source [srcIdx].so -> oname);
488 <                     error(WARNING, errmsg);
489 <                     srcNumEmit = 0;
483 >                      * running average, indicating negligible contributions
484 >                      * at the expense of excessive distribution time; only
485 >                      * output from subproc 0 to reduce console clutter */
486 >                     if (!proc) {
487 >                        sprintf(errmsg,
488 >                                "source %s: itsy bitsy photon flux, skipped",
489 >                                source [srcIdx].so -> oname);                    
490 >                        error(WARNING, errmsg);
491 >                     }
492 >
493 >                     srcNumEmit = 0;   /* Or just break??? */
494                    }
495                          
496                    /* Update sum of photon flux per light source */
497                    photonFluxSum += srcPhotonFlux;
498                 }
499 <              
499 >                              
500                 portCnt = 0;
501                 do {    /* Need at least one iteration if no ports! */
502                    emap.src = source + srcIdx;
503                    emap.port = emap.src -> sflags & SDISTANT
504                                ? photonPorts + portCnt : NULL;
505                    photonPartition [emap.src -> so -> otype] (&emap);
506 <                  
507 <                  if (photonRepTime && !proc) {
506 >
507 >                  if (verbose && !proc) {
508 >                     /* Output from subproc 0 only to avoid race condition
509 >                      * on console I/O */
510                       if (!passCnt)
511 <                        sprintf(errmsg, "PREPASS %d on source %s (mod %s) ",
512 <                                prePassCnt, source [srcIdx].so -> oname,
475 <                                objptr(source[srcIdx].so->omod) -> oname);
511 >                        sprintf(errmsg, "\tPREPASS %d on source %s ",
512 >                                prePassCnt, source [srcIdx].so -> oname);
513                       else
514 <                        sprintf(errmsg, "MAIN PASS on source %s (mod %s) ",
515 <                                source [srcIdx].so -> oname,
516 <                                objptr(source[srcIdx].so->omod) -> oname);
480 <                            
514 >                        sprintf(errmsg, "\tMAIN PASS on source %s ",
515 >                                source [srcIdx].so -> oname);
516 >
517                       if (emap.port) {
518                          sprintf(errmsg2, "via port %s ",
519                                  photonPorts [portCnt].so -> oname);
520                          strcat(errmsg, errmsg2);
521                       }
522 <                    
522 >
523                       sprintf(errmsg2, "(%lu partitions)\n",
524                               emap.numPartitions);
525 <                     strcat(errmsg, errmsg2);
525 >                     strcat(errmsg, errmsg2);                    
526                       eputs(errmsg);
527 + #if NIX                    
528                       fflush(stderr);
529 <                  }
529 > #endif                    
530 >                  }                
531                    
532                    for (emap.partitionCnt = 0; emap.partitionCnt < emap.numPartitions;
533                         emap.partitionCnt++) {
534 + #ifndef PMAP_SIGUSR                      
535                       double partNumEmit;
536                       unsigned long partEmitCnt;
537 + #endif
538                      
539                       /* Get photon origin within current source partishunn
540                        * and build emission map */
# Line 513 | Line 553 | void distribPhotonContrib (PhotonMap* pm, unsigned num
553                          partEmitCnt++;
554                          
555                       /* Update local and shared global emission counter */
516                     localNumEmitted += partEmitCnt;                                    
556                       photonCnt [PHOTONCNT_NUMEMIT(srcIdx)] += partEmitCnt;
557 +                     localNumEmitted += partEmitCnt;                                    
558                      
559 <                     /* Integer counter avoids FP rounding errors */
559 >                     /* Integer counter avoids FP rounding errors during
560 >                      * iteration */
561                       while (partEmitCnt--) {
562                          RAY photonRay;
563                      
# Line 525 | Line 566 | void distribPhotonContrib (PhotonMap* pm, unsigned num
566                           * until absorbed/leaked; emitPhoton() sets the
567                           * emitting light source index in photonRay */
568                          emitPhoton(&emap, &photonRay);
569 + #if 1
570 +                        if (emap.port)
571 +                           /* !!!  PHOTON PORT REJECTION SAMPLING HACK: set
572 +                            * !!!  photon port as fake hit object for
573 +                            * !!!  primary ray to check for intersection in
574 +                            * !!!  tracePhoton() */                        
575 +                           photonRay.ro = emap.port -> so;
576 + #endif
577                          newPhotonPrimary(pm, &photonRay, primaryHeap[proc]);
578                          /* Set subprocess index in photonRay for post-
579                           * distrib primary index linearisation; this is
# Line 538 | Line 587 | void distribPhotonContrib (PhotonMap* pm, unsigned num
587                       photonCnt [PHOTONCNT_NUMPHOT] += pm -> numPhotons -
588                                                        lastNumPhotons;
589                       lastNumPhotons = pm -> numPhotons;
590 + #if !NIX
591 +                     /* Synchronous progress report on Windoze */
592 +                     if (!proc && photonRepTime > 0 &&
593 +                           time(NULL) >= repLastTime + photonRepTime) {
594 +                        unsigned s;                        
595 +                        repComplete = pm -> distribTarget * numProc;
596 +                        repProgress = photonCnt [PHOTONCNT_NUMPHOT];
597 +                        
598 +                        for (repEmitted = 0, s = 0; s < nsources; s++)
599 +                           repEmitted += photonCnt [PHOTONCNT_NUMEMIT(s)];
600 +
601 +                        pmapDistribReport();
602 +                     }
603 + #endif
604                    }
605  
606                    portCnt++;
607                 } while (portCnt < numPhotonPorts);                  
608  
609 <               if (pm -> numPhotons == srcNumDistrib)
609 >               if (pm -> numPhotons == srcNumDistrib) {
610                    /* Double predistrib factor in case no photons were stored
611                     * for this source and redo pass 1 */
612                    srcPreDistrib *= 2;
613 +               }
614                 else {
615                    /* Now do pass 2 */
616                    passCnt++;
553 /*                if (photonRepTime)
554                     eputs("\n"); */
617                 }
618              }
619           }
620                          
621           /* Flush heap buffa one final time to prevent data corruption */
622 <         flushPhotonHeap(pm);
561 <         fclose(pm -> heap);
562 <        
622 >         flushPhotonHeap(pm);        
623           /* Flush final photon primary to primary heap file */
624           newPhotonPrimary(pm, NULL, primaryHeap [proc]);
625 <         fclose(primaryHeap [proc]);
625 >         /* Heap files closed automatically on exit
626 >            fclose(pm -> heap);
627 >            fclose(primaryHeap [proc]); */
628                    
629   #ifdef DEBUG_PMAP
630 <         sprintf(errmsg, "Proc %d exited with total %ld photons\n", proc,
630 >         sprintf(errmsg, "Proc %d total %ld photons\n", proc,
631                   pm -> numPhotons);
632           eputs(errmsg);
633 +         fflush(stderr);
634   #endif
635  
636 + #ifdef PMAP_SIGUSR
637 +         signal(SIGUSR1, SIG_DFL);
638 + #endif
639 +
640 + #if NIX
641 +         /* Terminate subprocess */
642           exit(0);
643 + #endif
644        }
645        else if (pid < 0)
646           error(SYSTEM, "failed to fork subprocess in distribPhotonContrib");
647     }
648  
649 + #if NIX
650     /* PARENT PROCESS CONTINUES HERE */
580   /* Record start time and enable progress report signal handler */
581   repStartTime = time(NULL);
651   #ifdef SIGCONT
652 +   /* Enable progress report signal handler */
653     signal(SIGCONT, pmapDistribReport);
654   #endif
585 /*
586   if (photonRepTime)
587      eputs("\n"); */
588  
655     /* Wait for subprocesses to complete while reporting progress */
656     proc = numProc;
657     while (proc) {
# Line 599 | Line 665 | void distribPhotonContrib (PhotonMap* pm, unsigned num
665        
666        /* Nod off for a bit and update progress  */
667        sleep(1);
668 <      
669 <      /* Update progress report from shared subprocess counters */
668 >
669 >      /* Asynchronous progress report from shared subprocess counters */      
670        repComplete = pm -> distribTarget * numProc;
671 <      repProgress = photonCnt [PHOTONCNT_NUMPHOT];
671 >      repProgress = photonCnt [PHOTONCNT_NUMPHOT];      
672 >      
673        for (repEmitted = 0, srcIdx = 0; srcIdx < nsources; srcIdx++)
674           repEmitted += photonCnt [PHOTONCNT_NUMEMIT(srcIdx)];
675  
# Line 615 | Line 682 | void distribPhotonContrib (PhotonMap* pm, unsigned num
682        else signal(SIGCONT, pmapDistribReport);
683   #endif
684     }
685 + #endif /* NIX */
686  
687     /* ================================================================
688      * POST-DISTRIBUTION - Set photon flux and build kd-tree, etc.
689      * ================================================================ */
690   #ifdef SIGCONT    
691 +   /* Reset signal handler */
692     signal(SIGCONT, SIG_DFL);
693   #endif  
694     free(emap.samples);
695  
696     if (!pm -> numPhotons)
697 <      error(USER, "empty photon map");
697 >      error(USER, "empty contribution photon map");
698  
699     /* Load per-subprocess primary rays into pm -> primary array */
700 <   pm -> numPrimary = buildPrimaries(pm, primaryHeap, primaryOfs, numProc);
700 >   /* Dumb compilers apparently need the char** cast */
701 >   pm -> numPrimary = buildPrimaries(pm, primaryHeap,
702 >                                     (char**)primaryHeapFname,
703 >                                     primaryOfs, numProc);
704     if (!pm -> numPrimary)
705        error(INTERNAL, "no primary rays in contribution photon map");
706    
707     /* Set photon flux per source */
708     for (srcIdx = 0; srcIdx < nsources; srcIdx++)
709        srcFlux [srcIdx] /= photonCnt [PHOTONCNT_NUMEMIT(srcIdx)];
710 <
710 > #if NIX
711     /* Photon counters no longer needed, unmap shared memory */
712     munmap(photonCnt, sizeof(*photonCnt));
713     close(shmFile);
642 #if 0  
643   shm_unlink(shmFname);
644 #else
714     unlink(shmFname);
715 + #else
716 +   free(photonCnt);  
717   #endif      
718    
719 <   if (photonRepTime) {
720 <      eputs("\nBuilding contrib photon map...\n");
719 >   if (verbose) {
720 >      eputs("\nBuilding contribution photon map...\n");
721 > #if NIX      
722        fflush(stderr);
723 + #endif      
724     }
725    
726     /* Build underlying data structure; heap is destroyed */
727 <   buildPhotonMap(pm, srcFlux, primaryOfs, numProc);  
655 < }
656 <
657 <
658 <
659 < void photonContrib (PhotonMap *pmap, RAY *ray, COLOR irrad)
660 < /* Sum up light source contributions from photons in pmap->srcContrib */
661 < {
662 <   unsigned                i;
663 <   PhotonSearchQueueNode   *sqn;
664 <   float                   r, invArea;
665 <   RREAL                   rayCoeff [3];
666 <   Photon                  *photon;
667 <   static char             warn = 1;
668 <
669 <   setcolor(irrad, 0, 0, 0);
670 <
671 <   if (!pmap -> maxGather)
672 <      return;
673 <      
674 <   /* Ignore sources */
675 <   if (ray -> ro && islight(objptr(ray -> ro -> omod) -> otype))
676 <      return;
677 <
678 <   /* Get cumulative path coefficient up to photon lookup point */
679 <   raycontrib(rayCoeff, ray, PRIMARY);
680 <
681 <   /* Lookup photons */
682 <   pmap -> squeue.tail = 0;
683 <   findPhotons(pmap, ray);
727 >   buildPhotonMap(pm, srcFlux, primaryOfs, numProc);
728    
729 <   /* Need at least 2 photons */
730 <   if (pmap -> squeue.tail < 2) {
731 < #ifdef PMAP_NONEFOUND
688 <      sprintf(errmsg, "no photons found on %s at (%.3f, %.3f, %.3f)",
689 <              ray -> ro ? ray -> ro -> oname : "<null>",
690 <              ray -> rop [0], ray -> rop [1], ray -> rop [2]);
691 <      error(WARNING, errmsg);
692 < #endif
729 >   /* Free per-subprocess primary heap files */
730 >   for (proc = 0; proc < numProc; proc++)
731 >      free(primaryHeapFname [proc]);
732        
733 <      return;
734 <   }
735 <
697 <   /* Average (squared) radius between furthest two photons to improve
698 <    * accuracy and get inverse search area 1 / (PI * r^2), with extra
699 <    * normalisation factor 1 / PI for ambient calculation */
700 <   sqn = pmap -> squeue.node + 1;
701 <   r = max(sqn -> dist2, (sqn + 1) -> dist2);
702 <   r = 0.25 * (pmap -> maxDist2 + r + 2 * sqrt(pmap -> maxDist2 * r));  
703 <   invArea = 1 / (PI * PI * r);
733 >   free(primaryHeapFname);
734 >   free(primaryHeap);
735 >   free(primaryOfs);
736    
737 <   /* Skip the extra photon */
738 <   for (i = 1 ; i < pmap -> squeue.tail; i++, sqn++) {        
707 <      COLOR flux;
708 <      
709 <      /* Get photon's contribution to density estimate */
710 <      photon = getNearestPhoton(&pmap -> squeue, sqn -> idx);
711 <      getPhotonFlux(photon, flux);
712 <      scalecolor(flux, invArea);      
713 < #ifdef PMAP_EPANECHNIKOV
714 <      /* Apply Epanechnikov kernel to photon flux based on photon distance */
715 <      scalecolor(flux, 2 * (1 - sqn -> dist2 / r));
716 < #endif
717 <      addcolor(irrad, flux);
718 <      
719 <      if (pmap -> srcContrib) {      
720 <         const PhotonPrimary  *primary = pmap -> primaries +
721 <                                         photon -> primary;
722 <         const SRCREC         *sp = &source [primary -> srcIdx];
723 <         OBJREC               *srcMod = findmaterial(sp -> so);
724 <         MODCONT *srcContrib = (MODCONT*)lu_find(pmap -> srcContrib,
725 <                                                 srcMod -> oname) -> data;
726 <         double   srcBinReal;
727 <         int      srcBin;
728 <         RAY      srcRay;                                                
729 <                                                
730 <         if (!srcContrib)
731 <            continue;
732 <
733 <         /* Photon's emitting light source has modifier whose contributions
734 <          * are sought */
735 <         if (srcContrib -> binv -> type != NUM) {
736 <            /* Use intersection function to set shadow ray parameters if
737 <             * it's not simply a constant */
738 <            rayorigin(&srcRay, SHADOW, NULL, NULL);
739 <            srcRay.rsrc = primary -> srcIdx;
740 < #ifdef PMAP_PRIMARYPOS
741 <            VCOPY(srcRay.rorg, primary -> pos);
742 < #else
743 <            /* No primary hitpoints; set dummy ray origin and warn once */
744 <            srcRay.rorg [0] = srcRay.rorg [1] = srcRay.rorg [2] = 0;
745 <            if (warn) {
746 <               error(WARNING, "no photon primary hitpoints for bin evaluation;"
747 <                     " using dummy (0,0,0) !");
748 <               warn = 0;
749 <            }
750 < #endif          
751 <            decodedir(srcRay.rdir, primary -> dir);
752 <
753 <            if (!(sp->sflags & SDISTANT
754 <                  ? sourcehit(&srcRay)
755 <                  : (*ofun[sp -> so -> otype].funp)(sp -> so, &srcRay)))
756 <               continue;                /* XXX shouldn't happen! */
757 <
758 <            worldfunc(RCCONTEXT, &srcRay);
759 <            set_eparams((char *)srcContrib -> params);
760 <         }
761 <
762 <         if ((srcBinReal = evalue(srcContrib -> binv)) < -.5)
763 <            continue;           /* silently ignore negative bins */
764 <  
765 <         if ((srcBin = srcBinReal + .5) >= srcContrib -> nbins) {
766 <            error(WARNING, "bad bin number (ignored)");
767 <            continue;
768 <         }
769 <            
770 <         if (!contrib) {
771 <            /* Ray coefficient mode; normalise by light source radiance
772 <             * after applying distrib pattern */
773 <            int j;
774 <            
775 <            raytexture(ray, srcMod -> omod);
776 <            setcolor(ray -> rcol, srcMod -> oargs.farg [0],
777 <                     srcMod -> oargs.farg [1], srcMod -> oargs.farg [2]);
778 <            multcolor(ray -> rcol, ray -> pcol);
779 <            for (j = 0; j < 3; j++)
780 <               flux [j] = ray -> rcol [j] ? flux [j] / ray -> rcol [j] : 0;
781 <         }
782 <                    
783 <         multcolor(flux, rayCoeff);
784 <         addcolor(srcContrib -> cbin [srcBin], flux);
785 <      }
786 <   }
787 <        
788 <   return;
737 >   if (verbose)
738 >      eputs("\n");
739   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines