ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/RcontribSimulManager.h
Revision: 2.2
Committed: Tue Oct 29 19:47:19 2024 UTC (6 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.1: +25 -7 lines
Log Message:
fix(rxcontrib): Fixed handling of -ld and -I command-line flags

File Contents

# User Rev Content
1 greg 2.2 /* RCSid $Id: RcontribSimulManager.h,v 2.1 2024/10/29 00:36:54 greg Exp $ */
2 greg 2.1 /*
3     * RcontribSimulManager.h
4     *
5     * Rcontrib simulation manager class declaration
6     *
7     * Created by Greg Ward on 10/11/2024.
8     */
9    
10     #ifndef RcontribSimulManager_h
11     #define RcontribSimulManager_h
12    
13     #include "RtraceSimulManager.h"
14     #include "RdataShare.h"
15     #include "lookup.h"
16     #include "rtprocess.h"
17    
18     /*
19     * As with other single-object classes, many global variable affect
20     * behavior. Besides rendering parameters, there are spectral parameters
21     * and output dimensions taken from the environment.
22     *
23     * NOTE: "record" and "row" are used interchangeably throughout.
24     */
25    
26     extern char RCCONTEXT[]; // global rcontrib context
27    
28 greg 2.2 extern int contrib; // computing contributions?
29    
30 greg 2.1 extern int xres, yres; // global resolution settings
31    
32 greg 2.2 class RcontribSimulManager; // need forward decl
33 greg 2.1
34     /// Shared data object for record output (includes header; may be write-only)
35     class RcontribOutput {
36     RcontribOutput * next; // next in sorted list
37     char * ofname; // output file name
38     uint32 rowCountPos; // row count position in header
39     void * rowp; // current row memory
40     bool NewHeader(const RcontribSimulManager *rcp);
41     int CheckHeader(const RcontribSimulManager *rcp);
42     public:
43     RdataShare * rData; // data sharing object
44     size_t rowBytes; // byte count per row
45     const char * omod; // single modifier (or NULL)
46     int32 obin; // single output bin (or -1)
47     uint32 begData; // start of data (type-aligned)
48     int32 curRow; // current output row
49     uint32 nRows; // total number of rows
50     RcontribOutput(const char *fnm = NULL) {
51     next = NULL;
52     omod = NULL;
53     obin = -1;
54     rData = NULL;
55     ofname = savqstr(fnm);
56     rowBytes = 0;
57     nRows = 0;
58     rowp = NULL; curRow = -1;
59     }
60     ~RcontribOutput() {
61     DoneRow();
62     delete rData;
63     delete next;
64     freeqstr(ofname);
65     }
66     /// Return output channel name
67     const char * GetName() const {
68     if (rData) return rData->GetName();
69     return ofname;
70     }
71     /// Update output row count
72     bool SetRowsDone(int r) {
73     if (!rData | (0 >= r) | (r > nRows)) return false;
74     char * rbuf = (char *)rData->GetMemory(rowCountPos, 17, 0);
75     sprintf(rbuf, "%-16d", r);
76     rbuf[16] = '\n'; // replaces nul byte
77     return rData->ReleaseMemory(rbuf, RDSwrite);
78     }
79     /// Get buffer for indicated row (contents may be random)
80     void * GetRow(int r) {
81     if (!rData | (r < 0)) return NULL;
82     if (r != curRow) {
83     DoneRow();
84     if (r < nRows)
85     rowp = rData->GetMemory(begData + r*rowBytes,
86     rowBytes, 0);
87     if (rowp) curRow = r;
88     }
89     return rowp;
90     }
91     /// Current row with byte offset
92     void * InsertionP(int coffset) const {
93     if (!rowp | (coffset < 0) | (coffset >= rowBytes))
94     return NULL;
95     return (char *)rowp + coffset;
96     }
97     /// Release current row, writing contents
98     void DoneRow() {
99     if (rowp) rData->ReleaseMemory(rowp, RDSwrite);
100     rowp = NULL; curRow = -1;
101     }
102     /// Get next in list
103     const RcontribOutput * Next() const {
104     return next;
105     }
106     RcontribOutput * Next() {
107     return next;
108     }
109     /// RcontribSimulManager gets full access
110     friend class RcontribSimulManager;
111     };
112    
113     typedef double DCOLORV; // color accumulator type
114    
115     /// Modifier channel for recording contributions (no constructor/destructor)
116     struct RcontribMod;
117    
118     /// Allocate rcontrib accumulator
119     extern RcontribMod * NewRcMod(const char *prms = NULL, const char *binexpr = NULL, int ncbins = 1);
120     /// Free an RcontribMod
121     extern lut_free_t FreeRcMod;
122    
123     /*
124     * General RcontribSimulManager class operation:
125     *
126     * 1) Call LoadOctree(), then alter the header as desired
127     * 2) Set number of spectral samples (NCSAMP) and call SetDataFormat()
128     * 3) Call AddModifier() and AddModFile() to indicate tracked modifiers
129     * 4) Set outOp and cdsF according to desired output/recovery
130     * 5) Call PrepOutput() to open output channels
131     * 6) Call SetThreadCount() to fork children if desired
132     * 7) Set accum to the number of ray samples per record
133     * 8) Call ComputeRecord() with accum ray samples
134     * 9) Continue until GetRowMax() records have been sent
135     * 10) Call Cleanup()
136     *
137     * The order of some of these calls may be changed. Technically, the octree
138     * may be loaded anytime before PrepOutput() is called. Also, SetThreadCount()
139     * may be called anytime after PrepOutput() and interleaved with
140     * calls to ComputeRecord(). The accum setting may be changed at any time.
141     * Finally, it is possible to restart the output using ResetRow(), and
142     * a zero argument will rewind to the beginning, whence all records
143     * may be recalculated. The previous output rows are not zeroed or deleted,
144     * but are overwritten as the calculation proceeds from the new starting point.
145     * However, the output file(s) will indicate in the NROWS= line in the header
146     * that only the newly calculated rows are present.
147     *
148     * It is not possible to write to standard output, but the output
149     * model is quite flexible thanks to the RdataShare polymorphic class.
150     * The current default output class creates a shared, memory-mapped file,
151     * which is the most efficient object on most systems.
152     *
153     * ASCII output is not supported, so full data recovery is.
154     */
155    
156     /// Output channel opening options: new/exclusive, overwrite if exists, or recover data
157     enum RCOutputOp {RCOnew, RCOforce, RCOrecover};
158    
159     /// Converts above to RdataShare open flags (may be adjusted by calling program)
160     extern int RSDOflags[];
161    
162     /// Call-back function type to create named data channel (freed using "delete" operator)
163     typedef RdataShare * RcreateDataShareF(const char *name, RCOutputOp op, size_t siz);
164    
165     /// Our default data share function
166     extern RcreateDataShareF defDataShare;
167    
168 greg 2.2 /// Modifiable ray-tracing flags for rcontrib
169     #define RCmask (RTlimDist|RTimmIrrad)
170 greg 2.1
171     /// rcontrib-like simulation manager (at most one such object)
172     class RcontribSimulManager : protected RtraceSimulManager {
173     protected:
174     static RayReportCall RctCall; // our callback for traced rays
175     ABitMap rowsDone; // bit mask of completed rows
176     uint32 rInPos; // which row (record) is next on input?
177     uby8 nChan; // NCSAMP setting for this calculation
178     char dtyp; // data type ('f', 'd', or 'c')
179     uint16 dsiz; // N-component element size in bytes
180     RcontribOutput * outList; // ordered list of output channels
181     LUTAB modLUT; // modifier lookup table
182     SUBPROC * kid; // array of child processes
183     int32 * kidRow; // row assigned to each child
184     int nkids; // child process count (-1 in child)
185     bool UpdateRowsDone(int r);
186     int GetChild(bool forceWait = false);
187     bool StartKids(int n2go);
188     int StopKids(int n2end = 0);
189     void RunChild();
190     public:
191     RCOutputOp outOp; // output operation
192     RcreateDataShareF * cdsF; // data share creator
193     uint32 accum; // # rays to accumulate per record
194     RcontribSimulManager(const char *octn = NULL)
195     : RtraceSimulManager(NULL, NULL, octn) {
196     rInPos = 0;
197     nChan = 0;
198     dtyp = 'f';
199     dsiz = 0;
200     outList = NULL;
201     memset(&modLUT, 0, sizeof(modLUT));
202     modLUT.hashf = lu_shash;
203     modLUT.keycmp = strcmp;
204     modLUT.freek = efree;
205     modLUT.freed = FreeRcMod;
206     kid = NULL; kidRow = NULL; nkids = 0;
207     rtFlags = RTtraceSources;
208     SetTraceCall(&RctCall, this);
209     outOp = RCOnew;
210     cdsF = &defDataShare;
211     accum = 1;
212     }
213     ~RcontribSimulManager() {
214     Cleanup();
215     }
216 greg 2.2 /// Check modifiable ray-tracing computation flag(s)
217     bool HasFlag(int fl) const {
218     return ((rtFlags & RCmask & fl) != 0);
219     }
220     /// Set/reset modifiable ray-tracing computation flag(s)
221     bool SetFlag(int fl, bool val = true) {
222     if (!(fl &= RCmask)) return false;
223     if (val) rtFlags |= fl;
224     else rtFlags &= ~fl;
225     return true;
226     }
227 greg 2.1 /// Load octree and prepare renderer
228     bool LoadOctree(const char *octn) {
229     return RtraceSimulManager::LoadOctree(octn);
230     }
231     /// Prepare header from previous input (or clear)
232     bool NewHeader(const char *inspec=NULL) {
233     return RtraceSimulManager::NewHeader(inspec);
234     }
235     /// Add a string to header (adds newline if none)
236     bool AddHeader(const char *str) {
237     return RtraceSimulManager::AddHeader(str);
238     }
239     /// Append program line to header
240     bool AddHeader(int ac, char *av[]) {
241     return RtraceSimulManager::AddHeader(ac, av);
242     }
243     /// Get current header length in bytes
244     int GetHeadLen() const {
245     return RtraceSimulManager::GetHeadLen();
246     }
247     /// Get header lines if any
248     const char * GetHeadStr() const {
249     return RtraceSimulManager::GetHeadStr();
250     }
251     /// Look for specific header keyword, return value
252     const char * GetHeadStr(const char *key, bool inOK = false) const {
253     return RtraceSimulManager::GetHeadStr(key, inOK);
254     }
255     /// Set output format ('f', 'd', or 'c'), call before mods
256     bool SetDataFormat(int ty);
257     /// Get current format (and element size in bytes)
258     int GetFormat(int *siz = NULL) const {
259     if (siz) *siz = dsiz;
260     return dtyp;
261     }
262     /// Add a modifier and arguments, create output(s)
263     bool AddModifier(const char *modn, const char *outspec,
264     const char *prms = NULL,
265     const char *binval = NULL, int bincnt = 1);
266     /// Add a file of modifiers with associated arguments
267     bool AddModFile(const char *modfn, const char *outspec,
268     const char *prms = NULL,
269     const char *binval = NULL, int bincnt = 1);
270 greg 2.2 /// Get named rcontrib output (or list)
271     const RcontribOutput * GetOutput(const char *nm = NULL) const {
272     if (!nm) return outList;
273     const RcontribOutput * op = outList;
274     while (op && strcmp(op->GetName(), nm))
275     op = op->next;
276     return op;
277     }
278 greg 2.1 /// Open output channels and return # completed rows
279     int PrepOutput();
280     /// Are we ready to compute some records?
281     bool Ready() const {
282     return rowsDone.Length();
283     }
284     /// Set number of computation threads (0 => #cores)
285     int SetThreadCount(int nt = 0);
286     /// Check thread count (1 means no multi-processing)
287     int NThreads() const {
288     return nkids + !nkids;
289     }
290     /// What is maximum row?
291     int GetRowMax() const {
292     if (!outList) return yres * (xres + !xres);
293     return outList->nRows;
294     }
295     /// Get current row count (# rows sent for computation)
296     int GetRowCount() const {
297     return rInPos;
298     }
299     /// Get # rows completed
300     int GetRowFinished() const {
301     if (!nkids) return rInPos;
302     uint32 nDone = rowsDone.Find(0, false);
303     if (nDone == ABMend)
304     return rowsDone.Length();
305     return nDone;
306     }
307     /// Rewind calculation (previous results unchanged)
308     bool ResetRow(int r);
309     /// Add a ray/bundle to compute next record (n=accum)
310     int ComputeRecord(const FVECT orig_direc[]);
311     /// Finish pending rays if multi-processing
312     bool FlushQueue() {
313     if (nkids <= 0) return true;
314     while (GetChild(true) >= 0)
315     ;
316     return true;
317     }
318     /// Close octree, free data, return status
319     int Cleanup(bool everything = false) {
320     if (rowsDone.Length()) {
321     SetThreadCount(1);
322     cow_doneshare();
323     rowsDone.NewBitMap(0);
324     }
325     lu_done(&modLUT);
326     delete outList; outList = NULL;
327     nChan = 0;
328     return RtraceSimulManager::Cleanup(everything);
329     }
330     };
331    
332     #endif /* RcontribSimulManager_h */