You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Right now Phoenix renders everything with three.js's WebGLRenderer. I checked the code: renderer-manager.ts only ever does new WebGLRenderer(...) in one place, and there is no WebGPU anywhere in the source.
WebGL has served us well, but it has a ceiling on how many objects we can draw, and a lot of the per-object work (cuts, culling, picking) runs as CPU loops every frame.
The events we will need to show keep getting bigger:
HL-LHC (starting around 2029) stacks ~200 pileup collisions into one event
High Granularity Calorimeters (CMS HGCAL and similar) have on the order of millions of channels
Heavy-ion events are very dense
So the real question is whether Phoenix can still show these in a few years?
Why now (the CERN angle)
ROOT's own event display (ROOT-EVE / REve) is already moving its renderer to WebGPU. Their engine, RenderCore, uses WebGPU compute shaders, and in their CHEP paper they show 1.2 million HGCAL hexagonal prisms at interactive frame rates on a 10-year-old GPU (GTX 970). The catch is that REve requires a C++/ROOT server running behind it.
Phoenix's whole point is zero install (just a URL, runs fully in the browser, can be hosted on GitHub Pages). If we add a WebGPU path, Phoenix could be the first event display that reaches that kind of scale with no server at all. That is a genuine differentiator, not just catching up.
The timing also lines up:
WebGPU is now supported in all major browsers (Chrome, Firefox, Safari 26, Edge, roughly 95% of users), with WebGL2 fallback for the rest.
Three.js already ships WebGPURenderer.
We are already on Three.js r178, and I checked node_modules: it already includes the three/webgpu and three/tsl builds, so there is no dependency upgrade needed just to begin.
Proposal
Add a second renderer path using three.js's WebGPURenderer, selected automatically when the browser supports it, with automatic fallback to the current WebGLRenderer otherwise.
Nothing changes for users without WebGPU or for existing experiment routes.
Then progressively move the heavy per-object work (cuts, culling, picking) onto the GPU instead of running CPU loops every frame.
To keep this reviewable, I'd split it into three phases.
When available, construct a WebGPURenderer instead of WebGLRenderer at the single renderer construction site (renderer-manager.ts). Otherwise continue using today's WebGLRenderer.
Verify the materials Phoenix already uses render correctly on WebGPU. From what I found these are almost entirely standard Three.js materials (MeshBasicMaterial, MeshPhongMaterial, LineBasicMaterial, MeshToonMaterial, PointsMaterial), which automatically convert to node materials under WebGPURenderer.
Port the small number of custom shaders to TSL (Three.js Shading Language), so one shader source works on both WebGPU and WebGL. I found only three custom shader locations:
Add a benchmark so we can compare cells rendered, FPS, and draw calls before and after.
This phase needs no compute shaders. It is mostly "swap the renderer, keep the fallback, confirm everything still renders, scale the instanced path up, and measure." It also tells us exactly which WebGPU features still need work, since Three.js still marks WebGPURenderer as experimental.
Phase 2: Move cuts and culling onto the GPU
Use TSL compute shaders to evaluate collection cuts (energy thresholds, η/φ windows) on the GPU instead of CPU loops.
Perform frustum and occlusion culling on the GPU so off-screen and hidden objects cost essentially nothing.
This is where large object counts become much smoother because the per-frame CPU work is no longer O(n).
Phase 3: GPU picking for instanced collections
Today selection walks the scene graph (selection-manager.ts), which is O(n).
For large instanced collections, replace this with GPU picking by rendering object IDs into an off-screen buffer and reading back the ID under the cursor.
Hover and click remain responsive even with millions of rendered objects.
Why this is safe
Capability detection with automatic fallback means existing users and experiment routes continue using today's renderer unchanged.
Renderer construction happens in one place, so the change is localized rather than spread throughout the codebase.
The custom shader surface is small (three locations), and TSL allows one shader source to target both rendering backends.
What this is about
Right now Phoenix renders everything with
three.js'sWebGLRenderer. I checked the code:renderer-manager.tsonly ever doesnew WebGLRenderer(...)in one place, and there is no WebGPU anywhere in the source.WebGL has served us well, but it has a ceiling on how many objects we can draw, and a lot of the per-object work (cuts, culling, picking) runs as CPU loops every frame.
The events we will need to show keep getting bigger:
So the real question is whether Phoenix can still show these in a few years?
Why now (the CERN angle)
ROOT's own event display (ROOT-EVE / REve) is already moving its renderer to WebGPU. Their engine, RenderCore, uses WebGPU compute shaders, and in their CHEP paper they show 1.2 million HGCAL hexagonal prisms at interactive frame rates on a 10-year-old GPU (GTX 970). The catch is that REve requires a C++/ROOT server running behind it.
Phoenix's whole point is zero install (just a URL, runs fully in the browser, can be hosted on GitHub Pages). If we add a WebGPU path, Phoenix could be the first event display that reaches that kind of scale with no server at all. That is a genuine differentiator, not just catching up.
The timing also lines up:
WebGPURenderer.node_modules: it already includes thethree/webgpuandthree/tslbuilds, so there is no dependency upgrade needed just to begin.Proposal
Add a second renderer path using
three.js'sWebGPURenderer, selected automatically when the browser supports it, with automatic fallback to the currentWebGLRendererotherwise.Nothing changes for users without WebGPU or for existing experiment routes.
Then progressively move the heavy per-object work (cuts, culling, picking) onto the GPU instead of running CPU loops every frame.
To keep this reviewable, I'd split it into three phases.
Phase 1: WebGPU renderer path + fallback (foundation)
WebGPURendererinstead ofWebGLRendererat the single renderer construction site (renderer-manager.ts). Otherwise continue using today'sWebGLRenderer.MeshBasicMaterial,MeshPhongMaterial,LineBasicMaterial,MeshToonMaterial,PointsMaterial), which automatically convert to node materials underWebGPURenderer.TracksMaterial(tracks.ts)ShaderMaterialinphoenix-objects.tseffects-manager.tsInstancedMeshCaloCells path (added in Enabling calo cells causes a big performance hit #474 / fix: use InstancedMesh for CaloCells to prevent WebGL crash (#474) #849) beyond its current limits.This phase needs no compute shaders. It is mostly "swap the renderer, keep the fallback, confirm everything still renders, scale the instanced path up, and measure." It also tells us exactly which WebGPU features still need work, since Three.js still marks
WebGPURendereras experimental.Phase 2: Move cuts and culling onto the GPU
This is where large object counts become much smoother because the per-frame CPU work is no longer O(n).
Phase 3: GPU picking for instanced collections
selection-manager.ts), which is O(n).Hover and click remain responsive even with millions of rendered objects.
Why this is safe
Out of scope
References