Make held animation frames free: skip pre-skin / weld / BLAS refit for avatars whose pose was not re-evaluated (pelvis-local pre-skin) #632

Closed
opened 2026-10-10 09:27:32 +00:00 by sky_line · 3 comments
Owner

Exploration. Proposed by the 2026-10-10 GPU pipeline audit; not yet implemented.

Idea

Pre-skinning writes its output relative to the eye, and the eye moves every frame. So identical poses still produce different output every frame, and nothing can be skipped exactly. Instead:

  1. Write pre-skin output in pelvis-local (avatar-local) space for every rigged item, and apply the avatar's world/eye transform later (in the vertex/instance transform and the BLAS instance transform).
  2. Skip items whose joint palette is bitwise unchanged since last frame: no pre-skin, no rig weld, no BLAS refit for them.

Why

Measured 2026-10-10 in a ~62-avatar crowd: c_preskin ~1.5-1.7 ms, c_rigweld ~0.6 ms and c_blas_refit ~1.1-1.3 ms per frame. Avatars standing still (held frames are already counted: avHeldFrame ~23-59) would cost nothing. This is the largest remaining GPU lever for crowds.

Open questions

  • Output format: this changes the stored skinned-vertex format and frame. Output differs from today's by float rounding, so this is not bit-identical. Check for precision issues far from the origin (see #555).
  • Consumers: gbuffer, shadows, probes, RT BLAS (refit from local space plus an instance transform), weld (runs on local-space output), motion vectors / previous-frame history (F6 RenderVKPreskinPrevHistory stores positions only).
  • Palette comparison: a cheap exact palette comparison on the GPU, per item or per avatar.
  • Interaction with existing throttles: RenderVKAvatarAnimScreenLOD and the refit throttle.

Measure

GPU sub ms/frame line (c_preskin, c_rigweld, c_blas_refit, total=) in the same crowded sim, before and after.

Related: #258 (cheaper rigged skinning), #616, #617, #564.

**Exploration.** Proposed by the 2026-10-10 GPU pipeline audit; not yet implemented. ## Idea Pre-skinning writes its output relative to the eye, and the eye moves every frame. So identical poses still produce different output every frame, and nothing can be skipped exactly. Instead: 1. Write pre-skin output in **pelvis-local (avatar-local) space** for every rigged item, and apply the avatar's world/eye transform later (in the vertex/instance transform and the BLAS instance transform). 2. **Skip items whose joint palette is bitwise unchanged** since last frame: no pre-skin, no rig weld, no BLAS refit for them. ## Why Measured 2026-10-10 in a ~62-avatar crowd: `c_preskin` ~1.5-1.7 ms, `c_rigweld` ~0.6 ms and `c_blas_refit` ~1.1-1.3 ms per frame. Avatars standing still (held frames are already counted: `avHeldFrame` ~23-59) would cost nothing. This is the largest remaining GPU lever for crowds. ## Open questions - **Output format:** this changes the stored skinned-vertex format and frame. Output differs from today's by float rounding, so this is not bit-identical. Check for precision issues far from the origin (see #555). - **Consumers:** gbuffer, shadows, probes, RT BLAS (refit from local space plus an instance transform), weld (runs on local-space output), motion vectors / previous-frame history (F6 `RenderVKPreskinPrevHistory` stores positions only). - **Palette comparison:** a cheap exact palette comparison on the GPU, per item or per avatar. - **Interaction with existing throttles:** `RenderVKAvatarAnimScreenLOD` and the refit throttle. ## Measure GPU sub ms/frame line (`c_preskin`, `c_rigweld`, `c_blas_refit`, `total=`) in the same crowded sim, before and after. Related: #258 (cheaper rigged skinning), #616, #617, #564.
sky_line added this to the Slipstream project 2026-10-10 09:27:32 +00:00
sky_line changed title from Explore: pre-skin in pelvis-local space + skip items whose joint palette is unchanged (cut preskin / weld / BLAS refit for idle avatars) to Make held animation frames free: skip pre-skin / weld / BLAS refit for avatars whose pose was not re-evaluated (pelvis-local pre-skin) 2026-10-10 12:06:02 +00:00
Author
Owner

Re-scoped 2026-10-10

Owner point: nearly every visible avatar has idle motion every frame (breathing, head look-at, eye saccades, blinks, AO stand sway), so "skip when the palette is bitwise unchanged" rarely fires for nearby avatars.

The real skips come from frames where we didn't re-evaluate animation:

  • screen-size / distance throttled avatars (30/20/15 fps);
  • hidden avatars (5 fps);
  • the rare truly frozen avatar.

In the ~62-avatar crowd, avAnimEval ~23/62 means about half to two-thirds of avatar-frames are held.

Scope:

  1. Pre-skin into avatar-local (pelvis-local) space, with the avatar's world/camera transform applied per instance in the vertex shaders and as the TLAS instance transform. This keeps the BLAS local.
  2. On a held frame, skip pre-skin, weld and BLAS refit for that avatar; only the instance/TLAS transform updates.
  3. Motion vectors: previous position = previous local pose × previous avatar transform.

Expected: ~1-1.5 ms of the ~3-3.5 ms (preskin + weld + refit) in crowds, almost all from distant avatars; close-up crowds save little. The weld cost is handled separately by #641 (pairs decided at rest pose).

## Re-scoped 2026-10-10 Owner point: nearly every visible avatar has idle motion every frame (breathing, head look-at, eye saccades, blinks, AO stand sway), so "skip when the palette is bitwise unchanged" rarely fires for nearby avatars. The real skips come from frames where **we didn't re-evaluate animation**: - screen-size / distance throttled avatars (30/20/15 fps); - hidden avatars (5 fps); - the rare truly frozen avatar. In the ~62-avatar crowd, `avAnimEval` ~23/62 means about half to two-thirds of avatar-frames are held. **Scope:** 1. Pre-skin into avatar-local (pelvis-local) space, with the avatar's world/camera transform applied per instance in the vertex shaders and as the TLAS instance transform. This keeps the BLAS local. 2. On a held frame, skip pre-skin, weld and BLAS refit for that avatar; only the instance/TLAS transform updates. 3. Motion vectors: previous position = previous local pose × previous avatar transform. **Expected:** ~1-1.5 ms of the ~3-3.5 ms (preskin + weld + refit) in crowds, almost all from distant avatars; close-up crowds save little. The weld cost is handled separately by #641 (pairs decided at rest pose).
Author
Owner

Started 2026-10-10 together with #641 (rest-pose weld pairs), as one combined agent pass.

Started 2026-10-10 together with #641 (rest-pose weld pairs), as one combined agent pass.
Author
Owner

Shipped in 1.3.0 Beta 2: avatars on held animation frames reuse an avatar-local skin cache, and the ray-tracing BLAS refit is skipped for them.

Shipped in 1.3.0 Beta 2: avatars on held animation frames reuse an avatar-local skin cache, and the ray-tracing BLAS refit is skipped for them.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sky_line/Slipstream#632
No description provided.