Expand description
The backend-agnostic, GPU-free render-prep layer: the
RenderBackend/SceneControl trait seam the device backends implement, plus
the record builders, render graph, and CPU-side math that turn components
into GPU-ready data.
Sits above crate::gfx, which holds the layouts and the kernels this
prepares into, and owns no device or window handle of its own: a frame’s
work is built here and handed to whichever backend implements the seam. The
device backends (concinnity-device) and the runtime driver
(concinnity-engine) are the two consumers.
Modules§
- area_
light - Packs authored
RectAreaLights into the per-sceneAreaLightDatatable the forward pass reads alongside theGpuLightbuffer. - backend
- RenderBackend trait: the union of methods every graphics backend implements, dispatched dynamically by GraphicsSystem so the per-frame step + setup logic lives in one cfg-free copy instead of three.
- backend_
init - Grouped construction inputs for the render backends, plus the requirements
derivation that trims scene-scoped features when a world has no 3D content.
GraphicsSystem init assembles a
BackendInitfrom the drained world assets, callsresolve_requirements(), and hands it to the backend constructor selected at compile time (Metal / DirectX / Vulkan). Every backend receives the same struct; each reads the fields its feature set consumes. - call_
buffer - Assembly buffer for an overlay draw list: the calls built so far plus a pool of spent vertex/index buffers. A frame’s spent list is recycled back in whole, so steady-state assembly reuses both the list and every call’s geometry allocations.
- chunk_
window - Sliding-window streaming policy for an infinite voxel world.
- csm
- Cascaded shadow map cascade computation. Produces a
ShadowUniformscarrying one orthographic light-view-projection matrix per cascade plus the view-space far depth for each cascade (the fragment shader uses these to select which cascade slice to sample). - cursor
- In-engine mouse cursor geometry. A
follow_cursorSprite is drawn as a classic arrow pointer rather than a plain quad: a filled polygon with a contrasting outline so it stays legible over any scene. Like the rest of the UI overlay, it rides the text pass’s sentinel-UV solid-fill path (u < 0), so it needs no new pipeline and renders on every backend. The arrow’s diagonal edges are real geometry, not a stair-stepped stack of quads. - decal
- Backend-agnostic decal helpers. Owns the per-decal model / inverse-model
matrix math the projected-decal pass needs at runtime, plus the
DecalRecordthe backends consume. Decals are stamped onto the scene depth buffer by drawing a unit-box volume per decal: the fragment shader reconstructs the world-space point of each rasterised pixel from depth and tests whether it lies inside the box. - directx
- The same for the DirectX and Vulkan backends: their repr(C) uniform / probe
structs + GPU-timing slot arithmetic (mirrored in the HLSL / GLSL shaders).
Backend-specific but device-free (plain repr(C), no windows/ash types), so
they compile unconditionally and their layout tests count toward coverage.
The DirectX / Vulkan backends (concinnity-device) re-export them under their
own
directx/vulkan. - display_
mode - The backend-agnostic display-mode list behind the “Resolution” settings row. A backend enumerates the modes (width x height at refresh rate) the display it renders to supports; this module holds the shared shaping: the row/list label format, the dedup + sort that turns a raw enumeration into the menu list, the persisted-choice -> list-index recovery, and the static fallback a backend without enumeration (or an embedded view with no window) uses so the row still drives the windowed resize path.
- draw_
slot - Free-list allocator for backend draw-object slots. A backend appends draw
objects into a single
Vecand stores raw indices into it on each entity’s RenderHandle, so a despawned object’s slot cannot be compacted away without invalidating every later index. Instead the allocator hands out a vacated slot before growing the vec:retirepushes a freed index, the next runtime spawn pops it. Streamed chunks were the first consumer (one freed chunk’s slot reused by the next); runtime entity spawn/despawn is the second. All three backends (Metal, DirectX, Vulkan) route their draw-slot allocation through this. - error
- The typed error vocabulary of the
RenderBackendboundary. Backends map their native failure codes (VkResult, HRESULT, MTLCommandBuffer status) into these classes at the detection sites; the frame loop dispatches recovery policy on the class, never on prose.Othercarries legacy string errors so interior call sites can migrate incrementally. - feedback
- The render half’s per-frame report back to the simulation: the sampled
window input, the frame’s render stats, what the snapshot’s op replay
produced, and the consumed snapshot returned for buffer reuse. The
counterpart of
RenderSnapshoton the pipelined driver’s return channel. - frame_
dirty - Write tracking for a uniform block a backend rings over its frames in flight. The CPU owns the values; every slot is marked when they change and one slot is cleared per frame, so a world whose values are steady writes nothing after the ring has caught up.
- fullscreen
- Backend-agnostic fullscreen-pass encoder seam, the first pilot of a hardware
abstraction layer over the three render backends. The bloom
prefilter -> downsample -> upsample chain is structurally identical on every
backend, so its orchestration lives here once and each backend implements
BloomEncoderto bind + draw one sub-pass in its own command stream. - hdr_
output - Backend-agnostic representation of the renderer’s swapchain colour-output
mode. Built from the world’s
PostProcessConfig.hdr_displayrequest plus the active display’s measured EDR capability (the backend supplies the capability; this module is pure CPU). The result drives: - input
- Backend-agnostic input snapshot returned by RenderBackend::take_input. Each backend was previously carrying its own structurally-identical InputState; this single type replaces those duplicates.
- keymap
- The runtime, rebindable key map for the gameplay movement keys. Each backend
decodes physical keys into the same semantic booleans (forward, jump, …);
this map says which canonical InputKey drives each action, so the settings menu can
remap them at runtime. The map is canonical (backend-agnostic InputKey values); a
backend resolves it to its own native key codes when it is pushed via
RenderBackend::set_keymap. - lights
- Converts drained DirectionalLight, PointLight, SpotLight, and RectAreaLight asset components into the GPU data the renderer consumes: the fixed LightUniforms uniform (directional lights, ambient, and the legacy point array the raymarch / fog / probe paths read), the GpuLight storage buffer the clustered forward pass iterates, the per-slice spot shadow projections, and the rect area-light extents.
- ltc
- The linearly-transformed-cosine lookup tables the rectangular area-light
shading path samples, generated at build time by the fitter in
fit.rs. - metal
- GPU-free host-side layout contract for the Metal backend’s shader structs
(uniform structs, math, shader-layout asserts). Metal-specific but device-free,
so it is compiled unconditionally and its layout tests run on every platform’s
CI. The Metal backend (concinnity-device) re-exports it under its own
metal. - mipmap
- Backend-agnostic mip-chain generation for streamed RGBA8 textures. Each
backend’s texture upload calls
generate_mip_chainand uploads every level, so albedo and normal maps minify through a proper trilinear chain instead of aliasing from a single mip-0 sample at a distance. - ops
- Recorded backend effects: simulation systems queue their GPU mutations as ops instead of calling the backend directly, and the submit path replays them in record order before the frame’s draw. Ordering across systems is preserved by the single queue, so the GPU-visible result matches the old direct calls exactly. Ops own their payloads, so a queue can cross a thread boundary with the snapshot that carries it.
- overlay_
maps - The side tables the overlay builders take alongside the components they draw.
- parallel_
ctx - Generic Send/Sync shim for parallel per-pass command recording, shared by all
three backend executors (
{metal,directx,vulkan}/graph_exec.rs). Each backend fans its non-composite render-graph passes onto worker threads; every worker records into its own command buffer/list and reaches the immutable subset of the backend context it needs through aParallelCtxRef. - particles
- Backend-agnostic resolution of
ParticleEmittercomponents into theParticleEmitterRecords the backends consume. Each record carries the clamped emitter tunables, the resolved texture pool slot, and the per-frame uniform builder the GPU compute + render passes share. Pure CPU; the per-emitter GPU buffers themselves are allocated by the backend at init. - pass_
timing - Per-pass GPU timing slot arithmetic, shared by every backend that times passes with a timestamp query pool.
- planar_
reflection - Planar reflection math: mirror a camera across a world plane and oblique-clip the projection so geometry behind the plane never leaks into the reflection.
- reflection_
probe - Reflection probe capture math: the six cube-face view-projection matrices a probe renders the scene through, plus the load-time conversion of the captured faces into the prefiltered IBL payload the environment sampler consumes. Backend-agnostic; the Metal backend drives the actual scene render into each face (see metal/probe.rs). DirectX / Vulkan can reuse this math.
- render_
graph - Backend-agnostic render graph. Types, builder, and compile pass with
unit tests; the per-backend executors live alongside each backend
(
metal/graph_exec.rs,vulkan/graph_exec.rs,directx/graph_exec.rs) and consume theCompiledGraphthis module produces. - rt_geom
- GPU-free builders for the ray-tracing geometry table plus the dynamic-update
mode ladder, shared by the backends that hardware-ray-trace reflections. Each
backend fills its own
RtGeomEntrytable from the participating draw set; the per-entry packing (index slice, resolved shared-pool texture indices, material, model matrix) is identical across backends and lives here. The per-backend TLAS instance transform (MTLPackedFloat4x3/VkTransformMatrixKHR/ DXR[f32; 12]) is a real hardware type and stays in each backend. - rt_
refit - Backend-agnostic refit cadence for the per-frame skinned bottom-level
acceleration structures. A skinned object’s BLAS traces vertices a compute
pass re-poses every frame, so it has to be updated every frame – but while
the triangle set is unchanged that update can be a REFIT (Vulkan’s
VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR, DXR’sPERFORM_UPDATE), which re-fits the existing tree’s bounding volumes in place instead of rebuilding it from scratch. - rt_
topology - Backend-agnostic planner for the incremental RT acceleration-structure topology refresh. When the participating draw set changes at runtime (a cloned prop, a streamed chunk added/removed), the BLAS head must be brought back in line with the current set without rebuilding every BLAS: reuse every BLAS whose geometry slice is unchanged, build only the new ones, and retire the orphans. This module owns only the pure decision (which slot reuses which old BLAS, which are orphaned); the actual GPU allocation / build / retire is per-backend (directx/raytrace.rs, vulkan/raytrace.rs). Split out so the plan is unit-testable without a GPU.
- scene_
flow - Platform-agnostic active-scene state and transition logic. Scenes are pure content groupings; changes are imperative jumps (UI actions, Behaviors), so this module tracks only which scene is active and drives fade transitions. The SceneControl trait decouples this module from any specific backend; callers supply a concrete backend that implements the two mutation methods.
- scene_
residency - Scene residency bookkeeping: which scenes are pinned (their streamed
content wanted on the GPU), which of each scene’s members are currently
resident, and the derived per-scene load state and progress. Pure
bookkeeping against
core+alloconly, like the streaming policy core: the driver applies pin changes to the stream planners as blocked flags and reports residency transitions back here. - shaders
- The single-source
.slangengine shaders, embedded once for every consumer. - shadow_
bias - The depth-bias raster state every shadow pass binds, on every host.
- shadow_
schedule - Cross-backend cascade re-render scheduling for the cascaded shadow map. The
shadow pass re-rasterizes all scene geometry into every cascade slice, so it
is one of the heaviest passes;
ShadowUpdate::Hybridamortizes the far cascades across frames (near cascade every frame, one far cascade round-robin) while keeping each slice primed before it is sampled. Shared by all three backends so the policy lives once next to the CSM math incsm.rs. - skinned_
pool - Free pool for pre-reserved skinned instance slots. A skinned mesh that opts into runtime spawning (SkinnedMesh.max_instances > 0) has that many hidden bind-pose copies appended to the skinned geometry at load. Each copy is its own skinned draw object with its own vertex region in the shared skinned buffer, which is required because the GPU skin fold writes the deformed buffer keyed by global vertex index: two live instances sharing a region would clobber each other’s pose. This pool tracks, per template, which of those copies are currently free so a spawn can claim one and a despawn can return it. Slot indices are stable skinned-draw-object indices; nothing is compacted, so the per-frame skinned arrays that parallel them stay valid.
- slang_
programs - What each backend compiles from the single-source
.slangshaders. - slang_
source - Source assembly for the single-source
.slangengine shaders. - slot_
rewrites - Propagates a streamed texture-pool slot swap across per-frame descriptor
copies without stalling the device. Backends that bake the texture pool
into per-frame-in-flight descriptor sets (Vulkan) or heap regions (DirectX)
cannot legally rewrite a descriptor while a command buffer referencing it
is pending; instead a swap queues its slot here, and each
draw_frameapplies the queued slots to the copy owned by the frame slot it just fence-waited (which is therefore not referenced by any pending work). An entry retires once every frame-in-flight copy has been rewritten. - snapshot
- The owned per-frame snapshot the extraction phase fills from world state and the submission phase consumes. Self-contained by construction: no borrows into component storage, resources, or the backend, so a frame’s draw inputs can outlive the world borrow that produced them and later cross a thread boundary. Buffers keep their capacity across frames; a steady-state extraction allocates nothing.
- spot_
shadow - Slice assignment and light-space projections for the spot shadow map array.
- sprite
- Sprite quad assembly. Piggybacks on the text render pass: a plain Sprite is
emitted as a TextDrawCall containing a single quad with the sentinel UV
(u < 0) the text shader interprets as a solid-coloured fill (alpha carried
in v); a Sprite with a
textureis emitted with real 0..1 UVs and a positive vertexmodeso the shader samples the sprite’s texture, which lives in the same atlas pool as the font atlases. Either way, screen-space rectangles need no pipeline of their own. - streaming
- Asset-streaming policy core.
- text
- Font atlas data and text draw-call assembly. No backend ownership; the renderer uploads the atlas textures; this module only builds the quad geometry from TextLabel components each frame.
- transparent
- Backend-agnostic helpers for the transparent (translucent) pass. The pass itself is encoded per backend; this module owns only the CPU-side ordering policy so it can be unit-tested without a GPU and reused as the Vulkan / DirectX transparent ports land.
- uniforms
- The
#[repr(C)]blocks the CPU uploads into the single-source.slangshaders, declared once for every backend (seeuniforms/mod.rs). - volumetric_
fog - Backend-agnostic resolution of the authored
VolumetricFogasset into a clamped settings struct plus the per-frameFogParamsuniform the Metal fog fragment shader consumes. Pure CPU; unit-testable without a GPU. - vulkan
- GPU-free, CPU-side pieces of the Vulkan backend: the repr(C) uniform structs
mirrored in the GLSL shaders (std140/std430 layouts) and the per-pass
GPU-timing slot arithmetic. The blocks every backend shares live in
crate::render::uniforms. None of these touch a Vulkan device or command buffer, and they are unit-tested without a GPU. They live incore::render(not the excluded concinnity-device crate) and are compiled unconditionally, so their layout tests run on every platform’s CI and count toward coverage. The Vulkan backend re-exports them undervulkanso it keeps its existingpass_timing/uniformspaths.