ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/Development/ray/src/rt/RcontribSimulManager.cpp
(Generate patch)

Comparing ray/src/rt/RcontribSimulManager.cpp (file contents):
Revision 2.2 by greg, Tue Oct 29 19:47:19 2024 UTC vs.
Revision 2.16 by greg, Thu Oct 23 01:26:48 2025 UTC

# Line 24 | Line 24 | extern const char      HDRSTR[];
24   extern const char       BIGEND[];
25   extern const char       FMTSTR[];
26  
27 int     contrib = 0;                    // computing contributions?
28
29 int     xres = 0;                       // horizontal (scan) size
30 int     yres = 0;                       // vertical resolution
31
27   // new/exclusive, overwrite if exists, or recover data
28   int     RSDOflags[] = {RDSwrite|RDSexcl|RDSextend, RDSwrite|RDSextend,
29                                  RDSread|RDSwrite};
# Line 40 | Line 35 | static const char      ROWZEROSTR[] = "NROWS=00000000000000
35   struct RcontribMod {
36          RcontribOutput *        opl;            // pointer to first output channel
37          char *                  params;         // parameters string
38 <        EPNODE *                binv;           // bin expression
38 >        EPNODE *                binv;           // bin expression (NULL if 1 bin)
39          int                     nbins;          // bin count this modifier
40          int                     coffset;        // column offset in bytes
41          DCOLORV                 cbin[1];        // bin accumulator (extends struct)
# Line 57 | Line 52 | struct RowAssignment {
52          uint32                  ac;             // accumulation count
53   };
54  
55 < // Our default data share function
61 < RdataShare *
62 < defDataShare(const char *name, RCOutputOp op, size_t siz)
63 < {
64 <        return new RdataShareMap(name, RSDOflags[op], siz);
65 < }
55 > static const char       ROW_DONE[] = "ROW FINISHED\n";
56  
57 < // Allocate rcontrib accumulator
58 < RcontribMod *
57 > // allocate rcontrib accumulator
58 > static RcontribMod *
59   NewRcMod(const char *prms, const char *binexpr, int ncbins)
60   {
61 <        if (ncbins <= 0) return NULL;
61 >        if (binexpr && !*binexpr) binexpr = NULL;
62          if (!prms) prms = "";
63 <        if (!binexpr | (ncbins == 1))
64 <                binexpr = "0";
65 <
63 >        if ((ncbins > 1) & !binexpr) {
64 >                error(USER, "missing bin expression");
65 >                return NULL;
66 >        }
67 >        if (ncbins < 1) ncbins = 1;
68 >        
69          RcontribMod *   mp = (RcontribMod *)ecalloc(1, sizeof(RcontribMod) +
70                                                  sizeof(DCOLORV)*(NCSAMP*ncbins-1) +
71                                                  strlen(prms)+1);
72  
73 +        if (binexpr) {                          // get/check bin expression
74 +                mp->binv = eparse(const_cast<char *>(binexpr));
75 +                if (mp->binv->type == NUM) {    // constant expression (0)?
76 +                        if ((int)evalue(mp->binv) != 0) {
77 +                                sprintf(errmsg, "illegal non-zero constant for bin (%s)",
78 +                                                binexpr);
79 +                                error(USER, errmsg);
80 +                        }
81 +                        if (ncbins > 1) {
82 +                                sprintf(errmsg, "bad bin count (%d should be 1)", ncbins);
83 +                                error(USER, errmsg);
84 +                        }
85 +                        epfree(mp->binv, true);
86 +                        mp->binv = NULL;
87 +                        prms = "";
88 +                        ncbins = 1;
89 +                }
90 +        }
91          mp->params = strcpy((char *)(mp->cbin + ncbins*NCSAMP), prms);
81        mp->binv = eparse(const_cast<char *>(binexpr));
92          mp->nbins = ncbins;
93          return mp;
94   }
95  
96 < // Free an RcontribMod
96 > // Free an RcontribMod (public for RcontribSimulManager constructor)
97   void
98   FreeRcMod(void *p)
99   {
100          if (!p) return;
101 <        epfree((*(RcontribMod *)p).binv, true);
101 >        EPNODE *        bep = (*(RcontribMod *)p).binv;
102 >        if (bep) epfree(bep, true);
103          efree(p);
104   }
105  
106 + // Get format identifier
107 + const char *
108 + formstr(int f)
109 + {
110 +        switch (f) {
111 +        case 'a': return("ascii");
112 +        case 'f': return("float");
113 +        case 'd': return("double");
114 +        case 'c': return(NCSAMP==3 ? COLRFMT : SPECFMT);
115 +        }
116 +        return("unknown");
117 + }
118 +
119 + // Our default data share function
120 + RdataShare *
121 + defDataShare(const char *name, RCOutputOp op, size_t siz)
122 + {
123 +        return new RdataShareMap(name, RSDOflags[op], siz);
124 + }
125 +
126   // Set output format ('f', 'd', or 'c')
127   bool
128   RcontribSimulManager::SetDataFormat(int ty)
# Line 135 | Line 166 | RcontribSimulManager::RctCall(RAY *r, void *cd)
166          if (!mp)
167                  return 0;               // not in our modifier list
168  
169 <        worldfunc(RCCONTEXT, r);        // compute bin #
170 <        set_eparams(mp->params);
171 <        double          bval = evalue(mp->binv);
172 <        if (bval <= -.5)
173 <                return 0;       // silently ignore negative bin index
174 <        DCOLORV *       dvp = (*mp)[int(bval + .5)];
169 >        int                     bi = 0; // get bin index
170 >        if (mp->binv) {
171 >                worldfunc(RCCONTEXT, r);
172 >                set_eparams(mp->params);
173 >                double          bval = evalue(mp->binv);
174 >                if (bval <= -.5)
175 >                        return 0;       // silently ignore negative bin index
176 >                bi = int(bval + .5);
177 >        }
178 >        DCOLORV *       dvp = (*mp)[bi];
179          if (!dvp) {
180 <                sprintf(errmsg, "bad bin number for '%s' (%.1f ignored)", mname, bval);
180 >                sprintf(errmsg, "bad bin number for '%s' (%d ignored)", mname, bi);
181                  error(WARNING, errmsg);
182                  return 0;
183          }
184          SCOLOR          contr;
185          raycontrib(contr, r, PRIMARY);          // compute coefficient
186 <        if (contrib)
186 >        if (rcp->HasFlag(RCcontrib))
187                  smultscolor(contr, r->rcol);    // -> value contribution
188 +
189          for (int i = 0; i < NCSAMP; i++)
190                  *dvp++ += contr[i];             // accumulate color/spectrum
191          return 1;
# Line 178 | Line 214 | bool
214   RcontribSimulManager::AddModifier(const char *modn, const char *outspec,
215                                  const char *prms, const char *binval, int bincnt)
216   {
217 <        if (!modn | !outspec | (bincnt <= 0) || !*modn | !*outspec) {
217 >        if (!modn | !outspec || !*modn | !*outspec) {
218                  error(WARNING, "ignoring bad call to AddModifier()");
219                  return false;
220          }
221 +        if (*outspec == '!') {
222 +                error(USER, "command output not supported by RcontribSimulManager");
223 +                return false;
224 +        }
225          if (!nChan) {                           // initial call?
226 +                if ((xres < 0) | (yres <= 0)) {
227 +                        error(USER, "xres, yres must be set before first modifier");
228 +                        return false;
229 +                }
230                  if (!SetDataFormat(dtyp))
231                          return false;
232                  nChan = NCSAMP;
233          } else if (nChan != NCSAMP) {
234 <                error(INTERNAL, "number of spectral channels must be fixed");
234 >                error(USER, "# spectral channels must be fixed in AddModifier()");
235                  return false;
236          }
237          if (Ready()) {
# Line 210 | Line 254 | RcontribSimulManager::AddModifier(const char *modn, co
254          const int       binndx = hasFormat(outspec, "diouxX");
255          int             bin0 = 0;
256          char            fnbuf[512];
257 <        if (!modndx | (modndx > binndx))
257 >        if (!modndx || (binndx > 0) & (modndx > binndx))
258                  sprintf(fnbuf, outspec, bin0, modn);
259          else
260                  sprintf(fnbuf, outspec, modn, bin0);
# Line 239 | Line 283 | RcontribSimulManager::AddModifier(const char *modn, co
283          mp->opl = op;                   // first (maybe only) output channel
284          if (modndx)                     // remember modifier if part of name
285                  op->omod = lp->key;
286 <        if (binndx > 0) {               // append output image/bin list
286 >        if (binndx) {                   // append output image/bin list
287                  op->rowBytes += dsiz;
288                  op->obin = bin0;
289                  for (bincnt = 1; bincnt < mp->nbins; bincnt++) {
290 <                        if (!modndx | (modndx > binndx))
290 >                        if (!modndx || (binndx > 0) &  (modndx > binndx))
291                                  sprintf(fnbuf, outspec, bin0+bincnt, modn);
292                          else
293                                  sprintf(fnbuf, outspec, modn, bin0+bincnt);
# Line 262 | Line 306 | RcontribSimulManager::AddModifier(const char *modn, co
306                          op->rowBytes += dsiz;
307                  }
308          } else                          // else send all results to this channel
309 <                op->rowBytes += bincnt*dsiz;
309 >                op->rowBytes += mp->nbins*dsiz;
310          return true;
311   }
312  
# Line 283 | Line 327 | RcontribSimulManager::AddModFile(const char *modfn, co
327          }
328          char            mod[MAXSTR];
329          while (fgetword(mod, sizeof(mod), fp))
330 <                if (!AddModifier(mod, outspec, prms, binval, bincnt))
330 >                if (!AddModifier(mod, outspec, prms, binval, bincnt)) {
331 >                        fclose(fp);
332                          return false;
333 +                }
334          fclose(fp);
335          return true;
336   }
337  
338 + // call-back to check if modifier has been loaded
339 + static int
340 + checkModExists(const LUENT *lp, void *p)
341 + {
342 +        OBJECT  mod = modifier(lp->key);
343 +
344 +        if ((mod != OVOID) & (mod < nsceneobjs))
345 +                return 1;
346 +
347 +        sprintf(errmsg, "tracked modifier '%s' not found in main scene", lp->key);
348 +        error(WARNING, errmsg);
349 +        return 0;
350 + }
351 +
352   // Prepare output channels and return # completed rows
353   int
354   RcontribSimulManager::PrepOutput()
355   {
356          if (!outList || !RtraceSimulManager::Ready()) {
357 <                error(INTERNAL, "PrepOutput() called before octree & modifiers assigned");
357 >                error(INTERNAL, "PrepOutput() called before octree & modifiers set");
358                  return -1;
359          }
360 +        if (!cdsF) {
361 +                error(INTERNAL, "missing RdataShare constructor call (cdsF)");
362 +                return -1;
363 +        }
364 +        if (lu_doall(&modLUT, checkModExists, NULL) < 0)
365 +                return -1;
366 +
367 +        outList->nRows = yres * (xres + !xres); // all outputs have same #rows
368          int     remWarnings = 20;
369          for (RcontribOutput *op = outList; op; op = op->next) {
370                  if (op->rData) {
371                          error(INTERNAL, "output channel already open in PrepOutput()");
372                          return -1;
373                  }
374 <                op->nRows = yres * (xres + !xres);
374 >                op->nRows = outList->nRows;
375                  op->rData = (*cdsF)(op->ofname, outOp,
376                                          GetHeadLen()+1024 + op->nRows*op->rowBytes);
377                  freeqstr(op->ofname); op->ofname = NULL;
# Line 313 | Line 381 | RcontribSimulManager::PrepOutput()
381                                  return -1;
382                          if (rd >= op->nRows) {
383                                  if (remWarnings >= 0) {
384 <                                        sprintf(errmsg, "recovered output '%s' already done",
384 >                                        sprintf(errmsg, "recovered output '%s' is complete",
385                                                          op->GetName());
386 <                                        error(WARNING, remWarnings ? errmsg : "etc...");
319 <                                        remWarnings--;
386 >                                        error(WARNING, --remWarnings ? errmsg : "etc...");
387                                  }
388                                  rd = op->nRows;
389                          }
# Line 358 | Line 425 | RcontribOutput::NewHeader(const RcontribSimulManager *
425          strcpy(hdr+begData, ROWZEROSTR);
426          rowCountPos = begData+LNROWSTR;
427          begData += sizeof(ROWZEROSTR)-1;
428 <        if (!xres | (rowBytes > esiz)) {
428 >        if (!rcp->xres | (rowBytes > esiz)) {
429                  sprintf(hdr+begData, "NCOLS=%d\n", int(rowBytes/esiz));
430                  begData += strlen(hdr+begData);
431          }
# Line 396 | Line 463 | RcontribOutput::NewHeader(const RcontribSimulManager *
463                          hdr[begData++] = ' ';
464          hdr[begData++] = '\n';          // EOL for data format
465          hdr[begData++] = '\n';          // end of nominal header
466 <        if ((xres > 0) & (rowBytes == esiz)) {  // tack on resolution string?
467 <                sprintf(hdr+begData, PIXSTDFMT, yres, xres);
466 >        if ((rcp->xres > 0) & (rowBytes == esiz)) {     // tack on resolution string?
467 >                sprintf(hdr+begData, PIXSTDFMT, rcp->yres, rcp->xres);
468                  begData += strlen(hdr+begData);
469          }
470          return rData->ReleaseMemory(hdr, RDSwrite);
# Line 443 | Line 510 | RcontribOutput::CheckHeader(const RcontribSimulManager
510                  return -1;
511          }
512                                                  // check format
513 <        if (!(cp = findArgs(hdr, FMTSTR, begData)) || strcmp(cp, formstr(etyp))) {
513 >        if (!(cp = findArgs(hdr, FMTSTR, begData)) ||
514 >                                strncmp(cp, formstr(etyp), strlen(formstr(etyp)))) {
515                  sprintf(errmsg, "expected %s%s in '%s'", FMTSTR, formstr(etyp), GetName());
516                  error(USER, errmsg);
517                  return -1;
518          }
519                                                  // check #columns
520          if (((cp = findArgs(hdr, "NCOLS=", begData)) && atoi(cp)*esiz != rowBytes) ||
521 <                        !xres | (rowBytes > esiz)) {
521 >                        !rcp->xres | (rowBytes > esiz)) {
522                  sprintf(errmsg, "expected NCOLS=%d in '%s'",
523                                  int(rowBytes/esiz), GetName());
524                  error(USER, errmsg);
# Line 465 | Line 533 | RcontribOutput::CheckHeader(const RcontribSimulManager
533          rowCountPos = cp - hdr;
534          int     rlast = atoi(cp);
535          begData++;                              // advance past closing EOL
536 <        if ((xres > 0) & (rowBytes == esiz)) {  // check/skip resolution string?
536 >        if ((rcp->xres > 0) & (rowBytes == esiz)) {     // check/skip resolution string?
537                  char    rbuf[64];
538 <                sprintf(rbuf, PIXSTDFMT, yres, xres);
538 >                sprintf(rbuf, PIXSTDFMT, rcp->yres, rcp->xres);
539                  int     rlen = strlen(rbuf);
540                  if (strncmp(rbuf, hdr+begData, rlen)) {
541                          sprintf(errmsg, "bad resolution string in '%s'", GetName());
# Line 541 | Line 609 | putModContrib(const LUENT *lp, void *p)
609                  }
610                  } break;
611          default:
612 <                error(CONSISTENCY, "unsupported output type in sendModContrib()");
612 >                error(CONSISTENCY, "unsupported output type in putModContrib()");
613                  return -1;
614          }
615                                                  // clear for next tally
# Line 560 | Line 628 | RcontribSimulManager::ComputeRecord(const FVECT orig_d
628                  return 0;
629          }
630          if (nkids > 0) {                        // in parent process?
631 <                int     k = GetChild();         // updates output rows
632 <                if (k < 0) return -1;           // can't really happen
631 >                int     k = GetChild(false);    // updates output rows
632 >                if (k < 0) return -1;           // someone died?
633                  RowAssignment   rass;
634                  rass.row = kidRow[k] = rInPos++;
635                  rass.ac = accum;
# Line 606 | Line 674 | RcontribSimulManager::GetChild(bool forceWait)
674                  return -1;
675                                                  // take inventory
676          int     pn, n = 0;
677 <        fd_set  writeset, errset;
678 <        FD_ZERO(&writeset); FD_ZERO(&errset);
677 >        fd_set  readset, errset;
678 >        FD_ZERO(&readset); FD_ZERO(&errset);
679          for (pn = nkids; pn--; ) {
680                  if (kidRow[pn] < 0) {           // child already ready?
681                          if (forceWait) continue;
682                          return pn;              // good enough
683                  }
684 <                FD_SET(kid[pn].w, &writeset);   // will check on this one
685 <                FD_SET(kid[pn].w, &errset);
686 <                if (kid[pn].w >= n)
687 <                        n = kid[pn].w + 1;
684 >                FD_SET(kid[pn].r, &readset);    // will check on this one
685 >                FD_SET(kid[pn].r, &errset);
686 >                if (kid[pn].r >= n)
687 >                        n = kid[pn].r + 1;
688          }
689          if (!n)                                 // every child is idle?
690                  return -1;
691                                                  // wait on "busy" child(ren)
692 <        while ((n = select(n, NULL, &writeset, &errset, NULL)) <= 0)
692 >        while ((n = select(n, &readset, NULL, &errset, NULL)) <= 0)
693                  if (errno != EINTR) {
694                          error(SYSTEM, "select call failed in GetChild()");
695                          return -1;
696                  }
697 +        char    buf[sizeof(ROW_DONE)] = "X";
698          pn = -1;                                // get flags set by select
699          for (n = nkids; n--; )
700                  if (kidRow[n] >= 0 &&
701 <                                FD_ISSET(kid[n].w, &writeset) |
702 <                                FD_ISSET(kid[n].w, &errset)) {
701 >                                FD_ISSET(kid[n].r, &readset) |
702 >                                FD_ISSET(kid[n].r, &errset)) {
703 >                                                // check for error
704 >                        if (FD_ISSET(kid[n].r, &errset) ||
705 >                                        read(kid[n].r, buf, sizeof(ROW_DONE)) <= 0 ||
706 >                                        memcmp(buf, ROW_DONE, sizeof(ROW_DONE)))
707 >                                return -1;
708                                                  // update output row counts
709                          UpdateRowsDone(kidRow[n]);
710 <                        kidRow[n] = -1;         // flag it available
710 >                        kidRow[n] = -1;         // flag child available
711                          pn = n;
712                  }
713          return pn;
# Line 671 | Line 745 | RcontribSimulManager::RunChild()
745                          error(CONSISTENCY, "bad accumulator count in child");
746                          exit(1);
747                  }
748 <                if (rass.ac > accum)
749 <                        vecList = (FVECT *)erealloc(vecList,
750 <                                                sizeof(FVECT)*2*rass.ac);
748 >                if (rass.ac > accum) {
749 >                        efree(vecList);
750 >                        vecList = (FVECT *)emalloc(sizeof(FVECT)*2*rass.ac);
751 >                }
752                  accum = rass.ac;
753                  rInPos = rass.row;
754  
# Line 683 | Line 758 | RcontribSimulManager::RunChild()
758  
759                  if (ComputeRecord(vecList) <= 0)
760                          exit(1);
761 +                                                // signal this row is done
762 +                if (write(1, ROW_DONE, sizeof(ROW_DONE)) != sizeof(ROW_DONE))
763 +                        exit(1);
764          }
765          if (nr) {
766                  error(SYSTEM, "read error in child process");
# Line 708 | Line 786 | RcontribSimulManager::StartKids(int n2go)
786          fflush(stdout);                         // shouldn't use, anyway
787          while (nkids < n2go) {
788                  kid[nkids] = sp_inactive;
711                kid[nkids].w = dup(1);
712                kid[nkids].flags |= PF_FILT_OUT;
789                  int     rv = open_process(&kid[nkids], NULL);
790                  if (!rv) {                      // in child process?
791 <                        while (nkids-- > 0)
791 >                        while (nkids-- > 0) {
792 >                                close(kid[nkids].r);
793                                  close(kid[nkids].w);
794 +                        }
795                          free(kid); free(kidRow);
796                          kid = NULL; kidRow = NULL;
719                        rowsDone.NewBitMap(0);
797                          RunChild();             // should never return
798                          _exit(1);
799                  }
# Line 765 | Line 842 | RcontribSimulManager::SetThreadCount(int nt)
842                  return 0;
843          }
844          if (nt < 0)
845 <                return nkids;
845 >                return NThreads();
846          if (!nt) nt = GetNCores();
847          int     status = 0;
848          if (nt == 1)
# Line 778 | Line 855 | RcontribSimulManager::SetThreadCount(int nt)
855                  sprintf(errmsg, "non-zero (%d) status from child", status);
856                  error(WARNING, errmsg);
857          }
858 <        return nkids;
858 >        return NThreads();
859   }

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)