Skip to content

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

cpp
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.

cpp
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:

cpp
// 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

cpp
// 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

cpp
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.

cpp
// 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.

cpp
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.

cpp
auto model = ModelDescriptor::create("cube", "models/cube.obj"_engine);
rm->register_model(model);

Material

A material groups texture references and shader parameters.

cpp
auto mat = MaterialDescriptor::create("pbr_metal");
rm->register_material(mat);

Font

A font atlas for text rendering.

cpp
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.

cpp
struct Handle {
    uint32_t index;
    uint32_t generation;

    bool is_valid() const;
};

using ResourceHandle = Handle;

Release a resource by descriptor ID:

cpp
// (called internally by resource pools)
pool.release("my_shader");