Measure first.
Reproduce exactly.
Glint separates visible frame throughput, fixed-step simulation cost, deterministic state verification, and seeded stress workloads so performance and correctness are inspectable.
Inspect renderer throughput
Set showStats: true on a viewport to see trailing FPS, latest frame time, draw calls, and submitted triangles.
FPSCompleted renders over the trailing second.
Frame timeLatest render wall time through GPU completion.
Draw callsSubmitted calls after culling and batching.
TrianglesSubmitted triangle count for the latest frame.
Measure each fixed step
physics.addStepCompletedCallback((stats) {
debugPrint(
'step ${stats.simulationStep}: '
'callbacks=${stats.callbackTime.inMicroseconds}us '
'backend=${stats.backendTime.inMicroseconds}us '
'bodies=${stats.bodyCount} '
'contacts=${stats.activeContactCount}',
);
});The callback separates gameplay fixed-callback time from native backend time and records body, active contact, and active trigger counts for that tick.
Capture rollback state
final checkpoint = physics.captureSnapshot();
// Predict, retry, or inspect a branch.
physics.stepFixed();
physics.restoreSnapshot(checkpoint);Snapshots retain world identity and restore the fixed-step clock, accumulator, interpolation, gravity, body transforms and velocities, sleep state, and every registered gameplay participant such as vehicles and characters.
Snapshots are in-memory rollback points for one live world. Portable recordings recreate the level and replay inputs instead of serializing native body handles.
Record one input per tick
final recorder = GlintPhysicsReplayRecorder<CarInput>(
world: physics,
applyInput: (input, fixedDt) => car.apply(input),
);
for (final input in recordedInputs) {
recorder.record(input);
}
final replay = recorder.finish();
final result = replay.play(
physics,
(input, fixedDt) => car.apply(input),
);
assert(result.deterministic);Each frame stores a quantized digest. A mismatch reports the first divergent tick instead of only showing that the final pose differs. Applications provide codecs when serializing input tapes to JSON.
Run a seeded mixed workload
final result = await GlintPhysicsStressRunner(
world: physics,
config: const GlintPhysicsStressConfig(
bodyCount: 512,
vehicleCount: 2,
steps: 1200,
queriesPerStep: 4,
),
).run();
expect(result.passed, isTrue);
print(result.toJson());The workload mixes boxes, spheres, capsules, cylinders, dense contacts, impulses, ray/overlap/shape queries, optional vehicles, sleeping, escape checks, finite checks, and a final state digest.
Use layered release checks
Static
Run analyzers for the engine, example, and every optional package.
Deterministic
Run unit tests, native backend integration, replay, and seeded stress.
Build
Build iOS, macOS, and Android targets with real shader bundles and native assets.
Physical
Profile representative release workloads on physical iOS and Android hardware.