Skip to main content

Module render

Module render 

Source
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-scene AreaLightData table the forward pass reads alongside the GpuLight buffer.
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 BackendInit from the drained world assets, calls resolve_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 ShadowUniforms carrying 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_cursor Sprite 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 support. Owns the per-decal model / inverse-model matrix math the projected-decal pass needs at runtime, the DecalRecord the backends consume, and the DecalSet slot table they drive the pass from. 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 Vec and 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: retire pushes 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 RenderBackend boundary. 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. Other carries 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 RenderSnapshot on 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 BloomEncoder to 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_display request plus the active display’s measured EDR capability (the backend supplies the capability; this module is pure CPU). The result drives:
hiz_spd
Dispatch geometry for the single-pass Hi-Z downsampler.
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_chain and 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.
model_history
Decides, per cull record, whether the model-history ring holds a usable previous-frame transform for the G-buffer pre-pass’s motion vectors.
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 a ParallelCtxRef.
particles
Backend-agnostic resolution of ParticleEmitter components into the ParticleEmitterRecords 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 the CompiledGraph this 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 RtGeomEntry table 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’s PERFORM_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 + alloc only, 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 .slang engine 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::Hybrid amortizes 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 in csm.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 .slang shaders.
slang_source
Source assembly for the single-source .slang engine 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_frame applies 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 texture is emitted with real 0..1 UVs and a positive vertex mode so 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 .slang shaders, declared once for every backend (see uniforms/mod.rs).
volumetric_fog
Backend-agnostic resolution of the authored VolumetricFog asset into a clamped settings struct plus the per-frame FogParams uniform 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 in core::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 under vulkan so it keeps its existing pass_timing / uniforms paths.