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.9 by greg, Tue Dec 3 17:39:42 2024 UTC vs.
Revision 2.15 by greg, Fri Oct 17 17:43:53 2025 UTC

# Line 52 | Line 52 | struct RowAssignment {
52          uint32                  ac;             // accumulation count
53   };
54  
55 < // Get format identifier
56 < const char *
57 < formstr(int f)
58 < {
59 <        switch (f) {
60 <        case 'a': return("ascii");
61 <        case 'f': return("float");
62 <        case 'd': return("double");
63 <        case 'c': return(NCSAMP==3 ? COLRFMT : SPECFMT);
64 <        }
65 <        return("unknown");
66 < }
55 > static const char       ROW_DONE[] = "ROW FINISHED\n";
56  
57 < // Our default data share function
58 < RdataShare *
70 < defDataShare(const char *name, RCOutputOp op, size_t siz)
71 < {
72 <        return new RdataShareMap(name, RSDOflags[op], siz);
73 < }
74 <
75 < // Allocate rcontrib accumulator
76 < RcontribMod *
57 > // allocate rcontrib accumulator
58 > static RcontribMod *
59   NewRcMod(const char *prms, const char *binexpr, int ncbins)
60   {
61          if (!prms) prms = "";
62 <        if (!binexpr & (ncbins > 1)) {
62 >        if ((ncbins > 1) & !binexpr) {
63                  error(USER, "missing bin expression");
64                  return NULL;
65          }
66 <        if (ncbins <= 1) {              // shouldn't have bin expression?
67 <                if (binexpr && strcmp(binexpr, "0"))
86 <                        error(WARNING, "ignoring non-zero expression for single bin");
87 <                prms = "";
88 <                binexpr = NULL;
89 <                ncbins = 1;
90 <        }
66 >        if (ncbins < 1) ncbins = 1;
67 >        
68          RcontribMod *   mp = (RcontribMod *)ecalloc(1, sizeof(RcontribMod) +
69                                                  sizeof(DCOLORV)*(NCSAMP*ncbins-1) +
70                                                  strlen(prms)+1);
71  
72 <        mp->params = strcpy((char *)(mp->cbin + ncbins*NCSAMP), prms);
96 <        if (binexpr) {
72 >        if (binexpr) {                          // get/check bin expression
73                  mp->binv = eparse(const_cast<char *>(binexpr));
74 <                CHECK(mp->binv->type==NUM, WARNING, "constant bin expression");
74 >                if (mp->binv->type == NUM) {    // constant expression (0)?
75 >                        if ((int)evalue(mp->binv) != 0) {
76 >                                sprintf(errmsg, "illegal non-zero constant for bin (%s)",
77 >                                                binexpr);
78 >                                error(USER, errmsg);
79 >                        }
80 >                        if (ncbins > 1) {
81 >                                sprintf(errmsg, "bad bin count (%d should be 1)", ncbins);
82 >                                error(USER, errmsg);
83 >                        }
84 >                        epfree(mp->binv, true);
85 >                        mp->binv = NULL;
86 >                        prms = "";
87 >                        ncbins = 1;
88 >                }
89          }
90 +        mp->params = strcpy((char *)(mp->cbin + ncbins*NCSAMP), prms);
91          mp->nbins = ncbins;
92          return mp;
93   }
94  
95 < // Free an RcontribMod
95 > // Free an RcontribMod (public for RcontribSimulManager constructor)
96   void
97   FreeRcMod(void *p)
98   {
# Line 111 | Line 102 | FreeRcMod(void *p)
102          efree(p);
103   }
104  
105 + // Get format identifier
106 + const char *
107 + formstr(int f)
108 + {
109 +        switch (f) {
110 +        case 'a': return("ascii");
111 +        case 'f': return("float");
112 +        case 'd': return("double");
113 +        case 'c': return(NCSAMP==3 ? COLRFMT : SPECFMT);
114 +        }
115 +        return("unknown");
116 + }
117 +
118 + // Our default data share function
119 + RdataShare *
120 + defDataShare(const char *name, RCOutputOp op, size_t siz)
121 + {
122 +        return new RdataShareMap(name, RSDOflags[op], siz);
123 + }
124 +
125   // Set output format ('f', 'd', or 'c')
126   bool
127   RcontribSimulManager::SetDataFormat(int ty)
# Line 173 | Line 184 | RcontribSimulManager::RctCall(RAY *r, void *cd)
184          raycontrib(contr, r, PRIMARY);          // compute coefficient
185          if (rcp->HasFlag(RCcontrib))
186                  smultscolor(contr, r->rcol);    // -> value contribution
187 +
188          for (int i = 0; i < NCSAMP; i++)
189                  *dvp++ += contr[i];             // accumulate color/spectrum
190          return 1;
# Line 205 | Line 217 | RcontribSimulManager::AddModifier(const char *modn, co
217                  error(WARNING, "ignoring bad call to AddModifier()");
218                  return false;
219          }
220 +        if (*outspec == '!') {
221 +                error(USER, "command output not supported by RcontribSimulManager");
222 +                return false;
223 +        }
224          if (!nChan) {                           // initial call?
225                  if ((xres < 0) | (yres <= 0)) {
226                          error(USER, "xres, yres must be set before first modifier");
# Line 214 | Line 230 | RcontribSimulManager::AddModifier(const char *modn, co
230                          return false;
231                  nChan = NCSAMP;
232          } else if (nChan != NCSAMP) {
233 <                error(USER, "number of spectral channels must be fixed");
233 >                error(USER, "# spectral channels must be fixed in AddModifier()");
234                  return false;
235          }
236          if (Ready()) {
# Line 310 | Line 326 | RcontribSimulManager::AddModFile(const char *modfn, co
326          }
327          char            mod[MAXSTR];
328          while (fgetword(mod, sizeof(mod), fp))
329 <                if (!AddModifier(mod, outspec, prms, binval, bincnt))
329 >                if (!AddModifier(mod, outspec, prms, binval, bincnt)) {
330 >                        fclose(fp);
331                          return false;
332 +                }
333          fclose(fp);
334          return true;
335   }
# Line 320 | Line 338 | RcontribSimulManager::AddModFile(const char *modfn, co
338   static int
339   checkModExists(const LUENT *lp, void *p)
340   {
341 <        if (modifier(lp->key) != OVOID)
341 >        OBJECT  mod = modifier(lp->key);
342 >
343 >        if ((mod != OVOID) & (mod < nsceneobjs))
344                  return 1;
345  
346          sprintf(errmsg, "tracked modifier '%s' not found in main scene", lp->key);
# Line 333 | Line 353 | int
353   RcontribSimulManager::PrepOutput()
354   {
355          if (!outList || !RtraceSimulManager::Ready()) {
356 <                error(INTERNAL, "PrepOutput() called before octree & modifiers assigned");
356 >                error(INTERNAL, "PrepOutput() called before octree & modifiers set");
357                  return -1;
358          }
359          if (!cdsF) {
360 <                error(INTERNAL, "missing RdataShare constructor call (*cdsF)");
360 >                error(INTERNAL, "missing RdataShare constructor call (cdsF)");
361                  return -1;
362          }
363          if (lu_doall(&modLUT, checkModExists, NULL) < 0)
364                  return -1;
365  
366 +        outList->nRows = yres * (xres + !xres); // all outputs have same #rows
367          int     remWarnings = 20;
368          for (RcontribOutput *op = outList; op; op = op->next) {
369                  if (op->rData) {
370                          error(INTERNAL, "output channel already open in PrepOutput()");
371                          return -1;
372                  }
373 <                op->nRows = yres * (xres + !xres);
373 >                op->nRows = outList->nRows;
374                  op->rData = (*cdsF)(op->ofname, outOp,
375                                          GetHeadLen()+1024 + op->nRows*op->rowBytes);
376                  freeqstr(op->ofname); op->ofname = NULL;
# Line 359 | Line 380 | RcontribSimulManager::PrepOutput()
380                                  return -1;
381                          if (rd >= op->nRows) {
382                                  if (remWarnings >= 0) {
383 <                                        sprintf(errmsg, "recovered output '%s' already done",
383 >                                        sprintf(errmsg, "recovered output '%s' is complete",
384                                                          op->GetName());
385 <                                        error(WARNING, remWarnings ? errmsg : "etc...");
365 <                                        remWarnings--;
385 >                                        error(WARNING, --remWarnings ? errmsg : "etc...");
386                                  }
387                                  rd = op->nRows;
388                          }
# Line 588 | Line 608 | putModContrib(const LUENT *lp, void *p)
608                  }
609                  } break;
610          default:
611 <                error(CONSISTENCY, "unsupported output type in sendModContrib()");
611 >                error(CONSISTENCY, "unsupported output type in putModContrib()");
612                  return -1;
613          }
614                                                  // clear for next tally
# Line 607 | Line 627 | RcontribSimulManager::ComputeRecord(const FVECT orig_d
627                  return 0;
628          }
629          if (nkids > 0) {                        // in parent process?
630 <                int     k = GetChild();         // updates output rows
631 <                if (k < 0) return -1;           // can't really happen
630 >                int     k = GetChild(false);    // updates output rows
631 >                if (k < 0) return -1;           // someone died?
632                  RowAssignment   rass;
633                  rass.row = kidRow[k] = rInPos++;
634                  rass.ac = accum;
# Line 653 | Line 673 | RcontribSimulManager::GetChild(bool forceWait)
673                  return -1;
674                                                  // take inventory
675          int     pn, n = 0;
676 <        fd_set  writeset, errset;
677 <        FD_ZERO(&writeset); FD_ZERO(&errset);
676 >        fd_set  readset, errset;
677 >        FD_ZERO(&readset); FD_ZERO(&errset);
678          for (pn = nkids; pn--; ) {
679                  if (kidRow[pn] < 0) {           // child already ready?
680                          if (forceWait) continue;
681                          return pn;              // good enough
682                  }
683 <                FD_SET(kid[pn].w, &writeset);   // will check on this one
684 <                FD_SET(kid[pn].w, &errset);
685 <                if (kid[pn].w >= n)
686 <                        n = kid[pn].w + 1;
683 >                FD_SET(kid[pn].r, &readset);    // will check on this one
684 >                FD_SET(kid[pn].r, &errset);
685 >                if (kid[pn].r >= n)
686 >                        n = kid[pn].r + 1;
687          }
688          if (!n)                                 // every child is idle?
689                  return -1;
690                                                  // wait on "busy" child(ren)
691 <        while ((n = select(n, NULL, &writeset, &errset, NULL)) <= 0)
691 >        while ((n = select(n, &readset, NULL, &errset, NULL)) <= 0)
692                  if (errno != EINTR) {
693                          error(SYSTEM, "select call failed in GetChild()");
694                          return -1;
695                  }
696 +        char    buf[sizeof(ROW_DONE)] = "X";
697          pn = -1;                                // get flags set by select
698          for (n = nkids; n--; )
699                  if (kidRow[n] >= 0 &&
700 <                                FD_ISSET(kid[n].w, &writeset) |
701 <                                FD_ISSET(kid[n].w, &errset)) {
700 >                                FD_ISSET(kid[n].r, &readset) |
701 >                                FD_ISSET(kid[n].r, &errset)) {
702 >                                                // check for error
703 >                        if (FD_ISSET(kid[n].r, &errset) ||
704 >                                        read(kid[n].r, buf, sizeof(ROW_DONE)) <= 0 ||
705 >                                        memcmp(buf, ROW_DONE, sizeof(ROW_DONE)))
706 >                                return -1;
707                                                  // update output row counts
708 <                        if (!FD_ISSET(kid[n].w, &errset))
709 <                                UpdateRowsDone(kidRow[n]);
684 <                        kidRow[n] = -1;         // flag it available
708 >                        UpdateRowsDone(kidRow[n]);
709 >                        kidRow[n] = -1;         // flag child available
710                          pn = n;
711                  }
712          return pn;
# Line 719 | Line 744 | RcontribSimulManager::RunChild()
744                          error(CONSISTENCY, "bad accumulator count in child");
745                          exit(1);
746                  }
747 <                if (rass.ac > accum)
748 <                        vecList = (FVECT *)erealloc(vecList,
749 <                                                sizeof(FVECT)*2*rass.ac);
747 >                if (rass.ac > accum) {
748 >                        efree(vecList);
749 >                        vecList = (FVECT *)emalloc(sizeof(FVECT)*2*rass.ac);
750 >                }
751                  accum = rass.ac;
752                  rInPos = rass.row;
753  
# Line 731 | Line 757 | RcontribSimulManager::RunChild()
757  
758                  if (ComputeRecord(vecList) <= 0)
759                          exit(1);
760 +                                                // signal this row is done
761 +                if (write(1, ROW_DONE, sizeof(ROW_DONE)) != sizeof(ROW_DONE))
762 +                        exit(1);
763          }
764          if (nr) {
765                  error(SYSTEM, "read error in child process");
# Line 756 | Line 785 | RcontribSimulManager::StartKids(int n2go)
785          fflush(stdout);                         // shouldn't use, anyway
786          while (nkids < n2go) {
787                  kid[nkids] = sp_inactive;
759                kid[nkids].w = dup(1);
760                kid[nkids].flags |= PF_FILT_OUT;
788                  int     rv = open_process(&kid[nkids], NULL);
789                  if (!rv) {                      // in child process?
790 <                        while (nkids-- > 0)
790 >                        while (nkids-- > 0) {
791 >                                close(kid[nkids].r);
792                                  close(kid[nkids].w);
793 +                        }
794                          free(kid); free(kidRow);
795                          kid = NULL; kidRow = NULL;
796                          RunChild();             // should never return

Diff Legend

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