API Design
/* Asset types */
typedef enum {
SH_ASSET_TEXTURE,
SH_ASSET_MESH,
SH_ASSET_SOUND,
SH_ASSET_MATERIAL,
} sh_asset_type_t;
/* Asset ID (typed handle, 32-bit) */
typedef struct {
uint16_t index; /* Slot in manager pool */
uint8_t generation; /* Generational index (detects use-after-free) */
uint8_t type; /* sh_asset_type_t */
} sh_asset_id_t;
#define SH_ASSET_INVALID ((sh_asset_id_t){0, 0, 0})
/* Asset manager */
typedef struct {
/* Pools per type */
sh_texture_t textures[64];
sh_mesh_t meshes[64];
/* ... sounds, materials ... */
uint8_t tex_refcount[64];
uint8_t mesh_refcount[64];
uint8_t tex_generation[64];
uint8_t mesh_generation[64];
/* Memory tracking */
uint32_t vram_used;
uint32_t ram_used;
} sh_asset_mgr_t;
/* Initialize asset manager. */
void sh_assets_init(sh_asset_mgr_t *mgr);
/* Load a texture, return ID. Increments refcount. */
sh_asset_id_t sh_assets_load_texture(sh_asset_mgr_t *mgr, const char *path);
/* Load a mesh, return ID. */
sh_asset_id_t sh_assets_load_mesh(sh_asset_mgr_t *mgr, const char *path);
/* Get pointer to texture by ID. Returns NULL if ID is stale. */
sh_texture_t *sh_assets_get_texture(sh_asset_mgr_t *mgr, sh_asset_id_t id);
/* Get pointer to mesh by ID. */
sh_mesh_t *sh_assets_get_mesh(sh_asset_mgr_t *mgr, sh_asset_id_t id);
/* Increment refcount (when shared between scenes). */
void sh_assets_retain(sh_asset_mgr_t *mgr, sh_asset_id_t id);
/* Decrement refcount. Frees when refcount hits 0. */
void sh_assets_release(sh_asset_mgr_t *mgr, sh_asset_id_t id);
/* Check if an ID is still valid. */
int sh_assets_valid(const sh_asset_mgr_t *mgr, sh_asset_id_t id);
/* Query memory usage. */
uint32_t sh_assets_vram_used(const sh_asset_mgr_t *mgr);
uint32_t sh_assets_ram_used(const sh_asset_mgr_t *mgr);
uint32_t sh_assets_vram_free(const sh_asset_mgr_t *mgr);
/* Release all assets with refcount 0. Call between scenes. */
void sh_assets_gc(sh_asset_mgr_t *mgr);
/* Release ALL assets. Call on shutdown. */
void sh_assets_shutdown(sh_asset_mgr_t *mgr);