Skip to content

Commit

Permalink
shaders: Add cleanup and convert to doubly linked lists
Browse files Browse the repository at this point in the history
Most shaders are dropped when the last model3d using them drops, but
some are never used, so never cleaned up. Fix this. While at it, convert
to doubly linked lists, which necessitates an API change and an update
to all the callers.

Signed-off-by: Alexander Shishkin <[email protected]>
  • Loading branch information
virtuoso committed Oct 5, 2024
1 parent 49327ef commit 983cffd
Show file tree
Hide file tree
Showing 11 changed files with 70 additions and 42 deletions.
4 changes: 3 additions & 1 deletion core/gltf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1064,7 +1064,9 @@ int gltf_instantiate_one(struct gltf_data *gd, int mesh)
mesh_attr_dup(me, MESH_TANGENTS, gltf_tangent(gd, mesh), gltf_tangent_stride(gd, mesh), gltf_nr_tangent(gd, mesh));
mesh_optimize(me);

m = model3d_new_from_mesh(gltf_mesh_name(gd, mesh), gd->scene->prog, me);
struct shader_prog *prog = shader_prog_find(&gd->scene->shaders, "model");

m = model3d_new_from_mesh(gltf_mesh_name(gd, mesh), prog, me);
if (gltf_has_tangent(gd, mesh)) {
dbg("added tangents for mesh '%s'\n", gltf_mesh_name(gd, mesh));
}
Expand Down
6 changes: 3 additions & 3 deletions core/model.c
Original file line number Diff line number Diff line change
Expand Up @@ -972,7 +972,7 @@ static void model_obj_loaded(struct lib_handle *h, void *data)
struct model_data * md;
struct model3d *m;

prog = shader_prog_find(s->prog, "model");
prog = shader_prog_find(&s->shaders, "model");
dbg("loaded '%s' %p %zu %d\n", h->name, h->buf, h->size, h->state);
if (!h->buf)
return;
Expand All @@ -998,7 +998,7 @@ static void model_bin_vec_loaded(struct lib_handle *h, void *data)
float *vx, *tx, *norm;
unsigned short *idx;

prog = shader_prog_find(s->prog, "model");
prog = shader_prog_find(&s->shaders, "model");

dbg("loaded '%s' nr_vertices: %" PRIu64 "\n", h->name, hdr->nr_vertices);
vx = h->buf + sizeof(*hdr);
Expand Down Expand Up @@ -1601,7 +1601,7 @@ struct debug_draw *__debug_draw_new(struct scene *scene, float *vx, size_t vxsz,
struct model3dtx *txm;
struct model3d *m;

p = shader_prog_find(scene->prog, "debug");
p = shader_prog_find(&scene->shaders, "debug");
CHECK(dd = ref_new(debug_draw));
CHECK(m = model3d_new_from_vectors("debug", p, vx, vxsz, idx, idxsz, tx, vxsz / 3 * 2, NULL, 0));
m->debug = true;
Expand Down
2 changes: 1 addition & 1 deletion core/pipeline.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ struct render_pass *pipeline_add_pass(struct pipeline *pl, struct render_pass *s
if (!prog_name)
return pass;

p = shader_prog_find(pl->scene->prog, prog_name);
p = shader_prog_find(&pl->scene->shaders, prog_name);
m = model3d_new_quad(p, -1, 1, 0.1, 2, -2);
m->cull_face = false;
m->alpha_blend = false;
Expand Down
13 changes: 11 additions & 2 deletions core/scene.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ bool scene_camera_follows(struct scene *s, struct character *ch)

int scene_camera_add(struct scene *s)
{
struct model3d *m = model3d_new_cube(s->prog);
struct model3d *m = model3d_new_cube(list_first_entry(&s->shaders, struct shader_prog, entry));
struct model3dtx *txm = model3dtx_new(m, "transparent.png");
struct entity3d *entity;

Expand Down Expand Up @@ -337,6 +337,7 @@ int scene_init(struct scene *scene)
mq_init(&scene->mq, scene);
list_init(&scene->characters);
list_init(&scene->instor);
list_init(&scene->shaders);
list_init(&scene->debug_draws);

subscribe(MT_INPUT, scene_handle_input, scene);
Expand Down Expand Up @@ -675,7 +676,15 @@ void scene_done(struct scene *scene)

if (scene->terrain)
terrain_done(scene->terrain);
ref_put_last(scene->camera->ch);

mq_release(&scene->mq);

struct shader_prog *prog, *it;

/*
* clean up the shaders that weren't freed by model3d_drop()
* via mq_release()
*/
list_for_each_entry_iter(prog, it, &scene->shaders, entry)
ref_put(prog);
}
2 changes: 1 addition & 1 deletion core/scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ struct scene {
struct list debug_draws;
struct entity3d *focus;
struct character *control;
struct shader_prog *prog;
struct list shaders;
struct matrix4f *proj_mx;
struct terrain *terrain;
struct camera *camera;
Expand Down
26 changes: 17 additions & 9 deletions core/shader.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,15 @@ static GLuint createProgram(const char* vertexSource, const char * fragmentSourc
struct shader_var {
char *name;
GLint loc;
struct shader_var *next;
struct list entry;
};

/* XXX use a hashlist */
GLint shader_prog_find_var(struct shader_prog *p, const char *var)
{
struct shader_var *v;

for (v = p->var; v; v = v->next)
list_for_each_entry(v, &p->vars, entry)
if (!strcmp(v->name, var))
return v->loc;
return -1;
Expand Down Expand Up @@ -138,8 +138,7 @@ static int shader_prog_scan(struct shader_prog *p, const char *txt)
break;
}
//dbg("# found var '%s' @%d\n", v->name, v->loc);
v->next = p->var;
p->var = v;
list_append(&p->vars, &v->entry);
pos = pend;
}
}
Expand All @@ -150,7 +149,14 @@ static int shader_prog_scan(struct shader_prog *p, const char *txt)
static void shader_prog_drop(struct ref *ref)
{
struct shader_prog *p = container_of(ref, struct shader_prog, ref);
struct shader_var *var, *iter;

list_for_each_entry_iter(var, iter, &p->vars, entry) {
free(var->name);
free(var);
}

list_del(&p->entry);
dbg("dropping shader '%s'\n", p->name);
}

Expand Down Expand Up @@ -186,6 +192,7 @@ shader_prog_from_strings(const char *name, const char *vsh, const char *fsh)
if (!p)
return NULL;

list_init(&p->vars);
p->name = name;
p->prog = createProgram(vsh, fsh);
if (!p->prog) {
Expand Down Expand Up @@ -229,16 +236,18 @@ void shader_prog_done(struct shader_prog *p)
ref_put(p);
}

struct shader_prog *shader_prog_find(struct shader_prog *prog, const char *name)
struct shader_prog *shader_prog_find(struct list *shaders, const char *name)
{
for (; prog; prog = prog->next)
struct shader_prog *prog;

list_for_each_entry(prog, shaders, entry)
if (!strcmp(prog->name, name))
return ref_get(prog);

return NULL;
}

int lib_request_shaders(const char *name, struct shader_prog **progp)
int lib_request_shaders(const char *name, struct list *shaders)
{
//char *nvert CUX(string), *nfrag CUX(string), *vert CUX(string), *frag CUX(string);
struct lib_handle *hv, *hf;
Expand All @@ -261,8 +270,7 @@ int lib_request_shaders(const char *name, struct shader_prog **progp)
if (!p)
return -1;

p->next = *progp;
*progp = p;
list_append(shaders, &p->entry);
ref_put_last(hv);
ref_put_last(hf);

Expand Down
8 changes: 4 additions & 4 deletions core/shader.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,17 @@ struct shader_prog {
GLint weights;
GLint tex;
struct ref ref;
struct shader_var *var;
struct list vars;
struct shader_data data;
struct shader_prog *next;
struct list entry;
};

struct shader_prog *
shader_prog_from_strings(const char *name, const char *vsh, const char *fsh);
GLint shader_prog_find_var(struct shader_prog *p, const char *var);
void shader_prog_use(struct shader_prog *p);
void shader_prog_done(struct shader_prog *p);
struct shader_prog *shader_prog_find(struct shader_prog *prog, const char *name);
int lib_request_shaders(const char *name, struct shader_prog **progp);
struct shader_prog *shader_prog_find(struct list *shaders, const char *name);
int lib_request_shaders(const char *name, struct list *shaders);

#endif /* __CLAP_SHADER_H__ */
2 changes: 1 addition & 1 deletion core/terrain.c
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ struct terrain *terrain_init_square_landscape(struct scene *s, float x, float y,
struct terrain *t;
struct model3d *model;
struct model3dtx *txm;
struct shader_prog *prog = shader_prog_find(s->prog, "terrain"); /* XXX */
struct shader_prog *prog = shader_prog_find(&s->shaders, "terrain"); /* XXX */
unsigned long total = nr_v * nr_v, it, bottom;
size_t vxsz, txsz, idxsz;
float *vx, *norm, *tx;
Expand Down
35 changes: 22 additions & 13 deletions core/ui.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ static void ui_add_model_tail(struct ui *ui, struct model3dtx *txmodel)
static int ui_model_init(struct ui *ui)
{
float x = 0.f, y = 0.f, w = 1.f, h = 1.f;
struct shader_prog *prog = shader_prog_find(ui->prog, "ui"); /* XXX */
struct shader_prog *prog = shader_prog_find(&ui->shaders, "ui"); /* XXX */

if (!prog) {
err("couldn't load 'ui' shaders\n");
Expand Down Expand Up @@ -393,7 +393,6 @@ ui_render_string(struct ui *ui, struct font *font, struct ui_element *parent,

fbo_ui.width = uit.width + uit.margin_x * 2;
fbo_ui.height = uit.height + uit.margin_y * 2;
fbo_ui.prog = ui->prog;
mq_init(&fbo_ui.mq, &fbo_ui);
fbo = fbo_new(fbo_ui.width, fbo_ui.height);
// fbo->retain_tex = 1;
Expand All @@ -406,7 +405,7 @@ ui_render_string(struct ui *ui, struct font *font, struct ui_element *parent,
y = (float)uit.margin_y + uit.y_off;
dbg_on(y < 0, "y: %f, height: %d y_off: %d, margin_y: %d\n",
y, uit.height, uit.y_off, uit.margin_y);
CHECK(prog = shader_prog_find(ui->prog, "glyph"));
CHECK(prog = shader_prog_find(&ui->shaders, "glyph"));
CHECK(uies = calloc(len, sizeof(struct ui_element *)));
uit.nr_uies = len;
for (line = 0, i = 0, x = x_off(&uit, line); i < len; i++) {
Expand Down Expand Up @@ -471,7 +470,7 @@ ui_render_string(struct ui *ui, struct font *font, struct ui_element *parent,
free(uit.line_ws);
free(uit.line_w);

prog = shader_prog_find(ui->prog, "ui");
prog = shader_prog_find(&ui->shaders, "ui");
m = model3d_new_quad(prog, 0, 1, 0, 1, -1);
model3d_set_name(m, "ui_text: '%s'", str);
m->cull_face = false;
Expand Down Expand Up @@ -943,7 +942,7 @@ ui_menu_build(struct ui *ui, struct ui_widget_builder *uwb, const char **items,
int i;

menu->focus = -1;
model = model3d_new_quad(ui->prog, 0, 0, 0.05, 1, 1);
model = model3d_new_quad(list_first_entry(&ui->shaders, struct shader_prog, entry), 0, 0, 0.05, 1, 1);
model3d_set_name(model, "ui_menu");
// /* XXX^1: texture model(s) hardcoded */
txm = model3dtx_new(ref_pass(model), "green.png");
Expand Down Expand Up @@ -1111,21 +1110,21 @@ void ui_inventory_init(struct ui *ui, int number_of_apples, float apple_ages[],
number_of_immature_apples++;
}
if (number_of_apples > 0) {
apple_m = model3d_new_quad(ui->prog, 0, 0, 0.05, 1, 1);
apple_m = model3d_new_quad(list_first_entry(&ui->shaders, struct shader_prog, entry), 0, 0, 0.05, 1, 1);
model3d_set_name(apple_m, "inventory apple");
apple_m->alpha_blend = true;
apple_txm = model3dtx_new(ref_pass(apple_m), "apple.png");
ui_add_model(ui, apple_txm);
}
if (number_of_immature_apples > 0) {
bar_m = model3d_new_quad(ui->prog, 0, 0, 0.03, 1, 1);
bar_m = model3d_new_quad(list_first_entry(&ui->shaders, struct shader_prog, entry), 0, 0, 0.03, 1, 1);
model3d_set_name(bar_m, "inventory bar on immature apple");
bar_m->cull_face = false;
bar_m->alpha_blend = false;
bar_txm = model3dtx_new(ref_pass(bar_m), "green.png");
ui_add_model(ui, bar_txm);
}
frame_m = model3d_new_frame(ui->prog, 0, 0, 0.01, 1, 1, 0.02);
frame_m = model3d_new_frame(list_first_entry(&ui->shaders, struct shader_prog, entry), 0, 0, 0.01, 1, 1, 0.02);
model3d_set_name(frame_m, "inventory item frame");
frame_m->cull_face = false;
frame_m->alpha_blend = false;
Expand Down Expand Up @@ -1429,7 +1428,7 @@ void ui_pip_update(struct ui *ui, struct fbo *fbo)
if (uie0)
ref_put(uie0);

prog = shader_prog_find(ui->prog, "ui");
prog = shader_prog_find(&ui->shaders, "ui");
m = model3d_new_quad(prog, 0, 1, 0.1, 1, -1);
m->cull_face = false;
m->alpha_blend = false;
Expand Down Expand Up @@ -1463,7 +1462,7 @@ struct ui_element *ui_pocket_new(struct ui *ui, const char **tex, int nr)
p = ui_element_new(ui, NULL, ui_quadtx, UI_AF_TOP | UI_AF_RIGHT,
10, 10, 200, 100 * nr);
for (i = 0; i < nr; i++) {
model = model3d_new_quad(ui->prog, 0, 0, 0.0, 1, 1);
model = model3d_new_quad(list_first_entry(&ui->shaders, struct shader_prog, entry), 0, 0, 0.0, 1, 1);
model3d_set_name(model, "ui_pocket_element");
txm = model3dtx_new(ref_pass(model), tex[i]);
if (!txm)
Expand Down Expand Up @@ -1541,7 +1540,7 @@ struct ui_element *ui_progress_new(struct ui *ui)

health_bar_width = width;

prog = shader_prog_find(ui->prog, "ui");
prog = shader_prog_find(&ui->shaders, "ui");

frame_m = model3d_new_frame(prog, 0, 0, 0.01, total_width, total_height, 1);
frame_txm = model3dtx_new(ref_pass(frame_m), "green.png");
Expand Down Expand Up @@ -1604,8 +1603,9 @@ int ui_init(struct ui *ui, int width, int height)

ui_debug_mod_str("off");
mq_init(&ui->mq, ui);
lib_request_shaders("glyph", &ui->prog);
lib_request_shaders("ui", &ui->prog);
list_init(&ui->shaders);
lib_request_shaders("glyph", &ui->shaders);
lib_request_shaders("ui", &ui->shaders);

ui->click = sound_load("stapler.ogg");
sound_set_gain(ui->click, 0.2);
Expand Down Expand Up @@ -1659,6 +1659,15 @@ void ui_done(struct ui *ui)
ui_roll_done();

mq_release(&ui->mq);

struct shader_prog *prog, *iter;

/*
* clean up the shaders that weren't freed by model3d_drop()
* via mq_release()
*/
list_for_each_entry_iter(prog, iter, &ui->shaders, entry)
ref_put(prog);
}

void ui_show(struct ui *ui)
Expand Down
2 changes: 1 addition & 1 deletion core/ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ struct ui_widget {
//int ui_element_init(struct scene *s, float x, float y, float w, float h);
struct ui {
struct mq mq;
struct shader_prog *prog;
struct list shaders;
struct sound *click;
struct ui_widget *menu;
struct ui_widget *inventory;
Expand Down
12 changes: 6 additions & 6 deletions demo/ldjam56/onehandclap.c
Original file line number Diff line number Diff line change
Expand Up @@ -383,12 +383,12 @@ int main(int argc, char **argv, char **envp)
sound_play(intro_sound);

/* Before models are created */
lib_request_shaders("contrast", &scene.prog);
lib_request_shaders("hblur", &scene.prog);
lib_request_shaders("vblur", &scene.prog);
lib_request_shaders("debug", &scene.prog);
lib_request_shaders("terrain", &scene.prog);
lib_request_shaders("model", &scene.prog);
lib_request_shaders("contrast", &scene.shaders);
lib_request_shaders("hblur", &scene.shaders);
lib_request_shaders("vblur", &scene.shaders);
lib_request_shaders("debug", &scene.shaders);
// lib_request_shaders("terrain", &scene.shaders);
lib_request_shaders("model", &scene.shaders);
//lib_request_shaders("ui", &scene);

fuzzer_input_init();
Expand Down

0 comments on commit 983cffd

Please sign in to comment.