From 65be907095fe4ff598bf8564dc5e8bec62674b86 Mon Sep 17 00:00:00 2001 From: Olivier Guyot Date: Thu, 16 May 2019 23:00:06 +0200 Subject: [PATCH] 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. --- src/ol/renderer/webgl/PointsLayer.js | 54 +++++++++++++++------------- src/ol/worker/webgl.js | 38 ++++++++++++++++++++ 2 files changed, 67 insertions(+), 25 deletions(-) create mode 100644 src/ol/worker/webgl.js diff --git a/src/ol/renderer/webgl/PointsLayer.js b/src/ol/renderer/webgl/PointsLayer.js index 26dd3e24e3..61b46878dc 100644 --- a/src/ol/renderer/webgl/PointsLayer.js +++ b/src/ol/renderer/webgl/PointsLayer.js @@ -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; diff --git a/src/ol/worker/webgl.js b/src/ol/worker/webgl.js new file mode 100644 index 0000000000..174f7751f5 --- /dev/null +++ b/src/ol/worker/webgl.js @@ -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;