ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/src/rt/RcontribSimulManager.h
Revision: 2.12
Committed: Fri Oct 17 17:43:53 2025 UTC (2 weeks, 5 days ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.11: +1 -6 lines
Log Message:
refactor(rxcontrib): Privatized things that didn't need to be extern

File Contents

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