# How the GfxResourceSystem Manages Rendering Resources in EquilibriumEngine

> **The GfxResourceSystem tracks, updates, and safely disposes of all bgfx rendering resources by attaching a GfxResource component to entities and using flecs observers to automatically call the appropriate bgfx_destroy_* functi...

- Repository: [Alexander/equilibriumengine](https://github.com/clibequilibrium/equilibriumengine)
- Tags: 
- Published: 2026-02-27

---

**The GfxResourceSystem tracks, updates, and safely disposes of all bgfx rendering resources by attaching a GfxResource component to entities and using flecs observers to automatically call the appropriate bgfx_destroy_* functions when components are removed.**

The `gfx_resource_system` serves as the central authority for GPU resource lifecycle management in the [clibequilibrium/equilibriumengine](https://github.com/clibequilibrium/equilibriumengine). Built on top of the flecs entity component system (ECS) and the bgfx rendering library, this system ensures that textures, buffers, shaders, and framebuffers are automatically cleaned up without manual intervention, preventing memory leaks and handle exhaustion.

## Core Architecture of the GfxResourceSystem

### Resource Tracking with GfxResource Components

At the heart of the system lies the **GfxResource** component, a lightweight struct that pairs a bgfx handle with its type classification. According to the source code in [`equilibrium/systems/rendering/gfx_resource_system.h`](https://github.com/clibequilibrium/equilibriumengine/blob/main/equilibrium/systems/rendering/gfx_resource_system.h) (lines 8–22), this component stores:

```c
typedef struct {
    ResourceType type;
    uint16_t handle;
} GfxResource;

```

Any entity that owns a bgfx-created object—whether a texture, vertex buffer, or shader program—must have this component attached. The `handle` field stores the bgfx index value, while the `type` field determines which destruction function the system will invoke during cleanup.

### The ResourceType Enum

The **ResourceType** enum (defined in [`gfx_resource_system.h`](https://github.com/clibequilibrium/equilibriumengine/blob/main/gfx_resource_system.h)) enumerates all supported bgfx resource categories:

- `RESOURCE_TYPE_TEXTURE`
- `RESOURCE_TYPE_VERTEX_BUFFER`
- `RESOURCE_TYPE_DYNAMIC_VERTEX_BUFFER`
- `RESOURCE_TYPE_INDEX_BUFFER`
- `RESOURCE_TYPE_PROGRAM`
- `RESOURCE_TYPE_FRAME_BUFFER`
- `RESOURCE_TYPE_UNIFORM`

This classification enables the `DestroyGfxResources` observer to dispatch the correct `bgfx_destroy_*` call without requiring manual type checking by the user.

## Automatic Resource Lifecycle Management

### The DestroyGfxResources Observer

The system registers a flecs observer that triggers on the `EcsUnSet` event for the `GfxResource` component. As implemented in [`equilibrium/systems/rendering/gfx_resource_system.c`](https://github.com/clibequilibrium/equilibriumengine/blob/main/equilibrium/systems/rendering/gfx_resource_system.c) (lines 45–84), this observer iterates through all components slated for removal and executes the corresponding bgfx destruction logic:

```c
switch (resources[i].type) {
    case RESOURCE_TYPE_TEXTURE:
        bgfx_destroy_texture(bgfx_texture_handle_t{resources[i].handle});
        break;
    case RESOURCE_TYPE_VERTEX_BUFFER:
        bgfx_destroy_vertex_buffer(bgfx_vertex_buffer_handle_t{resources[i].handle});
        break;
    case RESOURCE_TYPE_DYNAMIC_VERTEX_BUFFER:
        bgfx_destroy_dynamic_vertex_buffer(bgfx_dynamic_vertex_buffer_handle_t{resources[i].handle});
        break;
    case RESOURCE_TYPE_INDEX_BUFFER:
        bgfx_destroy_index_buffer(bgfx_index_buffer_handle_t{resources[i].handle});
        break;
    case RESOURCE_TYPE_PROGRAM:
        bgfx_destroy_program(bgfx_program_handle_t{resources[i].handle});
        break;
    case RESOURCE_TYPE_FRAME_BUFFER:
        bgfx_destroy_frame_buffer(bgfx_frame_buffer_handle_t{resources[i].handle});
        break;
    case RESOURCE_TYPE_UNIFORM:
        bgfx_destroy_uniform(bgfx_uniform_handle_t{resources[i].handle});
        break;
    default:
        ecs_err("Unsupported resource type");
}

```

Because this observer runs automatically when a `GfxResource` component is unset—either through entity deletion or explicit component removal—the engine guarantees that no bgfx handles leak, even during complex scene transitions or error conditions.

## Shader Hot-Reloading Mechanism

The `gfx_resource_system` extends beyond simple cleanup to support iterative shader development through its hot-reload pipeline. This feature uses three additional components: **HotReloadableShader**, **FileWatcher**, and **ReloadShader**.

### HotReloadableShader Component Structure

The `HotReloadableShader` component stores metadata required to recreate shader programs at runtime. It tracks:

- The target entity owning the shader
- The component ID and field offset where the program handle resides
- File paths for vertex and fragment shader sources

This design allows the system to update the program handle in place within user-defined components without requiring the user to manually manage the shader entity.

### FileWatcher Integration and Reload Triggers

The hot-reload workflow operates through a coordinated observer chain:

1. **InitHotReloadShaders**: When both `FileWatcher` and `HotReloadableShader` exist on an entity, this observer registers the shader files with the underlying `xWatcher` system (a cross-platform file-watcher).

2. **UpdateFileWatcher**: Runs every frame via the `OnInput` tag to poll for file modifications.

3. **HotReloadShaders**: Triggers on `EcsOnSet` when `ReloadShader` is present. This observer:
   - Loads new vertex/fragment shaders via `shader_load()`
   - Destroys the old program using `bgfx_destroy_program()`
   - Creates a new program with `bgfx_create_program()`
   - Writes the new handle back to the component at the stored `filed_offset`

According to the source in [`gfx_resource_system.c`](https://github.com/clibequilibrium/equilibriumengine/blob/main/gfx_resource_system.c) (lines 41–42), when the file-watcher detects a change, it tags the entity with a `ReloadShader` component, queuing the reload for the next frame.

## System Initialization and Registration

During engine startup, `GfxResourceSystemImport()` registers all components and observers with the flecs world. The initialization sequence in [`equilibrium/systems/rendering/gfx_resource_system.c`](https://github.com/clibequilibrium/equilibriumengine/blob/main/equilibrium/systems/rendering/gfx_resource_system.c) (lines 80–99) defines the component types:

```c
void GfxResourceSystemImport(ecs_world_t *world) {
    ECS_COMPONENT_DEFINE(world, GfxResource);
    ECS_COMPONENT_DEFINE(world, HotReloadableShader);
    ECS_COMPONENT_DEFINE(world, FileWatcher);
    ECS_COMPONENT_DEFINE(world, ReloadShader);
    
    // Observer registrations follow...
}

```

This import function establishes the contract that any system creating bgfx resources must attach a `GfxResource` component to participate in automatic cleanup.

## Practical Usage Examples

### Creating and Attaching a Texture

To create a texture that participates in automatic resource management:

```c
// Create the bgfx texture handle
bgfx_texture_handle_t tex = bgfx_create_texture_2d(
    512, 512, false, 1,
    BGFX_TEXTURE_FORMAT_RGBA8,
    BGFX_TEXTURE_NONE, nullptr);

// Wrap it in a GfxResource component
GfxResource res = {
    .type = RESOURCE_TYPE_TEXTURE,
    .handle = tex.idx
};

// Attach to entity
ecs_set(world, entity, GfxResource, {res});

```

When `entity` is destroyed or the component is removed via `ecs_remove(world, entity, GfxResource)`, the `DestroyGfxResources` observer automatically invokes `bgfx_destroy_texture()`.

### Setting Up Hot-Reloadable Shaders

To enable live shader editing:

```c
// Define a component to hold the program handle
typedef struct {
    bgfx_program_handle_t prog;
} MyMaterial;

// Create shader entity
ecs_entity_t shader_ent = ecs_new_id(world);
ecs_set(world, shader_ent, MyMaterial, {BGFX_INVALID_HANDLE});

// Configure hot-reload metadata
HotReloadableShader hot = {
    .shader_entity = shader_ent,
    .component_id = ecs_id(MyMaterial),
    .component_size = sizeof(MyMaterial),
    .filed_offset = offsetof(MyMaterial, prog),
    .vertex_shader_name = strdup("shaders/vs_myshader.sc"),
    .fragment_shader_name = strdup("shaders/fs_myshader.sc")
};

ecs_set(world, shader_ent, HotReloadableShader, {hot});

```

The `gfx_resource_system` will now monitor the shader files and automatically recompile the program when changes are detected, updating `MyMaterial.prog` without requiring engine restart.

### Explicit Resource Cleanup

For immediate resource destruction without deleting the entity:

```c
// This triggers the DestroyGfxResources observer immediately
ecs_remove(world, entity, GfxResource);

```

This pattern is useful when swapping textures or rebuilding buffers where the entity itself must persist but the underlying GPU resource must change.

## Summary

- The **GfxResourceSystem** integrates with flecs ECS to provide automatic lifecycle management for all bgfx resources.
- The **GfxResource** component pairs a `uint16_t` handle with a **ResourceType** enum to enable type-safe destruction.
- The **DestroyGfxResources** observer runs on `EcsUnSet`, ensuring `bgfx_destroy_*` functions are called for textures, buffers, programs, and uniforms.
- **HotReloadableShader** components enable runtime shader recompilation through integration with the `xWatcher` file-monitoring system.
- All resource management logic is centralized in [`equilibrium/systems/rendering/gfx_resource_system.c`](https://github.com/clibequilibrium/equilibriumengine/blob/main/equilibrium/systems/rendering/gfx_resource_system.c) and [`gfx_resource_system.h`](https://github.com/clibequilibrium/equilibriumengine/blob/main/gfx_resource_system.h).

## Frequently Asked Questions

### How does the GfxResourceSystem prevent memory leaks when entities are destroyed?

The system registers a flecs observer that triggers on the `EcsUnSet` event for `GfxResource` components. When an entity is deleted or the component is removed, the observer automatically executes the appropriate `bgfx_destroy_texture`, `bgfx_destroy_program`, or other destruction function based on the `ResourceType` field, ensuring GPU handles are always released.

### What types of rendering resources does the GfxResourceSystem support?

The system supports all major bgfx resource types through the `ResourceType` enum: textures, static and dynamic vertex buffers, index buffers, shader programs, frame buffers, and uniforms. Each type maps to a specific bgfx destruction function in the `DestroyGfxResources` observer switch statement.

### Can the GfxResourceSystem handle hot-reloading of shaders during development?

Yes. By attaching a `HotReloadableShader` component alongside `FileWatcher`, the system monitors shader source files on disk. When modifications are detected, the `HotReloadShaders` observer automatically reloads the vertex and fragment shaders, destroys the old program, creates a new bgfx program, and updates the handle in the target component.

### Where is the GfxResourceSystem initialized in the EquilibriumEngine?

The system is initialized via `GfxResourceSystemImport()`, defined in [`equilibrium/systems/rendering/gfx_resource_system.c`](https://github.com/clibequilibrium/equilibriumengine/blob/main/equilibrium/systems/rendering/gfx_resource_system.c) (lines 80–99). This function registers the `GfxResource`, `HotReloadableShader`, `FileWatcher`, and `ReloadShader` components with the flecs world and attaches all lifecycle observers during engine startup.