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

# Content
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 */