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 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

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.4 static const char RCSid[] = "$Id: RtraceSimulManager.cpp,v 2.3 2023/07/31 23:14:02 greg Exp $";
3 greg 2.1 #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 greg 2.3 Cleanup(false);
25 greg 2.1 }
26     if (!octn)
27     return false;
28    
29     ray_init((char *)octn);
30     return true;
31     }
32    
33 greg 2.2 // How many processors are there?
34     int
35     RadSimulManager::GetNCores()
36     {
37     return 1; // XXX temporary
38     }
39    
40 greg 2.1 // Set number of computation threads (0 => #cores)
41     int
42     RadSimulManager::SetThreadCount(int nt)
43     {
44     return nThreads = 1; // XXX temporary
45     }
46    
47 greg 2.4 // 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 greg 2.1 // Close octree, free data, return status
86     int
87 greg 2.3 RadSimulManager::Cleanup(bool everything)
88 greg 2.1 {
89 greg 2.3 ray_done(everything);
90 greg 2.1 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 greg 2.4 if (misMatch & RTdoFIFO && FlushQueue() < 0)
131     return false;
132 greg 2.1 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 greg 2.4 // 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 greg 2.1 // 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 greg 2.4 double d = normalize(res.rdir);
213     bool sendRes = (cookedCall != NULL);
214 greg 2.1 if (d > 0) { // direction vector is valid?
215     if (curFlags & RTlimDist)
216     res.rmax = d;
217 greg 2.4 if ((sendRes &= ProcessRay(&res)) &&
218     rtFlags & RTdoFIFO && NThreads() > 1) {
219     if (QueueResult(res) < 0)
220     return -1;
221     sendRes = false;
222     }
223 greg 2.1 } else if (ThreadsAvailable() < NThreads() &&
224 greg 2.4 FlushQueue() < 0)
225 greg 2.1 return -1;
226 greg 2.4 if (sendRes) // may be dummy ray
227 greg 2.1 (*cookedCall)(&res, ccData);
228 greg 2.3 nqueued++;
229 greg 2.1 }
230     return nqueued;
231     }
232    
233     // Finish pending rays and complete callbacks
234 greg 2.4 int
235 greg 2.1 RtraceSimulManager::FlushQueue()
236     {
237 greg 2.4 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 greg 2.1 }