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);