ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rxpmain.cpp
Revision: 2.7
Committed: Thu Jan 2 20:19:48 2025 UTC (4 months ago) by greg
Branch: MAIN
Changes since 2.6: +2 -5 lines
Log Message:
perf(rxpiece,rxcontrib): Don't bother to free data structs on exit

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.7 static const char RCSid[] = "$Id: rxpmain.cpp,v 2.6 2024/12/27 19:44:53 greg Exp $";
3 greg 2.1 #endif
4     /*
5     * rxpmain.cpp - main for rxpict batch rendering program
6     */
7    
8     #include "copyright.h"
9    
10     #include <time.h>
11     #include <signal.h>
12    
13     #include "rtprocess.h" /* getpid() */
14     #include "platform.h"
15     #include "RpictSimulManager.h"
16    
17     extern char *progname; /* argv[0] */
18     const char *sigerr[NSIG]; /* signal error messages */
19     char *errfile = NULL; /* error output file */
20    
21     VIEW ourview = STDVIEW; /* view parameters */
22     int hresolu = 512; /* horizontal resolution */
23     int vresolu = 512; /* vertical resolution */
24     double pixaspect = 1.0; /* pixel aspect ratio */
25     int hres, vres; /* current image resolution for srcdraw.c */
26    
27     int psample = 4; /* pixel sample size */
28     double maxdiff = .05; /* max. difference for interpolation */
29     double dstrpix = 0.67; /* square pixel distribution */
30    
31     double mblur = 0.; /* motion blur parameter */
32    
33     double dblur = 0.; /* depth-of-field blur parameter */
34    
35     int nproc = 1; /* number of processes to run */
36    
37     int ralrm = 0; /* seconds between reports */
38    
39     double pctdone = 0.0; /* percentage done */
40     time_t tlastrept = 0L; /* time at last report */
41     time_t tstart; /* starting time */
42    
43     RenderDataType dtype = RDTrgbe; // output data flags
44    
45     RpictSimulManager myRPmanager; // global simulation manager
46    
47     static void onsig(int signo);
48     static void sigdie(int signo, const char *msg);
49     static void printdefaults(void);
50    
51     /* rxpict additional features */
52     #define RXPICT_FEATURES "Recovery\nIrradianceCalc\nViewTypes=v,l,a,h,s,c\n" \
53     "ParticipatingMedia=Mist\n" \
54     "HessianAmbientCache\nAmbientAveraging\nAmbientValueSharing\n" \
55     "PixelJitter\nPixelSampling\nPixelMotion\nPixelDepthOfField\n" \
56     "SmallSourceDrawing\nViewSequence\nProgressReporting\n" \
57     "AdaptiveShadowTesting\nOutputs=v,l\n" \
58     "OutputCS=RGB,XYZ,prims,spec\n"
59    
60     void
61 greg 2.3 quit(int code) /* quit program */
62 greg 2.1 {
63 greg 2.7 exit(code); // don't bother about freeing anything
64 greg 2.1 }
65    
66 greg 2.5 /* Set default options */
67     static void
68     default_options(void)
69     {
70     shadthresh = .05;
71     shadcert = .5;
72     srcsizerat = .25;
73     directrelay = 1;
74     ambacc = 0.2;
75     ambres = 64;
76     ambdiv = 512;
77     ambssamp = 128;
78     maxdepth = 7;
79     }
80 greg 2.1
81     int
82     main(int argc, char *argv[])
83     {
84     #define check(ol,al) if (argv[i][ol] || \
85     badarg(argc-i-1,argv+i+1,al)) \
86     goto badopt
87     #define check_bool(olen,var) switch (argv[i][olen]) { \
88     case '\0': var = !var; break; \
89     case 'y': case 'Y': case 't': case 'T': \
90     case '+': case '1': var = 1; break; \
91     case 'n': case 'N': case 'f': case 'F': \
92     case '-': case '0': var = 0; break; \
93     default: goto badopt; }
94     RGBPRIMS our_prims; /* private output color primitives */
95     int seqstart = 0;
96     char *recover = NULL;
97     char *outfile = NULL;
98     char *zfile = NULL;
99     int outfmt = 'c';
100     int rval;
101     int i;
102     /* record start time */
103     tstart = time(NULL);
104     /* global program name */
105     progname = argv[0];
106     /* feature check only? */
107     strcat(RFeatureList, RXPICT_FEATURES);
108     if (argc > 1 && !strcmp(argv[1], "-features"))
109     return feature_status(argc-2, argv+2);
110 greg 2.5 /* set defaults */
111     default_options();
112 greg 2.1 /* option city */
113     for (i = 1; i < argc; i++) {
114     /* expand arguments */
115     while ((rval = expandarg(&argc, &argv, i)) > 0)
116     ;
117     if (rval < 0) {
118     sprintf(errmsg, "cannot expand '%s'", argv[i]);
119     error(SYSTEM, errmsg);
120     }
121     if (argv[i] == NULL || argv[i][0] != '-')
122     break; /* break from options */
123     if (!strcmp(argv[i], "-version")) {
124     puts(VersionID);
125     quit(0);
126     }
127     if (!strcmp(argv[i], "-defaults") ||
128     !strcmp(argv[i], "-help")) {
129     printdefaults();
130     quit(0);
131     }
132     rval = getrenderopt(argc-i, argv+i);
133     if (rval >= 0) {
134     i += rval;
135     continue;
136     }
137     rval = getviewopt(&ourview, argc-i, argv+i);
138     if (rval >= 0) {
139     i += rval;
140     continue;
141     }
142     /* rxpict options */
143     switch (argv[i][1]) {
144     case 'v': /* view file */
145     if (argv[i][2] != 'f')
146     goto badopt;
147     check(3,"s");
148     rval = viewfile(argv[++i], &ourview, NULL);
149     if (rval < 0) {
150     sprintf(errmsg,
151     "cannot open view file \"%s\"",
152     argv[i]);
153     error(SYSTEM, errmsg);
154     } else if (rval == 0) {
155     sprintf(errmsg,
156     "bad view file \"%s\"",
157     argv[i]);
158     error(USER, errmsg);
159     }
160     break;
161     case 'n': /* number of processes */
162     check(2,"i");
163     nproc = atoi(argv[++i]);
164     if (nproc < 0 && (nproc += RadSimulManager::GetNCores()) <= 0)
165     nproc = 1;
166     break;
167     case 'f': /* output format */
168     if ((argv[i][2] != 'c') & (argv[i][2] != 'f')
169     || argv[i][3])
170     goto badopt;
171     outfmt = argv[i][2];
172     break;
173     case 'p': /* pixel */
174     switch (argv[i][2]) {
175     case 's': /* sample */
176     check(3,"i");
177     psample = atoi(argv[++i]);
178     if (psample < 1) psample = 1;
179     break;
180     case 't': /* threshold */
181     check(3,"f");
182     maxdiff = atof(argv[++i]);
183     break;
184     case 'j': /* jitter */
185     check(3,"f");
186     dstrpix = atof(argv[++i]);
187     break;
188     case 'a': /* aspect */
189     check(3,"f");
190     pixaspect = atof(argv[++i]);
191     break;
192     case 'm': /* motion */
193     check(3,"f");
194     mblur = atof(argv[++i]);
195     mblur *= (mblur > 0);
196     break;
197     case 'd': /* aperture */
198     check(3,"f");
199     dblur = atof(argv[++i]);
200     dblur *= (dblur > 0);
201     break;
202     case 'R': /* standard RGB output */
203     if (strcmp(argv[i]+2, "RGB"))
204     goto badopt;
205     myRPmanager.prims = stdprims;
206     dtype = RDTnewCT(dtype, RDTrgbe);
207     break;
208     case 'X': /* XYZ output */
209     if (strcmp(argv[i]+2, "XYZ"))
210     goto badopt;
211     myRPmanager.prims = xyzprims;
212     dtype = RDTnewCT(dtype, RDTxyze);
213     break;
214     case 'c': /* chromaticities */
215     check(3,"ffffffff");
216     rval = 0;
217     for (int j = 0; j < 8; j++) {
218     our_prims[0][j] = atof(argv[++i]);
219     rval |= fabs(our_prims[0][j]-stdprims[0][j]) > .001;
220     }
221     if (rval) {
222     if (!colorprimsOK(our_prims))
223     error(USER, "illegal primary chromaticities");
224     myRPmanager.prims = our_prims;
225     } else
226     myRPmanager.prims = stdprims;
227     dtype = RDTnewCT(dtype, RDTrgbe);
228     break;
229     default:
230     goto badopt;
231     }
232     break;
233     case 'd': /* reference depth */
234     if (argv[i][2] || !myRPmanager.SetReferenceDepth(argv[++i]))
235     goto badopt;
236     dtype = RDTnewDT(dtype, RDTdshort);
237     break;
238     case 'x': /* x resolution */
239     check(2,"i");
240     hresolu = atoi(argv[++i]);
241     break;
242     case 'y': /* y resolution */
243     check(2,"i");
244     vresolu = atoi(argv[++i]);
245     break;
246     case 'S': /* start index */
247     check(2,"i");
248     seqstart = atoi(argv[++i]);
249     seqstart *= (seqstart > 0);
250     break;
251     case 'o': /* output file */
252     check(2,"s");
253     outfile = argv[++i];
254     break;
255     case 'z': /* z file */
256     check(2,"s");
257     zfile = argv[++i];
258     break;
259     case 'r': /* recover file */
260     if (argv[i][2] == 'o') { /* +output */
261     check(3,"s");
262     outfile = argv[i+1];
263     } else
264     check(2,"s");
265     recover = argv[++i];
266     break;
267     #if MAXCSAMP>3
268     case 'c': /* output spectral results */
269     if (argv[i][2] != 'o')
270     goto badopt;
271     rval = (myRPmanager.prims == NULL);
272     check_bool(3,rval);
273     if (rval)
274     myRPmanager.prims = NULL;
275     else if (myRPmanager.prims == NULL)
276     myRPmanager.prims = stdprims;
277     dtype = RDTnewCT(dtype, rval ? RDTscolr : RDTrgbe);
278     break;
279     #endif
280     case 't': /* timer */
281     check(2,"i");
282     ralrm = atoi(argv[++i]);
283     break;
284     case 'w': /* warnings */
285     rval = erract[WARNING].pf != NULL;
286     check_bool(2,rval);
287     if (rval) erract[WARNING].pf = wputs;
288     else erract[WARNING].pf = NULL;
289     break;
290     case 'e': /* error file */
291     check(2,"s");
292     errfile = argv[++i];
293     break;
294     default:
295     goto badopt;
296     }
297     }
298     if (maxdiff <= FTINY) /* check for useless sampling */
299     psample = 1;
300     if (zfile == NULL) /* set up depth output */
301     dtype = RDTnewDT(dtype, RDTnone);
302     else if (!RDTdepthT(dtype))
303     dtype = RDTnewDT(dtype, RDTdfloat);
304     /* check pixel output type */
305     if ((myRPmanager.prims == NULL) & (NCSAMP == 3)) {
306     myRPmanager.prims = stdprims;
307     dtype = RDTnewCT(dtype, RDTrgbe);
308     }
309     if (outfmt == 'f')
310     switch (RDTcolorT(dtype)) {
311     case RDTrgbe:
312     dtype = RDTnewCT(dtype, RDTrgb);
313     break;
314     case RDTxyze:
315     dtype = RDTnewCT(dtype, RDTxyz);
316     break;
317     case RDTscolr:
318     dtype = RDTnewCT(dtype, RDTscolor);
319     break;
320     case RDTrgb:
321     case RDTxyz:
322     case RDTscolor:
323     break;
324     default:
325     error(INTERNAL, "botched color output type");
326     }
327     /* set up signal handling */
328     sigdie(SIGINT, "Interrupt");
329     #ifdef SIGHUP
330     sigdie(SIGHUP, "Hangup");
331     #endif
332     sigdie(SIGTERM, "Terminate");
333     #ifdef SIGPIPE
334     sigdie(SIGPIPE, "Broken pipe");
335     #endif
336     #ifdef SIGALRM
337     sigdie(SIGALRM, "Alarm clock");
338     #endif
339     #ifdef SIGXCPU
340     sigdie(SIGXCPU, "CPU limit exceeded");
341     sigdie(SIGXFSZ, "File size exceeded");
342     #endif
343     /* open error file */
344     if (errfile != NULL) {
345     if (freopen(errfile, "a", stderr) == NULL)
346     quit(2);
347     fprintf(stderr, "**************\n*** PID %5d: ",
348     getpid());
349     printargs(argc, argv, stderr);
350     putc('\n', stderr);
351     fflush(stderr);
352     }
353     #ifdef NICE
354     nice(NICE); /* lower priority */
355     #endif
356     if (i < argc-1)
357     goto badopt;
358     // load octree
359     if (!myRPmanager.LoadOctree(argv[i]))
360     error(USER, "missing octree argument");
361     // add new header info
362     myRPmanager.AddHeader(i, argv);
363     {
364     char buf[128] = "SOFTWARE= ";
365     strcpy(buf+10, VersionID);
366     myRPmanager.AddHeader(buf);
367     }
368     // start our engines
369     nproc = myRPmanager.SetThreadCount(nproc);
370     // batch render picture(s)
371     rpict(seqstart, outfile, zfile, recover);
372    
373     quit(0); // clean up and exit
374    
375     badopt:
376     sprintf(errmsg, "command line error at '%s'", argv[i]);
377     error(USER, errmsg);
378     return 1; /* pro forma return */
379    
380     #undef check
381     #undef check_bool
382     }
383    
384    
385     void
386     wputs( /* warning output function */
387     const char *s
388     )
389     {
390     int lasterrno = errno;
391     eputs(s);
392     errno = lasterrno;
393     }
394    
395    
396     void
397     eputs( /* put string to stderr */
398     const char *s
399     )
400     {
401     static int midline = 0;
402    
403     if (!*s)
404     return;
405     if (!midline++) {
406     fputs(progname, stderr);
407     fputs(": ", stderr);
408     }
409     fputs(s, stderr);
410     if (s[strlen(s)-1] == '\n') {
411     fflush(stderr);
412     midline = 0;
413     }
414     }
415    
416    
417     static void
418     onsig( /* fatal signal */
419     int signo
420     )
421     {
422     static int gotsig = 0;
423    
424     if (gotsig++) /* two signals and we're gone! */
425     _exit(signo);
426    
427     #ifdef SIGALRM /* XXX how critical is this? */
428     alarm(30); /* allow 30 seconds to clean up */
429     signal(SIGALRM, SIG_DFL); /* make certain we do die */
430     #endif
431     eputs("signal - ");
432     eputs(sigerr[signo]);
433     eputs("\n");
434     quit(3);
435     }
436    
437    
438     static void
439     sigdie( /* set fatal signal */
440     int signo,
441     const char *msg
442     )
443     {
444     if (signal(signo, onsig) == SIG_IGN)
445     signal(signo, SIG_IGN);
446     sigerr[signo] = msg;
447     }
448    
449    
450     static void
451     printdefaults(void) /* print default values to stdout */
452     {
453     printf("-n %-2d\t\t\t\t# number of rendering processes\n", nproc);
454     printf("-vt%c\t\t\t\t# view type %s\n", ourview.type,
455     ourview.type==VT_PER ? "perspective" :
456     ourview.type==VT_PAR ? "parallel" :
457     ourview.type==VT_HEM ? "hemispherical" :
458     ourview.type==VT_ANG ? "angular" :
459     ourview.type==VT_CYL ? "cylindrical" :
460     ourview.type==VT_PLS ? "planisphere" :
461     "unknown");
462     printf("-vp %f %f %f\t# view point\n",
463     ourview.vp[0], ourview.vp[1], ourview.vp[2]);
464     printf("-vd %f %f %f\t# view direction\n",
465     ourview.vdir[0], ourview.vdir[1], ourview.vdir[2]);
466     printf("-vu %f %f %f\t# view up\n",
467     ourview.vup[0], ourview.vup[1], ourview.vup[2]);
468     printf("-vh %f\t\t\t# view horizontal size\n", ourview.horiz);
469     printf("-vv %f\t\t\t# view vertical size\n", ourview.vert);
470     printf("-vo %f\t\t\t# view fore clipping plane\n", ourview.vfore);
471     printf("-va %f\t\t\t# view aft clipping plane\n", ourview.vaft);
472     printf("-vs %f\t\t\t# view shift\n", ourview.hoff);
473     printf("-vl %f\t\t\t# view lift\n", ourview.voff);
474     printf("-x %-9d\t\t\t# x resolution\n", hresolu);
475     printf("-y %-9d\t\t\t# y resolution\n", vresolu);
476     if (myRPmanager.prims == stdprims)
477     printf("-pRGB\t\t\t\t# standard RGB color output\n");
478     else if (myRPmanager.prims == xyzprims)
479     printf("-pXYZ\t\t\t\t# CIE XYZ color output\n");
480     else if (myRPmanager.prims != NULL)
481     printf("-pc %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f\t# output color primaries and white point\n",
482     myRPmanager.prims[RED][0], myRPmanager.prims[RED][1],
483     myRPmanager.prims[GRN][0], myRPmanager.prims[GRN][1],
484     myRPmanager.prims[BLU][0], myRPmanager.prims[BLU][1],
485     myRPmanager.prims[WHT][0], myRPmanager.prims[WHT][1]);
486     if (NCSAMP > 3)
487     printf(myRPmanager.prims != NULL ? "-co-\t\t\t\t# output tristimulus colors\n" :
488     "-co+\t\t\t\t# output spectral values\n");
489     printf("-pa %f\t\t\t# pixel aspect ratio\n", pixaspect);
490     printf("-pj %f\t\t\t# pixel jitter\n", dstrpix);
491     printf("-pm %f\t\t\t# pixel motion\n", mblur);
492     printf("-pd %f\t\t\t# pixel depth-of-field\n", dblur);
493     printf("-ps %-9d\t\t\t# pixel sample\n", psample);
494     printf("-pt %f\t\t\t# pixel threshold\n", maxdiff);
495     printf("-t %-9d\t\t\t# time between reports\n", ralrm);
496     printf(erract[WARNING].pf != NULL ?
497     "-w+\t\t\t\t# warning messages on\n" :
498     "-w-\t\t\t\t# warning messages off\n");
499     print_rdefaults();
500     }
501    
502    
503     // my progress report call-back
504     static void
505     progReporter(double pct)
506     {
507     static time_t lastReportTime = 0;
508     time_t tnow = time(NULL);
509    
510 greg 2.2 if (pct < 100.-FTINY && tnow - lastReportTime < ralrm)
511 greg 2.1 return; // too soon, my Precious...
512    
513     sprintf(errmsg, "%7.3f%% done after %7.3f hours\n", pct, (tnow-tstart)/3600.);
514     eputs(errmsg);
515     // reset timer at 100%
516     lastReportTime = tnow * (pct < 100.-FTINY);
517     }
518    
519    
520     // Principal function for rpict execution (prototype in ray.h for some reason)
521     void
522     rpict(int seq, char *pout, char *zout, char *prvr)
523     /*
524 greg 2.6 * If seq is greater than zero, we will render a sequence of
525 greg 2.1 * images based on view parameter strings read from the standard input.
526     * If pout is NULL, then all images will be sent to the standard ouput.
527     * If seq is greater than zero and prvr is an integer, then it is the
528     * frame number at which rendering should begin. Preceeding view parameter
529     * strings will be skipped in the input.
530     * Note that pout and zout should contain %d format specifications for
531     * sequenced file naming.
532     */
533     {
534     char fbuf[256], dbuf[256];
535    
536     if (!zout ^ !RDTdepthT(dtype))
537     error(INTERNAL, "output depth type requires spec and vice versa");
538    
539     if (prvr && isint(prvr)) { // sequence recovery?
540     if (!seq)
541     error(USER, "sequence recovery requires starting frame");
542     if (!pout)
543     error(USER, "need output spec for sequence recovery");
544     int rno = atoi(prvr);
545     if (rno < seq)
546     error(USER, "recovery frame before starting frame");
547     while (seq <= rno) {
548     if (!fgets(fbuf, sizeof(fbuf), stdin))
549     error(USER, "recovery frame past end of sequence");
550     seq += (isview(fbuf) && sscanview(&ourview, fbuf) > 0);
551     }
552     sprintf(prvr=fbuf, pout, rno);
553     }
554     if (ralrm > 0)
555     myRPmanager.prCB = progReporter;
556     else
557     myRPmanager.prCB = NULL;
558     if (prvr) { // recovering partial render?
559     if ((seq > 0) & (prvr != fbuf))
560     error(USER, "recover spec must be number in sequence");
561     if (zout) sprintf(dbuf, zout, seq);
562     if (ralrm > 0) {
563     sprintf(errmsg, "resuming partial rendering '%s'\n", prvr);
564     eputs(errmsg);
565     }
566     dtype = myRPmanager.ResumeFrame(prvr, zout ? dbuf : zout);
567     if (!dtype)
568     error(USER, "ResumeFrame() failed");
569     if (!seq)
570 greg 2.6 return; // all done if not a sequence
571 greg 2.1 }
572     do {
573     if (prvr) // have view from sequence recovery?
574     prvr = NULL;
575     else if (seq) { // else read next view in sequence
576     while (fgets(fbuf, sizeof(fbuf), stdin))
577     if (isview(fbuf) && sscanview(&ourview, fbuf) > 0)
578     break;
579     if (feof(stdin))
580     return; // reached end of view input
581     }
582     // get (indexed) output file name(s)
583     if (pout) sprintf(fbuf, pout, seq);
584     if (zout) sprintf(dbuf, zout, seq);
585    
586     if (ralrm > 0) { // start report if requested
587     if (myRPmanager.NThreads() > 1)
588     sprintf(errmsg, "%2d processes ", myRPmanager.NThreads());
589     else
590     sprintf(errmsg, "PID %6d ", getpid());
591     eputs(errmsg);
592     if (seq) {
593     sprintf(errmsg, "rendering frame %5d ", seq);
594     eputs(errmsg);
595     } else
596     eputs("rendering picture ");
597     if (pout) {
598     sprintf(errmsg, "to '%s'\n", fbuf);
599     eputs(errmsg);
600     } else
601     eputs("to stdout\n");
602     if (zout) {
603     sprintf(errmsg, "\twith %s depth map in '%s'\n",
604     RDTdepthT(dtype)==RDTdshort ?
605     "encoded 16-bit" : "raw float",
606     dbuf);
607     eputs(errmsg);
608     }
609     }
610     // set up view and size
611     int xydim[2] = {hresolu, vresolu};
612     if (!myRPmanager.NewFrame(ourview, xydim, &pixaspect))
613     error(USER, "NewFrame() failed");
614    
615     myRPmanager.frameNo = seq;
616    
617     errno = 0; // render frame, skipping if it exists
618     if (!myRPmanager.RenderFrame(pout ? fbuf : pout, dtype,
619     zout ? dbuf : zout)
620     && !seq | (errno != EEXIST))
621     error(USER, "RenderFrame() failed");
622 greg 2.6 } while (seq++); // all done if not a sequence
623 greg 2.1 }