-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Description
@sgolbabaei and I had a really good session yesterday and discovered some neat optimization opportunities.
The Hypothesis:
Currently, we introduce some jank and take a hit on our load times due to slowness in compiling shaders, which is mostly caused by calling gl.getProgramParameter() to retrieve the number of uniforms and attributes in each program.

The above screenshot shows it takes roughly 100 ms on a Macbook Pro to render the first frame.
Further investigation showed that querying for attributes is more time consuming than querying for uniforms,

Logically it seems like we can eliminate the call to gl.getProgramParameter() completely since our styling pipeline with ProgramConfiguration + Binders already tracks and computes the necessary attributes and uniforms necessary for runtime styling. We should be able to combine that, with the static data in the shader to extract this metadata ourselves, instead of querying gl.
The Experiment:
For a quick prototype, we created a style with just one layer type, lines. The screenshot above shows timing logs for each gl.getProgramParameter() call. It’s roughly between 10 ~30ms and it seems to scale with the number of attributes.
In line.vertex.glsl there are two fixed attributes a_data and a_pos_normal, by adding a tiny predefined metadata object we can quickly lookup the number of fixed attributes at runtime.
export const shaderMetaData = {
line: 2,
lineGradient: 2,
linePattern: 2,
lineSDF: 2,
clippingMask: 1
}
We can likely generate this at compile time with some codegen that analyzes the shader text, rather than updating it by hand.
For calculating the variable attributes, i,e the ones that depend on runtime-styling parameters, we can go through all attribute Binders and sum up the number of vertex attributes.
The Results:
The attribute Query time is down from 10 ~30ms to sub 1ms. 🎉
The experimental branch lives here.
cc @mapbox/gl-core @mapbox/gl-js
