summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrodri <rgl@antares-labs.eu>2024-05-23 21:26:19 +0000
committerrodri <rgl@antares-labs.eu>2024-05-23 21:26:19 +0000
commitcbfa17d446effcfc1e7d17aed624af8f098370f1 (patch)
tree526394c2dc24503b18a676a742187a648365b269
parent22edbd9f543509ab129ba03af92baed79139e07f (diff)
download3dee-cbfa17d446effcfc1e7d17aed624af8f098370f1.tar.gz
3dee-cbfa17d446effcfc1e7d17aed624af8f098370f1.tar.bz2
3dee-cbfa17d446effcfc1e7d17aed624af8f098370f1.zip
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.
-rw-r--r--med.c52
-rw-r--r--solar.c54
-rw-r--r--vis.c40
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(;;){
@@ -492,6 +493,18 @@ drawproc(void *)
}
void
+drawproc(void *)
+{
+ threadsetname("drawproc");
+
+ for(;;)
+ if(recv(drawc, nil) && canqlock(&drawlk)){
+ redraw();
+ qunlock(&drawlk);
+ }
+}
+
+void
lmb(void)
{
if((om.buttons^mctl->buttons) == 0)
@@ -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){
@@ -522,6 +523,18 @@ drawproc(void *)
}
void
+drawproc(void *)
+{
+ threadsetname("drawproc");
+
+ for(;;)
+ if(recv(drawc, nil) && canqlock(&drawlk)){
+ redraw();
+ qunlock(&drawlk);
+ }
+}
+
+void
lmb(void)
{
if((om.buttons^mctl->buttons) == 0)
@@ -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;
}
}
}