ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/RtraceSimulManager.cpp
Revision: 2.4
Committed: Wed Aug 2 00:04:31 2023 UTC (21 months, 2 weeks ago) by greg
Branch: MAIN
CVS Tags: rad5R4
Changes since 2.3: +74 -13 lines
Log Message:
feat: further fleshing out thread model

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: RtraceSimulManager.cpp,v 2.3 2023/07/31 23:14:02 greg Exp $";
3 #endif
4 /*
5 * RtraceSimulManager.cpp
6 *
7 * Rtrace simulation manager class implementation
8 *
9 * Created by Greg Ward on 2/2/2023.
10 */
11
12 #include "RtraceSimulManager.h"
13 #include "source.h"
14
15 extern int castonly; // doing ray-casting only?
16
17 // Load octree and prepare renderer
18 bool
19 RadSimulManager::LoadOctree(const char *octn)
20 {
21 if (octname) { // already running?
22 if (octn && !strcmp(octn, octname))
23 return true;
24 Cleanup(false);
25 }
26 if (!octn)
27 return false;
28
29 ray_init((char *)octn);
30 return true;
31 }
32
33 // How many processors are there?
34 int
35 RadSimulManager::GetNCores()
36 {
37 return 1; // XXX temporary
38 }
39
40 // Set number of computation threads (0 => #cores)
41 int
42 RadSimulManager::SetThreadCount(int nt)
43 {
44 return nThreads = 1; // XXX temporary
45 }
46
47 // Assign ray to subthread (fails if NThreads()<2)
48 bool
49 RadSimulManager::SplitRay(RAY *r)
50 {
51 if (NThreads() < 2 || ThreadsAvailable() < 1)
52 return false;
53
54 return false; // UNIMPLEMENTED
55 }
56
57 // Process a ray (in subthread), optional result
58 bool
59 RadSimulManager::ProcessRay(RAY *r)
60 {
61 if (!r || !Ready()) return false;
62 if (NThreads() < 2) { // single-threaded mode?
63 samplendx++;
64 rayvalue(r);
65 return true;
66 }
67 if (ThreadsAvailable() >= 1) {
68 SplitRay(r); // queue not yet full
69 return false;
70 }
71 RAY toDo = *r;
72 if (!WaitResult(r)) // need a free thread
73 return false;
74 SplitRay(&toDo); // queue up new ray
75 return true; // return older result
76 }
77
78 // Wait for next result (or fail)
79 bool
80 RadSimulManager::WaitResult(RAY *r)
81 {
82 return false; // UNIMPLEMENTED
83 }
84
85 // Close octree, free data, return status
86 int
87 RadSimulManager::Cleanup(bool everything)
88 {
89 ray_done(everything);
90 return 0;
91 }
92
93 // How many threads are currently unoccupied?
94 int
95 RadSimulManager::ThreadsAvailable() const
96 {
97 return 1; // XXX temporary
98 }
99
100 // Global pointer to simulation manager for trace call-back (only one)
101 static const RtraceSimulManager * ourRTsimMan = NULL;
102
103 void // static call-back
104 RtraceSimulManager::RTracer(RAY *r)
105 {
106 (*ourRTsimMan->traceCall)(r, ourRTsimMan->tcData);
107 }
108
109 // Check for changes to render flags & adjust accordingly
110 bool
111 RtraceSimulManager::UpdateMode()
112 {
113 rtFlags &= RTmask;
114 if (!cookedCall)
115 rtFlags &= ~RTdoFIFO;
116 if (!traceCall)
117 rtFlags &= ~RTtraceSources;
118 if (rtFlags & RTimmIrrad)
119 rtFlags &= ~RTlimDist;
120
121 int misMatch = rtFlags ^ curFlags;
122 // updates based on toggled flags
123 if (misMatch & RTtraceSources) {
124 if (rtFlags & RTtraceSources) {
125 for (int sn = 0; sn < nsources; sn++)
126 source[sn].sflags |= SFOLLOW;
127 } else // cannot undo this...
128 rtFlags |= RTtraceSources;
129 }
130 if (misMatch & RTdoFIFO && FlushQueue() < 0)
131 return false;
132 curFlags = rtFlags;
133 // update trace callback
134 if (traceCall) {
135 if (ourRTsimMan && ourRTsimMan != this)
136 error(WARNING, "Competing top-level simulation managers?");
137 ourRTsimMan = this;
138 trace = RTracer;
139 } else if (ourRTsimMan == this) {
140 trace = NULL;
141 ourRTsimMan = NULL;
142 }
143 return true;
144 }
145
146 extern "C" int m_normal(OBJREC *m, RAY *r);
147
148 /* compute irradiance rather than radiance */
149 static void
150 rayirrad(RAY *r)
151 {
152 /* pretend we hit surface */
153 r->rxt = r->rot = 1e-5;
154 VSUM(r->rop, r->rorg, r->rdir, r->rot);
155 r->ron[0] = -r->rdir[0];
156 r->ron[1] = -r->rdir[1];
157 r->ron[2] = -r->rdir[2];
158 r->rod = 1.0;
159 /* compute result */
160 r->revf = raytrace;
161 m_normal(&Lamb, r);
162 r->revf = rayirrad;
163 }
164
165 /* compute first ray intersection only */
166 static void
167 raycast(RAY *r)
168 {
169 if (!localhit(r, &thescene)) {
170 if (r->ro == &Aftplane) { /* clipped */
171 r->ro = NULL;
172 r->rot = FHUGE;
173 } else
174 sourcehit(r);
175 }
176 }
177
178 // Add a ray result to FIFO, flushing what we can
179 int
180 RtraceSimulManager::QueueResult(const RAY &ra)
181 {
182 return 0; // UNIMPLEMENTED
183 }
184
185 // Add ray bundle to queue w/ optional 1st ray ID
186 int
187 RtraceSimulManager::EnqueueBundle(const FVECT orig_direc[], int n, RNUMBER rID0)
188 {
189 int nqueued = 0;
190 RAY res;
191
192 if (!Ready())
193 return -1;
194
195 if (castonly && !cookedCall)
196 error(CONSISTENCY, "EnqueueBundle() called in castonly mode without cookedCall");
197
198 if (!UpdateMode()) // update rendering mode if requested
199 return -1;
200
201 while (n-- > 0) { // queue each ray
202 VCOPY(res.rorg, orig_direc[0]);
203 VCOPY(res.rdir, orig_direc[1]);
204 orig_direc += 2;
205 rayorigin(&res, PRIMARY, NULL, NULL);
206 if (rID0) res.rno = rID0++;
207 else res.rno = ++lastRayID;
208 if (curFlags & RTimmIrrad)
209 res.revf = rayirrad;
210 else if (castonly)
211 res.revf = raycast;
212 double d = normalize(res.rdir);
213 bool sendRes = (cookedCall != NULL);
214 if (d > 0) { // direction vector is valid?
215 if (curFlags & RTlimDist)
216 res.rmax = d;
217 if ((sendRes &= ProcessRay(&res)) &&
218 rtFlags & RTdoFIFO && NThreads() > 1) {
219 if (QueueResult(res) < 0)
220 return -1;
221 sendRes = false;
222 }
223 } else if (ThreadsAvailable() < NThreads() &&
224 FlushQueue() < 0)
225 return -1;
226 if (sendRes) // may be dummy ray
227 (*cookedCall)(&res, ccData);
228 nqueued++;
229 }
230 return nqueued;
231 }
232
233 // Finish pending rays and complete callbacks
234 int
235 RtraceSimulManager::FlushQueue()
236 {
237 int nsent = 0;
238 RAY res;
239
240 while (WaitResult(&res)) {
241 if (!cookedCall) continue;
242 if (rtFlags & RTdoFIFO) {
243 int ns = QueueResult(res);
244 if (ns < 0) return ns;
245 nsent += ns;
246 } else {
247 (*cookedCall)(&res, ccData);
248 nsent++;
249 }
250 }
251 return nsent;
252 }