From cbfa17d446effcfc1e7d17aed624af8f098370f1 Mon Sep 17 00:00:00 2001 From: rodri Date: Thu, 23 May 2024 21:26:19 +0000 Subject: get rid of rendering latency by decoupling it from i/o. i was using a single alternator to mux both i/o and drawing in a single proc, and avoid locking. the problem is that it causes a fight to break up every time there's any input (steady 100Hz) or a lot of drawing requests from the renderer (up to 60Hz.) i added a drawproc to handle exclusively drawing requests, and a drawing lock for UI widgets that kidnap the display. --- med.c | 52 ++++++++++++++++++++++++++++++++++++++++------------ solar.c | 54 +++++++++++++++++++++++++++++++++++++----------------- vis.c | 40 ++++++++++++++++++++++++++++------------ 3 files changed, 105 insertions(+), 41 deletions(-) diff --git a/med.c b/med.c index 670997a..0e49f44 100644 --- a/med.c +++ b/med.c @@ -76,6 +76,7 @@ Entity *subject; Model *model; Shadertab *shader; QLock scenelk; +QLock drawlk; Mouse om; Quaternion orient = {1,0,0,0}; @@ -466,11 +467,11 @@ redraw(void) } void -drawproc(void *) +renderproc(void *) { uvlong t0, Δt; - threadsetname("drawproc"); + threadsetname("renderproc"); t0 = nsec(); for(;;){ @@ -491,6 +492,18 @@ drawproc(void *) } } +void +drawproc(void *) +{ + threadsetname("drawproc"); + + for(;;) + if(recv(drawc, nil) && canqlock(&drawlk)){ + redraw(); + qunlock(&drawlk); + } +} + void lmb(void) { @@ -516,6 +529,7 @@ mmb(void) }; static Menu menu = { .item = items }; + qlock(&drawlk); switch(menuhit(2, mctl, &menu, _screen)){ case TSNEAREST: tsampler = neartexsampler; @@ -526,35 +540,50 @@ mmb(void) case QUIT: threadexitsall(nil); } + qunlock(&drawlk); nbsend(drawc, nil); } static char * genrmbmenuitem(int idx) { + static char *items[] = { + "", + "add cube", + nil + }; if(idx < nelem(shadertab)) return shadertab[idx].name; - else if(idx == nelem(shadertab)) - return ""; - else if(idx == nelem(shadertab)+1) - return "add cube"; - return nil; + idx -= nelem(shadertab); + return items[idx]; } void rmb(void) { + enum { + SP, + ADDCUBE, + }; static Menu menu = { .gen = genrmbmenuitem }; int idx; + qlock(&drawlk); idx = menuhit(3, mctl, &menu, _screen); if(idx < 0) - return; + goto nohit; if(idx < nelem(shadertab)){ shader = &shadertab[idx]; memset(&cam.stats, 0, sizeof(cam.stats)); - }else if(idx == nelem(shadertab)+1) + } + idx -= nelem(shadertab); + switch(idx){ + case ADDCUBE: addcube(); + break; + } +nohit: + qunlock(&drawlk); nbsend(drawc, nil); } @@ -763,22 +792,21 @@ threadmain(int argc, char *argv[]) proccreate(kbdproc, nil, mainstacksize); proccreate(keyproc, keyc, mainstacksize); + proccreate(renderproc, nil, mainstacksize); proccreate(drawproc, nil, mainstacksize); for(;;){ - enum {MOUSE, RESIZE, KEY, DRAW}; + enum {MOUSE, RESIZE, KEY}; Alt a[] = { {mctl->c, &mctl->Mouse, CHANRCV}, {mctl->resizec, nil, CHANRCV}, {keyc, nil, CHANRCV}, - {drawc, nil, CHANRCV}, {nil, nil, CHANEND} }; switch(alt(a)){ case MOUSE: mouse(); break; case RESIZE: resize(); break; case KEY: handlekeys(); break; - case DRAW: redraw(); break; } } } diff --git a/solar.c b/solar.c index 3f3c494..8d7b49e 100644 --- a/solar.c +++ b/solar.c @@ -136,6 +136,7 @@ int kdown; Tm date; char datestr[16]; Scene *scene; +QLock drawlk; Camera camera; Camcfg cameracfg = { @@ -408,11 +409,11 @@ redraw(void) } void -drawproc(void *) +renderproc(void *) { uvlong t0, Δt; - threadsetname("drawproc"); + threadsetname("renderproc"); t0 = nsec(); for(;;){ @@ -431,6 +432,18 @@ drawproc(void *) } } +void +drawproc(void *) +{ + threadsetname("drawproc"); + + for(;;) + if(recv(drawc, nil) && canqlock(&drawlk)){ + redraw(); + qunlock(&drawlk); + } +} + static char * genplanetmenu(int idx) { @@ -446,11 +459,13 @@ lookat_cmd(Cmdbut *) Planet *p; int idx; + qlock(&drawlk); idx = menuhit(1, mctl, &menu, _screen); - if(idx < 0) - return; - p = &planets[idx]; - placecamera(&camera, camera.p, p->body->p, cameracfg.up); + if(idx >= 0){ + p = &planets[idx]; + placecamera(&camera, camera.p, p->body->p, cameracfg.up); + } + qunlock(&drawlk); nbsend(drawc, nil); } @@ -460,10 +475,11 @@ goto_cmd(Cmdbut *) static Menu menu = { .gen = genplanetmenu }; int idx; + qlock(&drawlk); idx = menuhit(1, mctl, &menu, _screen); - if(idx < 0) - return; - gotoplanet(&planets[idx]); + if(idx >= 0) + gotoplanet(&planets[idx]); + qunlock(&drawlk); nbsend(drawc, nil); } @@ -477,13 +493,17 @@ date_cmd(Cmdbut *) return; memmove(buf, datestr, sizeof buf); + qlock(&drawlk); if(enter("new date", buf, sizeof buf, mctl, kctl, nil) <= 0) - return; + goto nodate; if(tmparse(&t, datefmt, buf, nil, nil) == nil) - return; + goto nodate; date = t; snprint(datestr, sizeof datestr, "%τ", tmfmt(&date, datefmt)); updateplanets(); +nodate: + qunlock(&drawlk); + nbsend(drawc, nil); } Cmdbut cmds[] = { @@ -554,16 +574,17 @@ mmb(void) if((om.buttons ^ mctl->buttons) == 0) return; + qlock(&drawlk); switch(menuhit(2, mctl, &menu, _screen)){ case CHGSPEED: snprint(buf, sizeof buf, "%g", speed); - if(enter("speed (km)", buf, sizeof buf, mctl, kctl, nil) <= 0) - return; - speed = fabs(strtod(buf, nil)); + if(enter("speed (km)", buf, sizeof buf, mctl, kctl, nil) > 0) + speed = fabs(strtod(buf, nil)); break; case QUIT: threadexitsall(nil); } + qunlock(&drawlk); nbsend(drawc, nil); } @@ -808,22 +829,21 @@ threadmain(int argc, char *argv[]) proccreate(kbdproc, nil, mainstacksize); proccreate(keyproc, keyc, mainstacksize); + proccreate(renderproc, nil, mainstacksize); proccreate(drawproc, nil, mainstacksize); for(;;){ - enum {MOUSE, RESIZE, KEY, DRAW}; + enum {MOUSE, RESIZE, KEY}; Alt a[] = { {mctl->c, &mctl->Mouse, CHANRCV}, {mctl->resizec, nil, CHANRCV}, {keyc, nil, CHANRCV}, - {drawc, nil, CHANRCV}, {nil, nil, CHANEND} }; switch(alt(a)){ case MOUSE: mouse(); break; case RESIZE: resize(); break; case KEY: handlekeys(); break; - case DRAW: redraw(); break; } } } diff --git a/vis.c b/vis.c index 12d5d6c..e5a7795 100644 --- a/vis.c +++ b/vis.c @@ -50,6 +50,7 @@ Shadertab *shader; Model *model; Entity *subject; Scene *scene; +QLock drawlk; Mouse om; Quaternion orient = {1,0,0,0}; @@ -481,12 +482,12 @@ redraw(void) } void -drawproc(void *) +renderproc(void *) { uvlong t0, Δt; int fd; - threadsetname("drawproc"); + threadsetname("renderproc"); fd = -1; if(inception){ @@ -521,6 +522,18 @@ drawproc(void *) } } +void +drawproc(void *) +{ + threadsetname("drawproc"); + + for(;;) + if(recv(drawc, nil) && canqlock(&drawlk)){ + redraw(); + qunlock(&drawlk); + } +} + void lmb(void) { @@ -546,14 +559,15 @@ mmb(void) char buf[256], *f[3]; int nf; + qlock(&drawlk); switch(menuhit(2, mctl, &menu, _screen)){ case MOVELIGHT: snprint(buf, sizeof buf, "%g %g %g", light.p.x, light.p.y, light.p.z); if(enter("light pos", buf, sizeof buf, mctl, kctl, nil) <= 0) - return; + break; nf = tokenize(buf, f, 3); if(nf != 3) - return; + break; light.p.x = strtod(f[0], nil); light.p.y = strtod(f[1], nil); light.p.z = strtod(f[2], nil); @@ -565,6 +579,7 @@ mmb(void) tsampler = bilitexsampler; break; } + qunlock(&drawlk); nbsend(drawc, nil); } @@ -582,12 +597,14 @@ rmb(void) static Menu menu = { .gen = genrmbmenuitem }; int idx; + qlock(&drawlk); idx = menuhit(3, mctl, &menu, _screen); - if(idx < 0) - return; - shader = &shadertab[idx]; - for(idx = 0; idx < nelem(cams); idx++) - memset(&cams[idx].stats, 0, sizeof(cams[idx].stats)); + if(idx >= 0){ + shader = &shadertab[idx]; + for(idx = 0; idx < nelem(cams); idx++) + memset(&cams[idx].stats, 0, sizeof(cams[idx].stats)); + } + qunlock(&drawlk); nbsend(drawc, nil); } @@ -843,22 +860,21 @@ threadmain(int argc, char *argv[]) proccreate(kbdproc, nil, mainstacksize); proccreate(keyproc, keyc, mainstacksize); + proccreate(renderproc, nil, mainstacksize); proccreate(drawproc, nil, mainstacksize); for(;;){ - enum {MOUSE, RESIZE, KEY, DRAW}; + enum {MOUSE, RESIZE, KEY}; Alt a[] = { {mctl->c, &mctl->Mouse, CHANRCV}, {mctl->resizec, nil, CHANRCV}, {keyc, nil, CHANRCV}, - {drawc, nil, CHANRCV}, {nil, nil, CHANEND} }; switch(alt(a)){ case MOUSE: mouse(); break; case RESIZE: resize(); break; case KEY: handlekeys(); break; - case DRAW: redraw(); break; } } } -- cgit v1.2.3