Lysa  0.0
Lysa 3D Engine
Resource Constraints

As a GPU-driven engine Lysa pre-allocates GPU memory and descriptor space for all managed resources at startup. Every pool has a hard ceiling; exceeding it causes an assertion failure or out-of-memory error at runtime. This page lists every configurable limit, its default value, and how to raise it.

Table of contents


Global Resource Pools

Global resource pools are shared across all scenes and render targets. They are configured through lysa::ResourcesCapacity, which is embedded in lysa::ContextConfiguration:

.images = 500,
.samplers = 20,
.material = 100,
.meshes = 1000,
.surfaces = 5000,
.vertices = 5000000,
.indices = 50000000,
},
};
Field Default Description
images 500 Maximum number of images held in CPU and GPU memory simultaneously. Covers all textures loaded from assets packs and any render targets registered with the resource system.
samplers 20 Maximum number of GPU image samplers that can be created. Each unique combination of filtering and address-mode settings consumes one entry.
material 100 Maximum number of standard and shader materials (combined) resident in CPU and GPU memory at once.
meshes 1000 Maximum number of mesh objects in CPU and GPU memory. Every distinct mesh loaded from an assets pack or created at runtime occupies one slot.
surfaces meshes × 5 Maximum number of mesh surfaces across all meshes. A surface maps to one draw call and carries one material assignment.
vertices surfaces × 1000 Maximum number of vertices across all surfaces, stored in a single shared GPU vertex buffer.
indices vertices × 10 Maximum number of indices across all surfaces, stored in a single shared GPU index buffer.
Note
The surfaces, vertices, and indices defaults are computed from meshes at initialisation time. If you set meshes explicitly but leave the others at zero, the engine recalculates them. Override them individually when your meshes are unusually dense or unusually sparse.

Per-Scene Limits

Each lysa::Scene has its own budget configured through lysa::SceneConfiguration:

auto scene = std::make_shared<lysa::Scene>(lysa::SceneConfiguration {
.maxLights = 10,
.maxMeshInstances = 5000,
.maxMeshSurfacePerPipeline = 10000,
.maxPipelines = 25,
});
Field Default Description
asyncObjectUpdatesPerFrame 50 Maximum number of node transform updates processed per frame when instances are added asynchronously via addInstance(..., async=true). Raise this to reduce the lag between spawning objects and them appearing in the scene.
maxLights 10 Maximum number of lights active in the scene at once (point, spot, and directional combined). Backed by a fixed-size GPU buffer; adding more lights beyond this limit is silently ignored.
maxMeshInstances 5000 Maximum number of lysa::MeshInstance objects that can be registered with the scene simultaneously. Drives the size of the per-frame GPU instance buffer used by the GPU-driven draw-command pipeline.
maxMeshSurfacePerPipeline 10000 Maximum number of mesh surface draw calls submitted per graphics pipeline per frame. This is the indirect draw buffer size for the frustum-culling and draw-command generation compute passes.
maxPipelines 25 Maximum number of distinct graphics pipelines (unique material × render-pass combinations) that the scene can manage.
Note
maxLights directly affects the size of the light uniform buffer uploaded every frame. Setting it very high on scenes that only ever use a handful of lights wastes GPU memory. Conversely, if you add a light beyond the limit the engine will not raise an error : the extra light will be silently discarded.

Material Parameter Limit

Each lysa::ShaderMaterial exposes a fixed array of generic float4 parameters to the fragment shader:

A shader material therefore has room for 4 × float4 (64 bytes) of user-defined uniform data. This constant is compiled into both the engine and the HLSL/Slang shaders; changing it requires recompiling all shaders.


Other Engine-Level Limits

The following fields in lysa::ContextConfiguration affect global runtime behaviour:

Field Default Description
framesInFlight 2 Number of frames rendered concurrently. Affects the size of all per-frame GPU ring-buffers. Values above 3 are unlikely to improve throughput and increase latency and memory usage.
maxShadowMapsPerScene 20 Maximum number of shadow maps allocated per scene. One map is consumed per shadow-casting light; cascaded shadow maps consume one map per cascade.
eventsReserveCapacity 100 Initial capacity of the event queue. The queue grows dynamically, so this is only a hint to avoid early reallocations.
commandsReserveCapacity 1000 Initial capacity of the deferred command buffer. Like the event queue, it grows on demand.

Sizing Guidelines

The default values are intentionally conservative so that a basic application works without any configuration. A production scene will generally need to raise several of them. A rough starting checklist:

  1. Count your unique meshes across all assets packs you ship. Set resourcesCapacity.meshes to that number plus a margin for runtime-created meshes (e.g. procedural geometry, debug shapes).
  2. Count surfaces per mesh. If your meshes average more than 5 surfaces each, set resourcesCapacity.surfaces explicitly instead of relying on the meshes × 5 default.
  3. Estimate your vertex and index budget from your mesh export statistics. Prefer setting surfaces first and let the derived defaults cover vertices and indices, unless your meshes are unusually high- or low-polygon.
  4. Count visible instances. SceneConfiguration::maxMeshInstances must cover the peak number of lysa::MeshInstance objects alive in one scene at the same time, not the total across the game lifetime.
  5. Count active lights per scene and set maxLights accordingly. Remember that each cascade of a cascaded shadow map counts as one shadow map against maxShadowMapsPerScene.
  6. Count materials. Each unique material (including shader-material variants) needs one slot in resourcesCapacity.material. Instancing the same material on multiple meshes does not increase this count.
Note
All limits are checked at load time when the relevant GPU buffer is first created. If you hit a limit you will see an assertion failure or an engine exception with a message naming the exhausted pool..