Skip to content

[p5.js 2.0 Bug Report]: Browser UI completely freezes during WebGL shader compilation on Chromium #8371

@StRictOrDer

Description

@StRictOrDer

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:

javascript
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

Browser | Behavior -- | -- Chrome 131 | Complete UI freeze during compilation Brave 1.85 | Complete UI freeze during compilation Edge | Complete UI freeze during compilation Firefox 133 | UI remains responsive, compilation happens without blocking

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:

  1. 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.
  2. 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.
  3. Program binary caching - Once a shader is compiled it gets cached and subsequent loads are instant. The problem is just that first compilation.

Questions

  1. Is there anything that could be done at the p5.js level to leverage KHR_parallel_shader_compile when available?
  2. Would it be possible to call createShader() in a way that doesn't block the main thread?
  3. Is this something that's been looked into before? I searched the issues but didn't find anything directly related.
  4. 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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions