Engine / QUBICENGINE HANDBOOK

The life of a frame

Trace input, fixed simulation, animation, extraction, recording, GPU execution, presentation, and safe cleanup.

A frame has two clocks#

The CPU prepares work while the GPU executes earlier commands. A displayed frame is therefore the result of a schedule, not one function running from top to bottom. Simulation also has its own clock: physics advances in fixed steps so changing display frequency does not change the integration step. Application measures elapsed time, bounds unusually long pauses, and adds time to an accumulator. It performs as many fixed updates as the bounded accumulator permits, then calculates an interpolation fraction for rendering. Input events are sampled once and distributed so an edge-triggered action is not accidentally repeated for every physics step.

01SimulateInput · physics · pose02ExtractBounds · materials03RecordPasses · barriers04ExecuteGPU · present
Ownership and dependencies in QubicEngine’s documented reference architecture.
INTERACTIVE ILLUSTRATIONSIMULATION / BROWSER

Step through a complete frame This illustration uses canvas. The explanation below describes the same process.

Change a control to inspect the result. Values describe the simulation, not native engine benchmarks. Open full lab ↗

The ordered work#

  1. PlatformWindow pumps operating-system messages. InputRouter updates buttons, pointer motion, and actions.
  2. AnimationSystem samples root-motion intent for the controller. PhysicsWorld advances rigid bodies at a fixed timestep, then animation finalizes the visual pose.
  3. Scene resolves local-to-world transforms in parent-before-child order. Render extraction publishes an immutable RenderWorld.
  4. Renderer selects visible instances and levels of detail. AssetStore publishes completed uploads at a safe boundary.
  5. RenderGraph compiles pass dependencies. Workers record commands using their own allocators and contexts.
  6. The queue executes those commands. Presentation hands a completed image to the display system.
  7. Completed fence points retire temporary uploads, descriptors, and resources. In-flight work retains everything it references.

Physics and animation have explicit dependencies when root motion controls a body. Root-motion displacement is sent to the movement controller before collision resolution. The final body position drives the character’s scene transform; animation does not overwrite it a second time.

Inspect the overlap#

INTERACTIVE ILLUSTRATIONSIMULATION / BROWSER

CPU and GPU, in parallel This illustration uses canvas. The explanation below describes the same process.

Change a control to inspect the result. Values describe the simulation, not native engine benchmarks. Open full lab ↗

The lab models a single queue and fixed durations. It is a simulated schedule, not a timer for your computer. Add frames in flight and observe the gaps that disappear from the CPU row. A larger queue may hide waits while also putting more old input between the player and the next displayed image.

Implementation: a safe frame context
cpp · REFERENCE EXCERPT
struct FrameContext {
    ComPtr<ID3D12CommandAllocator> allocator;
    uint64_t completion = 0;
    UploadArena uploads;
    DescriptorArena descriptors;
};
// Wait until this context's previous submission has completed.
WaitForFence(frame.completion);
Check(frame.allocator->Reset());
frame.uploads.Reset();
frame.descriptors.Reset();
// Record, execute, then signal a new completion value.
frame.completion = SubmitAndSignal(recordedLists);

This is an architectural excerpt. UploadArena owns a mapped buffer and an aligned cursor; DescriptorArena owns a reserved region in a shader-visible heap. Both are exclusively assigned to a frame slot. Their Reset operations only rewind cursors after the slot’s fence passes. The complete sample shows real Signal and event-based wait calls without unexplained fence wrappers.

Resource state and resource lifetime#

A barrier establishes an allowed usage and required ordering. A fence tells the CPU when submitted work has finished. Neither replaces the other. A texture can have the correct shader-readable state while its upload buffer is still required by commands that have not executed. Back-buffer transitions normally move PRESENT to RENDER_TARGET before drawing and back to PRESENT before presentation. A frame allocator can be reset only after the GPU completes every command list that uses its storage. Queue ordering makes successive draws ordered, but cross-queue transfers require explicit queue synchronization.

Investigate a slow frame#

Compare CPU submission time with GPU pass durations. A long fence wait may be the symptom of GPU work, excessive queue depth, or a reused resource with too little buffering. A long CPU update may delay an otherwise idle GPU. Measure the cause before adding threads or buffers. Read synchronization for native ownership details and optimization for measurement strategy.

Search titles and full article text.