Webgl points / shifts the buffer write logic in a worker

The worker receives a transferable array of instructions
and sends back two transferable arrays (vertex and index buffer).
The projection transform is also sent so that when the main thread
receives the buffers from the worker it also knows which projection to
apply when rendering the geometries.
This commit is contained in:
Olivier Guyot
2019-05-16 23:00:06 +02:00
parent 532b8194b1
commit 65be907095
2 changed files with 67 additions and 25 deletions

View File

@@ -8,7 +8,7 @@ import GeometryType from '../../geom/GeometryType.js';
import WebGLLayerRenderer, {
getBlankTexture,
POINT_INSTRUCTIONS_COUNT, POINT_VERTEX_STRIDE,
writePointFeatureInstructions, writePointFeatureToBuffers
writePointFeatureInstructions
} from './Layer.js';
import ViewHint from '../../ViewHint.js';
import {createEmpty, equals} from '../../extent.js';
@@ -18,6 +18,7 @@ import {
multiply as multiplyTransform,
apply as applyTransform
} from '../../transform.js';
import {create as createWebGLWorker} from '../../worker/webgl.js';
const VERTEX_SHADER = `
precision mediump float;
@@ -272,6 +273,26 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
* @private
*/
this.renderInstructions_ = new Float32Array(0);
this.worker_ = createWebGLWorker();
this.worker_.addEventListener('message', function(event) {
if (event.data.type === 'buffers-generated') {
const vertexBuffer = Array.from(new Float32Array(event.data.vertexBuffer));
const indexBuffer = Array.from(new Uint32Array(event.data.indexBuffer));
const projectionTransform = event.data.projectionTransform;
// TODO: improve the WebGLBuffer private api: we shouldn't need to switch back to plain Arrays
// also we need to handle the case where Uint32 array cannot be used
this.verticesBuffer_.arr_ = vertexBuffer;
this.indicesBuffer_.arr_ = indexBuffer;
this.helper_.flushBufferData(ARRAY_BUFFER, this.verticesBuffer_);
this.helper_.flushBufferData(ELEMENT_ARRAY_BUFFER, this.indicesBuffer_);
// saves the projection transform for the current frame state
this.renderTransform_ = projectionTransform;
makeInverseTransform(this.invertRenderTransform_, this.renderTransform_);
}
}.bind(this));
}
/**
@@ -396,31 +417,14 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
);
}
const elementsCount = this.renderInstructions_.length / POINT_INSTRUCTIONS_COUNT;
const indexBuffer = new Uint32Array(elementsCount * 6);
const vertexBuffer = new Float32Array(elementsCount * 4 * POINT_VERTEX_STRIDE);
let bufferPositions = null;
for (let i = 0; i < this.renderInstructions_.length; i += POINT_INSTRUCTIONS_COUNT) {
bufferPositions = writePointFeatureToBuffers(
this.renderInstructions_,
i,
vertexBuffer,
indexBuffer,
bufferPositions,
POINT_INSTRUCTIONS_COUNT);
}
// TODO: improve the WebGLBuffer private api: we shouldn't need to switch back to plain Arrays
// also we need to handle the case where Uint32 array cannot be used
this.verticesBuffer_.arr_ = Array.from(vertexBuffer);
this.indicesBuffer_.arr_ = Array.from(indexBuffer);
this.helper_.flushBufferData(ARRAY_BUFFER, this.verticesBuffer_);
this.helper_.flushBufferData(ELEMENT_ARRAY_BUFFER, this.indicesBuffer_);
this.renderTransform_ = projectionTransform;
makeInverseTransform(this.invertRenderTransform_, this.renderTransform_);
this.worker_.postMessage({
type: 'generate-buffer',
renderInstructions: this.renderInstructions_.buffer,
projectionTransform: projectionTransform
}, [this.renderInstructions_.buffer]);
}
}
export default WebGLPointsLayerRenderer;

38
src/ol/worker/webgl.js Normal file
View File

@@ -0,0 +1,38 @@
/**
* @module ol/worker/webgl
* A worker that does cpu-heavy tasks related to webgl rendering
*/
import {POINT_INSTRUCTIONS_COUNT, POINT_VERTEX_STRIDE, writePointFeatureToBuffers} from '../renderer/webgl/Layer.js';
onmessage = event => {
if (event.data.type === 'generate-buffer') {
const renderInstructions = new Float32Array(event.data.renderInstructions);
const customAttributesCount = event.data.customAttributesCount || 0;
const instructionsCount = POINT_INSTRUCTIONS_COUNT + customAttributesCount;
const projectionTransform = event.data.projectionTransform;
const elementsCount = renderInstructions.length / instructionsCount;
const indexBuffer = new Uint32Array(elementsCount * 6);
const vertexBuffer = new Float32Array(elementsCount * 4 * (POINT_VERTEX_STRIDE + customAttributesCount));
let bufferPositions = null;
for (let i = 0; i < renderInstructions.length; i += instructionsCount) {
bufferPositions = writePointFeatureToBuffers(
renderInstructions,
i,
vertexBuffer,
indexBuffer,
bufferPositions,
instructionsCount);
}
postMessage({
type: 'buffers-generated',
vertexBuffer: vertexBuffer.buffer,
indexBuffer: indexBuffer.buffer,
projectionTransform
}, [vertexBuffer.buffer, indexBuffer.buffer]);
}
};
export let create;