Webgl worker / add tests, some typing and documentation
The worker currently works by receiving GENERATE_BUFFERS messages and will send back the same kind of message, with the generated buffers attached. All properties of the original message are kept, so that when a GENERATE_BUFFERS message comes back to the main thread it is possible to know what and how the buffers where generated. This is typically used for the `projectionTransform` matrix, and will also be necessary when working with tiles.
This commit is contained in:
@@ -5,6 +5,26 @@ import LayerRenderer from '../Layer.js';
|
|||||||
import WebGLHelper from '../../webgl/Helper.js';
|
import WebGLHelper from '../../webgl/Helper.js';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
export const WebGLWorkerMessageType = {
|
||||||
|
GENERATE_BUFFERS: 'GENERATE_BUFFERS'
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} WebGLWorkerGenerateBuffersMessage
|
||||||
|
* This message will trigger the generation of a vertex and an index buffer based on the given render instructions.
|
||||||
|
* When the buffers are generated, the worked will send a message of the same type to the main thread, with
|
||||||
|
* the generated buffers in it.
|
||||||
|
* Note that any addition properties present in the message *will* be sent back to the main thread.
|
||||||
|
* @property {WebGLWorkerMessageType} type Message type
|
||||||
|
* @property {ArrayBuffer} renderInstructions Render instructions raw binary buffer.
|
||||||
|
* @property {ArrayBuffer=} vertexBuffer Vertices array raw binary buffer (sent by the worker).
|
||||||
|
* @property {ArrayBuffer=} indexBuffer Indices array raw binary buffer (sent by the worker).
|
||||||
|
* @property {number=} customAttributesCount Amount of custom attributes count in the render instructions.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} PostProcessesOptions
|
* @typedef {Object} PostProcessesOptions
|
||||||
* @property {number} [scaleRatio] Scale ratio; if < 1, the post process will render to a texture smaller than
|
* @property {number} [scaleRatio] Scale ratio; if < 1, the post process will render to a texture smaller than
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {DefaultAttrib, DefaultUniform} from '../../webgl/Helper.js';
|
|||||||
import GeometryType from '../../geom/GeometryType.js';
|
import GeometryType from '../../geom/GeometryType.js';
|
||||||
import WebGLLayerRenderer, {
|
import WebGLLayerRenderer, {
|
||||||
getBlankTexture,
|
getBlankTexture,
|
||||||
POINT_INSTRUCTIONS_COUNT, POINT_VERTEX_STRIDE,
|
POINT_INSTRUCTIONS_COUNT, POINT_VERTEX_STRIDE, WebGLWorkerMessageType,
|
||||||
writePointFeatureInstructions
|
writePointFeatureInstructions
|
||||||
} from './Layer.js';
|
} from './Layer.js';
|
||||||
import ViewHint from '../../ViewHint.js';
|
import ViewHint from '../../ViewHint.js';
|
||||||
@@ -276,10 +276,11 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
|
|||||||
|
|
||||||
this.worker_ = createWebGLWorker();
|
this.worker_ = createWebGLWorker();
|
||||||
this.worker_.addEventListener('message', function(event) {
|
this.worker_.addEventListener('message', function(event) {
|
||||||
if (event.data.type === 'buffers-generated') {
|
const received = event.data;
|
||||||
const projectionTransform = event.data.projectionTransform;
|
if (received.type === WebGLWorkerMessageType.GENERATE_BUFFERS) {
|
||||||
this.verticesBuffer_.fromArrayBuffer(event.data.vertexBuffer);
|
const projectionTransform = received.projectionTransform;
|
||||||
this.indicesBuffer_.fromArrayBuffer(event.data.indexBuffer);
|
this.verticesBuffer_.fromArrayBuffer(received.vertexBuffer);
|
||||||
|
this.indicesBuffer_.fromArrayBuffer(received.indexBuffer);
|
||||||
this.helper_.flushBufferData(this.verticesBuffer_);
|
this.helper_.flushBufferData(this.verticesBuffer_);
|
||||||
this.helper_.flushBufferData(this.indicesBuffer_);
|
this.helper_.flushBufferData(this.indicesBuffer_);
|
||||||
|
|
||||||
@@ -415,11 +416,15 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.worker_.postMessage({
|
/** @type import('./Layer').WebGLWorkerGenerateBuffersMessage */
|
||||||
type: 'generate-buffer',
|
const message = {
|
||||||
renderInstructions: this.renderInstructions_.buffer,
|
type: WebGLWorkerMessageType.GENERATE_BUFFERS,
|
||||||
projectionTransform: projectionTransform
|
renderInstructions: this.renderInstructions_.buffer
|
||||||
}, [this.renderInstructions_.buffer]);
|
};
|
||||||
|
// additional properties will be sent back as-is by the worker
|
||||||
|
message['projectionTransform'] = projectionTransform;
|
||||||
|
|
||||||
|
this.worker_.postMessage(message, [this.renderInstructions_.buffer]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,21 @@
|
|||||||
/**
|
/**
|
||||||
|
* A worker that does cpu-heavy tasks related to webgl rendering.
|
||||||
* @module ol/worker/webgl
|
* @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';
|
import {
|
||||||
|
POINT_INSTRUCTIONS_COUNT,
|
||||||
|
POINT_VERTEX_STRIDE,
|
||||||
|
WebGLWorkerMessageType,
|
||||||
|
writePointFeatureToBuffers
|
||||||
|
} from '../renderer/webgl/Layer.js';
|
||||||
|
import {assign} from '../obj.js';
|
||||||
|
|
||||||
onmessage = event => {
|
onmessage = event => {
|
||||||
if (event.data.type === 'generate-buffer') {
|
const received = event.data;
|
||||||
const renderInstructions = new Float32Array(event.data.renderInstructions);
|
if (received.type === WebGLWorkerMessageType.GENERATE_BUFFERS) {
|
||||||
const customAttributesCount = event.data.customAttributesCount || 0;
|
const renderInstructions = new Float32Array(received.renderInstructions);
|
||||||
|
const customAttributesCount = received.customAttributesCount || 0;
|
||||||
const instructionsCount = POINT_INSTRUCTIONS_COUNT + customAttributesCount;
|
const instructionsCount = POINT_INSTRUCTIONS_COUNT + customAttributesCount;
|
||||||
const projectionTransform = event.data.projectionTransform;
|
|
||||||
|
|
||||||
const elementsCount = renderInstructions.length / instructionsCount;
|
const elementsCount = renderInstructions.length / instructionsCount;
|
||||||
const indexBuffer = new Uint32Array(elementsCount * 6);
|
const indexBuffer = new Uint32Array(elementsCount * 6);
|
||||||
@@ -26,13 +32,14 @@ onmessage = event => {
|
|||||||
instructionsCount);
|
instructionsCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
postMessage({
|
/** @type {import('../renderer/webgl/Layer').WebGLWorkerGenerateBuffersMessage} */
|
||||||
type: 'buffers-generated',
|
const message = assign({
|
||||||
vertexBuffer: vertexBuffer.buffer,
|
vertexBuffer: vertexBuffer.buffer,
|
||||||
indexBuffer: indexBuffer.buffer,
|
indexBuffer: indexBuffer.buffer,
|
||||||
renderInstructions: renderInstructions.buffer,
|
renderInstructions: renderInstructions.buffer
|
||||||
projectionTransform
|
}, received);
|
||||||
}, [vertexBuffer.buffer, indexBuffer.buffer, renderInstructions.buffer]);
|
|
||||||
|
postMessage(message, [vertexBuffer.buffer, indexBuffer.buffer, renderInstructions.buffer]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
46
test/spec/ol/worker/webgl.test.js
Normal file
46
test/spec/ol/worker/webgl.test.js
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import {create} from '../../../../src/ol/worker/webgl.js';
|
||||||
|
import {WebGLWorkerMessageType, writePointFeatureInstructions} from '../../../../src/ol/renderer/webgl/Layer';
|
||||||
|
|
||||||
|
|
||||||
|
describe('ol/worker/webgl', function() {
|
||||||
|
|
||||||
|
let worker;
|
||||||
|
beforeEach(function() {
|
||||||
|
worker = create();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
if (worker) {
|
||||||
|
worker.terminate();
|
||||||
|
}
|
||||||
|
worker = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('messaging', function() {
|
||||||
|
it('responds to GENERATE_BUFFERS message type', function(done) {
|
||||||
|
worker.addEventListener('error', done);
|
||||||
|
|
||||||
|
worker.addEventListener('message', function(event) {
|
||||||
|
expect(event.data.type).to.eql(WebGLWorkerMessageType.GENERATE_BUFFERS);
|
||||||
|
expect(event.data.renderInstructions.byteLength).to.greaterThan(0);
|
||||||
|
expect(event.data.indexBuffer.byteLength).to.greaterThan(0);
|
||||||
|
expect(event.data.vertexBuffer.byteLength).to.greaterThan(0);
|
||||||
|
expect(event.data.testInt).to.be(101);
|
||||||
|
expect(event.data.testString).to.be('abcd');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
const instructions = new Float32Array(100);
|
||||||
|
|
||||||
|
const message = {
|
||||||
|
type: WebGLWorkerMessageType.GENERATE_BUFFERS,
|
||||||
|
renderInstructions: instructions,
|
||||||
|
testInt: 101,
|
||||||
|
testString: 'abcd'
|
||||||
|
};
|
||||||
|
|
||||||
|
worker.postMessage(message);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user