Resources
The ResourceManager is a singleton that owns all GPU resources. It uses a generational slot pool per resource type, which provides safe handle invalidation when resources are released.
ResourceManager
inline Ref<ResourceManager> resource_manager() {
return ResourceManager::get();
}Registration
Descriptors must be registered before resources can be loaded. Registration is idempotent - registering the same descriptor ID twice returns the existing entry.
auto rm = resource_manager();
rm->register_shader(Shader::create("my_shader", frag_path, vert_path));
rm->register_texture(Texture2DDescriptor::create("albedo", path));
rm->register_texture(Texture3DDescriptor::create("sky_cube", faces));
rm->register_material(MaterialDescriptor::create("metal"));
rm->register_model(ModelDescriptor::create("sphere", model_path));
rm->register_font(FontDescriptor::create("roboto", font_path));
// Batch variants
rm->register_shaders({ shader_a, shader_b });
rm->register_textures({ tex_a, tex_b });
rm->register_models({ model_a, model_b });
rm->register_materials({ mat_a });
rm->register_fonts({ font_a });Loading
Loading uploads descriptors to the GPU. Call after registration:
// Load specific descriptor types
rm->load_from_descriptors<ShaderDescriptor, Texture2DDescriptor>(
RendererBackend::OpenGL
);
// Load specific IDs only
rm->load_from_descriptors_by_ids<ShaderDescriptor>(
RendererBackend::OpenGL,
{ "shadow_mapping_depth", "skybox_shader" }
);Lookup
// Returns nullptr if not found
Ref<Shader> shader = rm->get_by_descriptor_id<Shader>("my_shader");
// Asserts existence, throws on failure
Ref<Shader> shader = rm->find_strict_by_descriptor_id<Shader>("my_shader");
// Check existence without loading
rm->ensure_exists_by_descriptor_id<Shader>("my_shader");
// Convenience: get multiple models at once
std::vector<Model*> models = rm->get_model_by_descriptor_ids({ "cube", "sphere" });Slot Queries
int next_2d_slot = rm->texture_2d_slot(); // index for next 2D texture binding
int next_3d_slot = rm->texture_3d_slot();Resource Types
Shader
Manages a compiled AXSL shader program.
// Descriptor factory (registers but does not upload)
Ref<ShaderDescriptor> desc = Shader::create(
"my_shader",
"shaders/fragment/pbr.axsl"_engine,
"shaders/vertex/pbr.axsl"_engine,
/* optional */ "shaders/geometry/normals.axsl"_engine
);
// Uniform setters (after binding)
shader->bind();
shader->set_bool("u_flag", true);
shader->set_int("u_texture", 0);
shader->set_float("u_roughness", 0.5f);
shader->set_vec3("u_light_dir", glm::vec3(0, -1, 0));
shader->set_matrix("u_mvp", mvp);
shader->unbind();Texture2D / Texture3D
2D and 3D (cubemap) textures loaded from disk.
auto tex2d = Texture2DDescriptor::create("albedo", "textures/albedo.png"_engine);
auto tex3d = Texture3DDescriptor::create("sky", { face_paths... });
rm->register_texture(tex2d);
rm->register_texture(tex3d);Model
A model loaded from a mesh file (e.g. OBJ, FBX via assimp). Contains one or more sub-meshes.
auto model = ModelDescriptor::create("cube", "models/cube.obj"_engine);
rm->register_model(model);Material
A material groups texture references and shader parameters.
auto mat = MaterialDescriptor::create("pbr_metal");
rm->register_material(mat);Font
A font atlas for text rendering.
auto font = FontDescriptor::create("roboto", "fonts/Roboto-Regular.ttf"_engine);
rm->register_font(font);Resource Handles
Resources are accessed via ResourceHandle (a {index, generation} pair). The generational counter ensures stale handles are detected after a resource is released and the slot is reused.
struct Handle {
uint32_t index;
uint32_t generation;
bool is_valid() const;
};
using ResourceHandle = Handle;Release a resource by descriptor ID:
// (called internally by resource pools)
pool.release("my_shader");