Skip to content

Architecture Overview

Mainframe Engine is a C# (.NET 10) game engine built on Vulkan 1.2 through Silk.NET. It is a learning-oriented engine with a Godot-style scene model: a game is a project (project.mfproj) whose node library GameHost runs (or, for the editor and tests, an Engine subclass), with nodes in the engine-owned SceneTree, usually loaded from a scene file. The engine provides windowing, a Vulkan renderer, the node tree with servers behind it, scene/resource files, materials and model import, lighting, cascaded shadows, skies, Spine skeletal animation, RmlUi game UI, physics, audio, replication, localization and an RmlUi developer overlay (F12); the editor (MainframeEngine.Editor) is built on the same engine and UI stack.

Architecture layers

ProjectKindRole
MainframeEngineclass libraryThe engine. Ships Content/** (compiled .spv shaders, assets) to dependants’ output; shaders compile during the build (build/Shaders.targets).
MainframeEngine.GeneratorsRoslyn source generator (netstandard2.0, referenced as an analyzer)Registers every node/resource type’s [Export] properties and [Signal] events. See Scene serialization.
MainframeEngine.L10n (mf-l10n)exe (build tool)Localization tooling: RML/scene extraction, .po update, pseudo-locale, .po → .mo compiler run by build/Localization.targets. See Localization.
Examples/Demogame project (own solution, not in MainframeEngine.slnx)The Demo: a GameHost game with one scene per engine feature. See Demo.
Examples/Forestgame project (own solution, not in MainframeEngine.slnx)The Forest showcase: a first-person walk (scaffold: controller and a test stream). See Forest.
MainframeEngine.EditorexeThe editor (EditorApp : Engine, RmlUi panels); loads game projects’ assemblies into collectible contexts and plays them in separate processes. See Editor.
Templates/MainframeEngine.Templatesdotnet new template package (not in the solution)mfgame: a game’s node library + GameHost desktop project + project.mfproj. See Projects & GameHost.
Tests/*xUnit v3 test projects, render-test host, BenchmarkDotNetSee Testing.
Plugins/Spine/spine-csharpclass library (git submodule)Spine C# runtime. Vendored — do not modify.
FolderContentsDoc
Core/Engine, EngineOptions, GameTime, FPSCounter, ExitCode, RenderingBackendEngine lifecycle
Scene/Node, SceneTree, SceneViewport, World3D, Node3D/Node2D, Transform3D/Transform2D, NodePath, NodeId, Timer; Nodes3D/ (VisualInstance3D, Camera3D, lights, WorldEnvironment, Grid3D), Nodes2D/ (Camera2D), Input/Scene graph & nodes
Nodes/SpineNode, NetworkNodeScene graph & nodes
Scene/Nodes3D/GeometryInstance3D.cs, Scene/SubViewport.csGeometryInstance3D, MeshInstance3D, Sprite3D, SubViewportMaterials & meshes
Rendering/Resources/Mesh/ArrayMesh/MeshSurface, primitive meshes, StandardMaterial3D, Texture2DMaterials & meshes
Rendering/Meshes/MeshRenderer (batching), PipelineStateCache, DrawList, Aabb/Frustum, picking, sub-viewport compositorMaterials & meshes
Resources/Import/AssetImporters, TextureImporter, ModelImporter (Assimp)Asset pipeline
Servers/IServer, ServerRegistry, RenderServerScene graph & nodes
Resources/Resource, PackedScene, ResourceLoader, SceneSaver/ResourceSaver, AssetDatabase, AssetUidScene serialization
Serialization/attributes, TypeRegistry, NodeTypeInfo, codecs, scene reader/writerScene serialization
Rendering/Vulkan/VulkanRenderer, IVulkanContext, VulkanLoaderBootstrapVulkan renderer
Rendering/Shadows/ShadowSystemShadow system
Rendering/Sky/SkyEnvironment + Procedural/Panoramic/CubemapSky
Rendering/Spine/SpineRenderer, SpineTextureLoaderSpine
Rendering/SceneGrid/SceneGrid, SceneGrid2d, SceneGrid3dScene grid
Rendering/Camera/ICamera, PerspectiveCamera, OrthographicCamera (math; the nodes wrap them)Cameras & input
Rendering/Gizmos/, Debugging/DevOverlay/ScreenGizmoBatch, LightGizmos, AxisGizmo, DevOverlayDeveloper overlay
Debugging/, Utils/Log and its sinksProject & GameHost
Lighting/LightEnvironment, Light + Directional/Point/SpotLighting
Networking/MultiplayerApi (replication, RPCs), messages, transports (ENet, loopback, simulated), PeerId, NetBuffer*Networking
Physics/PhysicsServer3D (Jitter2), PhysicsServer2D (Box2D.NET), body/area/shape nodes, queries, DebugLinesPhysics
Audio/AudioServer (SoundFlow), buses, audio nodes, streams, decodersAudio
UI/Rml/ binding over mfrmlui, VulkanUiRenderer, UiServer/UiLayer/UiDocumentGame UI
Project/, EditorLink/ProjectSettings, GameHost/GameSession, InputMap, GameAssemblyLoader; the game ↔ editor protocolProjects & GameHost
Imaging/Png codecTesting
Steamworks/Static Steam wrappers, SteamServerSteamworks
Localization/Tr, LocalizationOptions, LocaleId, catalogs, RmlLocalization, ITextTranslator, FontFallbackTableLocalization
flowchart LR
    Demo["Examples/Demo<br/>(GameHost desktop project)"] --> Engine["MainframeEngine"]
    Editor["MainframeEngine.Editor"] --> Engine
    Game["mfgame projects<br/>(GameHost desktop project)"] --> Engine
    Game -. analyzer .-> Gen
    Demo -. analyzer .-> Gen["MainframeEngine.Generators"]
    Demo -. build tool .-> L10n["mf-l10n<br/>(Tools/MainframeEngine.L10n)"]
    L10n --> Engine
    Engine -. analyzer .-> Gen
    Engine --> SpineRT["spine-csharp<br/>(submodule)"]
    Engine --> Silk["Silk.NET<br/>Windowing + Input (SDL2) · Vulkan · MoltenVK"]
    Engine --> Stb["StbImageSharp"]
    Engine --> ENet["ENet-CSharp"]
    Engine --> Steam["Steamworks.NET"]
    Engine --> Jitter["Jitter2 (3D physics)"]
    Engine --> Box2D["Box2D.NET (2D physics)"]
    Engine --> GetText["GetText.NET"]
    Engine --> Audio["SoundFlow · NVorbis"]
    Engine --> Rml["mfrmlui<br/>(RmlUi + FreeType, in-house native shim)"]
    Engine --> Assimp["Silk.NET.Assimp"]
  • Games are node libraries. A game project’s code is node types; GameHost runs it from project.mfproj (no Engine subclass). An Engine subclass is still supported (the editor, the render-test host); its three legacy hooks (OnUpdate, OnShadowPass, OnRenderMainPass) are optional.
  • The engine owns the scene. A SceneTree (Godot model) runs lifecycle, physics/process, deferred calls, transform sync and input for every node; behaviour is C# node subclasses. Scenes are data (.mscene) loaded through ResourceLoader; node properties are discovered by a source generator, not reflection.
  • Nodes are front-ends to servers. Nodes hold editable state; servers (RenderServer, the physics servers PhysicsServer3D/PhysicsServer2D (M6), AudioServer (M7), UiServer (M8)) hold GPU, simulation, audio and native objects and are reached through SceneTree.Servers. Physics library calls (Jitter2, Box2D.NET) never leave the physics spaces (Physics).
  • Vulkan is the only backend. IRenderer is backend-neutral in name, but everything that draws casts to IVulkanContext. EngineOptions.RenderingBackend is not consulted.
  • Shared GPU state. Meshes are batched by the render server with pipelines from a state-hash PipelineStateCache, shared per-frame descriptor sets (set 0/1) and memory from the in-house GpuAllocator (GPU resources, Materials & meshes); the sky, grid and Spine renderers keep their own pipelines, created through the render server when their node enters the tree.
  • Per-frame-slot resources. Uniform buffers, dynamic vertex buffers and their descriptor sets are indexed by IVulkanContext.FrameSlot (MaxFramesInFlight = 2), never by swapchain image, so they survive swapchain image-count changes (see Vulkan renderer).
  • No static service locators for nodes. The old Node.Initialize(renderer, shadowSystem) globals are gone; per-world state lives in World3D, so the editor can render several worlds.
ObjectCreated byDisposed by
WindowEngine ctorEngine.Dispose
SceneTree (root viewport, World3D with its LightEnvironment)Engine ctorEngine.OnClose (Tree.Shutdown() frees every node)
Input context, VulkanRenderer, servers (RenderServer → ShadowSystem, DebugLinesRenderer; PhysicsServer3D/2D → one space per world)Engine.OnLoadEngine.OnClose (servers after the tree, before the renderer)
Nodes and their GPU objects (shapes, Spine, sky, grid)the game / PackedScene.Instantiate (GPU objects: the render server on enter)Free/QueueFree, else the tree shutdown; orphans by the render server
Loaded resources (PackedScene, .mres)ResourceLoader.Loadlast Release(), else ResourceLoader.ClearCache() in Engine.OnClose

Engine lifecycle · Build & platforms · Milestones