From 9fa21837ae7b54b62ea09939473aa987f07eaf90 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Wed, 9 Jul 2025 19:45:49 -0700 Subject: Rename scene_memory -> memory --- src/memory.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 src/memory.c (limited to 'src/memory.c') diff --git a/src/memory.c b/src/memory.c new file mode 100644 index 0000000..59bf8ca --- /dev/null +++ b/src/memory.c @@ -0,0 +1,178 @@ +#include "memory.h" + +#include + +#include "llr/light_impl.h" +#include "llr/material_impl.h" +#include "llr/mesh_impl.h" +#include "scene/animation_impl.h" +#include "scene/camera_impl.h" +#include "scene/model_impl.h" +#include "scene/node_impl.h" +#include "scene/object_impl.h" +#include "scene/scene_impl.h" + +#include +#include + +DEF_MEMPOOL(anima_pool, Anima, GFX_MAX_NUM_ANIMAS) +DEF_MEMPOOL(animation_pool, Animation, GFX_MAX_NUM_ANIMATIONS) +DEF_MEMPOOL(camera_pool, SceneCamera, GFX_MAX_NUM_CAMERAS) +DEF_MEMPOOL(light_pool, Light, GFX_MAX_NUM_LIGHTS) +DEF_MEMPOOL(material_pool, Material, GFX_MAX_NUM_MATERIALS) +DEF_MEMPOOL(mesh_pool, Mesh, GFX_MAX_NUM_MESHES) +DEF_MEMPOOL(mesh_link_pool, MeshLink, GFX_MAX_NUM_MESH_LINKS) +DEF_MEMPOOL(model_pool, Model, GFX_MAX_NUM_MODELS) +DEF_MEMPOOL(node_pool, SceneNode, GFX_MAX_NUM_NODES) +DEF_MEMPOOL(object_pool, SceneObject, GFX_MAX_NUM_OBJECTS) +DEF_MEMPOOL(scene_pool, Scene, GFX_MAX_NUM_SCENES) +DEF_MEMPOOL(skeleton_pool, Skeleton, GFX_MAX_NUM_SKELETONS) + +/// Scene memory. +/// +/// Holds memory pools for every type of scene object. +typedef struct SceneMemory { + anima_pool animas; + animation_pool animations; + camera_pool cameras; + light_pool lights; + material_pool materials; + mesh_pool meshs; // Purposeful typo to make the PLURAL() macro work. + mesh_link_pool mesh_links; + model_pool models; + node_pool nodes; + object_pool objects; + scene_pool scenes; + skeleton_pool skeletons; +} SceneMemory; + +static SceneMemory mem; + +#define ALLOC_DUMMY(POOL) \ + { \ + const void* object = mempool_alloc(POOL); \ + (void)object; /* Silence warning in release builds. */ \ + assert(mempool_get_block_index(POOL, object) == 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); + mempool_make(&mem.cameras); + mempool_make(&mem.lights); + mempool_make(&mem.materials); + mempool_make(&mem.meshs); + mempool_make(&mem.mesh_links); + mempool_make(&mem.models); + mempool_make(&mem.nodes); + mempool_make(&mem.objects); + mempool_make(&mem.scenes); + mempool_make(&mem.skeletons); + + // Allocate dummy objects at index 0 to guarantee that no objects allocated by + // the caller map to index 0. This allows 0 to be used as a sentinel. + ALLOC_DUMMY(&mem.animas); + ALLOC_DUMMY(&mem.animations); + ALLOC_DUMMY(&mem.cameras); + ALLOC_DUMMY(&mem.lights); + ALLOC_DUMMY(&mem.materials); + ALLOC_DUMMY(&mem.meshs); + ALLOC_DUMMY(&mem.mesh_links); + ALLOC_DUMMY(&mem.models); + ALLOC_DUMMY(&mem.nodes); + ALLOC_DUMMY(&mem.objects); + ALLOC_DUMMY(&mem.scenes); + ALLOC_DUMMY(&mem.skeletons); +} + +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); \ + } \ + }) + + // Print memory diagnostics. +#define PRINT_POOL(POOL_NAME, POOL) \ + { \ + const size_t capacity = mempool_capacity(POOL); \ + const size_t size = mempool_size(POOL); \ + const size_t block_size_bytes = mempool_block_size_bytes(POOL); \ + const size_t size_bytes = size * block_size_bytes; \ + const size_t capacity_bytes = capacity * block_size_bytes; \ + LOGI( \ + "%s pool: %lu/%lu (%lu/%lu bytes)", POOL_NAME, size, capacity, \ + size_bytes, capacity_bytes); \ + } + + LOGI("Pool diagnostics:"); + PRINT_POOL("Animas", &mem.animas); + PRINT_POOL("Animations", &mem.animations); + PRINT_POOL("Cameras", &mem.cameras); + PRINT_POOL("Lights", &mem.lights); + PRINT_POOL("Materials", &mem.materials); + PRINT_POOL("Meshes", &mem.meshs); + PRINT_POOL("Mesh links", &mem.mesh_links); + PRINT_POOL("Models", &mem.models); + PRINT_POOL("Nodes", &mem.nodes); + PRINT_POOL("Objects", &mem.objects); + PRINT_POOL("Scenes", &mem.scenes); + PRINT_POOL("Skeletons", &mem.skeletons); + + // Models contain scene elements. Destruction is handled by the remainder of + // scene destructionb elow. + // + // 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. + DESTROY(scene); + // Then delete stray nodes. This will delete their children nodes and + // resource. + DESTROY(node); + // Destroy remaining scene elements. + DESTROY(anima); + // Animations are owned by animas and do not have a destructor. + DESTROY(camera); + DESTROY(light); + DESTROY(material); + DESTROY(mesh); + // Mesh links don't have a destructor. + DESTROY(object); + // Skeletons are owned by animas and do not have a destructor. +} + +#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); */ \ + TYPE* mem_get_##NAME(NAMED_INDEX(NAME) index) { \ + assert(index.val != 0); /* 0 is the dummy allocation. */ \ + 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)}; \ + } + +DEF_MEMORY(anima, Anima) +DEF_MEMORY(animation, Animation) +DEF_MEMORY(camera, SceneCamera) +DEF_MEMORY(light, Light) +DEF_MEMORY(material, Material) +DEF_MEMORY(mesh, Mesh) +DEF_MEMORY(mesh_link, MeshLink) +DEF_MEMORY(model, Model) +DEF_MEMORY(node, SceneNode) +DEF_MEMORY(object, SceneObject) +DEF_MEMORY(scene, Scene) +DEF_MEMORY(skeleton, Skeleton) -- cgit v1.2.3