Repository navigation
Project API
NWBLot projects plug into the loader through a small callback surface. The Testbed is the current project using that API, and it is the best reference for how projects should create a world, register systems, and request shutdown.
The project-facing API consists of:
QueryProjectFrameClientSizeQueryProjectWindowTitleConfigureProjectRuntimeCreateProjectEntryCallbacksCreateInitialProjectWorldDestroyInitialProjectWorld
QueryProjectFrameClientSize returns a client-area size. Testbed returns 1280x900.
QueryProjectWindowTitle returns the platform window title. Testbed returns NWB Testbed.
ConfigureProjectRuntime(ProjectStartupContext&) runs after the loader creates its Core::Frame but before graphics/device initialization. The context provides graphics, the project object arena, and filesystemFactory. Use it for pre-device policies such as the required bindless heap ABI, an HDR10 request, or a project-owned IFilesystem factory; return false to stop startup. Testbed sets the bindless heap ABI and requests HDR10 through this callback, and leaves filesystemFactory empty so every mount uses VolumeFileSystem. See HDR10 Presentation and Filesystem.
CreateProjectEntryCallbacks returns an IProjectEntryCallbacks implementation. Testbed returns ProjectTestbed.
CreateInitialProjectWorld creates and wires the ECS world.
DestroyInitialProjectWorld unregisters render passes and frame graph contributors, waits for graphics work, clears the world, and releases it.
IProjectEntryCallbacks has three overridable callbacks:
onStartuponShutdownonUpdate(f32 delta)
The default implementation returns success and does nothing. Real projects normally use:
-
onStartupto create scene entities and register input handlers. -
onUpdateto update project-side state and return whether runtime should continue. -
onShutdownto release project-only resources.
Testbed creates the initial world in the ProjectTestbed constructor, verifies the required systems are present, creates scene entities during onStartup, and destroys the world during shutdown/destruction.
ProjectRuntimeContext provides engine services that project code is allowed to use:
- graphics backend facade
- input dispatcher
- project object arena
- thread pool
- job system
- typed asset manager
- mounted
IFilesystem - frame graph registry
- read-only perf session
- shader path resolver
- telemetry capture setter
- telemetry upload flush callback
- perf capture setter
- request quit callback
Convenience methods:
setTelemetryCapture(options)flushTelemetryUpload(clearAfterUpload)setPerfCapture(options)gpuTimingView()
The context is assembled by the loader after graphics initialization, cooked volume mounting, asset codec registration, asset manager creation, and shader archive loading. Project code can therefore assume those services exist when callbacks are created.
Testbed creates a Core::ECS::World using the context object arena and thread pool. It then adds these systems:
MeshSystemRendererSystemModelSystemMeshSkinningSystemUiSystem
The renderer is constructed with:
- the world
Core::GraphicsAssetManager- shader path resolver
The model system is constructed with model renderer hooks, so model expansion can create renderer-facing components.
The mesh skinning system is constructed with graphics, asset manager, the mesh system, and shader path resolver. It registers as a render pass before the main renderer, so skinned runtime mesh data is ready for renderer consumption.
The UI system is constructed with world, graphics, input, asset manager, and shader path resolver.
Testbed registers render passes in this order:
MeshSkinningSystemRendererSystemUiSystem
That order is important:
- skinning updates runtime mesh buffers before scene rendering
- renderer draws the scene into deferred/transparency/composite targets
- UI renders after scene composition
Testbed also registers RendererSystem as a frame graph contributor so telemetry capture can include renderer frame-graph information.
DestroyInitialProjectWorld validates that expected systems still exist, then:
- unregisters renderer frame graph contribution
- removes skinning, renderer, and UI render passes
- waits for graphics jobs
- waits for the graphics device to idle when available
- clears the ECS world
- releases the world pointer
This avoids destroying ECS-owned renderer state while backend command work may still reference it.
Project code should request shutdown through:
ProjectRuntimeContext::requestQuit
Do not call platform-specific quit APIs from project code or smoke-test projects. The frame owns the platform loop and can exit without submitting another graphics frame when quit is requested during project update.
During onStartup, Testbed creates:
- an active camera entity
- a camera entity positioned in front of the character
- a 45-degree directional light
- a point light
- a skinned character model entity
- a static ground plane model entity
- a UI entity with an ImGui draw callback
The character and ground plane are model-driven. Their ECS entities contain ModelComponent and RendererComponent with typed asset references; model expansion and renderer systems do the rest.
- Start Here
- Build and Verification
- Platform and GPU Support
- Graphics Device Selection
- Testbed
- Glossary
- Code Reading Guide
- Architecture
- Engine Concepts
- Asset Flow
- Frame Life Cycle
- Runtime Boot
- Project API
- Runtime and ECS
- CPU Task Scheduler
- Asset Pipeline
- Texture Conversion
- FBX to NWB Conversion
- Asset Types
- Cooked Volumes
- Filesystem
- Shader and Material System
- Mesh Model and Skinning