Context:
#9175 for WebGPU to WebGL fallback so sketches reach more browsers. #9191 covered the first part: createCanvas(..., WEBGPU) falls back to WebGL, adds rendererType, and fails early on createStorage, buildComputeShader, compute when not in WebGPU.
the followup from #9175 is: can we run compute shaders on CPU as a fallback, possibly with a smaller particle count.
Goals:
particles = createStorage(data)
computeShader = buildComputeShader(simulate)
compute(computeShader, N)
- User code should stay the same.
- When running in WebGL (or 2d?) mode, compute should fall back to the CPU instead of failing.
- Performance will be much lower, so the system should automatically use fewer items (particles, cells, etc.).
Approaches considered
-
Runtime dual-mode objects
createStorage, buildComputeShader and compute() detect the current renderer. on WebGPU they use the real GPU path. on other renderers they use a CPU path.
-
Dual compilation / JS backend
p5.strands already has separate backends (strands_glslBackend.js, strands_wgslBackend.js). adding a strands_jsBackend.js that evaluates the IR (or lowers it to plain JavaScript) instead of emitting shader source?
-
Full source-to-source rewriting of the sketch (its where i begin thinking, lets just ignore this approach. unnecessary)
I guess we might need some combination of 1 and 2.
Note:
the function passed to buildComputeShader is not normal runnable js. when strands executes it, it builds IR. simply calling that function in a for loop does nothing useful. therefore we might need:
- an interpreter that walks the IR, or
- a js backend that turns the IR into executable js.
- is it viable and also aligned with the project goals?
- how aggressively should we reduce the number of particles/cells on the cpu path? fixed limit?based on device?
- should the js backend interpret the ir directly, or lower it once to a normal js function?
- how much of the strands feature set do we need to support on cpu?
- where should the dual-mode logic live so it stays maintainable across RendererGL and RendererWebGPU?
- how should uniformStorage used inside material and filter shaders behave in WebGL when data lives on CPU.
thoughts welcome.
EDIT: this is roughly the behavior we want the fallback to produce internally: https://editor.p5js.org/skyash/sketches/8McCWmdSl
Context:
#9175 for WebGPU to WebGL fallback so sketches reach more browsers. #9191 covered the first part:
createCanvas(..., WEBGPU)falls back to WebGL, addsrendererType, and fails early oncreateStorage,buildComputeShader,computewhen not in WebGPU.the followup from #9175 is: can we run compute shaders on CPU as a fallback, possibly with a smaller particle count.
Goals:
Approaches considered
Runtime dual-mode objects
createStorage, buildComputeShader and compute() detect the current renderer. on WebGPU they use the real GPU path. on other renderers they use a CPU path.
Dual compilation / JS backend
p5.strands already has separate backends (strands_glslBackend.js, strands_wgslBackend.js). adding a
strands_jsBackend.jsthat evaluates the IR (or lowers it to plain JavaScript) instead of emitting shader source?Full source-to-source rewriting of the sketch (its where i begin thinking, lets just ignore this approach. unnecessary)
I guess we might need some combination of 1 and 2.
Note:
the function passed to buildComputeShader is not normal runnable js. when strands executes it, it builds IR. simply calling that function in a for loop does nothing useful. therefore we might need:
thoughts welcome.
EDIT: this is roughly the behavior we want the fallback to produce internally: https://editor.p5js.org/skyash/sketches/8McCWmdSl