Skip to content

Commit

Permalink
shader compilation speedup (#9497)
Browse files Browse the repository at this point in the history
* first draft

getting Attribute info

some clean-up

Code clean-up

Addressing PR comments

move Regex into the parameter list

Remove using Set since some the functionalities of Set is not supported in IE11.

* Fixing a render-test failure
  • Loading branch information
sgolbabaei authored May 1, 2020
1 parent ec726ef commit aa6b4b2
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 41 deletions.
2 changes: 1 addition & 1 deletion src/data/bucket/circle_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class CircleBucket<Layer: CircleStyleLayer | HeatmapStyleLayer> implements Bucke
this.layoutVertexArray = new CircleLayoutArray();
this.indexArray = new TriangleIndexArray();
this.segments = new SegmentVector();
this.programConfigurations = new ProgramConfigurationSet(layoutAttributes, options.layers, options.zoom);
this.programConfigurations = new ProgramConfigurationSet(options.layers, options.zoom);
this.stateDependentLayerIds = this.layers.filter((l) => l.isStateDependent()).map((l) => l.id);
}

Expand Down
2 changes: 1 addition & 1 deletion src/data/bucket/fill_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class FillBucket implements Bucket {
this.layoutVertexArray = new FillLayoutArray();
this.indexArray = new TriangleIndexArray();
this.indexArray2 = new LineIndexArray();
this.programConfigurations = new ProgramConfigurationSet(layoutAttributes, options.layers, options.zoom);
this.programConfigurations = new ProgramConfigurationSet(options.layers, options.zoom);
this.segments = new SegmentVector();
this.segments2 = new SegmentVector();
this.stateDependentLayerIds = this.layers.filter((l) => l.isStateDependent()).map((l) => l.id);
Expand Down
2 changes: 1 addition & 1 deletion src/data/bucket/fill_extrusion_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class FillExtrusionBucket implements Bucket {

this.layoutVertexArray = new FillExtrusionLayoutArray();
this.indexArray = new TriangleIndexArray();
this.programConfigurations = new ProgramConfigurationSet(layoutAttributes, options.layers, options.zoom);
this.programConfigurations = new ProgramConfigurationSet(options.layers, options.zoom);
this.segments = new SegmentVector();
this.stateDependentLayerIds = this.layers.filter((l) => l.isStateDependent()).map((l) => l.id);

Expand Down
2 changes: 1 addition & 1 deletion src/data/bucket/line_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class LineBucket implements Bucket {

this.layoutVertexArray = new LineLayoutArray();
this.indexArray = new TriangleIndexArray();
this.programConfigurations = new ProgramConfigurationSet(layoutAttributes, options.layers, options.zoom);
this.programConfigurations = new ProgramConfigurationSet(options.layers, options.zoom);
this.segments = new SegmentVector();

this.stateDependentLayerIds = this.layers.filter((l) => l.isStateDependent()).map((l) => l.id);
Expand Down
4 changes: 2 additions & 2 deletions src/data/bucket/symbol_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -382,8 +382,8 @@ class SymbolBucket implements Bucket {
}

createArrays() {
this.text = new SymbolBuffers(new ProgramConfigurationSet(symbolLayoutAttributes.members, this.layers, this.zoom, property => /^text/.test(property)));
this.icon = new SymbolBuffers(new ProgramConfigurationSet(symbolLayoutAttributes.members, this.layers, this.zoom, property => /^icon/.test(property)));
this.text = new SymbolBuffers(new ProgramConfigurationSet(this.layers, this.zoom, property => /^text/.test(property)));
this.icon = new SymbolBuffers(new ProgramConfigurationSet(this.layers, this.zoom, property => /^icon/.test(property)));

this.glyphOffsetArray = new GlyphOffsetArray();
this.lineVertexArray = new SymbolLineVertexArray();
Expand Down
38 changes: 33 additions & 5 deletions src/data/program_configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -398,13 +398,11 @@ class CrossFadedCompositeBinder implements AttributeBinder {
export default class ProgramConfiguration {
binders: {[_: string]: (AttributeBinder | UniformBinder) };
cacheKey: string;
layoutAttributes: Array<StructArrayMember>;

_buffers: Array<VertexBuffer>;

constructor(layer: TypedStyleLayer, zoom: number, filterProperties: (_: string) => boolean, layoutAttributes: Array<StructArrayMember>) {
constructor(layer: TypedStyleLayer, zoom: number, filterProperties: (_: string) => boolean) {
this.binders = {};
this.layoutAttributes = layoutAttributes;
this._buffers = [];

const keys = [];
Expand Down Expand Up @@ -500,6 +498,36 @@ export default class ProgramConfiguration {
return result;
}

getBinderAttributes(): Array<string> {
const result = [];
for (const property in this.binders) {
const binder = this.binders[property];
if (binder instanceof SourceExpressionBinder || binder instanceof CompositeExpressionBinder) {
for (let i = 0; i < binder.paintVertexAttributes.length; i++) {
result.push(binder.paintVertexAttributes[i].name);
}
} else if (binder instanceof CrossFadedCompositeBinder) {
for (let i = 0; i < patternAttributes.members.length; i++) {
result.push(patternAttributes.members[i].name);
}
}
}
return result;
}

getBinderUniforms(): Array<string> {
const uniforms = [];
for (const property in this.binders) {
const binder = this.binders[property];
if (binder instanceof ConstantBinder || binder instanceof CrossFadedConstantBinder || binder instanceof CompositeExpressionBinder) {
for (const uniformName of binder.uniformNames) {
uniforms.push(uniformName);
}
}
}
return uniforms;
}

getPaintVertexBuffers(): Array<VertexBuffer> {
return this._buffers;
}
Expand Down Expand Up @@ -567,10 +595,10 @@ export class ProgramConfigurationSet<Layer: TypedStyleLayer> {
_featureMap: FeaturePositionMap;
_bufferOffset: number;

constructor(layoutAttributes: Array<StructArrayMember>, layers: $ReadOnlyArray<Layer>, zoom: number, filterProperties: (_: string) => boolean = () => true) {
constructor(layers: $ReadOnlyArray<Layer>, zoom: number, filterProperties: (_: string) => boolean = () => true) {
this.programConfigurations = {};
for (const layer of layers) {
this.programConfigurations[layer.id] = new ProgramConfiguration(layer, zoom, filterProperties, layoutAttributes);
this.programConfigurations[layer.id] = new ProgramConfiguration(layer, zoom, filterProperties);
}
this.needsUpload = false;
this._featureMap = new FeaturePositionMap();
Expand Down
2 changes: 1 addition & 1 deletion src/render/painter.js
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ class Painter {
this.cache = this.cache || {};
const key = `${name}${programConfiguration ? programConfiguration.cacheKey : ''}${this._showOverdrawInspector ? '/overdraw' : ''}`;
if (!this.cache[key]) {
this.cache[key] = new Program(this.context, shaders[name], programConfiguration, programUniforms[name], this._showOverdrawInspector);
this.cache[key] = new Program(this.context, name, shaders[name], programConfiguration, programUniforms[name], this._showOverdrawInspector);
}
return this.cache[key];
}
Expand Down
74 changes: 46 additions & 28 deletions src/render/program.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ export type DrawMode =
| $PropertyType<WebGLRenderingContext, 'TRIANGLES'>
| $PropertyType<WebGLRenderingContext, 'LINE_STRIP'>;

function getTokenizedAttributesAndUniforms (array: Array<string>): Array<string> {
const result = [];

for (let i = 0; i < array.length; i++) {
if (array[i] === null) continue;
const token = array[i].split(' ');
result.push(token.pop());
}
return result;
}
class Program<Us: UniformBindings> {
program: WebGLProgram;
attributes: {[_: string]: number};
Expand All @@ -30,13 +40,27 @@ class Program<Us: UniformBindings> {
failedToCreate: boolean;

constructor(context: Context,
source: {fragmentSource: string, vertexSource: string},
configuration: ?ProgramConfiguration,
fixedUniforms: (Context, UniformLocations) => Us,
showOverdrawInspector: boolean) {
name: string,
source: {fragmentSource: string, vertexSource: string, staticAttributes: Array<string>, staticUniforms: Array<string>},
configuration: ?ProgramConfiguration,
fixedUniforms: (Context, UniformLocations) => Us,
showOverdrawInspector: boolean) {
const gl = context.gl;
this.program = gl.createProgram();

const staticAttrInfo = getTokenizedAttributesAndUniforms(source.staticAttributes);
const dynamicAttrInfo = configuration ? configuration.getBinderAttributes() : [];
const allAttrInfo = staticAttrInfo.concat(dynamicAttrInfo);

const staticUniformsInfo = source.staticUniforms ? getTokenizedAttributesAndUniforms(source.staticUniforms) : [];
const dynamicUniformsInfo = configuration ? configuration.getBinderUniforms() : [];
// remove duplicate uniforms
const uniformList = staticUniformsInfo.concat(dynamicUniformsInfo);
const allUniformsInfo = [];
for (const uniform of uniformList) {
if (allUniformsInfo.indexOf(uniform) < 0) allUniformsInfo.push(uniform);
}

const defines = configuration ? configuration.defines() : [];
if (showOverdrawInspector) {
defines.push('#define OVERDRAW_INSPECTOR;');
Expand Down Expand Up @@ -64,13 +88,16 @@ class Program<Us: UniformBindings> {
assert(gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS), (gl.getShaderInfoLog(vertexShader): any));
gl.attachShader(this.program, vertexShader);

// Manually bind layout attributes in the order defined by their
// ProgramInterface so that we don't dynamically link an unused
// attribute at position 0, which can cause rendering to fail for an
// entire layer (see #4607, #4728)
const layoutAttributes = configuration ? configuration.layoutAttributes : [];
for (let i = 0; i < layoutAttributes.length; i++) {
gl.bindAttribLocation(this.program, i, layoutAttributes[i].name);
this.attributes = {};
const uniformLocations = {};

this.numAttributes = allAttrInfo.length;

for (let i = 0; i < this.numAttributes; i++) {
if (allAttrInfo[i]) {
gl.bindAttribLocation(this.program, i, allAttrInfo[i]);
this.attributes[allAttrInfo[i]] = i;
}
}

gl.linkProgram(this.program);
Expand All @@ -79,23 +106,14 @@ class Program<Us: UniformBindings> {
gl.deleteShader(vertexShader);
gl.deleteShader(fragmentShader);

this.numAttributes = gl.getProgramParameter(this.program, gl.ACTIVE_ATTRIBUTES);

this.attributes = {};
const uniformLocations = {};

for (let i = 0; i < this.numAttributes; i++) {
const attribute = gl.getActiveAttrib(this.program, i);
if (attribute) {
this.attributes[attribute.name] = gl.getAttribLocation(this.program, attribute.name);
}
}

const numUniforms = gl.getProgramParameter(this.program, gl.ACTIVE_UNIFORMS);
for (let i = 0; i < numUniforms; i++) {
const uniform = gl.getActiveUniform(this.program, i);
if (uniform) {
uniformLocations[uniform.name] = gl.getUniformLocation(this.program, uniform.name);
const uniformsArray = Array.from(allUniformsInfo);
for (let it = 0; it < uniformsArray.length; it++) {
const uniform = uniformsArray[it];
if (uniform && !uniformLocations[uniform]) {
const uniformLocation = gl.getUniformLocation(this.program, uniform);
if (uniformLocation) {
uniformLocations[uniform] = uniformLocation;
}
}
}

Expand Down
7 changes: 6 additions & 1 deletion src/shaders/shaders.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ export const symbolTextAndIcon = compile(symbolTextAndIconFrag, symbolTextAndIco
function compile(fragmentSource, vertexSource) {
const re = /#pragma mapbox: ([\w]+) ([\w]+) ([\w]+) ([\w]+)/g;

const staticAttributes = vertexSource.match(/attribute ([\w]+) ([\w]+)/g);
const fragmentUniforms = fragmentSource.match(/uniform ([\w]+) ([\w]+)([\s]*)([\w]*)/g);
const vertexUniforms = vertexSource.match(/uniform ([\w]+) ([\w]+)([\s]*)([\w]*)/g);
const staticUniforms = vertexUniforms ? vertexUniforms.concat(fragmentUniforms) : fragmentUniforms;

const fragmentPragmas = {};

fragmentSource = fragmentSource.replace(re, (match, operation, precision, type, name) => {
Expand Down Expand Up @@ -176,5 +181,5 @@ uniform ${precision} ${type} u_${name};
}
});

return {fragmentSource, vertexSource};
return {fragmentSource, vertexSource, staticAttributes, staticUniforms};
}

0 comments on commit aa6b4b2

Please sign in to comment.