From c84f528325a7edf0f808d081106d3ff6a196cb8a Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sat, 7 Jan 2023 18:42:48 -0800 Subject: Destroy all scene and scene elements upon termination. --- gfx/src/gfx.c | 10 ++-------- gfx/src/scene/scene_memory.c | 47 +++++++++++++++++++++++++++++++++++++++++++- gfx/src/scene/scene_memory.h | 4 ++-- gltfview/src/game.c | 3 --- 4 files changed, 50 insertions(+), 14 deletions(-) diff --git a/gfx/src/gfx.c b/gfx/src/gfx.c index 8321f86..4640a52 100644 --- a/gfx/src/gfx.c +++ b/gfx/src/gfx.c @@ -14,8 +14,8 @@ typedef struct Gfx { RenderBackend render_backend; - Renderer renderer; - scene_idx scene; // First child scene. + Renderer renderer; + scene_idx scene; // First child scene. } Gfx; Gfx* gfx_init() { @@ -42,12 +42,6 @@ void gfx_destroy(Gfx** gfx) { if (!gfx) { return; } - // Destroy scenes for convenience. - for (scene_idx scene_index = (*gfx)->scene; scene_index.val;) { - Scene* scene = mem_get_scene(scene_index); - scene_index = scene->next; - gfx_destroy_scene(*gfx, &scene); - } scene_mem_destroy(); renderer_destroy(&(*gfx)->renderer, &(*gfx)->render_backend); gfx_del_render_backend(&(*gfx)->render_backend); diff --git a/gfx/src/scene/scene_memory.c b/gfx/src/scene/scene_memory.c index 7355ad2..83ecd57 100644 --- a/gfx/src/scene/scene_memory.c +++ b/gfx/src/scene/scene_memory.c @@ -63,7 +63,52 @@ void scene_mem_init() { ALLOC_DUMMY(&mem.scenes); } -void scene_mem_destroy() {} +void scene_mem_destroy() { + // NOTE: the dummy objects are not constructed, so the destruction code below + // always skips index 0. (I don't really like the conditional inside the loop, + // but this gets the job done without having to specialize the loop macro.) + // + // First destroy the scenes. This will recursively destroy the scene's nodes + // and their objects and avoid a double-free when we then destroy any stray + // scene elements. + mempool_foreach(&mem.scenes, scene, { + if (i > 0) { + scene_destroy(scene); + } + }); + // Destroy remaining scene elements. + mempool_foreach(&mem.cameras, camera, { + if (i > 0) { + gfx_destroy_camera(&camera); + } + }); + mempool_foreach(&mem.lights, light, { + if (i > 0) { + gfx_destroy_light(&light); + } + }); + mempool_foreach(&mem.materials, material, { + if (i > 0) { + gfx_destroy_material(&material); + } + }); + mempool_foreach(&mem.meshes, mesh, { + if (i > 0) { + gfx_destroy_mesh(&mesh); + } + }); + // Mesh links don't have a destructor. + mempool_foreach(&mem.nodes, node, { + if (i > 0) { + gfx_destroy_node(&node); + } + }); + mempool_foreach(&mem.objects, object, { + if (i > 0) { + gfx_destroy_object(&object); + } + }); +} // Memory allocation. SceneCamera* mem_alloc_camera() { return mempool_alloc(&mem.cameras); } diff --git a/gfx/src/scene/scene_memory.h b/gfx/src/scene/scene_memory.h index b0fa73c..bd2c691 100644 --- a/gfx/src/scene/scene_memory.h +++ b/gfx/src/scene/scene_memory.h @@ -15,10 +15,10 @@ typedef struct Scene Scene; /// Initialize scene memory. /// /// The scene memory guarantees that every object maps to an index different -/// than 0. In this way, 0 can be used as a special index to denote "no value". +/// than 0. This way, 0 can be used as a special index to denote "no value". void scene_mem_init(); -/// Destroy the scene memory. +/// Destroy the scene memory and all allocated objects. void scene_mem_destroy(); /// ---------------------------------------------------------------------------- diff --git a/gltfview/src/game.c b/gltfview/src/game.c index 93755e7..612ec67 100644 --- a/gltfview/src/game.c +++ b/gltfview/src/game.c @@ -218,9 +218,6 @@ bool game_new(Game* game, int argc, const char** argv) { cleanup: LOGE("Gfx error: %s", gfx_get_error()); - if (game->scene) { - gfx_destroy_scene(game->gfx, &game->scene); - } if (game->gfx) { gfx_destroy(&game->gfx); } -- cgit v1.2.3