Async Resource Loading
The ResourceManager decouples declaration from upload. Resources are first registered as CPU-side descriptors, then loaded asynchronously to the GPU on demand.
Loading Model
Descriptors
Every resource type has a corresponding descriptor that carries the CPU-side metadata needed to construct the GPU resource:
| Resource | Descriptor |
|---|---|
| Shader | ShaderDescriptor |
| Texture 2D | Texture2DDescriptor |
| Texture 3D | Texture3DDescriptor |
| Model | ModelDescriptor |
| Material | MaterialDescriptor |
| Font | FontDescriptor |
Descriptors are lightweight - they hold paths, formats, and flags, but allocate no GPU memory.
Registering Descriptors
auto res = ResourceManager::get();
res->register_shader(ShaderDescriptor::create("pbr", "shaders/vertex/pbr.axsl"_engine, "shaders/fragment/pbr.axsl"_engine));
res->register_texture(Texture2DDescriptor::create("albedo", "textures/albedo.png"_engine));
res->register_model(ModelDescriptor::create("cube", "models/cube.obj"_engine));Triggering the Upload
Call load_from_descriptors with the target backend and the descriptor types to upload:
res->load_from_descriptors<ShaderDescriptor, Texture2DDescriptor, ModelDescriptor>(
RendererBackend::OpenGL
);Each selected descriptor type is uploaded concurrently. The call blocks until all uploads for the requested types complete.
Load State
Each resource slot tracks an async load state:
| State | Meaning |
|---|---|
Pending | Descriptor registered, upload not yet started |
Loading | Upload in progress on worker thread |
Ready | GPU resource available for use |
Failed | Upload failed; resource is not usable |
Passes and components that reference a resource by handle will receive a null/fallback resource if the load state is not Ready.
Generational Handles
ResourceManager uses a generational slot pool internally. Registering a resource returns a typed handle:
ResourceHandle<Texture2D> handle = res->register_texture(
Texture2DDescriptor::create("albedo", "textures/albedo.png"_engine)
);The generational counter in the handle prevents stale access after a resource is unloaded and its slot is reused.
Unloading
res->unload<Texture2D>(handle); // frees GPU memory, slot becomes availableWARNING
Unloading a resource that is still referenced by an active pass will not crash, but the pass will receive a null resource until a new one is loaded into the same slot.