diff options
-rw-r--r-- | camera.c | 17 | ||||
-rw-r--r-- | doc/libgraphics.ms | 175 | ||||
-rw-r--r-- | doc/libgraphics.pdf | bin | 15087 -> 19045 bytes | |||
-rw-r--r-- | doc/libgraphics.ps | 597 | ||||
-rw-r--r-- | fb.c | 43 | ||||
-rw-r--r-- | graphics.h | 57 | ||||
-rw-r--r-- | internal.h | 25 | ||||
-rw-r--r-- | render.c | 483 | ||||
-rw-r--r-- | scene.c | 42 | ||||
-rw-r--r-- | util.c | 2 | ||||
-rw-r--r-- | viewport.c | 9 |
11 files changed, 1183 insertions, 267 deletions
@@ -21,6 +21,16 @@ updatestats(Camera *c, uvlong v) } static void +updatetimes(Camera *c, Renderjob *j) +{ + c->times.R[c->times.cur] = j->times.R; + c->times.E[c->times.cur] = j->times.E; + c->times.Tn[c->times.cur] = j->times.Tn; + c->times.Rn[c->times.cur] = j->times.Rn; + c->times.cur = ++c->times.cur % nelem(c->times.R); +} + +static void verifycfg(Camera *c) { assert(c->vp != nil); @@ -86,7 +96,7 @@ shootcamera(Camera *c, Shadertab *s) job = emalloc(sizeof *job); memset(job, 0, sizeof *job); - job->fb = c->vp->fbctl->fb[c->vp->fbctl->idx^1]; /* address the back buffer */ + job->fb = c->vp->fbctl->getbb(c->vp->fbctl); job->scene = c->s; job->shaders = s; job->donec = chancreate(sizeof(void*), 0); @@ -98,8 +108,9 @@ shootcamera(Camera *c, Shadertab *s) t1 = nanosec(); c->vp->fbctl->swap(c->vp->fbctl); + updatestats(c, t1-t0); + updatetimes(c, job); + chanfree(job->donec); free(job); - - updatestats(c, t1-t0); } diff --git a/doc/libgraphics.ms b/doc/libgraphics.ms index 87a23a7..31a44af 100644 --- a/doc/libgraphics.ms +++ b/doc/libgraphics.ms @@ -2,33 +2,152 @@ libgraphics .AU Rodrigo G. López -.sp rgl@antares-labs.eu -.AI -Antares Telecom Laboratories -Albatera, Alicante -.FS -ACHTUNG! this is a -.B "WORK IN PROGRESS" -.FE -.NH 1 -Data Structures -.NH 2 -Camera -.P1 -struct Camera { - RFrame3; /* VCS */ - Image *viewport; - double fov; /* vertical FOV */ - struct { - double n, f; /* near and far clipping planes */ - } clip; - Projection ptype; - Matrix3 proj; /* VCS to viewport xform */ -}; -.P2 +.AB +To be determined. +.AE +.SH +Rendering graph .PP -A camera is an image capturing entity, analog to the real world device -we all know, that allows us to see the virtual 3-D world by projecting -it into a viewport we can attach to a screen or window for real-time -visualization or write out into a file. +.PS +.ps 7 +circlerad = 0.3 +moveht = 0.1 +box "Renderjob" +arrow +R: circle "renderer" +arrow +E: circle "entityproc" +move +Tiler: [ + down + T0: circle "tiler 0" + move + T1: circle "tiler 1" + move + Td: circle "…" + move + Tn: circle "tiler n" +] +move +Raster: [ + down + R0: circle "rasterizer 0" + move + R1: circle "rasterizer 1" + move + Rd: circle "…" + move + Rn: circle "rasterizer n" +] +arrow from E to Tiler.T0 chop +arrow from E to Tiler.T1 chop +arrow from E to Tiler.Td chop +arrow from E to Tiler.Tn chop +arrow from Tiler.T0 to Raster.R0 chop +arrow from Tiler.T0 to Raster.R1 chop +arrow from Tiler.T0 to Raster.Rd chop +arrow from Tiler.T0 to Raster.Rn chop +arrow from Tiler.T1 to Raster.R0 chop +arrow from Tiler.T1 to Raster.R1 chop +arrow from Tiler.T1 to Raster.Rd chop +arrow from Tiler.T1 to Raster.Rn chop +.ps 10 +.PE +.B "Figure 1" : +For a +.B 2(n+1) +processor machine. +.SH +The scene +.PP +.PS +.ps 7 +boxwid = 0.5 +boxht = 0.2 +linewid = 0.1 +lineht = 0.2 +box "Scene" +down; line from last box.s; right; line +box "Entity" +down; line from last box.s; right; line +box "Model" +down; line from last box.s; right; line +box "Mesh" +down; line from last box.s; right; line +box "Primitive" +down +line from 2nd last line.s; line; right; line +box "Material" +.ps 10 +.PE +.SH +Tile-based rendering +.PP +.PS +.ps 7 +Tiles: [ + boxht = 0.2 + boxwid = 1.25 + down + T0: box dashed "tile 0" + T1: box dashed "tile 1" + Td: box dashed "…" + Tn: box dashed "tile n" +] +box ht last [].ht+0.1 wid last [].wid+0.1 at last [] +"Screen" rjust with .se at last [].nw - (0.1,0) +Raster: [ + moveht = 0.1 + down + R0: circle "rasterizer 0" + move + R1: circle "rasterizer 1" + move + Rd: circle "…" + move + Rn: circle "rasterizer n" +] with .w at Tiles.e + (0.5,0) +line from Tiles.T0.e to Raster.R0.w +line from Tiles.T1.e to Raster.R1.w +line from Tiles.Td.e to Raster.Rd.w +line from Tiles.Tn.e to Raster.Rn.w +.ps 10 +.PE +.B "Figure 2" : +Per tile rasterizers. +.PS +.ps 7 +Tiles: [ + boxht = 0.2 + boxwid = 1.25 + down + T0: box dashed "0" + T1: box dashed "1" + Td: box dashed "…" + Tn: box dashed "n" +] +line from last [].w + (0.1,-0.05) to last [].n - (-0.1,0.25) +line to last [].se - (0.3,-0.1) +line to 1st line +box ht last [].ht+0.1 wid last [].wid+0.1 at last [] +"Screen" rjust with .se at last [].nw - (0.1,0) +Raster: [ + moveht = 0.1 + down + R0: circle "rasterizer 0" + move + R1: circle "rasterizer 1" + move + Rd: circle "…" + move + Rn: circle "rasterizer n" +] with .w at Tiles.e + (0.5,0) +arrow dashed from Tiles.T0.e to Raster.R0.w +arrow from Tiles.T1.e to Raster.R1.w +arrow from Tiles.Td.e to Raster.Rd.w +arrow from Tiles.Tn.e to Raster.Rn.w +.ps 10 +.PE +.B "Figure 3" : +Raster task scheduling. diff --git a/doc/libgraphics.pdf b/doc/libgraphics.pdf Binary files differindex 0291710..775d825 100644 --- a/doc/libgraphics.pdf +++ b/doc/libgraphics.pdf diff --git a/doc/libgraphics.ps b/doc/libgraphics.ps index 1a566f7..081c5d0 100644 --- a/doc/libgraphics.ps +++ b/doc/libgraphics.ps @@ -191,7 +191,7 @@ /braceleftbt [203 490] /bracketrightex [220 -125 500 0] /radical [0 0 550 0] - /radicalex [-50 0 500 0] + /radicalex [-50 0 500 1] /parenleftex [-20 -170 0 0] /integral [100 -50 500 0] /infinity [10 -75 730 0] @@ -202,6 +202,82 @@ /endash [7 90 650 0] ] def % +% Version 3.3.2 drawing procedures for dpost. Automatically pulled in when +% needed. +% + +/inpath false def +/savematrix matrix def + +/Dl { + inpath + {neg lineto pop pop} + {newpath neg moveto neg lineto stroke} + ifelse +} bind def + +/De { + /y1 exch 2 div def + /x1 exch 2 div def + /savematrix savematrix currentmatrix def + neg exch x1 add exch translate + x1 y1 scale + 0 0 1 0 360 + inpath + {1 0 moveto arc savematrix setmatrix} + {newpath arc savematrix setmatrix stroke} + ifelse +} bind def + +/Da { + /dy2 exch def + /dx2 exch def + /dy1 exch def + /dx1 exch def + dy1 add neg exch dx1 add exch + dx1 dx1 mul dy1 dy1 mul add sqrt + dy1 dx1 neg atan + dy2 neg dx2 atan + inpath + {arc} + {newpath arc stroke} + ifelse +} bind def + +/DA { + /dy2 exch def + /dx2 exch def + /dy1 exch def + /dx1 exch def + dy1 add neg exch dx1 add exch + dx1 dx1 mul dy1 dy1 mul add sqrt + dy1 dx1 neg atan + dy2 neg dx2 atan + inpath + {arcn} + {newpath arcn stroke} + ifelse +} bind def + +/Ds { + /y2 exch def + /x2 exch def + /y1 exch def + /x1 exch def + /y0 exch def + /x0 exch def + x0 5 x1 mul add 6 div + y0 5 y1 mul add -6 div + x2 5 x1 mul add 6 div + y2 5 y1 mul add -6 div + x1 x2 add 2 div + y1 y2 add -2 div + inpath + {curveto} + {newpath x0 x1 add 2 div y0 y1 add -2 div moveto curveto stroke} + ifelse +} bind def +% % Tries to round clipping path dimensions, as stored in array pagebbox, so they % match one of the known sizes in the papersizes array. Lower left coordinates % are always set to 0. @@ -543,41 +619,504 @@ setup mark 1 pagesetup 12 /LucidaSans-Demi f -(libgraphics) 2533 1220 w +(libgraphics) 2533 1230 w 10 /LucidaSans-Italic f -(Rodrigo G. L\363pez) 2469 1480 w -(rgl@antares-labs.eu) 2377 1760 w +(Rodrigo G. L\363pez) 2469 1470 w +(rgl@antares-labs.eu) 2377 1590 w +(ABSTRACT) 2626 2030 w +10 /LucidaSansUnicode00 f +(To be determined.) 1330 2290 w +10 /LucidaSans-Demi f +(Rendering graph) 720 2650 w +1026 4000 1026 3640 Dl +1026 3640 1566 3640 Dl +1566 3640 1566 4000 Dl +1566 4000 1026 4000 Dl +7 /LucidaSansUnicode00 f +(Renderjob) 1123 3834 w +1566 3820 1926 3820 Dl +1854 3838 1926 3820 Dl +1854 3802 1926 3820 Dl +1926 3820 432 432 De +(renderer) 1997 3834 w +2358 3820 2718 3820 Dl +2646 3838 2718 3820 Dl +2646 3802 2718 3820 Dl +2718 3820 432 432 De +(entityproc) 2763 3834 w +3510 3064 432 432 De +(tiler) 3626 3078 w +(0) 3782 3078 w +3510 3568 432 432 De +(tiler) 3626 3582 w +(1) 3782 3582 w +3510 4072 432 432 De +7 /LucidaSansUnicode20 f +(&) 3691 4086 w +3510 4576 432 432 De +7 /LucidaSansUnicode00 f +(tiler) 3627 4590 w +(n) 3783 4590 w +4302 3064 432 432 De +(rasterizer) 4322 3078 w +(0) 4670 3078 w +4302 3568 432 432 De +(rasterizer) 4322 3582 w +(1) 4670 3582 w +4302 4072 432 432 De +7 /LucidaSansUnicode20 f +(&) 4483 4086 w +4302 4576 432 432 De +7 /LucidaSansUnicode00 f +(rasterizer) 4323 4590 w +(n) 4671 4590 w +3090 3670 3569 3213 Dl +3530 3275 3569 3213 Dl +3504 3249 3568 3213 Dl +3139 3754 3519 3634 Dl +3456 3672 3519 3634 Dl +3445 3637 3519 3633 Dl +3139 3885 3519 4005 Dl +3445 4002 3519 4006 Dl +3456 3967 3519 4005 Dl +3090 3969 3569 4426 Dl +3504 4390 3568 4426 Dl +3530 4364 3569 4426 Dl +3942 3064 4302 3064 Dl +4230 3082 4302 3064 Dl +4230 3046 4302 3064 Dl +3908 3179 4335 3451 Dl +4265 3428 4335 3451 Dl +4284 3398 4335 3452 Dl +3859 3233 4383 3901 Dl +4325 3856 4383 3901 Dl +4354 3834 4384 3901 Dl +3826 3255 4417 4384 Dl +4368 4329 4417 4384 Dl +4400 4312 4417 4384 Dl +3908 3452 4335 3180 Dl +4284 3233 4335 3179 Dl +4265 3203 4335 3180 Dl +3942 3568 4302 3568 Dl +4230 3586 4302 3568 Dl +4230 3550 4302 3568 Dl +3908 3683 4335 3955 Dl +4265 3932 4335 3955 Dl +4284 3902 4335 3956 Dl +3859 3737 4383 4405 Dl +4325 4360 4383 4405 Dl +4354 4338 4384 4405 Dl +10 /LucidaSans-Demi f +(Figure 1) 720 4990 w 10 /LucidaSansUnicode00 f -(Antares Telecom Laboratories) 2156 1960 w -(Albatera, Alicante) 2451 2100 w +(: For a) 1142 4990 w 10 /LucidaSans-Demi f -(1.) 720 2700 w -(Data Structures) 873 2700 w -(1.1.) 720 2940 w -(Camera) 962 2940 w -9 /LucidaTypewriter f -(struct) 920 3110 w -(Camera) 1375 3110 w -({) 1830 3110 w -(};) 920 3330 w +(2\(n+1\)) 1481 4990 w 10 /LucidaSansUnicode00 f -(A camera) 970 3546 w -8 /S1 f -(__________________) 720 6980 w -8 /LucidaSansUnicode00 f -(ACHTUNG!) 720 7080 w -(this) 1163 7080 w -(is) 1333 7080 w -(a) 1423 7080 w -8 /LucidaSans-Demi f -(WORK) 1493 7080 w -(IN) 1769 7080 w -(PROGRESS) 1883 7080 w +(processor machine.) 1843 4990 w +10 /LucidaSans-Demi f +(The scene) 720 5230 w +2196 5572 2196 5428 Dl +2196 5428 2556 5428 Dl +2556 5428 2556 5572 Dl +2556 5572 2196 5572 Dl +7 /LucidaSansUnicode00 f +(Scene) 2279 5514 w +2376 5572 2376 5716 Dl +2376 5716 2448 5716 Dl +2448 5788 2448 5644 Dl +2448 5644 2808 5644 Dl +2808 5644 2808 5788 Dl +2808 5788 2448 5788 Dl +(Entity) 2534 5730 w +2628 5788 2628 5932 Dl +2628 5932 2700 5932 Dl +2700 6004 2700 5860 Dl +2700 5860 3060 5860 Dl +3060 5860 3060 6004 Dl +3060 6004 2700 6004 Dl +(Model) 2777 5946 w +2880 6004 2880 6148 Dl +2880 6148 2952 6148 Dl +2952 6220 2952 6076 Dl +2952 6076 3312 6076 Dl +3312 6076 3312 6220 Dl +3312 6220 2952 6220 Dl +(Mesh) 3043 6162 w +3132 6220 3132 6364 Dl +3132 6364 3204 6364 Dl +3204 6436 3204 6292 Dl +3204 6292 3564 6292 Dl +3564 6292 3564 6436 Dl +3564 6436 3204 6436 Dl +(Primitive) 3237 6378 w +3132 6364 3132 6508 Dl +3132 6508 3132 6652 Dl +3132 6652 3204 6652 Dl +3204 6724 3204 6580 Dl +3204 6580 3564 6580 Dl +3564 6580 3564 6724 Dl +3564 6724 3204 6724 Dl +(Material) 3248 6666 w cleartomark showpage saveobj restore %%EndPage: 1 1 +%%Page: 2 2 +/saveobj save def +mark +2 pagesetup +10 /LucidaSansUnicode00 f +(\255 2 \255) 2783 480 w +10 /LucidaSans-Demi f +(Tile-based rendering) 720 840 w +2070 1866 2106 1866 Dl +2142 1866 2178 1866 Dl +2214 1866 2250 1866 Dl +2286 1866 2322 1866 Dl +2358 1866 2394 1866 Dl +2430 1866 2466 1866 Dl +2502 1866 2538 1866 Dl +2574 1866 2610 1866 Dl +2646 1866 2682 1866 Dl +2718 1866 2754 1866 Dl +2790 1866 2826 1866 Dl +2862 1866 2898 1866 Dl +2934 1866 2970 1866 Dl +2970 1866 2970 1830 Dl +2970 1812 2970 1776 Dl +2970 1758 2970 1722 Dl +2970 1722 2934 1722 Dl +2898 1722 2862 1722 Dl +2826 1722 2790 1722 Dl +2754 1722 2718 1722 Dl +2682 1722 2646 1722 Dl +2610 1722 2574 1722 Dl +2538 1722 2502 1722 Dl +2466 1722 2430 1722 Dl +2394 1722 2358 1722 Dl +2322 1722 2286 1722 Dl +2250 1722 2214 1722 Dl +2178 1722 2142 1722 Dl +2106 1722 2070 1722 Dl +2070 1722 2070 1758 Dl +2070 1776 2070 1812 Dl +2070 1830 2070 1866 Dl +7 /LucidaSansUnicode00 f +(tile 0) 2435 1808 w +2070 2010 2106 2010 Dl +2142 2010 2178 2010 Dl +2214 2010 2250 2010 Dl +2286 2010 2322 2010 Dl +2358 2010 2394 2010 Dl +2430 2010 2466 2010 Dl +2502 2010 2538 2010 Dl +2574 2010 2610 2010 Dl +2646 2010 2682 2010 Dl +2718 2010 2754 2010 Dl +2790 2010 2826 2010 Dl +2862 2010 2898 2010 Dl +2934 2010 2970 2010 Dl +2970 2010 2970 1974 Dl +2970 1956 2970 1920 Dl +2970 1902 2970 1866 Dl +2970 1866 2934 1866 Dl +2898 1866 2862 1866 Dl +2826 1866 2790 1866 Dl +2754 1866 2718 1866 Dl +2682 1866 2646 1866 Dl +2610 1866 2574 1866 Dl +2538 1866 2502 1866 Dl +2466 1866 2430 1866 Dl +2394 1866 2358 1866 Dl +2322 1866 2286 1866 Dl +2250 1866 2214 1866 Dl +2178 1866 2142 1866 Dl +2106 1866 2070 1866 Dl +2070 1866 2070 1902 Dl +2070 1920 2070 1956 Dl +2070 1974 2070 2010 Dl +(tile 1) 2435 1952 w +2070 2154 2106 2154 Dl +2142 2154 2178 2154 Dl +2214 2154 2250 2154 Dl +2286 2154 2322 2154 Dl +2358 2154 2394 2154 Dl +2430 2154 2466 2154 Dl +2502 2154 2538 2154 Dl +2574 2154 2610 2154 Dl +2646 2154 2682 2154 Dl +2718 2154 2754 2154 Dl +2790 2154 2826 2154 Dl +2862 2154 2898 2154 Dl +2934 2154 2970 2154 Dl +2970 2154 2970 2118 Dl +2970 2100 2970 2064 Dl +2970 2046 2970 2010 Dl +2970 2010 2934 2010 Dl +2898 2010 2862 2010 Dl +2826 2010 2790 2010 Dl +2754 2010 2718 2010 Dl +2682 2010 2646 2010 Dl +2610 2010 2574 2010 Dl +2538 2010 2502 2010 Dl +2466 2010 2430 2010 Dl +2394 2010 2358 2010 Dl +2322 2010 2286 2010 Dl +2250 2010 2214 2010 Dl +2178 2010 2142 2010 Dl +2106 2010 2070 2010 Dl +2070 2010 2070 2046 Dl +2070 2064 2070 2100 Dl +2070 2118 2070 2154 Dl +7 /LucidaSansUnicode20 f +(&) 2485 2096 w +2070 2298 2106 2298 Dl +2142 2298 2178 2298 Dl +2214 2298 2250 2298 Dl +2286 2298 2322 2298 Dl +2358 2298 2394 2298 Dl +2430 2298 2466 2298 Dl +2502 2298 2538 2298 Dl +2574 2298 2610 2298 Dl +2646 2298 2682 2298 Dl +2718 2298 2754 2298 Dl +2790 2298 2826 2298 Dl +2862 2298 2898 2298 Dl +2934 2298 2970 2298 Dl +2970 2298 2970 2262 Dl +2970 2244 2970 2208 Dl +2970 2190 2970 2154 Dl +2970 2154 2934 2154 Dl +2898 2154 2862 2154 Dl +2826 2154 2790 2154 Dl +2754 2154 2718 2154 Dl +2682 2154 2646 2154 Dl +2610 2154 2574 2154 Dl +2538 2154 2502 2154 Dl +2466 2154 2430 2154 Dl +2394 2154 2358 2154 Dl +2322 2154 2286 2154 Dl +2250 2154 2214 2154 Dl +2178 2154 2142 2154 Dl +2106 2154 2070 2154 Dl +2070 2154 2070 2190 Dl +2070 2208 2070 2244 Dl +2070 2262 2070 2298 Dl +7 /LucidaSansUnicode00 f +(tile n) 2435 2240 w +2034 2334 2034 1686 Dl +2034 1686 3006 1686 Dl +3006 1686 3006 2334 Dl +3006 2334 2034 2334 Dl +(Screen) 1774 1736 w +3330 1254 432 432 De +(rasterizer) 3350 1268 w +(0) 3698 1268 w +3330 1758 432 432 De +(rasterizer) 3350 1772 w +(1) 3698 1772 w +3330 2262 432 432 De +7 /LucidaSansUnicode20 f +(&) 3511 2276 w +3330 2766 432 432 De +7 /LucidaSansUnicode00 f +(rasterizer) 3351 2780 w +(n) 3699 2780 w +2970 1794 3330 1254 Dl +2970 1938 3330 1758 Dl +2970 2082 3330 2262 Dl +2970 2226 3330 2766 Dl +10 /LucidaSans-Demi f +(Figure 2) 720 3180 w +10 /LucidaSansUnicode00 f +(: Per tile rasterizers.) 1142 3180 w +2070 4170 2106 4170 Dl +2142 4170 2178 4170 Dl +2214 4170 2250 4170 Dl +2286 4170 2322 4170 Dl +2358 4170 2394 4170 Dl +2430 4170 2466 4170 Dl +2502 4170 2538 4170 Dl +2574 4170 2610 4170 Dl +2646 4170 2682 4170 Dl +2718 4170 2754 4170 Dl +2790 4170 2826 4170 Dl +2862 4170 2898 4170 Dl +2934 4170 2970 4170 Dl +2970 4170 2970 4134 Dl +2970 4116 2970 4080 Dl +2970 4062 2970 4026 Dl +2970 4026 2934 4026 Dl +2898 4026 2862 4026 Dl +2826 4026 2790 4026 Dl +2754 4026 2718 4026 Dl +2682 4026 2646 4026 Dl +2610 4026 2574 4026 Dl +2538 4026 2502 4026 Dl +2466 4026 2430 4026 Dl +2394 4026 2358 4026 Dl +2322 4026 2286 4026 Dl +2250 4026 2214 4026 Dl +2178 4026 2142 4026 Dl +2106 4026 2070 4026 Dl +2070 4026 2070 4062 Dl +2070 4080 2070 4116 Dl +2070 4134 2070 4170 Dl +7 /LucidaSansUnicode00 f +(0) 2498 4112 w +2070 4314 2106 4314 Dl +2142 4314 2178 4314 Dl +2214 4314 2250 4314 Dl +2286 4314 2322 4314 Dl +2358 4314 2394 4314 Dl +2430 4314 2466 4314 Dl +2502 4314 2538 4314 Dl +2574 4314 2610 4314 Dl +2646 4314 2682 4314 Dl +2718 4314 2754 4314 Dl +2790 4314 2826 4314 Dl +2862 4314 2898 4314 Dl +2934 4314 2970 4314 Dl +2970 4314 2970 4278 Dl +2970 4260 2970 4224 Dl +2970 4206 2970 4170 Dl +2970 4170 2934 4170 Dl +2898 4170 2862 4170 Dl +2826 4170 2790 4170 Dl +2754 4170 2718 4170 Dl +2682 4170 2646 4170 Dl +2610 4170 2574 4170 Dl +2538 4170 2502 4170 Dl +2466 4170 2430 4170 Dl +2394 4170 2358 4170 Dl +2322 4170 2286 4170 Dl +2250 4170 2214 4170 Dl +2178 4170 2142 4170 Dl +2106 4170 2070 4170 Dl +2070 4170 2070 4206 Dl +2070 4224 2070 4260 Dl +2070 4278 2070 4314 Dl +(1) 2498 4256 w +2070 4458 2106 4458 Dl +2142 4458 2178 4458 Dl +2214 4458 2250 4458 Dl +2286 4458 2322 4458 Dl +2358 4458 2394 4458 Dl +2430 4458 2466 4458 Dl +2502 4458 2538 4458 Dl +2574 4458 2610 4458 Dl +2646 4458 2682 4458 Dl +2718 4458 2754 4458 Dl +2790 4458 2826 4458 Dl +2862 4458 2898 4458 Dl +2934 4458 2970 4458 Dl +2970 4458 2970 4422 Dl +2970 4404 2970 4368 Dl +2970 4350 2970 4314 Dl +2970 4314 2934 4314 Dl +2898 4314 2862 4314 Dl +2826 4314 2790 4314 Dl +2754 4314 2718 4314 Dl +2682 4314 2646 4314 Dl +2610 4314 2574 4314 Dl +2538 4314 2502 4314 Dl +2466 4314 2430 4314 Dl +2394 4314 2358 4314 Dl +2322 4314 2286 4314 Dl +2250 4314 2214 4314 Dl +2178 4314 2142 4314 Dl +2106 4314 2070 4314 Dl +2070 4314 2070 4350 Dl +2070 4368 2070 4404 Dl +2070 4422 2070 4458 Dl +7 /LucidaSansUnicode20 f +(&) 2485 4400 w +2070 4602 2106 4602 Dl +2142 4602 2178 4602 Dl +2214 4602 2250 4602 Dl +2286 4602 2322 4602 Dl +2358 4602 2394 4602 Dl +2430 4602 2466 4602 Dl +2502 4602 2538 4602 Dl +2574 4602 2610 4602 Dl +2646 4602 2682 4602 Dl +2718 4602 2754 4602 Dl +2790 4602 2826 4602 Dl +2862 4602 2898 4602 Dl +2934 4602 2970 4602 Dl +2970 4602 2970 4566 Dl +2970 4548 2970 4512 Dl +2970 4494 2970 4458 Dl +2970 4458 2934 4458 Dl +2898 4458 2862 4458 Dl +2826 4458 2790 4458 Dl +2754 4458 2718 4458 Dl +2682 4458 2646 4458 Dl +2610 4458 2574 4458 Dl +2538 4458 2502 4458 Dl +2466 4458 2430 4458 Dl +2394 4458 2358 4458 Dl +2322 4458 2286 4458 Dl +2250 4458 2214 4458 Dl +2178 4458 2142 4458 Dl +2106 4458 2070 4458 Dl +2070 4458 2070 4494 Dl +2070 4512 2070 4548 Dl +2070 4566 2070 4602 Dl +7 /LucidaSansUnicode00 f +(n) 2499 4544 w +2142 4350 2592 4206 Dl +2592 4206 2754 4530 Dl +2754 4530 2142 4350 Dl +2034 4638 2034 3990 Dl +2034 3990 3006 3990 Dl +3006 3990 3006 4638 Dl +3006 4638 2034 4638 Dl +(Screen) 1774 4040 w +3330 3558 432 432 De +(rasterizer) 3350 3572 w +(0) 3698 3572 w +3330 4062 432 432 De +(rasterizer) 3350 4076 w +(1) 3698 4076 w +3330 4566 432 432 De +7 /LucidaSansUnicode20 f +(&) 3511 4580 w +3330 5070 432 432 De +7 /LucidaSansUnicode00 f +(rasterizer) 3351 5084 w +(n) 3699 5084 w +2970 4098 2990 4068 Dl +3007 4041 3027 4011 Dl +3045 3984 3065 3954 Dl +3083 3928 3103 3898 Dl +3121 3871 3141 3841 Dl +3158 3814 3178 3784 Dl +3196 3758 3216 3728 Dl +3234 3701 3254 3671 Dl +3272 3644 3292 3614 Dl +3309 3588 3329 3558 Dl +3304 3627 3329 3558 Dl +3275 3607 3329 3558 Dl +2970 4242 3330 4062 Dl +3273 4110 3329 4062 Dl +3257 4077 3329 4062 Dl +2970 4386 3330 4566 Dl +3257 4550 3329 4565 Dl +3273 4517 3329 4565 Dl +2970 4530 3330 5070 Dl +3275 5020 3329 5069 Dl +3304 5000 3329 5069 Dl +10 /LucidaSans-Demi f +(Figure 3) 720 5484 w +10 /LucidaSansUnicode00 f +(: Raster task scheduling.) 1142 5484 w +cleartomark +showpage +saveobj restore +%%EndPage: 2 2 %%Trailer done -%%DocumentFonts: S1 LucidaSansUnicode00 LucidaSans-Demi LucidaSans-Italic LucidaTypewriter -%%Pages: 1 +%%DocumentFonts: LucidaSansUnicode20 LucidaSansUnicode00 LucidaSans-Demi LucidaSans-Italic +%%Pages: 2 @@ -13,26 +13,29 @@ framebufctl_draw(Framebufctl *ctl, Image *dst) { Framebuf *fb; - fb = ctl->fb[ctl->idx]; - lock(&ctl->swplk); + lock(ctl); + fb = ctl->getfb(ctl); loadimage(dst, rectaddpt(fb->r, dst->r.min), byteaddr(fb->cb, fb->r.min), bytesperline(fb->r, fb->cb->depth)*Dy(fb->r)); - unlock(&ctl->swplk); + unlock(ctl); } static void framebufctl_memdraw(Framebufctl *ctl, Memimage *dst) { - lock(&ctl->swplk); - memimagedraw(dst, dst->r, ctl->fb[ctl->idx]->cb, ZP, nil, ZP, SoverD); - unlock(&ctl->swplk); + Framebuf *fb; + + lock(ctl); + fb = ctl->getfb(ctl); + memimagedraw(dst, dst->r, fb->cb, ZP, nil, ZP, SoverD); + unlock(ctl); } static void framebufctl_swap(Framebufctl *ctl) { - lock(&ctl->swplk); + lock(ctl); ctl->idx ^= 1; - unlock(&ctl->swplk); + unlock(ctl); } static void @@ -41,11 +44,23 @@ framebufctl_reset(Framebufctl *ctl) Framebuf *fb; /* address the back buffer—resetting the front buffer is VERBOTEN */ - fb = ctl->fb[ctl->idx^1]; - memsetd(fb->zbuf, Inf(-1), Dx(fb->r)*Dy(fb->r)); + fb = ctl->getbb(ctl); + memsetd(fb->zb, Inf(-1), Dx(fb->r)*Dy(fb->r)); memfillcolor(fb->cb, DTransparent); } +static Framebuf * +framebufctl_getfb(Framebufctl *ctl) +{ + return ctl->fb[ctl->idx]; /* front buffer */ +} + +static Framebuf * +framebufctl_getbb(Framebufctl *ctl) +{ + return ctl->fb[ctl->idx^1]; /* back buffer */ +} + Framebuf * mkfb(Rectangle r) { @@ -54,8 +69,8 @@ mkfb(Rectangle r) fb = emalloc(sizeof *fb); memset(fb, 0, sizeof *fb); fb->cb = eallocmemimage(r, RGBA32); - fb->zbuf = emalloc(Dx(r)*Dy(r)*sizeof(*fb->zbuf)); - memsetd(fb->zbuf, Inf(-1), Dx(r)*Dy(r)); + fb->zb = emalloc(Dx(r)*Dy(r)*sizeof(*fb->zb)); + memsetd(fb->zb, Inf(-1), Dx(r)*Dy(r)); fb->r = r; return fb; } @@ -63,7 +78,7 @@ mkfb(Rectangle r) void rmfb(Framebuf *fb) { - free(fb->zbuf); + free(fb->zb); freememimage(fb->cb); free(fb); } @@ -81,6 +96,8 @@ mkfbctl(Rectangle r) fc->memdraw = framebufctl_memdraw; fc->swap = framebufctl_swap; fc->reset = framebufctl_reset; + fc->getfb = framebufctl_getfb; + fc->getbb = framebufctl_getbb; return fc; } @@ -2,10 +2,16 @@ typedef enum { ORTHOGRAPHIC, - PERSPECTIVE + PERSPECTIVE, } Projection; enum { + PPoint, + PLine, + PTriangle, +}; + +enum { LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT, @@ -21,6 +27,7 @@ typedef struct Vertexattr Vertexattr; typedef struct Vertex Vertex; typedef struct LightSource LightSource; typedef struct Material Material; +typedef struct Primitive Primitive; typedef struct Model Model; typedef struct Entity Entity; typedef struct Scene Scene; @@ -29,6 +36,7 @@ typedef struct FSparams FSparams; typedef struct SUparams SUparams; typedef struct Shadertab Shadertab; typedef struct Renderer Renderer; +typedef struct Rendertime Rendertime; typedef struct Renderjob Renderjob; typedef struct Framebuf Framebuf; typedef struct Framebufctl Framebufctl; @@ -79,13 +87,12 @@ struct Vertex Color c; /* shading color */ Point2 uv; /* texture coordinate */ OBJMaterial *mtl; + /* TODO it'd be neat to use a dynamic hash table instead */ Vertexattr *attrs; /* attributes (aka varyings) */ ulong nattrs; }; -typedef Vertex Triangle[3]; - struct LightSource { Point3 p; @@ -101,16 +108,22 @@ struct Material double shininess; }; +struct Primitive +{ + int type; + Vertex v[3]; +}; + struct Model { - OBJ *obj; + Primitive *mesh; Memimage *tex; /* texture map */ Memimage *nor; /* normals map */ Material *materials; ulong nmaterials; - /* cache of renderable elems */ - OBJElem **elems; + OBJ *obj; + OBJElem **elems; /* cache of renderable elems */ ulong nelems; }; @@ -118,6 +131,7 @@ struct Entity { RFrame3; Model *mdl; + Entity *prev, *next; }; @@ -128,6 +142,7 @@ struct Scene ulong nents; void (*addent)(Scene*, Entity*); + void (*delent)(Scene*, Entity*); }; /* shader params */ @@ -149,12 +164,10 @@ struct FSparams struct SUparams { Framebuf *fb; - int id; Memimage *frag; - Channel *donec; Renderjob *job; - Entity *entity; + OBJElem **eb, **ee; uvlong uni_time; @@ -174,16 +187,22 @@ struct Renderer Channel *c; }; +struct Rendertime +{ + uvlong t0, t1; +}; + struct Renderjob { + Ref; Framebuf *fb; Scene *scene; Shadertab *shaders; Channel *donec; - ulong nrem; /* remaining entities to process */ - ulong lastid; - uvlong time0; + struct { + Rendertime R, E, Tn, Rn; /* renderer, entityproc, tilers, rasterizers */ + } times; Renderjob *next; }; @@ -191,21 +210,22 @@ struct Renderjob struct Framebuf { Memimage *cb; /* color buffer */ - double *zbuf; /* z/depth buffer */ - Lock zbuflk; + double *zb; /* z/depth buffer */ Rectangle r; }; struct Framebufctl { + Lock; Framebuf *fb[2]; /* double buffering */ uint idx; /* front buffer index */ - Lock swplk; void (*draw)(Framebufctl*, Image*); void (*memdraw)(Framebufctl*, Memimage*); void (*swap)(Framebufctl*); void (*reset)(Framebufctl*); + Framebuf *(*getfb)(Framebufctl*); + Framebuf *(*getbb)(Framebufctl*); }; struct Viewport @@ -215,6 +235,7 @@ struct Viewport void (*draw)(Viewport*, Image*); void (*memdraw)(Viewport*, Memimage*); + Framebuf *(*getfb)(Viewport*); }; struct Camera @@ -234,6 +255,11 @@ struct Camera uvlong min, avg, max, acc, n, v; uvlong nframes; } stats; + + struct { + Rendertime R[100], E[100], Tn[100], Rn[100]; + int cur; + } times; }; /* camera */ @@ -264,6 +290,7 @@ Entity *newentity(Model*); void delentity(Entity*); Scene *newscene(char*); void delscene(Scene*); +void clearscene(Scene*); /* vertex */ void addvattr(Vertex*, char*, int, void*); @@ -1,8 +1,27 @@ -typedef struct Jobqueue Jobqueue; +typedef struct Tilerparam Tilerparam; +typedef struct Rasterparam Rasterparam; +typedef struct Rastertask Rastertask; -struct Jobqueue +struct Tilerparam { - Renderjob *hd, *tl; + int id; + Channel *paramsc; + Channel **taskchans; /* Channel*[nproc] */ + Rectangle *wr; /* Rectangle[nproc] */ + ulong nproc; +}; + +struct Rasterparam +{ + int id; + Channel *taskc; +}; + +struct Rastertask +{ + SUparams *params; + Rectangle wr; /* working rect */ + Primitive p; }; /* alloc */ @@ -42,13 +42,13 @@ isvisible(Point3 p) } static int -isfacingback(Triangle t) +isfacingback(Primitive p) { double sa; /* signed area */ - sa = t[0].p.x * t[1].p.y - t[0].p.y * t[1].p.x + - t[1].p.x * t[2].p.y - t[1].p.y * t[2].p.x + - t[2].p.x * t[0].p.y - t[2].p.y * t[0].p.x; + sa = p.v[0].p.x * p.v[1].p.y - p.v[0].p.y * p.v[1].p.x + + p.v[1].p.x * p.v[2].p.y - p.v[1].p.y * p.v[2].p.x + + p.v[2].p.x * p.v[0].p.y - p.v[2].p.y * p.v[0].p.x; return sa <= 0; } @@ -105,7 +105,7 @@ cleanpoly(Polygon *p) * - https://github.com/aap/librw/blob/14dab85dcae6f3762fb2b1eda4d58d8e67541330/tools/playground/tl_tests.cpp#L522 */ static int -cliptriangle(Triangle *t) +cliptriangle(Primitive *p) { /* signed distance from each clipping plane */ static double sdm[6][4] = { @@ -126,7 +126,7 @@ cliptriangle(Triangle *t) memset(&Vin, 0, sizeof Vin); memset(&Vout, 0, sizeof Vout); for(i = 0; i < 3; i++) - addvert(&Vin, t[0][i]); + addvert(&Vin, p[0].v[i]); for(j = 0; j < 6 && Vin.n > 0; j++){ for(i = 0; i < Vin.n; i++){ @@ -169,9 +169,9 @@ allin: * are referenced on every triangle, so duplicate them * to avoid complications during rasterization. */ - t[nt][0] = i < Vout.n-2-1? dupvertex(&Vout.v[0]): Vout.v[0]; - t[nt][1] = Vout.v[i+1]; - t[nt][2] = i < Vout.n-2-1? dupvertex(&Vout.v[i+2]): Vout.v[i+2]; + p[nt].v[0] = i < Vout.n-2-1? dupvertex(&Vout.v[0]): Vout.v[0]; + p[nt].v[1] = Vout.v[i+1]; + p[nt].v[2] = i < Vout.n-2-1? dupvertex(&Vout.v[i+2]): Vout.v[i+2]; } free(Vout.v); free(Vin.v); @@ -292,8 +292,10 @@ orthographic(Matrix3 m, double l, double r, double b, double t, double n, double } static void -rasterize(SUparams *params, Triangle t) +rasterize(Rastertask *task) { + SUparams *params; + Primitive prim; FSparams fsp; Triangle2 t₂; Rectangle bbox; @@ -302,18 +304,22 @@ rasterize(SUparams *params, Triangle t) Color c; double z, depth; - t₂.p0 = Pt2(t[0].p.x, t[0].p.y, 1); - t₂.p1 = Pt2(t[1].p.x, t[1].p.y, 1); - t₂.p2 = Pt2(t[2].p.x, t[2].p.y, 1); - /* find the triangle's bbox and clip it against the fb */ - bbox = Rect( - min(min(t₂.p0.x, t₂.p1.x), t₂.p2.x), min(min(t₂.p0.y, t₂.p1.y), t₂.p2.y), - max(max(t₂.p0.x, t₂.p1.x), t₂.p2.x)+1, max(max(t₂.p0.y, t₂.p1.y), t₂.p2.y)+1 - ); - bbox.min.x = max(bbox.min.x, params->fb->r.min.x); - bbox.min.y = max(bbox.min.y, params->fb->r.min.y); - bbox.max.x = min(bbox.max.x, params->fb->r.max.x); - bbox.max.y = min(bbox.max.y, params->fb->r.max.y); + params = task->params; + prim = task->p; + memmove(prim.v, task->p.v, sizeof prim.v); + + t₂.p0 = Pt2(prim.v[0].p.x, prim.v[0].p.y, 1); + t₂.p1 = Pt2(prim.v[1].p.x, prim.v[1].p.y, 1); + t₂.p2 = Pt2(prim.v[2].p.x, prim.v[2].p.y, 1); + /* find the triangle's bbox and clip it against our wr */ + bbox.min.x = min(min(t₂.p0.x, t₂.p1.x), t₂.p2.x); + bbox.min.y = min(min(t₂.p0.y, t₂.p1.y), t₂.p2.y); + bbox.max.x = max(max(t₂.p0.x, t₂.p1.x), t₂.p2.x)+1; + bbox.max.y = max(max(t₂.p0.y, t₂.p1.y), t₂.p2.y)+1; + bbox.min.x = max(bbox.min.x, task->wr.min.x); + bbox.min.y = max(bbox.min.y, task->wr.min.y); + bbox.max.x = min(bbox.max.x, task->wr.max.x); + bbox.max.y = min(bbox.max.y, task->wr.max.y); fsp.su = params; memset(&fsp.v, 0, sizeof fsp.v); @@ -323,26 +329,22 @@ rasterize(SUparams *params, Triangle t) if(bc.x < 0 || bc.y < 0 || bc.z < 0) continue; - z = fberp(t[0].p.z, t[1].p.z, t[2].p.z, bc); + z = fberp(prim.v[0].p.z, prim.v[1].p.z, prim.v[2].p.z, bc); depth = fclamp(z, 0, 1); - lock(¶ms->fb->zbuflk); - if(depth <= params->fb->zbuf[p.x + p.y*Dx(params->fb->r)]){ - unlock(¶ms->fb->zbuflk); + if(depth <= params->fb->zb[p.x + p.y*Dx(params->fb->r)]) continue; - } - params->fb->zbuf[p.x + p.y*Dx(params->fb->r)] = depth; - unlock(¶ms->fb->zbuflk); + params->fb->zb[p.x + p.y*Dx(params->fb->r)] = depth; /* interpolate z⁻¹ and get actual z */ - z = fberp(t[0].p.w, t[1].p.w, t[2].p.w, bc); + z = fberp(prim.v[0].p.w, prim.v[1].p.w, prim.v[2].p.w, bc); z = 1.0/(z < 1e-5? 1e-5: z); /* perspective-correct attribute interpolation */ - bc.x *= t[0].p.w; - bc.y *= t[1].p.w; - bc.z *= t[2].p.w; + bc.x *= prim.v[0].p.w; + bc.y *= prim.v[1].p.w; + bc.z *= prim.v[2].p.w; bc = mulpt3(bc, z); - berpvertex(&fsp.v, &t[0], &t[1], &t[2], bc); + berpvertex(&fsp.v, &prim.v[0], &prim.v[1], &prim.v[2], bc); fsp.p = p; c = params->fshader(&fsp); @@ -354,123 +356,293 @@ rasterize(SUparams *params, Triangle t) } static void -entityproc(void *arg) +rasterizer(void *arg) { - Channel *paramsc; + Rasterparam *rp; + Rastertask *task; SUparams *params; + Memimage *frag; + uvlong t0; + + rp = arg; + frag = rgb(DBlack); + + threadsetname("rasterizer %d", rp->id); + + while((task = recvp(rp->taskc)) != nil){ + t0 = nanosec(); + + params = task->params; + /* end of job */ + if(params->entity == nil){ + if(decref(params->job) < 1){ + nbsend(params->job->donec, nil); + free(params); + } + free(task); + continue; + } + + if(params->job->times.Rn.t0 == 0) + params->job->times.Rn.t0 = t0; + + params->frag = frag; + rasterize(task); + + delvattrs(&task->p.v[0]); + delvattrs(&task->p.v[1]); + delvattrs(&task->p.v[2]); + params->job->times.Rn.t1 = nanosec(); + free(params); + free(task); + } +} + +static void +tilerdurden(void *arg) +{ + Tilerparam *tp; + SUparams *params, *newparams; + Rastertask *task; VSparams vsp; OBJVertex *verts, *tverts, *nverts; /* geometric, texture and normals vertices */ OBJIndexArray *idxtab; - OBJElem **ep, **eb, **ee; + OBJElem **ep; Point3 n; /* surface normal */ - Triangle *t; /* triangles to raster */ - int i, nt; - - threadsetname("entityproc"); - - paramsc = arg; - t = emalloc(sizeof(*t)*16); - - while((params = recvp(paramsc)) != nil){ + Primitive *p; /* primitives to raster */ + Rectangle *wr, bbox; + Channel **taskchans; + ulong Δy, nproc; + int i, np; + uvlong t0; + + tp = arg; + p = emalloc(sizeof(*p)*16); + taskchans = tp->taskchans; + nproc = tp->nproc; + wr = emalloc(nproc*sizeof(Rectangle)); + + threadsetname("tilerdurden %d", tp->id); + + while((params = recvp(tp->paramsc)) != nil){ + t0 = nanosec(); + if(params->job->times.Tn.t0 == 0) + params->job->times.Tn.t0 = t0; + + /* end of job */ + if(params->entity == nil){ + if(decref(params->job) < 1){ + params->job->ref = nproc; + for(i = 0; i < nproc; i++){ + task = emalloc(sizeof *task); + memset(task, 0, sizeof *task); + task->params = params; + sendp(taskchans[i], task); + } + } + continue; + } vsp.su = params; + wr[0] = params->fb->r; + Δy = Dy(wr[0])/nproc; + wr[0].max.y = wr[0].min.y + Δy; + for(i = 1; i < nproc; i++) + wr[i] = rectaddpt(wr[i-1], Pt(0,Δy)); + if(wr[nproc-1].max.y < params->fb->r.max.y) + wr[nproc-1].max.y = params->fb->r.max.y; + verts = params->entity->mdl->obj->vertdata[OBJVGeometric].verts; tverts = params->entity->mdl->obj->vertdata[OBJVTexture].verts; nverts = params->entity->mdl->obj->vertdata[OBJVNormal].verts; - eb = params->entity->mdl->elems; - ee = eb + params->entity->mdl->nelems; + for(ep = params->eb; ep != params->ee; ep++){ + np = 1; /* start with one. after clipping it might change */ - for(ep = eb; ep != ee; ep++){ - nt = 1; /* start with one. after clipping it might change */ + /* TODO handle all the primitive types */ idxtab = &(*ep)->indextab[OBJVGeometric]; - t[0][0].p = Pt3(verts[idxtab->indices[0]].x, - verts[idxtab->indices[0]].y, - verts[idxtab->indices[0]].z, - verts[idxtab->indices[0]].w); - t[0][1].p = Pt3(verts[idxtab->indices[1]].x, - verts[idxtab->indices[1]].y, - verts[idxtab->indices[1]].z, - verts[idxtab->indices[1]].w); - t[0][2].p = Pt3(verts[idxtab->indices[2]].x, - verts[idxtab->indices[2]].y, - verts[idxtab->indices[2]].z, - verts[idxtab->indices[2]].w); + p[0].v[0].p = Pt3(verts[idxtab->indices[0]].x, + verts[idxtab->indices[0]].y, + verts[idxtab->indices[0]].z, + verts[idxtab->indices[0]].w); + p[0].v[1].p = Pt3(verts[idxtab->indices[1]].x, + verts[idxtab->indices[1]].y, + verts[idxtab->indices[1]].z, + verts[idxtab->indices[1]].w); + p[0].v[2].p = Pt3(verts[idxtab->indices[2]].x, + verts[idxtab->indices[2]].y, + verts[idxtab->indices[2]].z, + verts[idxtab->indices[2]].w); idxtab = &(*ep)->indextab[OBJVNormal]; if(idxtab->nindex == 3){ - t[0][0].n = Vec3(nverts[idxtab->indices[0]].i, - nverts[idxtab->indices[0]].j, - nverts[idxtab->indices[0]].k); - t[0][0].n = normvec3(t[0][0].n); - t[0][1].n = Vec3(nverts[idxtab->indices[1]].i, - nverts[idxtab->indices[1]].j, - nverts[idxtab->indices[1]].k); - t[0][1].n = normvec3(t[0][1].n); - t[0][2].n = Vec3(nverts[idxtab->indices[2]].i, - nverts[idxtab->indices[2]].j, - nverts[idxtab->indices[2]].k); - t[0][2].n = normvec3(t[0][2].n); + p[0].v[0].n = Vec3(nverts[idxtab->indices[0]].i, + nverts[idxtab->indices[0]].j, + nverts[idxtab->indices[0]].k); + p[0].v[0].n = normvec3(p[0].v[0].n); + p[0].v[1].n = Vec3(nverts[idxtab->indices[1]].i, + nverts[idxtab->indices[1]].j, + nverts[idxtab->indices[1]].k); + p[0].v[1].n = normvec3(p[0].v[1].n); + p[0].v[2].n = Vec3(nverts[idxtab->indices[2]].i, + nverts[idxtab->indices[2]].j, + nverts[idxtab->indices[2]].k); + p[0].v[2].n = normvec3(p[0].v[2].n); }else{ /* TODO build a list of per-vertex normals earlier */ - n = normvec3(crossvec3(subpt3(t[0][1].p, t[0][0].p), subpt3(t[0][2].p, t[0][0].p))); - t[0][0].n = t[0][1].n = t[0][2].n = n; + n = normvec3(crossvec3(subpt3(p[0].v[1].p, p[0].v[0].p), subpt3(p[0].v[2].p, p[0].v[0].p))); + p[0].v[0].n = p[0].v[1].n = p[0].v[2].n = n; } idxtab = &(*ep)->indextab[OBJVTexture]; if(idxtab->nindex == 3){ - t[0][0].uv = Pt2(tverts[idxtab->indices[0]].u, - tverts[idxtab->indices[0]].v, 1); - t[0][1].uv = Pt2(tverts[idxtab->indices[1]].u, - tverts[idxtab->indices[1]].v, 1); - t[0][2].uv = Pt2(tverts[idxtab->indices[2]].u, - tverts[idxtab->indices[2]].v, 1); + p[0].v[0].uv = Pt2(tverts[idxtab->indices[0]].u, + tverts[idxtab->indices[0]].v, 1); + p[0].v[1].uv = Pt2(tverts[idxtab->indices[1]].u, + tverts[idxtab->indices[1]].v, 1); + p[0].v[2].uv = Pt2(tverts[idxtab->indices[2]].u, + tverts[idxtab->indices[2]].v, 1); }else{ - t[0][0].uv = t[0][1].uv = t[0][2].uv = Vec2(0,0); + p[0].v[0].uv = p[0].v[1].uv = p[0].v[2].uv = Vec2(0,0); } for(i = 0; i < 3; i++){ - t[0][i].c = Pt3(1,1,1,1); - t[0][i].mtl = (*ep)->mtl; - t[0][i].attrs = nil; - t[0][i].nattrs = 0; + p[0].v[i].c = Pt3(1,1,1,1); + p[0].v[i].mtl = (*ep)->mtl; + p[0].v[i].attrs = nil; + p[0].v[i].nattrs = 0; } - vsp.v = &t[0][0]; + vsp.v = &p[0].v[0]; vsp.idx = 0; - t[0][0].p = params->vshader(&vsp); - vsp.v = &t[0][1]; + p[0].v[0].p = params->vshader(&vsp); + vsp.v = &p[0].v[1]; vsp.idx = 1; - t[0][1].p = params->vshader(&vsp); - vsp.v = &t[0][2]; + p[0].v[1].p = params->vshader(&vsp); + vsp.v = &p[0].v[2]; vsp.idx = 2; - t[0][2].p = params->vshader(&vsp); + p[0].v[2].p = params->vshader(&vsp); - if(!isvisible(t[0][0].p) || !isvisible(t[0][1].p) || !isvisible(t[0][2].p)) - nt = cliptriangle(t); + if(!isvisible(p[0].v[0].p) || !isvisible(p[0].v[1].p) || !isvisible(p[0].v[2].p)) + np = cliptriangle(p); - while(nt--){ - t[nt][0].p = clip2ndc(t[nt][0].p); - t[nt][1].p = clip2ndc(t[nt][1].p); - t[nt][2].p = clip2ndc(t[nt][2].p); + while(np--){ + p[np].v[0].p = clip2ndc(p[np].v[0].p); + p[np].v[1].p = clip2ndc(p[np].v[1].p); + p[np].v[2].p = clip2ndc(p[np].v[2].p); /* culling */ -// if(isfacingback(t[nt])) +// if(isfacingback(p[np])) // goto skiptri; - t[nt][0].p = ndc2viewport(params->fb, t[nt][0].p); - t[nt][1].p = ndc2viewport(params->fb, t[nt][1].p); - t[nt][2].p = ndc2viewport(params->fb, t[nt][2].p); - - rasterize(params, t[nt]); + p[np].v[0].p = ndc2viewport(params->fb, p[np].v[0].p); + p[np].v[1].p = ndc2viewport(params->fb, p[np].v[1].p); + p[np].v[2].p = ndc2viewport(params->fb, p[np].v[2].p); + + bbox.min.x = min(min(p[np].v[0].p.x, p[np].v[1].p.x), p[np].v[2].p.x); + bbox.min.y = min(min(p[np].v[0].p.y, p[np].v[1].p.y), p[np].v[2].p.y); + bbox.max.x = max(max(p[np].v[0].p.x, p[np].v[1].p.x), p[np].v[2].p.x)+1; + bbox.max.y = max(max(p[np].v[0].p.y, p[np].v[1].p.y), p[np].v[2].p.y)+1; + + for(i = 0; i < nproc; i++) + if(rectXrect(bbox,wr[i])){ + newparams = emalloc(sizeof *newparams); + *newparams = *params; + task = emalloc(sizeof *task); + task->params = newparams; + task->wr = wr[i]; + task->p.v[0] = dupvertex(&p[np].v[0]); + task->p.v[1] = dupvertex(&p[np].v[1]); + task->p.v[2] = dupvertex(&p[np].v[2]); + sendp(taskchans[i], task); + } //skiptri: - delvattrs(&t[nt][0]); - delvattrs(&t[nt][1]); - delvattrs(&t[nt][2]); + delvattrs(&p[np].v[0]); + delvattrs(&p[np].v[1]); + delvattrs(&p[np].v[2]); } } - sendp(params->donec, params); + params->job->times.Tn.t1 = nanosec(); + free(params); + } +} + +static void +entityproc(void *arg) +{ + Channel *paramsin, **paramsout, **taskchans; + Tilerparam *tp; + Rasterparam *rp; + SUparams *params, *newparams; + OBJElem **eb, **ee; + char *nprocs; + ulong stride, nelems, nproc, nworkers; + int i; + uvlong t0; + + threadsetname("entityproc"); + + paramsin = arg; + nprocs = getenv("NPROC"); + if(nprocs == nil || (nproc = strtoul(nprocs, nil, 10)) < 2) + nproc = 1; + else + nproc /= 2; + free(nprocs); + + paramsout = emalloc(nproc*sizeof(*paramsout)); + taskchans = emalloc(nproc*sizeof(*taskchans)); + for(i = 0; i < nproc; i++){ + paramsout[i] = chancreate(sizeof(SUparams*), 8); + tp = emalloc(sizeof *tp); + tp->id = i; + tp->paramsc = paramsout[i]; + tp->taskchans = taskchans; + tp->nproc = nproc; + proccreate(tilerdurden, tp, mainstacksize); + } + for(i = 0; i < nproc; i++){ + rp = emalloc(sizeof *rp); + rp->id = i; + rp->taskc = taskchans[i] = chancreate(sizeof(Rastertask*), 32); + proccreate(rasterizer, rp, mainstacksize); + } + + while((params = recvp(paramsin)) != nil){ + t0 = nanosec(); + if(params->job->times.E.t0 == 0) + params->job->times.E.t0 = t0; + + /* end of job */ + if(params->entity == nil){ + params->job->ref = nproc; + for(i = 0; i < nproc; i++) + sendp(paramsout[i], params); + continue; + } + + eb = params->entity->mdl->elems; + nelems = params->entity->mdl->nelems; + ee = eb + nelems; + + if(nelems <= nproc){ + nworkers = nelems; + stride = 1; + }else{ + nworkers = nproc; + stride = nelems/nproc; + } + + for(i = 0; i < nworkers; i++){ + newparams = emalloc(sizeof *newparams); + *newparams = *params; + newparams->eb = eb + i*stride; + newparams->ee = i == nworkers-1? ee: newparams->eb + stride; + sendp(paramsout[i], newparams); + } + params->job->times.E.t1 = nanosec(); + free(params); } } @@ -478,83 +650,48 @@ static void renderer(void *arg) { Channel *jobc; - Jobqueue jobq; Renderjob *job; Scene *sc; Entity *ent; - SUparams *params, *params2; - Channel *paramsc, *donec; + SUparams *params; + Channel *paramsc; + uvlong time; threadsetname("renderer"); jobc = arg; - jobq.tl = jobq.hd = nil; - ent = nil; paramsc = chancreate(sizeof(SUparams*), 8); - donec = chancreate(sizeof(SUparams*), 0); proccreate(entityproc, paramsc, mainstacksize); - enum { JOB, PARM, DONE }; - Alt a[] = { - [JOB] {jobc, &job, CHANRCV}, - [PARM] {paramsc, ¶ms, CHANNOP}, - [DONE] {donec, ¶ms2, CHANRCV}, - {nil, nil, CHANEND} - }; - for(;;) - switch(alt(a)){ - case JOB: - sc = job->scene; - job->nrem = sc->nents; - job->lastid = 0; - job->time0 = nanosec(); - - if(jobq.tl == nil){ - jobq.tl = jobq.hd = job; - ent = sc->ents.next; - a[PARM].op = CHANSND; - goto sendparams; - }else - jobq.tl = jobq.tl->next = job; - break; - case PARM: -sendparams: - job = jobq.hd; - sc = job->scene; - - if(ent != nil && ent != &sc->ents){ - params = emalloc(sizeof *params); - memset(params, 0, sizeof *params); - params->fb = job->fb; - params->id = job->lastid++; - params->frag = rgb(DBlack); - params->donec = donec; - params->job = job; - params->entity = ent; - params->uni_time = job->time0; - params->vshader = job->shaders->vshader; - params->fshader = job->shaders->fshader; - ent = ent->next; - }else{ - jobq.hd = job->next; - if((job = jobq.hd) != nil){ - ent = job->scene->ents.next; - goto sendparams; - } + while((job = recvp(jobc)) != nil){ + time = nanosec(); + job->times.R.t0 = time; + sc = job->scene; + if(sc->nents < 1){ + nbsend(job->donec, nil); + continue; + } - jobq.tl = jobq.hd; - a[PARM].op = CHANNOP; - } - break; - case DONE: - if(--params2->job->nrem < 1) - send(params2->job->donec, nil); - - freememimage(params2->frag); - free(params2); - break; + for(ent = sc->ents.next; ent != &sc->ents; ent = ent->next){ + params = emalloc(sizeof *params); + memset(params, 0, sizeof *params); + params->fb = job->fb; + params->job = job; + params->entity = ent; + params->uni_time = time; + params->vshader = job->shaders->vshader; + params->fshader = job->shaders->fshader; + sendp(paramsc, params); } + /* mark end of job */ + params = emalloc(sizeof *params); + memset(params, 0, sizeof *params); + params->job = job; + sendp(paramsc, params); + + job->times.R.t1 = nanosec(); + } } Renderer * @@ -117,6 +117,16 @@ newmodel(void) void delmodel(Model *m) { + if(m == nil) + return; + if(m->obj != nil) + objfree(m->obj); + if(m->tex != nil) + freememimage(m->tex); + if(m->nor != nil) + freememimage(m->nor); + if(m->nelems > 0) + free(m->elems); free(m); } @@ -138,7 +148,10 @@ newentity(Model *m) void delentity(Entity *e) { - /* TODO free model */ + if(e == nil) + return; + if(e->mdl != nil) + delmodel(e->mdl); free(e); } @@ -152,6 +165,15 @@ scene_addent(Scene *s, Entity *e) s->nents++; } +static void +scene_delent(Scene *s, Entity *e) +{ + e->prev->next = e->next; + e->next->prev = e->prev; + e->prev = e->next = nil; + s->nents--; +} + Scene * newscene(char *name) { @@ -160,14 +182,30 @@ newscene(char *name) s = emalloc(sizeof *s); s->name = name == nil? nil: strdup(name); s->ents.prev = s->ents.next = &s->ents; + s->nents = 0; s->addent = scene_addent; + s->delent = scene_delent; return s; } void delscene(Scene *s) { - /* TODO free ents */ + if(s == nil) + return; + clearscene(s); free(s->name); free(s); } + +void +clearscene(Scene *s) +{ + Entity *e, *ne; + + for(e = s->ents.next; e != &s->ents; e = ne){ + ne = e->next; + s->delent(s, e); + delentity(e); + } +} @@ -46,7 +46,7 @@ rgb(ulong c) { Memimage *i; - i = eallocmemimage(UR, screen->chan); + i = eallocmemimage(UR, RGBA32); i->flags |= Frepl; i->clipr = Rect(-1e6, -1e6, 1e6, 1e6); memfillcolor(i, c); @@ -20,6 +20,12 @@ viewport_memdraw(Viewport *v, Memimage *dst) v->fbctl->memdraw(v->fbctl, dst); } +static Framebuf * +viewport_getfb(Viewport *v) +{ + return v->fbctl->getfb(v->fbctl); +} + Viewport * mkviewport(Rectangle r) { @@ -32,12 +38,15 @@ mkviewport(Rectangle r) v->fbctl = mkfbctl(r); v->draw = viewport_draw; v->memdraw = viewport_memdraw; + v->getfb = viewport_getfb; return v; } void rmviewport(Viewport *v) { + if(v == nil) + return; rmfbctl(v->fbctl); free(v); } |