Skip to content

perf(data-gpu): fix O(all) voxel scan in physicsRenderBridge, add static-instance fast path - #209

Merged
krisnye merged 2 commits into
mainfrom
knye/pbr-terrain-static-perf
Sep 28, 2026
Merged

krisnye merged 2 commits into
mainfrom
knye/pbr-terrain-static-perf

Conversation

@krisnye

@krisnye krisnye commented Sep 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • physicsRenderBridge excluded voxel-tagged and already-resolved rows with a per-row store.read/store.get check inside the scan loop, so it visited every row of every matching archetype each frame — including large static-collider populations (e.g. a terrain heightfield) that were always skipped anyway. The exclusion now happens at the archetype-query level (exclude: ["voxelShapeName", "mesh"]), so those rows never enter the loop (O(pending) instead of O(all)).
  • pbrFactorRender gains an opt-in _pbrFactorStaticInstances resource: once a scene's drawable count stabilizes, cache per-mesh instance buffers/bind groups and just re-issue drawIndexed on later frames, skipping the per-frame TRS gather + instance-buffer upload for scenes that never move or grow (e.g. baked terrain).
  • Bump all publishable package versions to 0.10.21 in lockstep (pnpm bump).

Found while profiling a 256×256 voxel terrain sample in a downstream app: physicsRenderBridge was costing 13-15ms/frame (the majority of CPU frame time) purely from scanning ~65k static terrain colliders it was always going to skip.

Test plan

  • pnpm --filter @adobe/data-gpu typecheck — passes (pre-existing, unrelated interpolate.ts error confirmed present on main before this branch too)
  • Verified in a downstream app (mechs terrain-world sample): frame time dropped from ~33ms to ~17ms after applying the equivalent fix locally

krisnye and others added 2 commits September 27, 2026 20:43
…e, static-instance fast path for pbrFactorRender

physicsRenderBridge previously excluded voxel-tagged and already-resolved
rows with a per-row `store.read`/`store.get` check inside the scan loop,
so it visited every row of every matching archetype each frame -
including large populations of static voxel colliders (e.g. a terrain
heightfield) that were always going to be skipped anyway. Move the
`voxelShapeName` / `mesh` exclusion into the archetype query itself so
those rows never enter the loop (O(pending) instead of O(all)).

pbrFactorRender gains an opt-in `_pbrFactorStaticInstances` resource:
once a scene's drawable count stabilizes, cache the per-mesh instance
buffers and bind groups and just re-issue `drawIndexed` on later frames,
skipping the per-frame TRS gather and instance-buffer upload for scenes
that never move or grow (e.g. baked terrain).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@krisnye
krisnye merged commit 7920ae8 into main Sep 28, 2026
3 checks passed
@krisnye
krisnye deleted the knye/pbr-terrain-static-perf branch September 28, 2026 03:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant