commit a1efa0bf5f3b85e04c5819a8ec54cc8722a7e659
parent 640f12d0e6bc5ed7944d999ce5c1c131d22eb63a
Author: William Casarin <jb55@jb55.com>
Date:   Fri,  5 Jul 2019 10:40:00 -0700
wip: static resources
Diffstat:
12 files changed, 143 insertions(+), 68 deletions(-)
diff --git a/src/common.h b/src/common.h
@@ -8,6 +8,7 @@ typedef int bool;
 
 #define MAT3_ELEMS 9
 #define MAT4_ELEMS 16
+#define U64HOB 0x8000000000000000
 
 #define SLAB(f) "etc/slab/" f
 #define RESOURCE(f) "etc/shaders/" f
diff --git a/src/entity.c b/src/entity.c
@@ -21,7 +21,7 @@ struct entity *get_all_entities(u32 *count, entity_id **ids) {
 
 struct entity *init_entity(struct entity *ent, node_id *id) {
     node_id new_id;
-    init_model_id(&ent->model_id);
+    init_id(&ent->model_id);
     if (id == NULL) {
         init_id(&new_id);
         new_node(&new_id);
diff --git a/src/geometry.c b/src/geometry.c
@@ -5,7 +5,6 @@
 #include "debug.h"
 #include <assert.h>
 
-
 static struct resource_manager geom_manager;
 
 void
@@ -174,7 +173,7 @@ void geometry_centroid(struct geometry *geom, float *dest) {
 
 void init_geometry_manager() {
     init_resource_manager(&geom_manager, sizeof(struct geometry),
-                          DEF_NUM_GEOMETRY, MAX_GEOMETRY, "geometry");
+                          DEF_NUM_GEOMETRY, MAX_GEOMETRY, "geometry", NULL);
 }
 
 struct geometry *get_geometry(geometry_id *geom_id) {
diff --git a/src/model.c b/src/model.c
@@ -17,13 +17,6 @@ static struct resource_manager dyn_modelman;
 
 static int static_models_initialized = 0;
 
-void init_model_id(model_id *id)
-{
-    /* assert((int)id->dyn_model_id.index != -1); */
-    id->type = DYNAMIC_MODEL;
-    init_id(&id->dyn_model_id);
-}
-
 struct model *init_model(struct model *model) {
     init_id(&model->geom_id);
     model->shading = SHADING_VERT_COLOR;
@@ -46,7 +39,7 @@ static inline struct model *new_uninitialized_model(struct resource_id *id) {
 
 static struct model *new_model_resource(model_id *model_id)
 {
-    struct model *model = new_uninitialized_model(&model_id->dyn_model_id);
+    struct model *model = new_uninitialized_model(model_id);
     /* debug("new model %llu\n", model_id->dyn_model_id.uuid); */
     init_id(&model->geom_id);
     new_geometry(&model->geom_id);
@@ -61,23 +54,13 @@ void init_model_manager() {
 
 struct model *new_model(model_id *id)
 {
-    id->type = DYNAMIC_MODEL;
     return new_model_resource(id);
 }
 
+
 struct model *get_model(model_id *model_id)
 {
-
-    switch(model_id->type) {
-    case DYNAMIC_MODEL:
-        return get_resource(&dyn_modelman, &model_id->dyn_model_id);
-    case STATIC_MODEL: {
-        struct model *model;
-        get_static_model(model_id->static_model_id, &model);
-        return model;
-    }
-    }
-    assert(!"unhandled case in get_model");
+    return get_resource(&dyn_modelman, model_id);
 }
 
 
@@ -106,26 +89,22 @@ static struct model *load_static_model(enum static_model m)
 
 void destroy_model(model_id *model_id)
 {
-    if (model_id->type == STATIC_MODEL)
+    if (is_static_resource(model_id))
         return;
 
-    struct resource_id *id = &model_id->dyn_model_id;
     struct model *model = get_model(model_id);
 
     destroy_geometry(&model->geom_id);
-    destroy_resource(&dyn_modelman, id);
+    destroy_resource(&dyn_modelman, model_id);
 }
 
+
 model_id get_static_model(enum static_model m, struct model **model)
 {
-    model_id model_id;
-    model_id.type = STATIC_MODEL;
-    model_id.static_model_id = m;
-
     if (model)
         *model = load_static_model(m);
 
-    return model_id;
+    return make_static_id(m);
 }
 
 
diff --git a/src/model.h b/src/model.h
@@ -12,6 +12,8 @@
 #define MAX_STATIC_MODELS 128
 #define MAX_DYNAMIC_MODELS 2048
 
+typedef struct resource_id model_id;
+
 enum static_model {
   model_tower,
   model_icosphere,
@@ -19,21 +21,6 @@ enum static_model {
   NUM_STATIC_MODELS
 };
 
-enum model_type {
-  STATIC_MODEL,
-  DYNAMIC_MODEL
-};
-
-typedef struct model_id_t
-{
-    enum model_type type;
-    union {
-        struct resource_id dyn_model_id;
-        enum static_model static_model_id;
-    };
-} model_id;
-
-
 enum shading {
     SHADING_TERRAIN,
     SHADING_VERT_COLOR,
diff --git a/src/node.c b/src/node.c
@@ -40,7 +40,13 @@ void destroy_node(node_id *id)
 
 void init_node_manager()
 {
-    init_resource_manager(&node_manager, sizeof(struct node), 128, 0xFFFF, "node");
+    struct static_resources nodes = {
+      .count     = 0,
+      .capacity  = N_STATIC_NODES,
+    };
+
+    init_resource_manager(&node_manager, sizeof(struct node), 128,
+                          0xFFFF, "node", &nodes);
 }
 
 struct node *node_init(struct node *node) {
diff --git a/src/node.h b/src/node.h
@@ -5,6 +5,7 @@
 #include "resource.h"
 
 #define MAX_NODE_CHILDREN 4
+#define N_STATIC_NODES 32
 
 enum node_flags {
   NODE_IGNORE_RECALC = 1 << 0
diff --git a/src/resource.c b/src/resource.c
@@ -9,10 +9,21 @@
 
 static u64 resource_uuids = 0;
 
-static inline void *index_resource(struct resource_manager *r, int i) {
-    unsigned char *p = r->resources;
-    assert(p);
-    return p + (i * r->elem_size);
+static inline void *index_resource_(u8 *res, u32 elem_size, int i)
+{
+    assert(res);
+    return res + (i * elem_size);
+}
+
+static inline void *index_resource(struct resource_manager *r, int i)
+{
+    return index_resource_(r->resources, r->elem_size, i);
+}
+
+
+static inline void *index_static_resource(struct resource_manager *r, int i)
+{
+    return index_resource_(r->static_res.resources, r->elem_size, i);
 }
 
 void *get_all_resources(struct resource_manager *r, u32 *count, struct resource_id **ids) {
@@ -39,7 +50,10 @@ void null_id(struct resource_id *id)
 }
 
 void init_resource_manager(struct resource_manager *r, u32 elem_size,
-                           u32 initial_elements, u32 max_elements, const char *name) {
+                           u32 initial_elements, u32 max_elements,
+                           const char *name,
+                           struct static_resources *static_res)
+{
     r->generation = 1;
     r->resource_count = 0;
     r->elem_size = elem_size;
@@ -47,6 +61,20 @@ void init_resource_manager(struct resource_manager *r, u32 elem_size,
     r->current_capacity = initial_elements;
     r->name = name;
 
+    if (static_res) {
+        r->static_res = *static_res;
+
+        if (r->static_res.resources == NULL) {
+            r->static_res.resources =
+                calloc(r->static_res.capacity, elem_size);
+        }
+    }
+    else {
+        r->static_res.count = 0;
+        r->static_res.capacity = 0;
+        r->static_res.resources = NULL;
+    }
+
     assert(initial_elements != 0);
 
     r->resources = calloc(initial_elements, elem_size);
@@ -97,6 +125,13 @@ static void new_id(struct resource_manager *r, struct resource_id *id)
     assert(id->generation);
 }
 
+static void new_static_id(struct resource_manager *r, struct resource_id *id)
+{
+    id->index = r->static_res.count;
+    id->uuid  = STATIC_UUID;
+    id->generation = 0xFFFFFFFF;
+}
+
 static void resize(struct resource_manager *r)
 {
     debug("resizing %s resources, count %d+1 > current capacity %d\n",
@@ -129,14 +164,37 @@ static void resize(struct resource_manager *r)
 
 void print_id(struct resource_id *id, int nl)
 {
+    int is_static = is_static_resource(id);
+
+    if (is_static) {
+        printf("sid(%llu @ %d)%s", id->uuid & ~U64HOB, id->index, nl?"\n":"");
+        return;
+    }
+
     printf("id(u:%llu i:%d g:%d)%s",
            id->uuid, id->index, id->generation, nl?"\n":"");
 }
 
+void *new_static_resource(struct resource_manager *r,
+                          struct resource_id *id)
+{
+    assert(r->static_res.resources);
+    assert(id);
+    assert(id->index == 0xFFFFFFFF && "res_id is uninitialized");
+    assert(r->static_res.count + 1 < r->static_res.capacity);
+    if    (r->static_res.count + 1 < r->static_res.capacity)
+        return NULL; // we're full
+
+    new_static_id(r, id);
+
+    return index_static_resource(r, r->static_res.count++);
+}
+
 void *new_resource(struct resource_manager *r, struct resource_id *id)
 {
     assert(id);
-    assert((int)id->index == -1 && "res_id is uninitialized");
+    assert(id->uuid != STATIC_UUID && "called new_resource with a static id");
+    assert(id->index == 0xFFFFFFFF && "res_id is uninitialized");
 
     struct resource_id *fresh_id;
 
@@ -147,16 +205,25 @@ void *new_resource(struct resource_manager *r, struct resource_id *id)
         resize(r);
 
     fresh_id = &r->ids[r->resource_count];
-
     new_id(r, fresh_id);
-
-    if (id)
-        *id = *fresh_id;
+    *id = *fresh_id;
 
     return index_resource(r, r->resource_count++);
 }
 
+void *get_static_resource(struct resource_manager *r,
+                          struct resource_id *id)
+{
+    assert(r->static_res.capacity > 0 && "trying to get a static "
+           "resource on a manager doesn't have static resources");
+
+    return index_static_resource(r, id->index);
+}
+
 void *get_resource(struct resource_manager *r, struct resource_id *id) {
+    if (id->uuid == STATIC_UUID)
+        return get_static_resource(r, id);
+
     assert((int64_t)id->generation != -1 && "id intialized but not allocated (needs new_ call)");
 
     if (id->generation == 0) {
@@ -214,8 +281,3 @@ void destroy_resource(struct resource_manager *r, struct resource_id *id) {
         r->ids[i].index--;
     }
 }
-
-int is_id_allocated(struct resource_id *id)
-{
-    return (int)id->index != -1;
-}
diff --git a/src/resource.h b/src/resource.h
@@ -4,6 +4,8 @@
 
 #include "common.h"
 
+#define STATIC_UUID 0x5A51C00000000000
+
 enum refresh_status {
     RESOURCE_DELETED,
     REFRESH_NOT_NEEDED,
@@ -16,8 +18,15 @@ struct resource_id {
     u32 generation;
 };
 
+struct static_resources {
+    u8 *resources;
+    u32 count;
+    u32 capacity;
+};
+
 struct resource_manager {
     u8 *resources;
+    struct static_resources static_res;
     struct resource_id *ids;
     u32 resource_count;
     u32 generation;
@@ -25,22 +34,47 @@ struct resource_manager {
     u32 slots_used;
     u32 max_capacity;
     u32 current_capacity;
+
     const char *name;
 };
 
 #define ideq(a, b) ((a)->uuid == (b)->uuid)
 
-int is_id_allocated(struct resource_id *id);
 void init_id(struct resource_id *id);
 void *get_resource(struct resource_manager *r, struct resource_id *id);
 void *get_all_resources(struct resource_manager *, u32 *count, struct resource_id **ids);
 void destroy_resource(struct resource_manager *, struct resource_id *id);
 void destroy_resource_manager(struct resource_manager *);
 void *new_resource(struct resource_manager *, struct resource_id *id);
+void *new_static_resource(struct resource_manager *, struct resource_id *id);
 void print_id(struct resource_id *, int nl);
 void null_id(struct resource_id *id);
+/* int is_static_resource(struct resource_id *id); */
 
 void init_resource_manager(struct resource_manager *r, u32 elem_size,
-                           u32 initial_elements, u32 max_elements, const char *name);
+                           u32 initial_elements, u32 max_elements, const char *name,
+                           struct static_resources *static_res
+                           );
+
+
+static inline struct resource_id make_static_id(u32 index)
+{
+    return (struct resource_id){
+        .uuid = STATIC_UUID,
+        .index = index,
+        .generation = -1
+    };
+}
+
+static inline int is_static_resource(struct resource_id *id)
+{
+    return id->uuid == STATIC_UUID;
+}
+
+
+static inline int is_id_allocated(struct resource_id *id)
+{
+    return (int)id->index != -1;
+}
 
 #endif /* RESOURCE_H */
diff --git a/src/scene.c b/src/scene.c
@@ -55,7 +55,7 @@ void entity_test_scene(struct game *game)
     player->model_id = get_static_model(model_pirate_officer, NULL);
 
     model_id rock_model;
-    init_model_id(&rock_model);
+    init_id(&rock_model);
 
     /* model_id rock_model = get_static_model(model_tower, NULL); */
     struct model *pmodel  = new_model(&rock_model); assert(pmodel);
diff --git a/src/skybox.c b/src/skybox.c
@@ -39,7 +39,7 @@ void create_skybox(struct skybox *skybox, struct gpu_program *program) {
     int ok;
 
     node_init(&skybox->node);
-    init_model_id(&skybox->model_id);
+    init_id(&skybox->model_id);
 
     skybox->program = program;
 
diff --git a/todo.org b/todo.org
@@ -3,11 +3,17 @@
 * TODO Proc Trees                                                   :procgen:
 * TODO [#A] Instance rendering for ground debris             :perf:rendering:
 * TODO [#B] Load bone weights                                          :anim:
+:LOGBOOK:
+CLOCK: [2019-07-05 Fri 09:28]
+:END:
 
 * TODO Simple pthreads job system                              :jobs:threads:
 
-* TODO Run pose                                                        :anim:
-* TODO Simple animation test                                           :anim:
+* Run pose                                                             :anim:
+:LOGBOOK:
+CLOCK: [2019-07-05 Fri 09:28]--[2019-07-05 Fri 09:28] =>  0:00
+:END:
+
 
 * TODO Initial physics system                                       :physics:
 * TODO Entity loading stress test                                      :perf: