ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/RtraceSimulManager.h
Revision: 2.22
Committed: Thu Jan 9 17:25:37 2025 UTC (3 months, 3 weeks ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 2.21: +2 -1 lines
Log Message:
fix(rxpiece,rxpict): Make sure child processes are waited for

File Contents

# User Rev Content
1 greg 2.22 /* RCSid $Id: RtraceSimulManager.h,v 2.21 2025/01/02 16:16:49 greg Exp $ */
2 greg 2.1 /*
3     * RtraceSimulManager.h
4     *
5     * Rtrace simulation manager class declaration (along with base class)
6     * Enqueuing rays will block caller iff #rays >= ThreadsAvail()
7     * Reporting call-backs made from EnqueBundle() and FlushQueue()
8     *
9     * Created by Greg Ward on 11/10/22.
10     */
11    
12     #ifndef RtraceSimulManager_h
13     #define RtraceSimulManager_h
14    
15     #include "ray.h"
16 greg 2.15 #include "abitmap.h"
17 greg 2.1
18     extern char * octname; // global octree name
19    
20 greg 2.6 extern int castonly; // doing ray-casting only?
21    
22     /// Ray reporting callback method -- returns # successfully reported, -1 to abort
23     typedef int RayReportCall(RAY *r, void *cd);
24 greg 2.1
25     /// Multi-threaded simulation manager base class
26     class RadSimulManager {
27 greg 2.9 char * header; // header (less intro and format)
28 greg 2.10 int hlen; // header string length
29 greg 2.4 protected:
30 greg 2.17 bool SplitRay(RAY *r) {
31     return (ray_pnprocs && ray_psend(r) > 0);
32     }
33 greg 2.1 public:
34     RadSimulManager(const char *octn = NULL) {
35 greg 2.10 header = NULL; hlen = 0;
36 greg 2.1 LoadOctree(octn);
37     }
38     ~RadSimulManager() {
39 greg 2.21 // Cleanup();
40 greg 2.22 if (ray_pnprocs > 0) ray_pclose(0);
41 greg 2.1 }
42     /// Load octree and prepare renderer
43     bool LoadOctree(const char *octn);
44 greg 2.9 /// Prepare header from previous input (or clear)
45     /// Normally called during octree load
46 greg 2.15 bool NewHeader(const char *inspec = NULL);
47 greg 2.10 /// Add a line to header (adds newline if none)
48 greg 2.9 bool AddHeader(const char *str);
49     /// Append program line to header
50 greg 2.13 bool AddHeader(int ac, char *av[]);
51 greg 2.16 /// Get current header length in bytes
52     int GetHeadLen() const {
53     return hlen;
54     }
55 greg 2.11 /// Get header lines or empty string
56 greg 2.14 const char * GetHeadStr() const {
57 greg 2.11 return hlen ? header : "";
58 greg 2.9 }
59 greg 2.14 /// Look for specific header keyword, return value
60     const char * GetHeadStr(const char *key, bool inOK = false) const;
61 greg 2.5 /// How many cores are available?
62 greg 2.3 static int GetNCores();
63 greg 2.1 /// Set number of computation threads (0 => #cores)
64     int SetThreadCount(int nt = 0);
65     /// Check thread count (1 means no multi-threading)
66     int NThreads() const {
67 greg 2.6 return ray_pnprocs + !ray_pnprocs;
68 greg 2.1 }
69     /// How many threads are currently unoccupied?
70 greg 2.17 int ThreadsAvailable() const {
71     return ray_pnprocs ? ray_pnidle : 1;
72     }
73 greg 2.1 /// Are we ready?
74     bool Ready() const {
75 greg 2.6 return (octname && nobjects > 0);
76 greg 2.1 }
77 greg 2.4 /// Process a ray (in subthread), optional result
78 greg 2.17 int ProcessRay(RAY *r);
79 greg 2.4 /// Wait for next result (or fail)
80     bool WaitResult(RAY *r);
81 greg 2.1 /// Close octree, free data, return status
82 greg 2.3 int Cleanup(bool everything = false);
83 greg 2.1 };
84    
85     /// Flags to control rendering operations
86     enum {RTdoFIFO=1, RTtraceSources=2, RTlimDist=4, RTimmIrrad=8, RTmask=15};
87    
88     /// rtrace-like simulation manager (at most one such object)
89     class RtraceSimulManager : public RadSimulManager {
90     RayReportCall * cookedCall; // callback for cooked primary rays
91     void * ccData; // client data for cooked primary rays
92     RayReportCall * traceCall; // call for every ray in tree
93     void * tcData; // client data for traced rays
94     int curFlags; // current operating flags
95 greg 2.15 ABitMap srcFollowed; // source flags changed
96 greg 2.1 // Call-back for global ray-tracing context
97     static void RTracer(RAY *r);
98 greg 2.6 // Call-back for FIFO
99     static int Rfifout(RAY *r);
100 greg 2.21 protected:
101 greg 2.1 // Check for changes to render flags, etc.
102     bool UpdateMode();
103     RNUMBER lastRayID; // last ray ID assigned
104     public:
105     int rtFlags; // operation (RT*) flags
106     RtraceSimulManager(RayReportCall *cb = NULL, void *cd = NULL,
107     const char *octn = NULL) : RadSimulManager(octn) {
108     lastRayID = 0;
109     rtFlags = curFlags = 0;
110     SetCookedCall(cb, cd);
111     traceCall = NULL; tcData = NULL;
112     }
113 greg 2.3 ~RtraceSimulManager() {
114     FlushQueue();
115     }
116 greg 2.21 /// Load octree and prepare renderer
117     bool LoadOctree(const char *octn) {
118     if ((octn != NULL) & (octname != NULL) &&
119     !strcmp(octn, octname))
120     return true;
121     srcFollowed.NewBitMap(0);
122     curFlags &= ~RTtraceSources;
123     return RadSimulManager::LoadOctree(octn);
124     }
125 greg 2.2 /// Set number of computation threads (0 => #cores)
126     int SetThreadCount(int nt = 0) {
127 greg 2.6 if (nt <= 0) nt = castonly ? 1 : GetNCores();
128 greg 2.2 if (nt == NThreads()) return nt;
129 greg 2.12 if (nt < NThreads() && FlushQueue() < 0) return 0;
130 greg 2.2 return RadSimulManager::SetThreadCount(nt);
131     }
132 greg 2.1 /// Add ray bundle to queue w/ optional 1st ray ID
133     int EnqueueBundle(const FVECT orig_direc[], int n,
134     RNUMBER rID0 = 0);
135     /// Enqueue a single ray w/ optional ray ID
136 greg 2.17 int EnqueueRay(const FVECT org, const FVECT dir,
137 greg 2.1 RNUMBER rID = 0) {
138     if (dir == org+1)
139 greg 2.3 return(EnqueueBundle((const FVECT *)org, 1, rID) > 0);
140 greg 2.1 FVECT orgdir[2];
141     VCOPY(orgdir[0], org); VCOPY(orgdir[1], dir);
142 greg 2.17 return EnqueueBundle(orgdir, 1, rID);
143 greg 2.1 }
144 greg 2.6 /// Set/change cooked ray callback
145 greg 2.1 void SetCookedCall(RayReportCall *cb, void *cd = NULL) {
146     if (cookedCall && (cookedCall != cb) | (ccData != cd))
147     FlushQueue();
148     cookedCall = cb;
149 greg 2.6 ccData = cb ? cd : NULL;
150 greg 2.1 }
151 greg 2.18 /// Set/change trace callback
152 greg 2.1 void SetTraceCall(RayReportCall *cb, void *cd = NULL) {
153 greg 2.19 if ((cb == traceCall) & (cd == tcData)) return;
154 greg 2.18 int nt = NThreads();
155     if (nt > 1) SetThreadCount(1);
156 greg 2.1 traceCall = cb;
157 greg 2.6 tcData = cb ? cd : NULL;
158 greg 2.20 UpdateMode();
159 greg 2.18 if (nt > 1) SetThreadCount(nt);
160 greg 2.1 }
161 greg 2.4 /// Finish pending rays and complete callbacks (return #sent)
162     int FlushQueue();
163 greg 2.1 /// Close octree, free data, return status
164 greg 2.3 int Cleanup(bool everything = false) {
165 greg 2.21 int st = RadSimulManager::Cleanup(everything);
166     srcFollowed.NewBitMap(0);
167     curFlags &= ~RTtraceSources;
168     if (everything) {
169     SetCookedCall(NULL);
170     SetTraceCall(NULL);
171     rtFlags &= ~RTmask;
172     }
173 greg 2.1 UpdateMode();
174     lastRayID = 0;
175 greg 2.21 return st;
176 greg 2.1 }
177     };
178    
179     /// Determine if vector is all zeroes
180     inline bool
181     IsZeroVec(const FVECT vec)
182     {
183     return (vec[0] == 0.0) & (vec[1] == 0.0) & (vec[2] == 0.0);
184     }
185    
186     #endif /* RtraceSimulManager_h */