aboutsummaryrefslogtreecommitdiff
path: root/src/scene
diff options
context:
space:
mode:
Diffstat (limited to 'src/scene')
-rw-r--r--src/scene/scene_graph.h42
-rw-r--r--src/scene/scene_memory.c59
2 files changed, 68 insertions, 33 deletions
diff --git a/src/scene/scene_graph.h b/src/scene/scene_graph.h
index a26f828..0b1f7d0 100644
--- a/src/scene/scene_graph.h
+++ b/src/scene/scene_graph.h
@@ -6,35 +6,41 @@
6// NOTE: SceneMemory guarantees that index 0 can be regarded as an invalid 6// NOTE: SceneMemory guarantees that index 0 can be regarded as an invalid
7// index. 7// index.
8 8
9#define MEM_GET(INDEX) \ 9#define MEM_GET(INDEX) \
10 _Generic((INDEX), camera_idx \ 10 _Generic( \
11 : mem_get_camera, material_idx \ 11 (INDEX), \
12 : mem_get_material, mesh_idx \ 12 camera_idx: mem_get_camera, \
13 : mem_get_mesh, mesh_link_idx \ 13 material_idx: mem_get_material, \
14 : mem_get_mesh_link, node_idx \ 14 mesh_idx: mem_get_mesh, \
15 : mem_get_node, object_idx \ 15 mesh_link_idx: mem_get_mesh_link, \
16 : mem_get_object, scene_idx \ 16 node_idx: mem_get_node, \
17 : mem_get_scene)(INDEX) 17 object_idx: mem_get_object, \
18 scene_idx: mem_get_scene)(INDEX)
18 19
19#define MEM_GET_INDEX(ITEM) \ 20#define MEM_GET_INDEX(ITEM) \
20 _Generic((ITEM), SceneCamera * \ 21 _Generic( \
21 : mem_get_camera_index, Material * \ 22 (ITEM), \
22 : mem_get_material_index, Mesh * \ 23 SceneCamera *: mem_get_camera_index, \
23 : mem_get_mesh_index, MeshLink * \ 24 Material *: mem_get_material_index, \
24 : mem_get_mesh_link_index, SceneNode * \ 25 Mesh *: mem_get_mesh_index, \
25 : mem_get_node_index, SceneObject * \ 26 MeshLink *: mem_get_mesh_link_index, \
26 : mem_get_object_index, Scene * \ 27 SceneNode *: mem_get_node_index, \
27 : mem_get_scene_index)(ITEM) 28 SceneObject *: mem_get_object_index, \
29 Scene *: mem_get_scene_index)(ITEM)
28 30
29/// Assert the list node invariant. 31/// Assert the list node invariant.
30/// 32///
31/// - A node does not point to itself. 33/// - A node does not point to itself.
34#if NDEBUG
35#define ASSERT_LIST_NODE_INVARIANT(ITEM)
36#else
32#define ASSERT_LIST_NODE_INVARIANT(ITEM) \ 37#define ASSERT_LIST_NODE_INVARIANT(ITEM) \
33 { \ 38 { \
34 const gfx_idx item_idx = MEM_GET_INDEX(ITEM).val; \ 39 const gfx_idx item_idx = MEM_GET_INDEX(ITEM).val; \
35 assert((ITEM)->prev.val != item_idx); \ 40 assert((ITEM)->prev.val != item_idx); \
36 assert((ITEM)->next.val != item_idx); \ 41 assert((ITEM)->next.val != item_idx); \
37 } 42 }
43#endif
38 44
39/// Assert the tree node invariant. 45/// Assert the tree node invariant.
40/// 46///
diff --git a/src/scene/scene_memory.c b/src/scene/scene_memory.c
index 85c27e7..d1d81a9 100644
--- a/src/scene/scene_memory.c
+++ b/src/scene/scene_memory.c
@@ -12,6 +12,7 @@
12#include "object_impl.h" 12#include "object_impl.h"
13#include "scene_impl.h" 13#include "scene_impl.h"
14 14
15#include <log/log.h>
15#include <mempool.h> 16#include <mempool.h>
16 17
17DEF_MEMPOOL(anima_pool, Anima, GFX_MAX_NUM_ANIMAS) 18DEF_MEMPOOL(anima_pool, Anima, GFX_MAX_NUM_ANIMAS)
@@ -47,10 +48,11 @@ typedef struct SceneMemory {
47 48
48static SceneMemory mem; 49static SceneMemory mem;
49 50
50#define ALLOC_DUMMY(POOL) \ 51#define ALLOC_DUMMY(POOL) \
51 { \ 52 { \
52 const void* object = mempool_alloc(POOL); \ 53 const void* object = mempool_alloc(POOL); \
53 assert(mempool_get_block_index(POOL, object) == 0); \ 54 (void)object; /* Silence warning in release builds. */ \
55 assert(mempool_get_block_index(POOL, object) == 0); \
54 } 56 }
55 57
56#define PLURAL(name) name##s 58#define PLURAL(name) name##s
@@ -90,13 +92,40 @@ void scene_mem_destroy() {
90 // NOTE: the dummy objects are not constructed, so the destruction code below 92 // NOTE: the dummy objects are not constructed, so the destruction code below
91 // always skips index 0. (I don't really like the conditional inside the loop, 93 // always skips index 0. (I don't really like the conditional inside the loop,
92 // but this gets the job done without having to specialize the loop macro.) 94 // but this gets the job done without having to specialize the loop macro.)
93#define DESTROY(name) \ 95#define DESTROY(NAME) \
94 mempool_foreach(&MEM_FIELD(name), obj, { \ 96 mempool_foreach(&MEM_FIELD(NAME), obj, { \
95 if (i > 0) { \ 97 if (i > 0) { \
96 gfx_destroy_##name(&obj); \ 98 gfx_destroy_##NAME(&obj); \
97 } \ 99 } \
98 }) 100 })
99 101
102 // Print memory diagnostics.
103#define PRINT_POOL(POOL_NAME, POOL) \
104 { \
105 const size_t capacity = mempool_capacity(POOL); \
106 const size_t size = mempool_size(POOL); \
107 const size_t block_size_bytes = mempool_block_size_bytes(POOL); \
108 const size_t size_bytes = size * block_size_bytes; \
109 const size_t capacity_bytes = capacity * block_size_bytes; \
110 LOGI( \
111 "%s pool: %lu/%lu (%lu/%lu bytes)", POOL_NAME, size, capacity, \
112 size_bytes, capacity_bytes); \
113 }
114
115 LOGI("Pool diagnostics:");
116 PRINT_POOL("Animas", &mem.animas);
117 PRINT_POOL("Animations", &mem.animations);
118 PRINT_POOL("Cameras", &mem.cameras);
119 PRINT_POOL("Lights", &mem.lights);
120 PRINT_POOL("Materials", &mem.materials);
121 PRINT_POOL("Meshes", &mem.meshs);
122 PRINT_POOL("Mesh links", &mem.mesh_links);
123 PRINT_POOL("Models", &mem.models);
124 PRINT_POOL("Nodes", &mem.nodes);
125 PRINT_POOL("Objects", &mem.objects);
126 PRINT_POOL("Scenes", &mem.scenes);
127 PRINT_POOL("Skeletons", &mem.skeletons);
128
100 // Models contain scene elements. Destruction is handled by the remainder of 129 // Models contain scene elements. Destruction is handled by the remainder of
101 // scene destructionb elow. 130 // scene destructionb elow.
102 // 131 //
@@ -119,20 +148,20 @@ void scene_mem_destroy() {
119 // Skeletons are owned by animas and do not have a destructor. 148 // Skeletons are owned by animas and do not have a destructor.
120} 149}
121 150
122#define DEF_MEMORY(name, type) \ 151#define DEF_MEMORY(NAME, TYPE) \
123 /* xyz* mem_alloc_xyz(); */ \ 152 /* xyz* mem_alloc_xyz(); */ \
124 type* mem_alloc_##name() { return mempool_alloc(&MEM_FIELD(name)); } \ 153 TYPE* mem_alloc_##NAME() { return mempool_alloc(&MEM_FIELD(NAME)); } \
125 /* void mem_free_xyz(xyz**); */ \ 154 /* void mem_free_xyz(xyz**); */ \
126 void mem_free_##name(type** obj) { mempool_free(&MEM_FIELD(name), obj); } \ 155 void mem_free_##NAME(TYPE** obj) { mempool_free(&MEM_FIELD(NAME), obj); } \
127 /* xyz* mem_get_xyz(xyz_idx); */ \ 156 /* xyz* mem_get_xyz(xyz_idx); */ \
128 type* mem_get_##name(NAMED_INDEX(name) index) { \ 157 TYPE* mem_get_##NAME(NAMED_INDEX(NAME) index) { \
129 assert(index.val != 0); /* 0 is the dummy allocation. */ \ 158 assert(index.val != 0); /* 0 is the dummy allocation. */ \
130 return mempool_get_block(&MEM_FIELD(name), index.val); \ 159 return mempool_get_block(&MEM_FIELD(NAME), index.val); \
131 } \ 160 } \
132 /* xyz_idx mem_get_xyz_index(const xyz*); */ \ 161 /* xyz_idx mem_get_xyz_index(const xyz*); */ \
133 NAMED_INDEX(name) mem_get_##name##_index(const type* obj) { \ 162 NAMED_INDEX(NAME) mem_get_##NAME##_index(const TYPE* obj) { \
134 return (NAMED_INDEX(name)){ \ 163 return (NAMED_INDEX(NAME)){ \
135 .val = mempool_get_block_index(&MEM_FIELD(name), obj)}; \ 164 .val = mempool_get_block_index(&MEM_FIELD(NAME), obj)}; \
136 } 165 }
137 166
138DEF_MEMORY(anima, Anima) 167DEF_MEMORY(anima, Anima)