ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/RtraceSimulManager.cpp
Revision: 2.7
Committed: Wed May 1 20:28:53 2024 UTC (12 months ago) by greg
Branch: MAIN
Changes since 2.6: +11 -7 lines
Log Message:
fix(rxtrace): Don't call FIFO routines with single process

File Contents

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