Skip to content

Commit

Permalink
Make symbolInstances array transferrable.
Browse files Browse the repository at this point in the history
This change decreases worker transfer time which should decrease jankiness during tile loading.
However, there is some extra overhead in accessing the StructArray of symbolInstances during render-time symbol placement. If we identify hotspots, the most direct optimization is to used indexed accessors into the underlying TypedArray, instead of using the `get(i).property` approach.
  • Loading branch information
ChrisLoer committed Aug 22, 2018
1 parent 57ee650 commit 0fd76c1
Show file tree
Hide file tree
Showing 8 changed files with 284 additions and 125 deletions.
5 changes: 3 additions & 2 deletions build/generate-struct-arrays.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ createStructArrayType('raster_bounds', rasterBoundsAttributes);

const circleAttributes = require('../src/data/bucket/circle_attributes').default;
const fillAttributes = require('../src/data/bucket/fill_attributes').default;
const fillExtrusionAttributes = require('../src/data/bucket/fill_extrusion_attributes').default ;
const fillExtrusionAttributes = require('../src/data/bucket/fill_extrusion_attributes').default;
const lineAttributes = require('../src/data/bucket/line_attributes').default;

// layout vertex arrays
Expand All @@ -150,6 +150,7 @@ const {
collisionCircleLayout,
collisionVertexAttributes,
placement,
symbolInstance,
glyphOffset,
lineVertex
} = require('../src/data/bucket/symbol_attributes');
Expand All @@ -162,6 +163,7 @@ createStructArrayType(`collision_box_layout`, collisionBoxLayout);
createStructArrayType(`collision_circle_layout`, collisionCircleLayout);
createStructArrayType(`collision_vertex`, collisionVertexAttributes);
createStructArrayType('placed_symbol', placement, true);
createStructArrayType('symbol_instance', symbolInstance, true);
createStructArrayType('glyph_offset', glyphOffset, true);
createStructArrayType('symbol_line_vertex', lineVertex, true);

Expand Down Expand Up @@ -233,4 +235,3 @@ export {
${[...arrayTypeEntries].join(',\n ')}
};
`);

141 changes: 141 additions & 0 deletions src/data/array_types.js
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,74 @@ StructArrayLayout2i2ui3ul3ui2f2ub40.prototype.bytesPerElement = 40;
register('StructArrayLayout2i2ui3ul3ui2f2ub40', StructArrayLayout2i2ui3ul3ui2f2ub40);


/**
* Implementation of the StructArray layout:
* [0]: Int16[4]
* [8]: Uint16[9]
* [28]: Uint32[1]
*
* @private
*/
class StructArrayLayout4i9ui1ul32 extends StructArray {
uint8: Uint8Array;
int16: Int16Array;
uint16: Uint16Array;
uint32: Uint32Array;

_refreshViews() {
this.uint8 = new Uint8Array(this.arrayBuffer);
this.int16 = new Int16Array(this.arrayBuffer);
this.uint16 = new Uint16Array(this.arrayBuffer);
this.uint32 = new Uint32Array(this.arrayBuffer);
}

emplaceBack(v0: number, v1: number, v2: number, v3: number, v4: number, v5: number, v6: number, v7: number, v8: number, v9: number, v10: number, v11: number, v12: number, v13: number) {
const i = this.length;
this.resize(i + 1);
const o2 = i * 16;
const o4 = i * 8;
this.int16[o2 + 0] = v0;
this.int16[o2 + 1] = v1;
this.int16[o2 + 2] = v2;
this.int16[o2 + 3] = v3;
this.uint16[o2 + 4] = v4;
this.uint16[o2 + 5] = v5;
this.uint16[o2 + 6] = v6;
this.uint16[o2 + 7] = v7;
this.uint16[o2 + 8] = v8;
this.uint16[o2 + 9] = v9;
this.uint16[o2 + 10] = v10;
this.uint16[o2 + 11] = v11;
this.uint16[o2 + 12] = v12;
this.uint32[o4 + 7] = v13;
return i;
}

emplace(i: number, v0: number, v1: number, v2: number, v3: number, v4: number, v5: number, v6: number, v7: number, v8: number, v9: number, v10: number, v11: number, v12: number, v13: number) {
const o2 = i * 16;
const o4 = i * 8;
this.int16[o2 + 0] = v0;
this.int16[o2 + 1] = v1;
this.int16[o2 + 2] = v2;
this.int16[o2 + 3] = v3;
this.uint16[o2 + 4] = v4;
this.uint16[o2 + 5] = v5;
this.uint16[o2 + 6] = v6;
this.uint16[o2 + 7] = v7;
this.uint16[o2 + 8] = v8;
this.uint16[o2 + 9] = v9;
this.uint16[o2 + 10] = v10;
this.uint16[o2 + 11] = v11;
this.uint16[o2 + 12] = v12;
this.uint32[o4 + 7] = v13;
return i;
}
}

StructArrayLayout4i9ui1ul32.prototype.bytesPerElement = 32;
register('StructArrayLayout4i9ui1ul32', StructArrayLayout4i9ui1ul32);


/**
* Implementation of the StructArray layout:
* [0]: Float32[1]
Expand Down Expand Up @@ -732,6 +800,11 @@ class StructArrayLayout1ui2 extends StructArray {
return i;
}

emplace(i: number, v0: number) {
const o2 = i * 1;
this.uint16[o2 + 0] = v0;
return i;
}
}

StructArrayLayout1ui2.prototype.bytesPerElement = 2;
Expand Down Expand Up @@ -941,6 +1014,73 @@ export class PlacedSymbolArray extends StructArrayLayout2i2ui3ul3ui2f2ub40 {

register('PlacedSymbolArray', PlacedSymbolArray);

class SymbolInstanceStruct extends Struct {
_structArray: SymbolInstanceArray;
anchorX: number;
anchorY: number;
horizontalPlacedTextSymbolIndex: number;
verticalPlacedTextSymbolIndex: number;
key: number;
textBoxStartIndex: number;
textBoxEndIndex: number;
iconBoxStartIndex: number;
iconBoxEndIndex: number;
featureIndex: number;
numGlyphVertices: number;
numVerticalGlyphVertices: number;
numIconVertices: number;
crossTileID: number;
get anchorX() { return this._structArray.int16[this._pos2 + 0]; }
set anchorX(x) { this._structArray.int16[this._pos2 + 0] = x; }
get anchorY() { return this._structArray.int16[this._pos2 + 1]; }
set anchorY(x) { this._structArray.int16[this._pos2 + 1] = x; }
get horizontalPlacedTextSymbolIndex() { return this._structArray.int16[this._pos2 + 2]; }
set horizontalPlacedTextSymbolIndex(x) { this._structArray.int16[this._pos2 + 2] = x; }
get verticalPlacedTextSymbolIndex() { return this._structArray.int16[this._pos2 + 3]; }
set verticalPlacedTextSymbolIndex(x) { this._structArray.int16[this._pos2 + 3] = x; }
get key() { return this._structArray.uint16[this._pos2 + 4]; }
set key(x) { this._structArray.uint16[this._pos2 + 4] = x; }
get textBoxStartIndex() { return this._structArray.uint16[this._pos2 + 5]; }
set textBoxStartIndex(x) { this._structArray.uint16[this._pos2 + 5] = x; }
get textBoxEndIndex() { return this._structArray.uint16[this._pos2 + 6]; }
set textBoxEndIndex(x) { this._structArray.uint16[this._pos2 + 6] = x; }
get iconBoxStartIndex() { return this._structArray.uint16[this._pos2 + 7]; }
set iconBoxStartIndex(x) { this._structArray.uint16[this._pos2 + 7] = x; }
get iconBoxEndIndex() { return this._structArray.uint16[this._pos2 + 8]; }
set iconBoxEndIndex(x) { this._structArray.uint16[this._pos2 + 8] = x; }
get featureIndex() { return this._structArray.uint16[this._pos2 + 9]; }
set featureIndex(x) { this._structArray.uint16[this._pos2 + 9] = x; }
get numGlyphVertices() { return this._structArray.uint16[this._pos2 + 10]; }
set numGlyphVertices(x) { this._structArray.uint16[this._pos2 + 10] = x; }
get numVerticalGlyphVertices() { return this._structArray.uint16[this._pos2 + 11]; }
set numVerticalGlyphVertices(x) { this._structArray.uint16[this._pos2 + 11] = x; }
get numIconVertices() { return this._structArray.uint16[this._pos2 + 12]; }
set numIconVertices(x) { this._structArray.uint16[this._pos2 + 12] = x; }
get crossTileID() { return this._structArray.uint32[this._pos4 + 7]; }
set crossTileID(x) { this._structArray.uint32[this._pos4 + 7] = x; }
}

SymbolInstanceStruct.prototype.size = 32;

export type SymbolInstance = SymbolInstanceStruct;


/**
* @private
*/
export class SymbolInstanceArray extends StructArrayLayout4i9ui1ul32 {
/**
* Return the SymbolInstanceStruct at the given location in the array.
* @param {number} index The index of the element.
*/
get(index: number): SymbolInstanceStruct {
assert(!this.isTransferred);
return new SymbolInstanceStruct(this, index);
}
}

register('SymbolInstanceArray', SymbolInstanceArray);

class GlyphOffsetStruct extends Struct {
_structArray: GlyphOffsetArray;
offsetX: number;
Expand Down Expand Up @@ -1054,6 +1194,7 @@ export {
StructArrayLayout2i2i2i12,
StructArrayLayout2ub4,
StructArrayLayout2i2ui3ul3ui2f2ub40,
StructArrayLayout4i9ui1ul32,
StructArrayLayout1f4,
StructArrayLayout3i6,
StructArrayLayout1ul2ui8,
Expand Down
17 changes: 17 additions & 0 deletions src/data/bucket/symbol_attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,23 @@ export const placement = createLayout([
{ type: 'Uint8', name: 'hidden' }
]);

export const symbolInstance = createLayout([
{ type: 'Int16', name: 'anchorX' },
{ type: 'Int16', name: 'anchorY' },
{ type: 'Int16', name: 'horizontalPlacedTextSymbolIndex' },
{ type: 'Int16', name: 'verticalPlacedTextSymbolIndex' },
{ type: 'Uint16', name: 'key' },
{ type: 'Uint16', name: 'textBoxStartIndex' },
{ type: 'Uint16', name: 'textBoxEndIndex' },
{ type: 'Uint16', name: 'iconBoxStartIndex' },
{ type: 'Uint16', name: 'iconBoxEndIndex' },
{ type: 'Uint16', name: 'featureIndex' },
{ type: 'Uint16', name: 'numGlyphVertices' },
{ type: 'Uint16', name: 'numVerticalGlyphVertices' },
{ type: 'Uint16', name: 'numIconVertices' },
{ type: 'Uint32', name: 'crossTileID' }
]);

export const glyphOffset = createLayout([
{ type: 'Float32', name: 'offsetX' }
]);
Expand Down
Loading

0 comments on commit 0fd76c1

Please sign in to comment.