ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/RpictSimulManager.h
Revision: 2.7
Committed: Fri Aug 23 02:08:28 2024 UTC (8 months, 1 week ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.6: +4 -3 lines
Log Message:
perf(rxpict): Improved quincunx sampling code -- still needs work

File Contents

# User Rev Content
1 greg 2.7 /* RCSid $Id: RpictSimulManager.h,v 2.6 2024/08/21 23:52:24 greg Exp $ */
2 greg 2.1 /*
3     * RpictSimulManager.h
4     *
5     * Rpict simulation manager class declaration
6     *
7     * Created by Greg Ward on 07/11/2024.
8     */
9    
10     #ifndef RpictSimulManager_h
11     #define RpictSimulManager_h
12    
13     #include "RtraceSimulManager.h"
14     #include "view.h"
15     #include "depthcodec.h"
16     #include "abitmap.h"
17    
18     /// Data type flags for pixel access and output
19     enum RenderDataType {
20     RDTnone=0,
21     RDTscolor=0x1, RDTrgb=0x2, RDTxyz=0x3, RDTscolr=0x4, RDTrgbe=0x5, RDTxyze=0x6,
22     RDTcolorM=0x7,
23     RDTdfloat=0x8, RDTdshort=0x10,
24     RDTdepthM=0x18
25     };
26    
27     #define RDTcolorT(f) RenderDataType((f) & RDTcolorM)
28     #define RDTdepthT(f) RenderDataType((f) & RDTdepthM)
29     #define RDTcommonE(f) (RDTcolorT(f) >= RDTscolr)
30 greg 2.2 #define RDTnewCT(f,c) RenderDataType((f) & ~RDTcolorM | (c) & RDTcolorM)
31     #define RDTnewDT(f,d) RenderDataType((f) & ~RDTdepthM | (d) & RDTdepthM)
32 greg 2.1
33     /// Pixel accessor (read/write to caller's buffer with possible conversion)
34     class PixelAccess {
35     union {
36     COLORV * f;
37     COLRV * b;
38     } pbase; // pixel base pointer
39     union {
40     float * f;
41     short * s;
42     } dbase; // depth base pointer
43     long rowStride; // # values to next y position
44     int dtyp; // data type flags
45     RGBPRIMP primp; // color primaries if tristimulus
46 greg 2.2 const COLORV * CF3(int x, int y) const {
47     return pbase.f + (rowStride*y + x)*3;
48     }
49 greg 2.1 COLORV * CF3(int x, int y) {
50     return pbase.f + (rowStride*y + x)*3;
51     }
52 greg 2.2 const COLRV * CB3(int x, int y) const {
53     return pbase.b + (rowStride*y + x)*4;
54     }
55     COLRV * CB3(int x, int y) {
56     return pbase.b + (rowStride*y + x)*4;
57     }
58     const COLORV * SCF(int x, int y) const {
59     return pbase.f + (rowStride*y + x)*NCSAMP;
60 greg 2.1 }
61     COLORV * SCF(int x, int y) {
62     return pbase.f + (rowStride*y + x)*NCSAMP;
63     }
64 greg 2.2 const COLRV * SCB(int x, int y) const {
65     return pbase.b + (rowStride*y + x)*(NCSAMP+1);
66 greg 2.1 }
67     COLRV * SCB(int x, int y) {
68     return pbase.b + (rowStride*y + x)*(NCSAMP+1);
69     }
70     public:
71     double refDepth; // reference depth
72     PixelAccess() {
73     refDepth = 1.;
74     Init();
75     }
76     PixelAccess(COLORV *rp, int ystride, float *zp=NULL) {
77     refDepth = 1.;
78     Init(rp, ystride, zp);
79     }
80     PixelAccess(COLRV *bp, int ystride, float *zp=NULL) {
81     refDepth = 1.;
82     Init(bp, ystride, zp);
83     }
84     PixelAccess(COLRV *bp, int ystride, short *dp) {
85     refDepth = 1.;
86     Init(bp, ystride, dp);
87     }
88 greg 2.4 PixelAccess(COLORV *rp, int ystride, short *dp) {
89     refDepth = 1.;
90     Init(rp, ystride, dp);
91     }
92 greg 2.1 void Init() {
93     pbase.f = NULL; dbase.f = NULL;
94     rowStride = 0;
95     primp = NULL;
96     dtyp = 0;
97     }
98     /// Initializers default to rendering color space
99     void Init(COLORV *rp, int ystride, float *zp=NULL) {
100     pbase.f = rp; dbase.f = zp;
101     rowStride = ystride;
102     if (NCSAMP > 3) {
103     dtyp = RDTscolor; primp = NULL;
104     } else {
105     dtyp = RDTrgb; primp = stdprims;
106     }
107     if (zp) dtyp |= RDTdfloat;
108     }
109     void Init(COLRV *bp, int ystride, float *zp=NULL) {
110     pbase.b = bp; dbase.f = zp;
111     rowStride = ystride;
112     if (NCSAMP > 3) {
113     dtyp = RDTscolr; primp = NULL;
114     } else {
115     dtyp = RDTrgbe; primp = stdprims;
116     }
117     if (zp) dtyp |= RDTdfloat;
118     }
119     void Init(COLRV *bp, int ystride, short *dp) {
120     pbase.b = bp; dbase.s = dp;
121     rowStride = ystride;
122     if (NCSAMP > 3) {
123     dtyp = RDTscolr; primp = NULL;
124     } else {
125     dtyp = RDTrgbe; primp = stdprims;
126     }
127     if (dp) dtyp |= RDTdshort;
128     }
129 greg 2.4 void Init(COLORV *rp, int ystride, short *dp) {
130     pbase.f = rp; dbase.s = dp;
131     rowStride = ystride;
132     if (NCSAMP > 3) {
133     dtyp = RDTscolor; primp = NULL;
134     } else {
135     dtyp = RDTrgb; primp = stdprims;
136     }
137     if (dp) dtyp |= RDTdshort;
138     }
139 greg 2.1 /// Set color space after non-empty initialization
140     bool SetColorSpace(RenderDataType cs, RGBPRIMP pr=NULL);
141     /// Get color space
142     RenderDataType ColorSpace() const {
143     return RDTcolorT(dtyp);
144     }
145     /// Get color primaries (NULL if spectral)
146     RGBPRIMP Primaries() const {
147     return primp;
148     }
149     /// Number of represented color/spectral components
150     int NC() const {
151     switch (ColorSpace()) {
152     case RDTrgb: case RDTrgbe:
153     case RDTxyz: case RDTxyze:
154     return 3;
155     case RDTscolor: case RDTscolr:
156     return NCSAMP;
157     default:;
158     }
159     return 0;
160     }
161     /// Get depth type
162     RenderDataType DepthType() const {
163     return RDTdepthT(dtyp);
164     }
165     /// Get row stride
166     long GetRowStride() const {
167     return rowStride;
168     }
169     /// Assign a pixel value (& depth) from rendered ray value
170     bool SetPixel(int x, int y, const RAY *rp);
171     /// Assign pixel color (& depth) -- may re-represent either/both
172     bool SetPixel(int x, int y, const COLORV *pv, float z=0) {
173     if (NC() == 3) {
174     if (RDTcommonE(dtyp))
175     setcolr(CB3(x,y), pv[RED], pv[GRN], pv[BLU]);
176     else
177     copycolor(CF3(x,y), pv);
178     } else if (RDTcommonE(dtyp))
179     scolor_scolr(SCB(x,y), pv);
180     else
181     copyscolor(SCF(x,y), pv);
182     if (RDTdepthT(dtyp) == RDTdfloat)
183     dbase.f[rowStride*y + x] = z;
184     else if (RDTdepthT(dtyp) == RDTdshort)
185     dbase.s[rowStride*y + x] = depth2code(z, refDepth);
186     return true;
187     }
188     /// Retrieve pixel color (& depth) -- may convert either/both
189     bool GetPixel(int x, int y, COLORV *pv, float *zp=NULL) const {
190     if (NC() == 3) {
191     if (RDTcommonE(dtyp))
192 greg 2.2 colr_color(pv, CB3(x,y));
193 greg 2.1 else
194 greg 2.2 copycolor(pv, CF3(x,y));
195 greg 2.1 } else if (RDTcommonE(dtyp))
196 greg 2.2 scolr_scolor(pv, SCB(x,y));
197 greg 2.1 else
198 greg 2.2 copyscolor(pv, SCF(x,y));
199 greg 2.1 if (!zp) return true;
200     if (RDTdepthT(dtyp) == RDTdfloat)
201     *zp = dbase.f[rowStride*y + x];
202     else if (RDTdepthT(dtyp) == RDTdshort)
203     *zp = code2depth(dbase.s[rowStride*y + x], refDepth);
204     else
205     *zp = .0f;
206     return true;
207     }
208     /// Copy pixel from one location to another (no conversion)
209     bool CopyPixel(int dx, int dy, int sx, int sy) {
210     if ((dx==sx) & (dy==sy)) return true;
211     const int nc = NC();
212     if (nc == 3) {
213     if (RDTcommonE(dtyp))
214 greg 2.2 copycolr(CB3(dx,dy), CB3(sx,sy));
215 greg 2.1 else
216 greg 2.2 copycolor(CF3(dx,dy), CF3(sx,sy));
217 greg 2.1 } else if (RDTcommonE(dtyp))
218 greg 2.2 copyscolr(SCB(dx,dy), SCB(sx,sy));
219 greg 2.1 else
220 greg 2.2 copyscolor(SCF(dx,dy), SCF(sx,sy));
221 greg 2.1 switch (RDTdepthT(dtyp)) {
222     case RDTdfloat:
223     dbase.f[rowStride*dy + dx] =
224     dbase.f[rowStride*sy + sx];
225     break;
226     case RDTdshort:
227     dbase.s[rowStride*dy + dx] =
228     dbase.s[rowStride*sy + sx];
229     break;
230     default:;
231     }
232     return true;
233     }
234     };
235    
236     /// Call-back function for progress reporting
237     typedef void ProgReportCB(double pct);
238    
239     /// rpict-like simulation manager (at most one such object)
240     class RpictSimulManager : protected RtraceSimulManager {
241     static RayReportCall RtCall; // our callback for cooked rays
242     VIEW vw; // frame view
243     VIEW pvw; // previous view
244     int hvres[2]; // overall picture dimensions
245     int tgsize[2]; // tile grid size
246     int thvres[2]; // tile dimensions
247     VIEW tvw, ptvw; // this tile's view (& previous)
248     PixelAccess pacc; // pixel accessor
249     char dunit[32]; // depth with units (if any)
250     ABitMap2 doneMap; // which tile pixels are done
251     COLORV * barPix; // current render bar pixels
252     float * barDepth; // current render bar depths
253     bool SetTile(const int ti[2]);
254 greg 2.7 bool RenderRect(const int x0 = 0, const int y0 = 0);
255 greg 2.1 bool ComputePixel(int x, int y);
256 greg 2.7 bool BelowSampThresh(const int x, const int y,
257     const int noff[4][2]) const;
258 greg 2.2 void FillSquare(const int x, const int y, const int noff[4][2]);
259 greg 2.1 void NewBar(int ht = 0);
260 greg 2.3 bool LowerBar(int v, int ytop);
261 greg 2.1 bool RenderBelow(int ytop, const int vstep, FILE *pfp,
262     const int dt, FILE *dfp=NULL);
263     public:
264     ProgReportCB * prCB; // progress report call-back
265     RGBPRIMP prims; // output primaries (NULL if spectral)
266     int frameNo; // frame number (0 if not sequence)
267     RpictSimulManager(const char *octn = NULL) :
268     RtraceSimulManager(RtCall, this, octn) {
269     tvw.type = vw.type = 0;
270     hvres[0] = hvres[1] = 0;
271     thvres[0] = thvres[1] = 0;
272     pacc.refDepth = 1.; dunit[0] = '1'; dunit[1] = '\0';
273     barPix = NULL; barDepth = NULL;
274     prCB = NULL;
275     prims = NULL;
276     frameNo = 0;
277     }
278     ~RpictSimulManager() {
279 greg 2.5 delete [] barPix; delete [] barDepth;
280 greg 2.1 }
281     /// Load octree and prepare renderer
282     bool LoadOctree(const char *octn) {
283     return RtraceSimulManager::LoadOctree(octn);
284     }
285     /// Prepare header from previous input (or clear)
286     bool NewHeader(const char *inspec=NULL) {
287     return RtraceSimulManager::NewHeader(inspec);
288     }
289     /// Add a string to header (adds newline if none)
290     bool AddHeader(const char *str) {
291     return RtraceSimulManager::AddHeader(str);
292     }
293     /// Append program line to header
294     bool AddHeader(int ac, char *av[]) {
295     return RtraceSimulManager::AddHeader(ac, av);
296     }
297     /// Get header lines if any
298     const char * GetHeader() const {
299     return RtraceSimulManager::GetHeader();
300     }
301     /// Set number of computation threads (0 => #cores)
302     int SetThreadCount(int nt = 0) {
303     return RtraceSimulManager::SetThreadCount(nt);
304     }
305     /// Check thread count (1 means no multi-threading)
306     int NThreads() const {
307     return RtraceSimulManager::NThreads();
308     }
309     /// How many threads are currently unoccupied?
310     int ThreadsAvailable() const {
311     return RtraceSimulManager::ThreadsAvailable();
312     }
313     /// Are we ready?
314     bool Ready() const {
315     return RtraceSimulManager::Ready();
316     }
317     /// Assign reference depth string (e.g., "2.5/meter")
318     bool SetReferenceDepth(const char *dstr) {
319     double dref = atof(dstr);
320     if (dref <= .0) return false;
321     strlcpy(dunit, dstr, sizeof(dunit));
322     pacc.refDepth = dref;
323     return true;
324     }
325     bool SetReferenceDepth(double dref, const char *unit=NULL) {
326     if (dref <= .0) return false;
327     if (unit) sprintf(dunit, "%g/%s", dref, unit);
328     else sprintf(dunit, "%g", dref);
329     pacc.refDepth = dref;
330     return true;
331     }
332     /// Return reference depth
333     double GetReferenceDepth(char *du=NULL) const {
334     if (du) strcpy(du, dunit);
335     return pacc.refDepth;
336     }
337     /// Set up rendering frame (call after octree loaded)
338     /// Overall dimensions may be adjusted for view,
339     /// optional pixel aspect ratio and tile grid
340     /// Increments frameNo if >0
341     bool NewFrame(const VIEW &v, int xydim[2], double *ap=NULL,
342     const int *tgrid=NULL);
343 greg 2.4 /// Get current view if set
344     const VIEW * GetView() const {
345     if (!vw.type) return NULL;
346     return &vw;
347     }
348     /// Writeable previous view (for motion blur)
349     VIEW & PreView() {
350     return pvw;
351     }
352 greg 2.1 /// Get current picture width
353     int GetWidth() const {
354     return hvres[0];
355     }
356     /// Get current picture height
357     int GetHeight() const {
358     return hvres[1];
359     }
360     /// Tile width
361     int TWidth() const {
362     return thvres[0];
363     }
364     /// Tile height
365     int THeight() const {
366     return thvres[1];
367     }
368     /// Render the specified tile in frame
369     /// Tile pixels are contiguous unless ystride != 0
370     /// Tiles numbered from lower-left at (0,0)
371     /// Pixel type influenced by this->prims assignment
372     bool RenderTile(COLORV *rp, int ystride=0, float *zp=NULL,
373     const int *tile=NULL);
374     /// Same but store as common-exponent COLR or SCOLR
375     bool RenderTile(COLRV *bp, int ystride=0, float *zp=NULL,
376     const int *tile=NULL);
377     /// Same but also use 16-bit encoded depth buffer
378     bool RenderTile(COLRV *bp, int ystride, short *dp,
379     const int *tile=NULL);
380 greg 2.4 /// Back to float color with 16-bit depth
381     bool RenderTile(COLORV *rp, int ystride, short *dp,
382     const int *tile=NULL);
383 greg 2.1 /// Render and write a frame to the named file
384     /// Include any header lines set prior to call
385 greg 2.5 /// Picture file must not exist
386 greg 2.2 /// Write pixels to stdout if !pfname
387     /// Write depth to a command if dfname[0]=='!'
388 greg 2.1 RenderDataType RenderFrame(const char *pfname,
389     RenderDataType dt=RDTrgbe,
390     const char *dfname=NULL);
391     /// Resume partially finished rendering
392     /// Picture file must exist with valid header
393     RenderDataType ResumeFrame(const char *pfname,
394     const char *dfname=NULL);
395 greg 2.5 /// Prepare new picture (and depth) output
396 greg 2.6 /// Called by RenderFrame()
397 greg 2.5 RenderDataType NewOutput(FILE *pdfp[2], const char *pfname,
398     RenderDataType dt=RDTrgbe,
399     const char *dfname=NULL);
400     /// Reopen existing picture (and depth) file
401 greg 2.6 /// Called by ResumeFrame()
402 greg 2.5 /// File pointers @ end of header (before res.)
403     RenderDataType ReopenOutput(FILE *pdfp[2], const char *pfname,
404     const char *dfname=NULL);
405 greg 2.1 /// Close octree, free data, return status
406     int Cleanup(bool everything = false) {
407     NewBar();
408     tvw.type = vw.type = 0;
409     hvres[0] = hvres[1] = 0;
410     thvres[0] = thvres[1] = 0;
411     prims = NULL;
412     frameNo = 0;
413     return RtraceSimulManager::Cleanup(everything);
414     }
415     };
416    
417     #endif /* RpictSimulManager_h */