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.8 by greg, Thu Nov 7 18:07:43 2024 UTC vs.
Revision 2.21 by greg, Mon Oct 27 18:38:32 2025 UTC

# Line 52 | Line 52 | struct RowAssignment {
52          uint32                  ac;             // accumulation count
53   };
54  
55 < // Our default data share function
56 < RdataShare *
57 < defDataShare(const char *name, RCOutputOp op, size_t siz)
58 < {
59 <        return new RdataShareMap(name, RSDOflags[op], siz);
60 < }
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 (binexpr && !*binexpr) binexpr = NULL;
62          if (!prms) prms = "";
63 <        if (!binexpr & (ncbins > 1)) {
63 >        if ((ncbins > 1) & !binexpr) {
64                  error(USER, "missing bin expression");
65                  return NULL;
66          }
67 <        if (ncbins <= 1) {              // shouldn't have bin expression?
68 <                if (binexpr && strcmp(binexpr, "0"))
73 <                        error(WARNING, "ignoring non-zero expression for single bin");
74 <                prms = "";
75 <                binexpr = NULL;
76 <                ncbins = 1;
77 <        }
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 <        mp->params = strcpy((char *)(mp->cbin + ncbins*NCSAMP), prms);
83 <        if (binexpr) {
73 >        if (binexpr) {                          // get/check bin expression
74                  mp->binv = eparse(const_cast<char *>(binexpr));
75 <                CHECK(mp->binv->type==NUM, WARNING, "constant bin expression");
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);
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   {
# Line 98 | Line 103 | FreeRcMod(void *p)
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 + // Standard file data share function
120 + RdataShare *
121 + fileDataShare(const char *name, RCOutputOp op, size_t siz)
122 + {
123 +        if (op == RCOrecover && access(name, R_OK|W_OK) < 0) {
124 +                sprintf(errmsg, "cannot recover from '%s'", name);
125 +                error(SYSTEM, errmsg);
126 +                return NULL;
127 +        }
128 +        RdataShare *    rds = new RdataShareFile(name, RSDOflags[op],
129 +                                                 siz*(op != RCOforce));
130 +                                                
131 +        if (!rds || (op == RCOforce && rds->Resize(siz) < siz)) {
132 +                delete rds;
133 +                sprintf(errmsg, "cannot create %lu byte output file '%s'",
134 +                                        (unsigned long)siz, name);
135 +                error(SYSTEM, errmsg);
136 +                return NULL;
137 +        }
138 +        return rds;
139 + }
140 +
141 + // Memory-mapped data share function
142 + RdataShare *
143 + mapDataShare(const char *name, RCOutputOp op, size_t siz)
144 + {
145 +        if (op == RCOrecover && access(name, R_OK|W_OK) < 0) {
146 +                sprintf(errmsg, "cannot recover from '%s'", name);
147 +                error(SYSTEM, errmsg);
148 +                return NULL;
149 +        }
150 +        RdataShare *    rds = new RdataShareMap(name, RSDOflags[op],
151 +                                                 siz*(op != RCOforce));
152 +
153 +        if (!rds || (op == RCOforce && rds->Resize(siz) < siz)) {
154 +                delete rds;
155 +                sprintf(errmsg, "cannot create %lu byte output map '%s'",
156 +                                        (unsigned long)siz, name);
157 +                error(SYSTEM, errmsg);
158 +                return NULL;
159 +        }
160 +        return rds;
161 + }
162 +
163   // Set output format ('f', 'd', or 'c')
164   bool
165   RcontribSimulManager::SetDataFormat(int ty)
# Line 160 | Line 222 | RcontribSimulManager::RctCall(RAY *r, void *cd)
222          raycontrib(contr, r, PRIMARY);          // compute coefficient
223          if (rcp->HasFlag(RCcontrib))
224                  smultscolor(contr, r->rcol);    // -> value contribution
225 +
226          for (int i = 0; i < NCSAMP; i++)
227                  *dvp++ += contr[i];             // accumulate color/spectrum
228          return 1;
# Line 192 | Line 255 | RcontribSimulManager::AddModifier(const char *modn, co
255                  error(WARNING, "ignoring bad call to AddModifier()");
256                  return false;
257          }
258 +        if (*outspec == '!') {
259 +                error(USER, "command output not supported by RcontribSimulManager");
260 +                return false;
261 +        }
262          if (!nChan) {                           // initial call?
263                  if ((xres < 0) | (yres <= 0)) {
264                          error(USER, "xres, yres must be set before first modifier");
# Line 201 | Line 268 | RcontribSimulManager::AddModifier(const char *modn, co
268                          return false;
269                  nChan = NCSAMP;
270          } else if (nChan != NCSAMP) {
271 <                error(USER, "number of spectral channels must be fixed");
271 >                error(USER, "# spectral channels must be fixed in AddModifier()");
272                  return false;
273          }
274          if (Ready()) {
# Line 297 | Line 364 | RcontribSimulManager::AddModFile(const char *modfn, co
364          }
365          char            mod[MAXSTR];
366          while (fgetword(mod, sizeof(mod), fp))
367 <                if (!AddModifier(mod, outspec, prms, binval, bincnt))
367 >                if (!AddModifier(mod, outspec, prms, binval, bincnt)) {
368 >                        fclose(fp);
369                          return false;
370 +                }
371          fclose(fp);
372          return true;
373   }
# Line 307 | Line 376 | RcontribSimulManager::AddModFile(const char *modfn, co
376   static int
377   checkModExists(const LUENT *lp, void *p)
378   {
379 <        if (modifier(lp->key) != OVOID)
379 >        OBJECT  mod = modifier(lp->key);
380 >
381 >        if ((mod != OVOID) & (mod < nsceneobjs))
382                  return 1;
383  
384          sprintf(errmsg, "tracked modifier '%s' not found in main scene", lp->key);
# Line 320 | Line 391 | int
391   RcontribSimulManager::PrepOutput()
392   {
393          if (!outList || !RtraceSimulManager::Ready()) {
394 <                error(INTERNAL, "PrepOutput() called before octree & modifiers assigned");
394 >                error(INTERNAL, "PrepOutput() called before octree & modifiers set");
395                  return -1;
396          }
397          if (!cdsF) {
398 <                error(INTERNAL, "missing RdataShare constructor call (*cdsF)");
398 >                error(INTERNAL, "missing RdataShare constructor call (cdsF)");
399                  return -1;
400          }
401          if (lu_doall(&modLUT, checkModExists, NULL) < 0)
402                  return -1;
403  
404 +        outList->nRows = yres * (xres + !xres); // all outputs have same #rows
405          int     remWarnings = 20;
406          for (RcontribOutput *op = outList; op; op = op->next) {
407                  if (op->rData) {
408                          error(INTERNAL, "output channel already open in PrepOutput()");
409                          return -1;
410                  }
411 <                op->nRows = yres * (xres + !xres);
411 >                op->nRows = outList->nRows;
412                  op->rData = (*cdsF)(op->ofname, outOp,
413                                          GetHeadLen()+1024 + op->nRows*op->rowBytes);
414                  freeqstr(op->ofname); op->ofname = NULL;
# Line 345 | Line 417 | RcontribSimulManager::PrepOutput()
417                          if (rd < 0)
418                                  return -1;
419                          if (rd >= op->nRows) {
420 <                                if (remWarnings >= 0) {
421 <                                        sprintf(errmsg, "recovered output '%s' already done",
420 >                                if (remWarnings > 0) {
421 >                                        sprintf(errmsg, "recovered output '%s' is complete",
422                                                          op->GetName());
423 <                                        error(WARNING, remWarnings ? errmsg : "etc...");
352 <                                        remWarnings--;
423 >                                        error(WARNING, --remWarnings ? errmsg : "etc...");
424                                  }
425                                  rd = op->nRows;
426                          }
# Line 363 | Line 434 | RcontribSimulManager::PrepOutput()
434          }
435          rowsDone.NewBitMap(outList->nRows);     // create row completion map
436          rowsDone.ClearBits(0, rInPos, true);
437 <        return rInPos;
437 >        return nrDone = rInPos;
438   }
439  
440   // Create header in open write-only channel
# Line 398 | Line 469 | RcontribOutput::NewHeader(const RcontribSimulManager *
469          sprintf(hdr+begData, "%s%d\n", NCOMPSTR, NCSAMP);
470          begData += strlen(hdr+begData);
471          if (NCSAMP > 3) {
472 <                sprintf(hdr+begData, "%s %f %f %f %f\n", WLSPLTSTR,
472 >                sprintf(hdr+begData, "%s %g %g %g %g\n", WLSPLTSTR,
473                                  WLPART[0], WLPART[1], WLPART[2], WLPART[3]);
474                  begData += strlen(hdr+begData);
475          }
# Line 483 | Line 554 | RcontribOutput::CheckHeader(const RcontribSimulManager
554                  return -1;
555          }
556                                                  // check #columns
557 <        if (((cp = findArgs(hdr, "NCOLS=", begData)) && atoi(cp)*esiz != rowBytes) ||
558 <                        !rcp->xres | (rowBytes > esiz)) {
559 <                sprintf(errmsg, "expected NCOLS=%d in '%s'",
489 <                                int(rowBytes/esiz), GetName());
557 >        if ((cp = findArgs(hdr, "NCOLS=", begData)) ? (atoi(cp)*esiz != rowBytes)
558 >                                                    : (!rcp->xres | (rowBytes > esiz))) {
559 >                sprintf(errmsg, "expected NCOLS=%d in '%s'", int(rowBytes/esiz), GetName());
560                  error(USER, errmsg);
561                  return -1;
562          }
# Line 528 | Line 598 | RcontribSimulManager::ResetRow(int r)
598                          return false;
599  
600          rowsDone.ClearBits(r, rInPos-r, false);
601 <        rInPos = r;
601 >        nrDone = rInPos = r;
602          return true;
603   }
604  
# Line 575 | Line 645 | putModContrib(const LUENT *lp, void *p)
645                  }
646                  } break;
647          default:
648 <                error(CONSISTENCY, "unsupported output type in sendModContrib()");
648 >                error(CONSISTENCY, "unsupported output type in putModContrib()");
649                  return -1;
650          }
651                                                  // clear for next tally
# Line 594 | Line 664 | RcontribSimulManager::ComputeRecord(const FVECT orig_d
664                  return 0;
665          }
666          if (nkids > 0) {                        // in parent process?
667 <                int     k = GetChild();         // updates output rows
668 <                if (k < 0) return -1;           // can't really happen
667 >                int     k = GetChild(false);    // updates output rows
668 >                if (k < 0) return -1;           // someone died?
669                  RowAssignment   rass;
670                  rass.row = kidRow[k] = rInPos++;
671                  rass.ac = accum;
# Line 640 | Line 710 | RcontribSimulManager::GetChild(bool forceWait)
710                  return -1;
711                                                  // take inventory
712          int     pn, n = 0;
713 <        fd_set  writeset, errset;
714 <        FD_ZERO(&writeset); FD_ZERO(&errset);
713 >        fd_set  readset, errset;
714 >        FD_ZERO(&readset); FD_ZERO(&errset);
715          for (pn = nkids; pn--; ) {
716                  if (kidRow[pn] < 0) {           // child already ready?
717                          if (forceWait) continue;
718                          return pn;              // good enough
719                  }
720 <                FD_SET(kid[pn].w, &writeset);   // will check on this one
721 <                FD_SET(kid[pn].w, &errset);
722 <                if (kid[pn].w >= n)
723 <                        n = kid[pn].w + 1;
720 >                FD_SET(kid[pn].r, &readset);    // will check on this one
721 >                FD_SET(kid[pn].r, &errset);
722 >                if (kid[pn].r >= n)
723 >                        n = kid[pn].r + 1;
724          }
725          if (!n)                                 // every child is idle?
726                  return -1;
727                                                  // wait on "busy" child(ren)
728 <        while ((n = select(n, NULL, &writeset, &errset, NULL)) <= 0)
728 >        while ((n = select(n, &readset, NULL, &errset, NULL)) <= 0)
729                  if (errno != EINTR) {
730                          error(SYSTEM, "select call failed in GetChild()");
731                          return -1;
732                  }
733 +        char    buf[sizeof(ROW_DONE)] = "X";
734          pn = -1;                                // get flags set by select
735          for (n = nkids; n--; )
736                  if (kidRow[n] >= 0 &&
737 <                                FD_ISSET(kid[n].w, &writeset) |
738 <                                FD_ISSET(kid[n].w, &errset)) {
737 >                                FD_ISSET(kid[n].r, &readset) |
738 >                                FD_ISSET(kid[n].r, &errset)) {
739 >                                                // check for error
740 >                        if (FD_ISSET(kid[n].r, &errset) ||
741 >                                        read(kid[n].r, buf, sizeof(ROW_DONE)) <= 0 ||
742 >                                        memcmp(buf, ROW_DONE, sizeof(ROW_DONE)))
743 >                                return -1;
744                                                  // update output row counts
745 <                        if (!FD_ISSET(kid[n].w, &errset))
746 <                                UpdateRowsDone(kidRow[n]);
671 <                        kidRow[n] = -1;         // flag it available
745 >                        UpdateRowsDone(kidRow[n]);
746 >                        kidRow[n] = -1;         // flag child available
747                          pn = n;
748                  }
749          return pn;
# Line 682 | Line 757 | RcontribSimulManager::UpdateRowsDone(int r)
757                  error(WARNING, "redundant call to UpdateRowsDone()");
758                  return false;
759          }
760 <        int     nDone = GetRowFinished();
761 <        if (nDone <= r)
760 >        GetRowFinished();
761 >        if (nrDone <= r)
762                  return true;                    // nothing to update, yet
763          for (RcontribOutput *op = outList; op; op = op->next)
764 <                if (!op->SetRowsDone(nDone))
764 >                if (!op->SetRowsDone(nrDone))
765                          return false;
766          return true;                            // up-to-date
767   }
# Line 706 | Line 781 | RcontribSimulManager::RunChild()
781                          error(CONSISTENCY, "bad accumulator count in child");
782                          exit(1);
783                  }
784 <                if (rass.ac > accum)
785 <                        vecList = (FVECT *)erealloc(vecList,
786 <                                                sizeof(FVECT)*2*rass.ac);
784 >                if (rass.ac > accum) {
785 >                        efree(vecList);
786 >                        vecList = (FVECT *)emalloc(sizeof(FVECT)*2*rass.ac);
787 >                }
788                  accum = rass.ac;
789                  rInPos = rass.row;
790  
# Line 718 | Line 794 | RcontribSimulManager::RunChild()
794  
795                  if (ComputeRecord(vecList) <= 0)
796                          exit(1);
797 +                                                // signal this row is done
798 +                if (write(1, ROW_DONE, sizeof(ROW_DONE)) != sizeof(ROW_DONE))
799 +                        exit(1);
800          }
801          if (nr) {
802                  error(SYSTEM, "read error in child process");
# Line 743 | Line 822 | RcontribSimulManager::StartKids(int n2go)
822          fflush(stdout);                         // shouldn't use, anyway
823          while (nkids < n2go) {
824                  kid[nkids] = sp_inactive;
746                kid[nkids].w = dup(1);
747                kid[nkids].flags |= PF_FILT_OUT;
825                  int     rv = open_process(&kid[nkids], NULL);
826                  if (!rv) {                      // in child process?
827 <                        while (nkids-- > 0)
827 >                        while (nkids-- > 0) {
828 >                                close(kid[nkids].r);
829                                  close(kid[nkids].w);
830 +                        }
831                          free(kid); free(kidRow);
832                          kid = NULL; kidRow = NULL;
833                          RunChild();             // should never return

Diff Legend

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