ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/RcontribSimulManager.h
Revision: 2.1
Committed: Tue Oct 29 00:36:54 2024 UTC (6 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
feat(rxcontrib): First compiled version of rxcontrib tool to test new C++ classes

File Contents

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