Skip to content

Commit

Permalink
Merge 3a95429 into 9d96290
Browse files Browse the repository at this point in the history
  • Loading branch information
Pessimistress committed Nov 16, 2019
2 parents 9d96290 + 3a95429 commit 0c8a0fe
Show file tree
Hide file tree
Showing 17 changed files with 102 additions and 124 deletions.
4 changes: 2 additions & 2 deletions modules/core/src/lib/attribute/attribute-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ export default class AttributeManager {
update({
data,
numInstances,
bufferLayout,
vertexStarts,
transitions,
props = {},
buffers = {},
Expand Down Expand Up @@ -246,7 +246,7 @@ export default class AttributeManager {
this._updateAttribute({
attribute,
numInstances,
bufferLayout,
vertexStarts,
data,
props,
context
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export default class AttributeTransitionManager {
// an attribute can change transition type when it updates
// let's remove the transition when that happens so we can create the new transition type
// TODO: when switching transition types, make sure to carry over the attribute's
// previous buffers, currentLength, bufferLayout, etc, to be used as the starting point
// previous buffers, currentLength, vertexStarts, etc, to be used as the starting point
// for the next transition
let isNew = !transition || transition.type !== settings.type;
if (isNew) {
Expand Down
12 changes: 6 additions & 6 deletions modules/core/src/lib/attribute/attribute-transition-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,21 +89,21 @@ export function padBuffer({
numInstances,
attribute,
fromLength,
fromBufferLayout,
fromVertexStarts,
getData = x => x
}) {
// TODO: move the precisionMultiplier logic to the attribute when retrieving
// its `size` and `elementOffset`?
const precisionMultiplier = attribute.doublePrecision ? 2 : 1;
const size = attribute.size * precisionMultiplier;
const offset = attribute.elementOffset * precisionMultiplier;
const toBufferLayout = attribute.bufferLayout;
const hasBufferLayout = fromBufferLayout && toBufferLayout;
const toVertexStarts = attribute.vertexStarts;
const hasVertexStarts = fromVertexStarts && toVertexStarts;
const toLength = getAttributeBufferLength(attribute, numInstances);
const isConstant = attribute.state.constant;

// check if buffer needs to be padded
if (!hasBufferLayout && fromLength >= toLength) {
if (!hasVertexStarts && fromLength >= toLength) {
return;
}

Expand All @@ -122,8 +122,8 @@ export function padBuffer({
padArray({
source,
target: data,
sourceLayout: fromBufferLayout,
targetLayout: toBufferLayout,
sourceVertexStarts: fromVertexStarts,
targetVertexStarts: toVertexStarts,
offset,
size,
getData: getMissingData
Expand Down
44 changes: 17 additions & 27 deletions modules/core/src/lib/attribute/attribute.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default class Attribute extends DataColumn {
update = null,
accessor = null,
transform = null,
bufferLayout = null
vertexStarts = null
} = opts;

Object.assign(this.settings, {
Expand All @@ -36,7 +36,7 @@ export default class Attribute extends DataColumn {
needsUpdate: true,
needsRedraw: false,
updateRanges: range.FULL,
bufferLayout
vertexStarts
});

Object.seal(this.settings);
Expand All @@ -46,12 +46,12 @@ export default class Attribute extends DataColumn {
this._validateAttributeUpdaters();
}

get bufferLayout() {
return this.state.bufferLayout;
get vertexStarts() {
return this.state.vertexStarts;
}

set bufferLayout(layout) {
this.state.bufferLayout = layout;
set vertexStarts(layout) {
this.state.vertexStarts = layout;
}

needsUpdate() {
Expand Down Expand Up @@ -136,7 +136,7 @@ export default class Attribute extends DataColumn {
return false;
}

updateBuffer({numInstances, bufferLayout, data, props, context}) {
updateBuffer({numInstances, vertexStarts, data, props, context}) {
if (!this.needsUpdate()) {
return false;
}
Expand All @@ -150,7 +150,7 @@ export default class Attribute extends DataColumn {
if (update) {
// Custom updater - typically for non-instanced layers
for (const [startRow, endRow] of updateRanges) {
update.call(context, this, {data, startRow, endRow, props, numInstances, bufferLayout});
update.call(context, this, {data, startRow, endRow, props, numInstances, vertexStarts});
}
if (!this.value) {
// no value was assigned during update
Expand Down Expand Up @@ -221,20 +221,9 @@ export default class Attribute extends DataColumn {
return true;
}

getVertexOffset(row, bufferLayout = this.bufferLayout) {
let offset = this.settings.elementOffset;
if (bufferLayout) {
let index = 0;
for (const geometrySize of bufferLayout) {
if (index >= row) {
break;
}
offset += geometrySize * this.size;
index++;
}
return offset;
}
return offset + row * this.size;
getVertexOffset(row, vertexStarts = this.vertexStarts) {
const vertexIndex = vertexStarts ? vertexStarts[row] : row;
return this.settings.elementOffset + vertexIndex * this.size;
}

getShaderAttributes() {
Expand All @@ -251,15 +240,15 @@ export default class Attribute extends DataColumn {
return shaderAttributes;
}

_standardAccessor(attribute, {data, startRow, endRow, props, numInstances, bufferLayout}) {
_standardAccessor(attribute, {data, startRow, endRow, props, numInstances, vertexStarts}) {
const {settings, value, size} = attribute;

const {accessor, transform} = settings;
const accessorFunc = typeof accessor === 'function' ? accessor : props[accessor];

assert(typeof accessorFunc === 'function', `accessor "${accessor}" is not a function`);

let i = attribute.getVertexOffset(startRow, bufferLayout);
let i = attribute.getVertexOffset(startRow, vertexStarts);
const {iterable, objectInfo} = createIterable(data, startRow, endRow);
for (const object of iterable) {
objectInfo.index++;
Expand All @@ -271,9 +260,10 @@ export default class Attribute extends DataColumn {
objectValue = transform.call(this, objectValue);
}

if (bufferLayout) {
if (vertexStarts) {
attribute._normalizeValue(objectValue, objectInfo.target);
const numVertices = bufferLayout[objectInfo.index];
const numVertices =
(vertexStarts[objectInfo.index + 1] || numInstances) - vertexStarts[objectInfo.index];
fillArray({
target: attribute.value,
source: objectInfo.target,
Expand All @@ -287,7 +277,7 @@ export default class Attribute extends DataColumn {
}
}
attribute.constant = false;
attribute.bufferLayout = bufferLayout;
attribute.vertexStarts = vertexStarts;
}

// Validate deck.gl level fields
Expand Down
16 changes: 8 additions & 8 deletions modules/core/src/lib/layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -425,12 +425,12 @@ export default class Layer extends Component {

// Figure out data length
const numInstances = this.getNumInstances(props);
const bufferLayout = this.getBufferLayout(props);
const vertexStarts = this.getVertexStarts(props);

attributeManager.update({
data: props.data,
numInstances,
bufferLayout,
vertexStarts,
props,
transitions: props.transitions,
buffers: props,
Expand Down Expand Up @@ -554,17 +554,17 @@ export default class Layer extends Component {
// The default (null) is one value each object.
// Some data formats (e.g. paths, polygons) have various length. Their buffer layout
// is in the form of [L0, L1, L2, ...]
getBufferLayout(props) {
getVertexStarts(props) {
props = props || this.props;

// First Check if bufferLayout is provided as an explicit value
if (props.bufferLayout !== undefined) {
return props.bufferLayout;
// First Check if vertexStarts is provided as an explicit value
if (props.vertexStarts !== undefined) {
return props.vertexStarts;
}

// Second check if the layer has set its own value
if (this.state && this.state.bufferLayout !== undefined) {
return this.state.bufferLayout;
if (this.state && this.state.vertexStarts) {
return this.state.vertexStarts;
}

return null;
Expand Down
8 changes: 4 additions & 4 deletions modules/core/src/transitions/gpu-interpolation-transition.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default class GPUInterpolationTransition {
// `attribute.userData` is the original options passed when constructing the attribute.
// This ensures that we set the proper `doublePrecision` flag and shader attributes.
this.attributeInTransition = new Attribute(gl, attribute.settings);
this.currentBufferLayout = attribute.bufferLayout;
this.currentVertexStarts = attribute.vertexStarts;
// storing currentLength because this.buffer may be larger than the actual length we want to use
// this is because we only reallocate buffers when they grow, not when they shrink,
// due to performance costs
Expand All @@ -45,7 +45,7 @@ export default class GPUInterpolationTransition {
// we need to start animating towards the new values
// this also correctly resizes / pads the transform's buffers
// in case the attribute's buffer has changed in length or in
// bufferLayout
// vertexStarts
start(transitionSettings, numInstances) {
if (transitionSettings.duration <= 0) {
this.transition.cancel();
Expand All @@ -62,15 +62,15 @@ export default class GPUInterpolationTransition {
numInstances,
attribute,
fromLength: this.currentLength,
fromBufferLayout: this.currentBufferLayout,
fromVertexStarts: this.currentVertexStarts,
getData: transitionSettings.enter
};

for (const buffer of buffers) {
padBuffer({buffer, ...padBufferOpts});
}

this.currentBufferLayout = attribute.bufferLayout;
this.currentVertexStarts = attribute.vertexStarts;
this.currentLength = getAttributeBufferLength(attribute, numInstances);
this.attributeInTransition.update({
buffer: buffers[1],
Expand Down
8 changes: 4 additions & 4 deletions modules/core/src/transitions/gpu-spring-transition.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export default class GPUSpringTransition {
gl,
Object.assign({}, attribute.settings, {normalized: false})
);
this.currentBufferLayout = attribute.bufferLayout;
this.currentVertexStarts = attribute.vertexStarts;
// storing currentLength because this.buffer may be larger than the actual length we want to use
// this is because we only reallocate buffers when they grow, not when they shrink,
// due to performance costs
Expand All @@ -52,22 +52,22 @@ export default class GPUSpringTransition {
// we need to start animating towards the new values
// this also correctly resizes / pads the transform's buffers
// in case the attribute's buffer has changed in length or in
// bufferLayout
// vertexStarts
start(transitionSettings, numInstances) {
const {gl, buffers, attribute} = this;
const padBufferOpts = {
numInstances,
attribute,
fromLength: this.currentLength,
fromBufferLayout: this.currentBufferLayout,
fromVertexStarts: this.currentVertexStarts,
getData: transitionSettings.enter
};

for (const buffer of buffers) {
padBuffer({buffer, ...padBufferOpts});
}

this.currentBufferLayout = attribute.bufferLayout;
this.currentVertexStarts = attribute.vertexStarts;
this.currentLength = getAttributeBufferLength(attribute, numInstances);
this.attributeInTransition.update({
buffer: buffers[1],
Expand Down
34 changes: 21 additions & 13 deletions modules/core/src/utils/array-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,25 @@ function padArrayChunk({source, target, start = 0, end, getData}) {
/*
* The padArray function stretches a source array to the size of a target array.
The arrays can have internal structures (like the attributes of PathLayer and
SolidPolygonLayer), defined by the optional sourceLayout and targetLayout parameters.
SolidPolygonLayer), defined by the optional sourceVertexStarts and targetVertexStarts parameters.
If the target array is larger, the getData callback is used to fill in the blanks.
* @params {TypedArray} source - original data
* @params {TypedArray} target - output data
* @params {Number} size - length per datum
* @params {Function} getData - callback to get new data when source is short
* @params {Array<Number>} [sourceLayout] - subdivision of the original data in [chunkSize0, chunkSize1, ...]
* @params {Array<Number>} [targetLayout] - subdivision of the output data in [chunkSize0, chunkSize1, ...]
* @params {Array<Number>} [sourceVertexStarts] - subdivision of the original data in [object0StartIndex, object1StartIndex, ...]
* @params {Array<Number>} [targetVertexStarts] - subdivision of the output data in [object0StartIndex, object1StartIndex, ...]
*/
export function padArray({source, target, size, offset = 0, getData, sourceLayout, targetLayout}) {
if (!Array.isArray(targetLayout)) {
export function padArray({
source,
target,
size,
offset = 0,
getData,
sourceVertexStarts,
targetVertexStarts
}) {
if (!Array.isArray(targetVertexStarts)) {
// Flat arrays
padArrayChunk({
source,
Expand All @@ -77,22 +85,22 @@ export function padArray({source, target, size, offset = 0, getData, sourceLayou
let targetIndex = offset;
const getChunkData = getData && ((i, chunk) => getData(i + targetIndex, chunk));

const n = Math.min(sourceLayout.length, targetLayout.length);
const n = Math.min(sourceVertexStarts.length, targetVertexStarts.length);

for (let i = 0; i < n; i++) {
const sourceChunkLength = sourceLayout[i] * size;
const targetChunkLength = targetLayout[i] * size;
for (let i = 1; i < n; i++) {
const nextSourceIndex = sourceVertexStarts[i] * size + offset;
const nextTargetIndex = targetVertexStarts[i] * size + offset;

padArrayChunk({
source: source.subarray(sourceIndex, sourceIndex + sourceChunkLength),
source: source.subarray(sourceIndex, nextSourceIndex),
target,
start: targetIndex,
end: targetIndex + targetChunkLength,
end: nextTargetIndex,
getData: getChunkData
});

sourceIndex += sourceChunkLength;
targetIndex += targetChunkLength;
sourceIndex = nextSourceIndex;
targetIndex = nextTargetIndex;
}

if (targetIndex < target.length) {
Expand Down
Loading

0 comments on commit 0c8a0fe

Please sign in to comment.