Gizmo Draw List
The gizmo system is a tiny line-list renderer the editor uses for selection outlines, debug visuals, and (soon) translate / rotate / scale handles. Any system, from any frame phase, can call safi_gizmo_draw_* to enqueue a line or wireframe for the current frame; the render system drains the queue inside the main pass and clears it at the end of the frame.
The pipeline is pos + rgba only — no lighting, no texturing, no model matrix. Blending is on (so alpha < 1 works), depth test is on, depth write is off (gizmos don't corrupt the depth buffer for other passes).
API
Init and destroy are called automatically by the engine alongside the debug UI (same enable_debug_ui gate — in a shipping build the GPU resources aren't allocated). The draw helpers are main-thread only.
Enqueue from anywhere
Frame lifecycle
Copy passes cannot run inside a render pass (SDL_gpu constraint), which is why uploads happen in a pre-pass step and draws happen later inside the pass. The queue is cleared at the end of safi_gizmo_system_draw, so every frame starts empty.
Overflow behaviour
The queue is capped (currently ≈ 3400 verts — one 128 KB VBO). Draws beyond the cap are dropped and a single warning is logged per frame. Wireframe boxes cost 24 verts each, sphere-wires at the default 16 segments cost 96. Expected working sets (a selection outline or two, a physics debug overlay) sit comfortably inside the cap.
Depth behaviour
depth_test = LESS_OR_EQUAL— gizmos are occluded by opaque geometry that sits in front of them.depth_write = false— gizmos do not push a Z value into the depth buffer, so subsequent translucent or UI passes see the mesh depth, not the gizmo depth.
For "always on top" gizmos (e.g. a selection pivot that should never be hidden), draw them after the renderer switches modes — a dedicated overlay system on top of this is planned for M4.
Shipping builds
safi_gizmo_system_init is only called when enable_debug_ui = true. In a shipping build the GPU pipeline is never created; the safi_gizmo_draw_* calls still compile (they just no-op), so user code can leave debug gizmos in place without #ifdefs.
See also
- Render Overview — frame lifecycle and pass rules
SafiCameraBuffer— the shared camera UBO the gizmo shader reads- Editor plan — M4 — gizmo entities (translate / rotate / scale) that will sit on top of this primitive