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
The browser takes several seconds to link the WebGL program. This blocks the main thread and causes a long delay when loading the page or whenever shaders are recompiled.
Additional information
Any browser that uses OpenGL to implement WebGL runs into this problem. In addition to desktop Firefox on Mac and Linux, this includes desktop Chrome/Safari whenever the WebGL backend is manually set to OpenGL, as well as Android Chrome/Firefox on at least some devices. Profiling shows that most of the time is spent in calls to glGetActiveUniform or glGetActiveUniformsiv.
What seems to be going on is:
While linking a WebGL program, the browser has to collect information about each active uniform with calls to glGetActiveUniformsiv and glGetActiveUniform. OpenGL treats each member of a struct as a different uniform resource (see OpenGL introspection documentation), so large arrays of large structs can have a giant number of uniforms to query.
The StandardMaterial PBR shader accesses clusterable_objects.data in pbr_lighting.wgsl. When storage buffers are unavailable, this is a uniform array of 204 ClusterableObject structs, each with 11 members as defined in mesh_view_types.wgsl. In Firefox's implementation, that makes 2244 uniforms for each of five calls to glGetActiveUniformsiv to check, plus 2244 calls to glGetActiveUniform.
Parts of a uniform array can be excluded from the list of active uniforms if the shader compiler finds that they're unused, but when the array is in a uniform block, all its uniforms are apparently counted as active (this might be implementation dependent). Naga translates WGSL uniform buffers to GLSL ES uniform blocks, so all members of all 204 entries are queried if any one is accessed.
If possible, it might help to make space for fewer than 204 entries in clusterable_objects at first if there aren't too many point or spot lights in the scene, then somehow increase the capacity up to MAX_UNIFORM_BUFFER_CLUSTERABLE_OBJECTS if more lights are added at runtime. This might require recompiling shaders, but it would only affect platforms without storage buffer support.
The text was updated successfully, but these errors were encountered:
I believe this particular delay only happens when using StandardMaterial, only on browsers with OpenGL backends for WebGL, and only because of the couple of lines in the pbr shader where this clusterable_objects array is accessed. Without that length 204 uniform array, I would expect shader link times to go from ~5 seconds of delay to a split second, leading to roughly the same responsiveness as Bevy projects without StandardMaterial and other web game engines/frameworks that also use WebGL.
Bevy version
0.15.3
Relevant system information
AdapterInfo { name: "Apple M1, or similar", vendor: 4203, device: 0, device_type: IntegratedGpu, driver: "", driver_info: "WebGL 2.0", backend: Gl }
Browser is Firefox 134.0, "WebGL 2 Driver WSI Info" in
about:support
says it's using CGLWhat you did
Open any Bevy project that uses
StandardMaterial
in Firefox with WebGL. This includes most of the WebGL examples on the Bevy official examples page like https://bevyengine.org/examples/3d-rendering/3d-scene/.Alternatively, run any Bevy WebGL project that uses a custom material with a large uniform array of large structs:
main.rs
test.wgsl
What went wrong
The browser takes several seconds to link the WebGL program. This blocks the main thread and causes a long delay when loading the page or whenever shaders are recompiled.
Additional information
Any browser that uses OpenGL to implement WebGL runs into this problem. In addition to desktop Firefox on Mac and Linux, this includes desktop Chrome/Safari whenever the WebGL backend is manually set to OpenGL, as well as Android Chrome/Firefox on at least some devices. Profiling shows that most of the time is spent in calls to
glGetActiveUniform
orglGetActiveUniformsiv
.What seems to be going on is:
glGetActiveUniformsiv
andglGetActiveUniform
. OpenGL treats each member of a struct as a different uniform resource (see OpenGL introspection documentation), so large arrays of large structs can have a giant number of uniforms to query.StandardMaterial
PBR shader accessesclusterable_objects.data
inpbr_lighting.wgsl
. When storage buffers are unavailable, this is a uniform array of 204ClusterableObject
structs, each with 11 members as defined inmesh_view_types.wgsl
. In Firefox's implementation, that makes 2244 uniforms for each of five calls toglGetActiveUniformsiv
to check, plus 2244 calls toglGetActiveUniform
.If possible, it might help to make space for fewer than 204 entries in
clusterable_objects
at first if there aren't too many point or spot lights in the scene, then somehow increase the capacity up toMAX_UNIFORM_BUFFER_CLUSTERABLE_OBJECTS
if more lights are added at runtime. This might require recompiling shaders, but it would only affect platforms without storage buffer support.The text was updated successfully, but these errors were encountered: