From 6ba8b628bf72c14372b70247e2f12df2bcd1c34e Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Fri, 2 Jun 2023 12:03:07 -0700 Subject: scene_memory refactor to make adding new types easier. --- gfx/include/gfx/gfx.h | 12 +-- gfx/include/gfx/scene/scene.h | 10 ++ gfx/src/gfx.c | 24 +---- gfx/src/scene/scene.c | 15 ++- gfx/src/scene/scene_impl.h | 6 -- gfx/src/scene/scene_memory.c | 221 ++++++++++-------------------------------- gfx/src/scene/scene_memory.h | 193 +++++------------------------------- gltfview/src/game.c | 2 +- 8 files changed, 99 insertions(+), 384 deletions(-) diff --git a/gfx/include/gfx/gfx.h b/gfx/include/gfx/gfx.h index 303ddcd..b8f2595 100644 --- a/gfx/include/gfx/gfx.h +++ b/gfx/include/gfx/gfx.h @@ -9,7 +9,7 @@ typedef struct SceneCamera SceneCamera; typedef struct Gfx Gfx; /// Create a new graphics system, -Gfx* gfx_init(); +Gfx* gfx_init(void); /// Destroy the graphics system. void gfx_destroy(Gfx**); @@ -23,16 +23,6 @@ Renderer* gfx_get_renderer(Gfx*); /// Get the immediate mode renderer. ImmRenderer* gfx_get_imm_renderer(Gfx*); -/// Create a new scene. -Scene* gfx_make_scene(Gfx*); - -/// Destroy the scene. -/// -/// This function destroys the scene and all objects that it owns (scene -/// objects, cameras, lights, etc), but not objects that could be shared with -/// other scenes (meshes, materials, etc). -void gfx_destroy_scene(Gfx*, Scene**); - /// Remove unused resources from the scene (meshes, materials). /// TODO: need to think about the interface for scene_purge(). Maybe this /// should be gfx_purge() and take a list of Scenes? diff --git a/gfx/include/gfx/scene/scene.h b/gfx/include/gfx/scene/scene.h index 5a1d823..f5c9ddf 100644 --- a/gfx/include/gfx/scene/scene.h +++ b/gfx/include/gfx/scene/scene.h @@ -7,6 +7,16 @@ typedef struct SceneNode SceneNode; typedef struct Scene Scene; +/// Create a new scene. +Scene* gfx_make_scene(void); + +/// Destroy the scene. +/// +/// This function destroys the scene and all objects that it owns (scene +/// objects, cameras, lights, etc), but not objects that could be shared with +/// other scenes (meshes, materials, etc). +void gfx_destroy_scene(Scene**); + /// Get the scene's root node. SceneNode* gfx_get_scene_root(Scene*); diff --git a/gfx/src/gfx.c b/gfx/src/gfx.c index 47f2187..fc720ed 100644 --- a/gfx/src/gfx.c +++ b/gfx/src/gfx.c @@ -14,13 +14,12 @@ #include typedef struct Gfx { - scene_idx scene; // First child scene. RenderBackend render_backend; Renderer renderer; ImmRenderer imm_renderer; } Gfx; -Gfx* gfx_init() { +Gfx* gfx_init(void) { if (!gladLoadGL()) { LOGE("Failed loading glad!"); return 0; @@ -72,24 +71,3 @@ ImmRenderer* gfx_get_imm_renderer(Gfx* gfx) { assert(gfx); return &gfx->imm_renderer; } - -Scene* gfx_make_scene(Gfx* gfx) { - Scene* scene = mem_alloc_scene(); - if (!scene) { - return 0; - } - scene_make(scene); - LIST_PREPEND(gfx->scene, scene); - return scene; -} - -void gfx_destroy_scene(Gfx* gfx, Scene** scene) { - assert(scene); - scene_destroy(*scene); - const scene_idx scene_index = mem_get_scene_index(*scene); - if (gfx->scene.val == scene_index.val) { - gfx->scene.val = 0; - } - LIST_REMOVE(*scene); - mem_free_scene(scene); -} diff --git a/gfx/src/scene/scene.c b/gfx/src/scene/scene.c index 19b9379..c3dae9c 100644 --- a/gfx/src/scene/scene.c +++ b/gfx/src/scene/scene.c @@ -1,18 +1,25 @@ #include "scene_impl.h" #include "node_impl.h" +#include "scene_memory.h" #include -void scene_make(Scene* scene) { - assert(scene); +Scene* gfx_make_scene(void) { + Scene* scene = mem_alloc_scene(); + if (!scene) { + return 0; + } scene->root = gfx_make_node(); assert(scene->root); + return scene; } -void scene_destroy(Scene* scene) { +void gfx_destroy_scene(Scene** scene) { assert(scene); - gfx_destroy_node(&scene->root); + assert(*scene); + gfx_destroy_node(&(*scene)->root); + mem_free_scene(scene); } SceneNode* gfx_get_scene_root(Scene* scene) { diff --git a/gfx/src/scene/scene_impl.h b/gfx/src/scene/scene_impl.h index 25ec8da..992f620 100644 --- a/gfx/src/scene/scene_impl.h +++ b/gfx/src/scene/scene_impl.h @@ -11,9 +11,3 @@ typedef struct Scene { scene_idx next; scene_idx prev; } Scene; - -/// Create a new scene. -void scene_make(Scene*); - -/// Destroy the scene. -void scene_destroy(Scene*); diff --git a/gfx/src/scene/scene_memory.c b/gfx/src/scene/scene_memory.c index 217c719..ecd9434 100644 --- a/gfx/src/scene/scene_memory.c +++ b/gfx/src/scene/scene_memory.c @@ -10,7 +10,6 @@ #include "node_impl.h" #include "object_impl.h" #include "scene_impl.h" -#include "types.h" #include @@ -37,7 +36,7 @@ typedef struct SceneMemory { joint_pool joints; light_pool lights; material_pool materials; - mesh_pool meshes; + mesh_pool meshs; // Purposeful typo to make the PLURAL() macro work. mesh_link_pool mesh_links; node_pool nodes; object_pool objects; @@ -50,6 +49,9 @@ static SceneMemory mem; #define ALLOC_DUMMY(POOL) \ assert(mempool_get_block_index(POOL, mempool_alloc(POOL)) == 0) +#define PLURAL(name) name##s +#define MEM_FIELD(name) mem.PLURAL(name) + void scene_mem_init() { mempool_make(&mem.animas); mempool_make(&mem.animations); @@ -57,7 +59,7 @@ void scene_mem_init() { mempool_make(&mem.joints); mempool_make(&mem.lights); mempool_make(&mem.materials); - mempool_make(&mem.meshes); + mempool_make(&mem.meshs); mempool_make(&mem.mesh_links); mempool_make(&mem.nodes); mempool_make(&mem.objects); @@ -72,7 +74,7 @@ void scene_mem_init() { ALLOC_DUMMY(&mem.joints); ALLOC_DUMMY(&mem.lights); ALLOC_DUMMY(&mem.materials); - ALLOC_DUMMY(&mem.meshes); + ALLOC_DUMMY(&mem.meshs); ALLOC_DUMMY(&mem.mesh_links); ALLOC_DUMMY(&mem.nodes); ALLOC_DUMMY(&mem.objects); @@ -84,182 +86,59 @@ 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.) - // +#define DESTROY(name) \ + mempool_foreach(&MEM_FIELD(name), obj, { \ + if (i > 0) { \ + gfx_destroy_##name(&obj); \ + } \ + }) + // 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(scene); // Then delete stray nodes. This will delete their children nodes and // resource. - mempool_foreach(&mem.nodes, node, { - if (i > 0) { - gfx_destroy_node(&node); - } - }); + DESTROY(node); // Destroy remaining scene elements. - mempool_foreach(&mem.animas, anima, { - if (i > 0) { - gfx_destroy_anima(&anima); - } - }); + DESTROY(anima); // Animations are owned by animas and do not have a destructor. - mempool_foreach(&mem.cameras, camera, { - if (i > 0) { - gfx_destroy_camera(&camera); - } - }); - mempool_foreach(&mem.joints, joint, { - if (i > 0) { - gfx_destroy_joint(&joint); - } - }); - 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); - } - }); + DESTROY(camera); + DESTROY(joint); + DESTROY(light); + DESTROY(material); + DESTROY(mesh); // Mesh links don't have a destructor. - mempool_foreach(&mem.objects, object, { - if (i > 0) { - gfx_destroy_object(&object); - } - }); + DESTROY(object); // Skeletons are owned by animas and do not have a destructor. } -// Memory allocation. -Anima* mem_alloc_anima() { return mempool_alloc(&mem.animas); } -Animation* mem_alloc_animation() { return mempool_alloc(&mem.animations); } -SceneCamera* mem_alloc_camera() { return mempool_alloc(&mem.cameras); } -Joint* mem_alloc_joint() { return mempool_alloc(&mem.joints); } -Light* mem_alloc_light() { return mempool_alloc(&mem.lights); } -Material* mem_alloc_material() { return mempool_alloc(&mem.materials); } -Mesh* mem_alloc_mesh() { return mempool_alloc(&mem.meshes); } -MeshLink* mem_alloc_mesh_link() { return mempool_alloc(&mem.mesh_links); } -SceneNode* mem_alloc_node() { return mempool_alloc(&mem.nodes); } -SceneObject* mem_alloc_object() { return mempool_alloc(&mem.objects); } -Scene* mem_alloc_scene() { return mempool_alloc(&mem.scenes); } -Skeleton* mem_alloc_skeleton() { return mempool_alloc(&mem.skeletons); } - -// Memory free. -void mem_free_anima(Anima** anima) { mempool_free(&mem.animas, anima); } -void mem_free_animation(Animation** animation) { - mempool_free(&mem.animations, animation); -} -void mem_free_camera(SceneCamera** camera) { - mempool_free(&mem.cameras, camera); -} -void mem_free_joint(Joint** joint) { mempool_free(&mem.joints, joint); } -void mem_free_light(Light** light) { mempool_free(&mem.lights, light); } -void mem_free_material(Material** material) { - mempool_free(&mem.materials, material); -} -void mem_free_mesh(Mesh** mesh) { mempool_free(&mem.meshes, mesh); } -void mem_free_mesh_link(MeshLink** mesh_link) { - mempool_free(&mem.mesh_links, mesh_link); -} -void mem_free_node(SceneNode** node) { mempool_free(&mem.nodes, node); } -void mem_free_object(SceneObject** object) { - mempool_free(&mem.objects, object); -} -void mem_free_scene(Scene** scene) { mempool_free(&mem.scenes, scene); } -void mem_free_skeleton(Skeleton** skeleton) { - mempool_free(&mem.skeletons, skeleton); -} - -// Query by index. -// -// TODO: Check for 0 index and return nullptr? Otherwise this can accidentally -// return a pointer to the dummy objects. -Anima* mem_get_anima(anima_idx index) { - return mempool_get_block(&mem.animas, index.val); -} -Animation* mem_get_animation(animation_idx index) { - return mempool_get_block(&mem.animations, index.val); -} -SceneCamera* mem_get_camera(camera_idx index) { - return mempool_get_block(&mem.cameras, index.val); -} -Joint* mem_get_joint(joint_idx index) { - return mempool_get_block(&mem.joints, index.val); -} -Light* mem_get_light(light_idx index) { - return mempool_get_block(&mem.lights, index.val); -} -Material* mem_get_material(material_idx index) { - return mempool_get_block(&mem.materials, index.val); -} -Mesh* mem_get_mesh(mesh_idx index) { - return mempool_get_block(&mem.meshes, index.val); -} -MeshLink* mem_get_mesh_link(mesh_link_idx index) { - return mempool_get_block(&mem.mesh_links, index.val); -} -SceneNode* mem_get_node(node_idx index) { - return mempool_get_block(&mem.nodes, index.val); -} -SceneObject* mem_get_object(object_idx index) { - return mempool_get_block(&mem.objects, index.val); -} -Scene* mem_get_scene(scene_idx index) { - return mempool_get_block(&mem.scenes, index.val); -} -Skeleton* mem_get_skeleton(skeleton_idx index) { - return mempool_get_block(&mem.skeletons, index.val); -} +#define DEF_MEMORY(name, type) \ + /* xyz* mem_alloc_xyz(); */ \ + type* mem_alloc_##name() { return mempool_alloc(&MEM_FIELD(name)); } \ + /* void mem_free_xyz(xyz**); */ \ + void mem_free_##name(type** obj) { mempool_free(&MEM_FIELD(name), obj); } \ + /* xyz* mem_get_xyz(xyz_idx); */ \ + /* TODO: Check for 0 index and return nullptr? Otherwise this can \ + * accidentally return a pointer to the dummy objects. */ \ + type* mem_get_##name(NAMED_INDEX(name) index) { \ + return mempool_get_block(&MEM_FIELD(name), index.val); \ + } \ + /* xyz_idx mem_get_xyz_index(const xyz*); */ \ + NAMED_INDEX(name) mem_get_##name##_index(const type* obj) { \ + return (NAMED_INDEX(name)){ \ + .val = mempool_get_block_index(&MEM_FIELD(name), obj)}; \ + } -// Map object to index. -anima_idx mem_get_anima_index(const Anima* anima) { - return (anima_idx){.val = mempool_get_block_index(&mem.animas, anima)}; -} -animation_idx mem_get_animation_index(const Animation* animation) { - return (animation_idx){ - .val = mempool_get_block_index(&mem.animations, animation)}; -} -camera_idx mem_get_camera_index(const SceneCamera* camera) { - return (camera_idx){.val = mempool_get_block_index(&mem.cameras, camera)}; -} -joint_idx mem_get_joint_index(const Joint* joint) { - return (joint_idx){.val = mempool_get_block_index(&mem.joints, joint)}; -} -light_idx mem_get_light_index(const Light* light) { - return (light_idx){.val = mempool_get_block_index(&mem.lights, light)}; -} -material_idx mem_get_material_index(const Material* material) { - return (material_idx){ - .val = mempool_get_block_index(&mem.materials, material)}; -} -mesh_idx mem_get_mesh_index(const Mesh* mesh) { - return (mesh_idx){.val = mempool_get_block_index(&mem.meshes, mesh)}; -} -mesh_link_idx mem_get_mesh_link_index(const MeshLink* mesh_link) { - return (mesh_link_idx){ - .val = mempool_get_block_index(&mem.mesh_links, mesh_link)}; -} -node_idx mem_get_node_index(const SceneNode* node) { - return (node_idx){.val = mempool_get_block_index(&mem.nodes, node)}; -} -object_idx mem_get_object_index(const SceneObject* object) { - return (object_idx){.val = mempool_get_block_index(&mem.objects, object)}; -} -scene_idx mem_get_scene_index(const Scene* scene) { - return (scene_idx){.val = mempool_get_block_index(&mem.scenes, scene)}; -} -skeleton_idx mem_get_skeleton_index(const Skeleton* skeleton) { - return (skeleton_idx){ - .val = mempool_get_block_index(&mem.skeletons, skeleton)}; -} +DEF_MEMORY(anima, Anima) +DEF_MEMORY(animation, Animation) +DEF_MEMORY(camera, SceneCamera) +DEF_MEMORY(joint, Joint) +DEF_MEMORY(light, Light) +DEF_MEMORY(material, Material) +DEF_MEMORY(mesh, Mesh) +DEF_MEMORY(mesh_link, MeshLink) +DEF_MEMORY(node, SceneNode) +DEF_MEMORY(object, SceneObject) +DEF_MEMORY(scene, Scene) +DEF_MEMORY(skeleton, Skeleton) diff --git a/gfx/src/scene/scene_memory.h b/gfx/src/scene/scene_memory.h index 197e4ca..9486ee6 100644 --- a/gfx/src/scene/scene_memory.h +++ b/gfx/src/scene/scene_memory.h @@ -4,19 +4,6 @@ #include "animation_impl.h" #include "types.h" -typedef struct Anima Anima; -typedef struct Animation Animation; -typedef struct Joint Joint; -typedef struct Light Light; -typedef struct Material Material; -typedef struct Mesh Mesh; -typedef struct MeshLink MeshLink; -typedef struct SceneCamera SceneCamera; -typedef struct SceneNode SceneNode; -typedef struct SceneObject SceneObject; -typedef struct Scene Scene; -typedef struct Skeleton Skeleton; - /// Initialize scene memory. /// /// The scene memory guarantees that every object maps to an index different @@ -26,158 +13,28 @@ void scene_mem_init(); /// Destroy the scene memory and all allocated objects. void scene_mem_destroy(); -/// ---------------------------------------------------------------------------- -/// Memory allocation. -/// ---------------------------------------------------------------------------- - -/// Allocate space for an anima. -Anima* mem_alloc_anima(); - -/// Allocate space for an animation. -Animation* mem_alloc_animation(); - -/// Allocate space for a camera. -SceneCamera* mem_alloc_camera(); - -/// Allocate space for a joint. -Joint* mem_alloc_joint(); - -/// Allocate space for a light. -Light* mem_alloc_light(); - -/// Allocate space for a material. -Material* mem_alloc_material(); - -/// Allocate space for a mesh. -Mesh* mem_alloc_mesh(); - -/// Allocate space for a mesh link. -MeshLink* mem_alloc_mesh_link(); - -/// Allocate space for a scene node. -SceneNode* mem_alloc_node(); - -/// Allocate space for a scene object. -SceneObject* mem_alloc_object(); - -/// Allocate space for a scene. -Scene* mem_alloc_scene(); - -/// Allocate space for a skeleton. -Skeleton* mem_alloc_skeleton(); - -/// Free the anima. -void mem_free_anima(Anima**); - -/// Free the animation. -void mem_free_animation(Animation**); - -/// Free the camera. -void mem_free_camera(SceneCamera**); - -/// Free the joint. -void mem_free_joint(Joint**); - -/// Free the light. -void mem_free_light(Light**); - -/// Free the material. -void mem_free_material(Material**); - -/// Free the mesh. -void mem_free_mesh(Mesh**); - -/// Free the mesh link. -void mem_free_mesh_link(MeshLink**); - -/// Free the scene node. -void mem_free_node(SceneNode**); - -/// Free the scene object. -void mem_free_object(SceneObject**); - -/// Free the scene. -void mem_free_scene(Scene**); - -/// Free the skeleton. -void mem_free_skeleton(Skeleton**); - -/// ---------------------------------------------------------------------------- -/// Query objects by index. -/// ---------------------------------------------------------------------------- - -/// Get an anima by index. -Anima* mem_get_anima(anima_idx); - -/// Get an animation by index. -Animation* mem_get_animation(animation_idx); - -/// Get a camera by index. -SceneCamera* mem_get_camera(camera_idx); - -/// Get a joint by index. -Joint* mem_get_joint(joint_idx); - -/// Get a light by index. -Light* mem_get_light(light_idx); - -/// Get a material by index. -Material* mem_get_material(material_idx); - -/// Get a mesh by index. -Mesh* mem_get_mesh(mesh_idx); - -/// Get a mesh link by index. -MeshLink* mem_get_mesh_link(mesh_link_idx); - -/// Get a node by index. -SceneNode* mem_get_node(node_idx); - -/// Get an object by index. -SceneObject* mem_get_object(object_idx); - -/// Get a scene by index. -Scene* mem_get_scene(scene_idx); - -/// Get a skeleton by index. -Skeleton* mem_get_skeleton(skeleton_idx); - -/// ---------------------------------------------------------------------------- -/// Map objects to indices. -/// ---------------------------------------------------------------------------- - -/// Get the anima's index. -anima_idx mem_get_anima_index(const Anima*); - -/// Get the animation's index. -animation_idx mem_get_animation_index(const Animation*); - -/// Get the camera's index. -camera_idx mem_get_camera_index(const SceneCamera*); - -/// Get the joint's index. -joint_idx mem_get_joint_index(const Joint*); - -/// Get the light's index. -light_idx mem_get_light_index(const Light*); - -/// Get the material's index. -material_idx mem_get_material_index(const Material*); - -/// Get the mesh's index. -mesh_idx mem_get_mesh_index(const Mesh*); - -/// Get the mesh link's index. -mesh_link_idx mem_get_mesh_link_index(const MeshLink*); - -/// Get the node's index. -node_idx mem_get_node_index(const SceneNode*); - -/// Get the object's index. -object_idx mem_get_object_index(const SceneObject*); - -/// Get the scene's index. -scene_idx mem_get_scene_index(const Scene*); - -/// Get the skeleton's index. -skeleton_idx mem_get_skeleton_index(const Skeleton*); +#define NAMED_INDEX(name) name##_idx + +#define DECL_MEMORY(name, type) \ + typedef struct type type; \ + /* xyz* mem_alloc_xyz() */ \ + type* mem_alloc_##name(); \ + /* mem_free_xyz(xyz**) */ \ + void mem_free_##name(type**); \ + /* xyz* mem_get_xyz(xyz_idx); */ \ + type* mem_get_##name(NAMED_INDEX(name)); \ + /* xyz_idx mem_get_xyz_index(const xyz*); */ \ + NAMED_INDEX(name) mem_get_##name##_index(const type*); + +DECL_MEMORY(anima, Anima) +DECL_MEMORY(animation, Animation) +DECL_MEMORY(camera, SceneCamera) +DECL_MEMORY(joint, Joint) +DECL_MEMORY(light, Light) +DECL_MEMORY(material, Material) +DECL_MEMORY(mesh, Mesh) +DECL_MEMORY(mesh_link, MeshLink) +DECL_MEMORY(node, SceneNode) +DECL_MEMORY(object, SceneObject) +DECL_MEMORY(scene, Scene) +DECL_MEMORY(skeleton, Skeleton) diff --git a/gltfview/src/game.c b/gltfview/src/game.c index 20f33bb..9709ea5 100644 --- a/gltfview/src/game.c +++ b/gltfview/src/game.c @@ -194,7 +194,7 @@ bool game_new(Game* game, int argc, const char** argv) { game->render_backend = gfx_get_render_backend(game->gfx); game->renderer = gfx_get_renderer(game->gfx); - game->scene = gfx_make_scene(game->gfx); + game->scene = gfx_make_scene(); if (!game->scene) { goto cleanup; } -- cgit v1.2.3