-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Description
Most appropriate sub-area of p5.js?
- Accessibility
- Color
- Core/Environment/Rendering
- Data
- DOM
- Events
- Image
- IO
- Math
- Typography
- Utilities
- WebGL
- Build process
- Unit testing
- Internationalization
- Friendly errors
- Other (specify if possible)
p5.js version
Browser UI completely freezes during WebGL shader compilation on Chromium
Web browser and version
Brave Browser v1.85.118 Or any other Chromium based browser.
Operating system
Windows
Steps to reproduce this
Description
When compiling complex WebGL shaders in p5.js WEBGL mode, the entire browser tab becomes unresponsive on Chromium-based browsers until compilation completes. This can last anywhere from 20-50 seconds depending on shader complexity and hardware. During this time users cannot interact with the page at all - no scrolling, no clicking, no UI updates, and sometimes the browser throws a "page unresponsive" dialog.
Firefox handles the same shaders without freezing the UI. The compilation still takes time but users can see loading indicators, interact with other page elements, etc.
Reproduction
Live example: https://openprocessing.org/sketch/2663057
This is a fractal explorer with multiple raymarching shaders. When switching between fractal types or on initial load, shader compilation triggers the freeze.
Minimal reproduction case - any sufficiently complex fragment shader will trigger this, but raymarching shaders with lots of iterations are the easiest way to see it:
let myShader;
const fragSrc = `
precision highp float;
uniform vec2 u_resolution;
// Any complex shader - raymarcher, fractal, etc.
// The more complex, the longer the freeze
void main() {
vec2 uv = gl_FragCoord.xy / u_resolution;
// Complex distance estimator loop
vec3 ro = vec3(0.0, 0.0, -3.0);
vec3 rd = normalize(vec3(uv - 0.5, 1.0));
float t = 0.0;
for (int i = 0; i < 200; i++) {
vec3 p = ro + rd * t;
// Mandelbulb or other complex DE here
float d = length(p) - 1.0;
if (d < 0.001) break;
t += d;
}
gl_FragColor = vec4(vec3(t * 0.1), 1.0);
}
`;
const vertSrc = `
attribute vec3 aPosition;
void main() {
gl_Position = vec4(aPosition, 1.0);
}
`;
function setup() {
createCanvas(800, 600, WEBGL);
myShader = createShader(vertSrc, fragSrc);
}
function draw() {
shader(myShader);
myShader.setUniform('u_resolution', [width, height]);
rect(0, 0, width, height);
}Observed Behavior
Expected Behavior
UI should remain responsive during shader compilation. At minimum, loading indicators should be able to update and users should be able to scroll or interact with page elements.
System Info
- p5.js version: 1.9.2 (via OpenProcessing, but likely affects all recent versions)
- OS: Windows 11
- GPU: NVIDIA RTX 3080
- Driver: 32.0.15.9159
Analysis
I believe this is related to ANGLE (the WebGL translation layer Chromium uses). ANGLE appears to compile shaders synchronously on the main thread, which blocks everything. Firefox uses a different WebGL implementation that doesn't have this issue.
Some things I looked into:
- KHR_parallel_shader_compile - This extension exists specifically for async shader compilation. Checking
gl.getExtension('KHR_parallel_shader_compile')returns the extension on Chrome, so it should theoretically be possible to compile without blocking. - WEBGL_debug_shaders - Could potentially be used to get translated shader source and cache it, but not sure if that helps with compilation time itself.
- Program binary caching - Once a shader is compiled it gets cached and subsequent loads are instant. The problem is just that first compilation.
Questions
- Is there anything that could be done at the p5.js level to leverage
KHR_parallel_shader_compilewhen available? - Would it be possible to call
createShader()in a way that doesn't block the main thread? - Is this something that's been looked into before? I searched the issues but didn't find anything directly related.
- Any recommended workarounds in the meantime? I'm currently showing a loading overlay but users can't even see it animate because the thread is blocked.
Additional Context
OpenProcessing suggested I report this here and mentioned @davepagurek as the person most knowledgeable about WebGL/shader stuff in p5.js. Tagging in case you have any insights.
This becomes a real usability problem for anyone building shader-heavy sketches. My fractal explorer has 2000+ users and I've had to add GPU detection code just to warn people that things might freeze. Would love to find a better solution if one exists.
Happy to test any experimental fixes or provide more detailed logs if that would help.