- Advance.
sm->advanceAndApply(dt)updates state machines, animations, layout, and data bindings. - Record.
RiveRendererrecords draw commands into the activeRenderContext. - Submit.
renderContext->flush(...)builds the GPU work and lets the backend submit it.
FrameDescriptor
Configures the upcoming frame. Values are reset every beginFrame.
FlushResources
Carries everything the backend needs to submit the recorded work.
On D3D12, Vulkan, and Metal you must update
currentFrameNumber and
safeFrameNumber every frame against your fence values. Otherwise the
renderer can’t safely recycle staging buffers and you’ll either see
overwrites mid-flight or unbounded memory growth.
Fixed-Timestep Accumulator
State machines and animations are deterministic at fixeddts. Wrap your
real-elapsed-time delta in an accumulator so playback is reproducible across
frame rates:
kMaxFrameDt) prevents catch-up storms after the app gets paused
in a debugger or backgrounded by the OS.
Resize Handling
Three things have to happen on a resize:- Resize your swap-chain / framebuffer.
- Re-create the
RenderTarget. - Either feed the new size into the artboard (for
Fit::layout) or callresetSize(), then runadvanceAndApply(0)so layout solves before the next draw.
Aligning Artboard to Viewport
UsecomputeAlignment (or Renderer::align) to map artboard-space into the
viewport. Stash the matrix — you’ll need its inverse to convert pointer
coordinates back into artboard-space.
When to Skip a Frame
advanceAndApply returns true if the state machine has more work; false if
everything has settled. For animations that have looped to rest, you can
skip both the advance step and the draw call, dropping CPU/GPU usage to
zero between user inputs.
Pointer events and external view-model writes can wake the state machine back up —
re-draw at least once after each.
Tear-Down
RenderContext and the
underlying GPU device. Rive objects hold reference-counted GPU resources;
killing the device first leaves them with dangling handles and crashes on
release.