impr: Radiance Cascades v2 - #2617
Conversation
… the new system, add cool factor
# Conflicts: # apps/typegpu-docs/package.json # apps/typegpu-docs/src/examples/rendering/radiance-cascades-drawing/drawInteraction.ts # apps/typegpu-docs/src/examples/rendering/radiance-cascades-drawing/index.ts # apps/typegpu-docs/src/examples/rendering/radiance-cascades/drag-controller.ts # apps/typegpu-docs/src/examples/rendering/radiance-cascades/index.ts # apps/typegpu-docs/tests/individual-example-tests/jump-flood-distance.test.ts # packages/typegpu-radiance-cascades/README.md # packages/typegpu-radiance-cascades/package.json # packages/typegpu-radiance-cascades/src/cascades.ts # packages/typegpu-radiance-cascades/src/index.ts # packages/typegpu-radiance-cascades/src/runner.ts # packages/typegpu-sdf/src/jumpFlood.ts # packages/typegpu/src/tgsl/accessProp.ts # pnpm-lock.yaml
|
pkg.pr.new packages benchmark commit |
Bundle size comparison (
|
| 🟢 Decreased | ➖ Unchanged | 🔴 Increased | ❔ Unknown |
|---|---|---|---|
| 0 | 322 | 0 | 0 |
import { ... } in PR vs import * as ... in PR (is the library tree-Shakeable?):
| Test | tsdown |
|---|---|
| tgpu_init.ts | 260.04 kB ( |
| tgpu_initFromDevice.ts | 259.51 kB ( |
| tgpu_resolve.ts | 165.41 kB ( |
| tgpu_resolveWithContext.ts | 165.35 kB ( |
| tgpu_bindGroupLayout.ts | 69.27 kB ( |
| tgpu_mutableAccessor.ts | 66.27 kB ( |
| tgpu_accessor.ts | 66.26 kB ( |
| tgpu_privateVar.ts | 65.61 kB ( |
| tgpu_workgroupVar.ts | 65.60 kB ( |
| tgpu_const.ts | 64.85 kB ( |
| tgpu_fn.ts | 38.45 kB ( |
| tgpu_fragmentFn.ts | 38.45 kB ( |
| tgpu_vertexFn.ts | 38.27 kB ( |
| tgpu_computeFn.ts | 37.97 kB ( |
| tgpu_vertexLayout.ts | 27.08 kB ( |
| tgpu_comptime.ts | 14.77 kB ( |
| tgpu_unroll.ts | 1.66 kB ( |
| tgpu_slot.ts | 1.54 kB ( |
| tgpu_lazy.ts | 1.19 kB ( |
If you wish to run a comparison for other, slower bundlers, run the 'Tree-shake test' from the GitHub Actions menu.
Resolution Time Benchmark---
config:
themeVariables:
xyChart:
plotColorPalette: "#E63946, #3B82F6, #059669"
---
xychart
title "Random Branching (🔴 PR | 🔵 main | 🟢 release)"
x-axis "max depth" [1, 2, 3, 4, 5, 6, 7, 8]
y-axis "time (ms)"
line [0.84, 1.68, 3.27, 5.50, 6.23, 10.50, 19.33, 21.60]
line [0.79, 1.70, 3.52, 5.38, 6.27, 10.40, 19.90, 21.48]
line [0.85, 1.69, 3.93, 5.37, 6.33, 10.10, 20.54, 21.59]
---
config:
themeVariables:
xyChart:
plotColorPalette: "#E63946, #3B82F6, #059669"
---
xychart
title "Linear Recursion (🔴 PR | 🔵 main | 🟢 release)"
x-axis "max depth" [1, 2, 3, 4, 5, 6, 7, 8]
y-axis "time (ms)"
line [0.29, 0.43, 0.62, 0.68, 0.98, 0.99, 1.23, 1.36]
line [0.30, 0.51, 0.58, 0.70, 1.01, 1.01, 1.26, 1.36]
line [0.28, 0.52, 0.59, 0.72, 1.06, 1.08, 1.35, 1.43]
---
config:
themeVariables:
xyChart:
plotColorPalette: "#E63946, #3B82F6, #059669"
---
xychart
title "Full Tree (🔴 PR | 🔵 main | 🟢 release)"
x-axis "max depth" [1, 2, 3, 4, 5, 6, 7, 8]
y-axis "time (ms)"
line [0.89, 1.77, 3.97, 6.08, 10.47, 23.47, 47.76, 96.71]
line [0.67, 1.81, 3.01, 5.74, 10.49, 22.57, 48.52, 95.53]
line [0.73, 1.79, 3.52, 5.44, 11.38, 23.04, 48.41, 100.25]
|
|
@pullfrog pls review |
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — v2 rewrite of the radiance cascades package with better cascade sizing, Morton ray ordering, configurable merge modes, encoder support, and memory optimization.
- Add
getCascadeInfowith per-layer metadata — replaces the flatgetCascadeDimwith a richCascadeInfostructure carrying per-layer probe counts, UV ranges, and valid dimensions. The oldgetCascadeDimis kept as a convenience wrapper. - Morton Z-order ray ordering — replaces linear ray indexing with Morton encoding for more uniform angular sampling.
part1By1andmorton2Dare defined incascades.tsand used inmakeCascadePassCompute. - Aspect-correct ray directions —
rayDirectionandsegmentMetricLengthuserenderAspectSlotto produce correct ray distributions on non-square render targets.rayBoxExitUvclips rays to the unit box. - Configurable cascade layers — support for
baseStoredRayDim(1/2/4),mergeMode(hardwareorbilinear-fix), per-layer uniform buffers (CascadeLayerParams), and exposure of common slots (maxRayStepsSlot,rayMarchStepSafetySlot,traceSegmentSlot). - Encoder support —
run()accepts an optionalGPUCommandEncoderso cascade and jump-flood passes can be batched with surrounding work. When omitted,run()creates and submits its own encoder. - 2D ping-pong cascade textures by default — reduces memory usage significantly. 3D array textures are used only when
keepCascadeLayers: true. - Prebuilt JFA pipelines —
createJumpFloodnow prebuilds one pipeline per JFA step instead of writingoffsetUniformat runtime. Fixesdestroy()to clean up offset buffers and uniforms.
DeepSeek Pro (free via Pullfrog for OSS) | 𝕏
|
@pullfrog could you estimate how much less gpu memory we allocate for a couple given resolutions? |
|
The biggest memory win comes from the cascade ping-pong textures switching from 3D arrays to 2D (the default Cascade texture memory: old vs new (default
|
| Resolution | Cascade Dim | Old Layers | Old Memory (2×3D) | New Memory (2×2D) | Savings |
|---|---|---|---|---|---|
| 4K (2160p) | 8192×4608 | 8 | 4.50 GB | 576 MB | 3.94 GB |
| 1440p | 4096×2304 | 7 | 1008 MB | 144 MB | 864 MB |
| 1080p | 4096×2304 | 7 | 1008 MB | 144 MB | 864 MB |
| 720p | 2048×1152 | 7→6 | 252 MB | 36 MB | 216 MB |
| 1024×768 | 2048×1536 | 7→6 | 336 MB | 48 MB | 288 MB |
| 800×600 | 1024×768 | 6 | 72 MB | 12 MB | 60 MB |
(1080p and 1440p share the same cascade dim because the closest-power-of-two diagonal rounds to the same value.)
Tuning baseStoredRayDim (new path, 2×2D only)
Lower values reduce cascade dimensions further at the cost of ray angular resolution:
| Resolution | baseStoredRayDim=1 |
baseStoredRayDim=2 (default) |
baseStoredRayDim=4 |
|---|---|---|---|
| 4K | 144 MB | 576 MB | 2.25 GB |
| 1080p / 1440p | 36 MB | 144 MB | 576 MB |
| 720p | 9 MB | 36 MB | 144 MB |
Uniform buffers
A negligible per-layer uniform buffer (CascadeLayerParams, ~48 B each) replaces the old single CascadeStaticParams + layerBuffer — about the same total, just split per-layer so no layerBuffer.write() is needed during dispatch.
Task list (4/4 completed)
- Explore codebase to understand GPU memory allocation patterns
- Find resolution-dependent buffer/texture allocations
- Calculate and estimate memory savings for given resolutions
- Report findings via pullfrog_report_progress
DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

Uh oh!
There was an error while loading. Please reload this page.