ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/RtraceSimulManager.cpp
(Generate patch)

Comparing ray/src/rt/RtraceSimulManager.cpp (file contents):
Revision 2.3 by greg, Mon Jul 31 23:14:02 2023 UTC vs.
Revision 2.8 by greg, Thu May 2 22:10:43 2024 UTC

# Line 9 | Line 9 | static const char RCSid[] = "$Id$";
9   *  Created by Greg Ward on 2/2/2023.
10   */
11  
12 + #include <unistd.h>
13   #include "RtraceSimulManager.h"
14   #include "source.h"
15  
15 extern int      castonly;       // doing ray-casting only?
16
16   // Load octree and prepare renderer
17   bool
18   RadSimulManager::LoadOctree(const char *octn)
# Line 21 | Line 20 | RadSimulManager::LoadOctree(const char *octn)
20          if (octname) {          // already running?
21                  if (octn && !strcmp(octn, octname))
22                          return true;
23 <                Cleanup(false);
23 >                Cleanup();
24          }
25          if (!octn)
26                  return false;
# Line 30 | Line 29 | RadSimulManager::LoadOctree(const char *octn)
29          return true;
30   }
31  
32 < // How many processors are there?
32 > // How many processors are available?
33   int
34   RadSimulManager::GetNCores()
35   {
36 <        return 1;               // XXX temporary
36 >        return sysconf(_SC_NPROCESSORS_ONLN);
37   }
38  
39   // Set number of computation threads (0 => #cores)
40   int
41   RadSimulManager::SetThreadCount(int nt)
42   {
43 <        return nThreads = 1;    // XXX temporary
43 >        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 >
55 >        return NThreads();
56   }
57  
58 + // Assign ray to subthread (fails if NThreads()<2)
59 + bool
60 + RadSimulManager::SplitRay(RAY *r)
61 + {
62 +        if (!ray_pnprocs || ThreadsAvailable() < 1)
63 +                return false;
64 +
65 +        return (ray_psend(r) > 0);
66 + }
67 +
68 + // Process a ray (in subthread), optional result
69 + bool
70 + RadSimulManager::ProcessRay(RAY *r)
71 + {
72 +        if (!Ready()) return false;
73 +
74 +        if (!ray_pnprocs) {     // single-threaded mode?
75 +                samplendx++;
76 +                rayvalue(r);
77 +                return true;
78 +        }
79 +        int     rv = ray_pqueue(r);
80 +        if (rv < 0) {
81 +                error(WARNING, "ray tracing process(es) died");
82 +                return false;
83 +        }
84 +        return (rv > 0);
85 + }
86 +
87 + // Wait for next result (or fail)
88 + bool
89 + RadSimulManager::WaitResult(RAY *r)
90 + {
91 +        if (!ray_pnprocs)
92 +                return false;
93 +
94 +        return (ray_presult(r, 0) > 0);
95 + }
96 +
97   // Close octree, free data, return status
98   int
99   RadSimulManager::Cleanup(bool everything)
100   {
101 <        ray_done(everything);
101 >        if (!ray_pnprocs)
102 >                ray_pdone(everything);
103 >        else
104 >                ray_done(everything);
105          return 0;
106   }
107  
# Line 56 | Line 109 | RadSimulManager::Cleanup(bool everything)
109   int
110   RadSimulManager::ThreadsAvailable() const
111   {
112 <        return 1;       // XXX temporary
112 >        if (!ray_pnprocs) return 1;
113 >
114 >        return ray_pnidle;
115   }
116  
117   // Global pointer to simulation manager for trace call-back (only one)
118   static const RtraceSimulManager *       ourRTsimMan = NULL;
119  
120 < void    // static call-back
120 > // Call-back for trace output
121 > void
122   RtraceSimulManager::RTracer(RAY *r)
123   {
124          (*ourRTsimMan->traceCall)(r, ourRTsimMan->tcData);
125   }
126  
127 + // Call-back for FIFO output
128 + int
129 + RtraceSimulManager::Rfifout(RAY *r)
130 + {
131 +        return (*ourRTsimMan->cookedCall)(r, ourRTsimMan->ccData);
132 + }
133 +
134   // Check for changes to render flags & adjust accordingly
135   bool
136   RtraceSimulManager::UpdateMode()
# Line 89 | Line 152 | RtraceSimulManager::UpdateMode()
152                  } else          // cannot undo this...
153                          rtFlags |= RTtraceSources;
154          }
155 <        if (misMatch & RTdoFIFO) {
156 <                if (!FlushQueue())
94 <                        return false;
95 <        }
155 >        if (misMatch & RTdoFIFO && FlushQueue() < 0)
156 >                return false;
157          curFlags = rtFlags;
158 <                                // update trace callback
159 <        if (traceCall) {
99 <                if (ourRTsimMan && ourRTsimMan != this)
100 <                        error(WARNING, "Competing top-level simulation managers?");
101 <                ourRTsimMan = this;
158 >                                // update callbacks
159 >        if (traceCall)
160                  trace = RTracer;
161 <        } else if (ourRTsimMan == this) {
161 >        else if (trace == RTracer)
162                  trace = NULL;
163 +        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                  ourRTsimMan = NULL;
169 +        } else if (ourRTsimMan != this) {
170 +                if (ourRTsimMan)
171 +                        error(WARNING, "Competing top-level simulation managers?");
172 +                ourRTsimMan = this;
173          }
174          return true;
175   }
176  
177   extern "C" int  m_normal(OBJREC *m, RAY *r);
178  
179 < /* compute irradiance rather than radiance */
179 > // compute irradiance rather than radiance
180   static void
181   rayirrad(RAY *r)
182   {
# Line 126 | Line 193 | rayirrad(RAY *r)
193          r->revf = rayirrad;
194   }
195  
196 < /* compute first ray intersection only */
196 > // compute first ray intersection only
197   static void
198   raycast(RAY *r)
199   {
# Line 150 | Line 217 | RtraceSimulManager::EnqueueBundle(const FVECT orig_dir
217                  return -1;
218  
219          if (castonly && !cookedCall)
220 <                error(CONSISTENCY, "EnqueueBundle() called in castonly mode without cookedCall");
220 >                error(INTERNAL, "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
159                double  d;
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;
230 >                if (!rID0)
231 >                        res.rno = ++lastRayID;
232 >                else if (curFlags & RTdoFIFO)
233 >                        error(INTERNAL, "Ray number assignment unsupported with FIFO");
234 >                else
235 >                        res.rno = lastRayID = rID0++;
236                  if (curFlags & RTimmIrrad)
237                          res.revf = rayirrad;
238                  else if (castonly)
239                          res.revf = raycast;
240 <                d = normalize(res.rdir);
240 >                double  d = normalize(res.rdir);
241 >                bool    sendRes = (cookedCall != NULL);
242                  if (d > 0) {            // direction vector is valid?
243                          if (curFlags & RTlimDist)
244                                  res.rmax = d;
245 <                        samplendx++;
246 <                        rayvalue(&res);         // XXX single-threaded for now
245 >                        if (((curFlags&RTdoFIFO) != 0) & (ray_pnprocs > 0)) {
246 >                                if (ray_fifo_in(&res) < 0)
247 >                                        return -1;
248 >                                sendRes = false;
249 >                        } else
250 >                                sendRes &= ProcessRay(&res);
251                  } else if (ThreadsAvailable() < NThreads() &&
252 <                                !FlushQueue())
252 >                                FlushQueue() < 0)
253                          return -1;
254 <                if (cookedCall)
255 <                        (*cookedCall)(&res, ccData);
254 >                                        // may be dummy ray
255 >                if (sendRes && (*cookedCall)(&res, ccData) < 0)
256 >                        return -1;
257                  nqueued++;
258          }
259          return nqueued;
260   }
261  
262   // Finish pending rays and complete callbacks
263 < bool
263 > int
264   RtraceSimulManager::FlushQueue()
265   {
266 <        return true;            // XXX no-op for now
266 >        if (curFlags & RTdoFIFO) {
267 >                if (ray_pnprocs)
268 >                        return ray_fifo_flush();
269 >                return 0;
270 >        }
271 >        int     nsent = 0;
272 >        RAY     res;
273 >
274 >        while (WaitResult(&res)) {
275 >                if (!cookedCall) continue;
276 >                int     rv = (*cookedCall)(&res, ccData);
277 >                if (rv < 0) return -1;
278 >                nsent += rv;
279 >        }
280 >        return nsent;
281   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines