Merge pull request #9562 from jahow/webgl-worker

Optimize the WebGL points renderer using a worker
This commit is contained in:
Olivier Guyot
2019-06-06 08:48:29 +02:00
committed by GitHub
14 changed files with 732 additions and 314 deletions
+78 -10
View File
@@ -2,6 +2,8 @@
* @module ol/webgl/Buffer
*/
import {STATIC_DRAW, STREAM_DRAW, DYNAMIC_DRAW} from '../webgl.js';
import {ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER} from '../webgl.js';
import {assert} from '../asserts.js';
/**
* Used to describe the intended usage for the data: `STATIC_DRAW`, `STREAM_DRAW`
@@ -17,43 +19,109 @@ export const BufferUsage = {
/**
* @classdesc
* Object used to store an array of data as well as usage information for that data.
* See the documentation of [WebGLRenderingContext.bufferData](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData) for more info.
* Stores typed arrays internally, either Float32Array or Uint16/32Array depending on
* the buffer type (ARRAY_BUFFER or ELEMENT_ARRAY_BUFFER) and available extensions.
*
* To populate the array, you can either use:
* * A size using `#ofSize(buffer)`
* * An `ArrayBuffer` object using `#fromArrayBuffer(buffer)`
* * A plain array using `#fromArray(array)`
*
* Note:
* See the documentation of [WebGLRenderingContext.bufferData](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData)
* for more info on buffer usage.
* @api
*/
class WebGLArrayBuffer {
/**
* @param {Array<number>=} opt_arr Array.
* @param {number=} opt_usage Usage, either `STATIC_DRAW`, `STREAM_DRAW` or `DYNAMIC_DRAW`. Default is `DYNAMIC_DRAW`.
* @param {number} type Buffer type, either ARRAY_BUFFER or ELEMENT_ARRAY_BUFFER.
* @param {number=} opt_usage Intended usage, either `STATIC_DRAW`, `STREAM_DRAW` or `DYNAMIC_DRAW`.
* Default is `DYNAMIC_DRAW`.
*/
constructor(opt_arr, opt_usage) {
constructor(type, opt_usage) {
/**
* @private
* @type {Array<number>}
* @type {Float32Array|Uint32Array}
*/
this.arr_ = opt_arr !== undefined ? opt_arr : [];
this.array = null;
/**
* @private
* @type {number}
*/
this.usage_ = opt_usage !== undefined ? opt_usage : BufferUsage.STATIC_DRAW;
this.type = type;
assert(type === ARRAY_BUFFER || type === ELEMENT_ARRAY_BUFFER, 62);
/**
* @private
* @type {number}
*/
this.usage = opt_usage !== undefined ? opt_usage : BufferUsage.STATIC_DRAW;
}
/**
* @return {Array<number>} Array.
* Populates the buffer with an array of the given size (all values will be zeroes).
* @param {number} size Array size
*/
ofSize(size) {
this.array = new (getArrayClassForType(this.type))(size);
}
/**
* Populates the buffer with an array of the given size (all values will be zeroes).
* @param {Array<number>} array Numerical array
*/
fromArray(array) {
this.array = (getArrayClassForType(this.type)).from(array);
}
/**
* Populates the buffer with a raw binary array buffer.
* @param {ArrayBuffer} buffer Raw binary buffer to populate the array with. Note that this buffer must have been
* initialized for the same typed array class.
*/
fromArrayBuffer(buffer) {
this.array = new (getArrayClassForType(this.type))(buffer);
}
/**
* @return {number} Buffer type.
*/
getType() {
return this.type;
}
/**
* @return {Float32Array|Uint32Array} Array.
*/
getArray() {
return this.arr_;
return this.array;
}
/**
* @return {number} Usage.
*/
getUsage() {
return this.usage_;
return this.usage;
}
}
/**
* Returns a typed array constructor based on the given buffer type
* @param {number} type Buffer type, either ARRAY_BUFFER or ELEMENT_ARRAY_BUFFER.
* @returns {Float32ArrayConstructor|Uint32ArrayConstructor} The typed array class to use for this buffer.
*/
export function getArrayClassForType(type) {
switch (type) {
case ARRAY_BUFFER:
return Float32Array;
case ELEMENT_ARRAY_BUFFER:
return Uint32Array;
default:
return Float32Array;
}
}
+12 -30
View File
@@ -2,12 +2,10 @@
* @module ol/webgl/Helper
*/
import {getUid} from '../util.js';
import {EXTENSIONS as WEBGL_EXTENSIONS} from '../webgl.js';
import Disposable from '../Disposable.js';
import {includes} from '../array.js';
import {listen, unlistenAll} from '../events.js';
import {clear} from '../obj.js';
import {ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, TEXTURE_2D, TEXTURE_WRAP_S, TEXTURE_WRAP_T} from '../webgl.js';
import {TEXTURE_2D, TEXTURE_WRAP_S, TEXTURE_WRAP_T, EXTENSIONS as WEBGL_EXTENSIONS} from '../webgl.js';
import ContextEventType from '../webgl/ContextEventType.js';
import {
compose as composeTransform,
@@ -19,6 +17,8 @@ import {
import {create, fromTransform} from '../vec/mat4.js';
import WebGLPostProcessingPass from './PostProcessingPass.js';
import {getContext} from '../webgl.js';
import {includes} from '../array.js';
import {assert} from '../asserts.js';
/**
@@ -258,15 +258,8 @@ class WebGLHelper extends Disposable {
*/
this.currentProgram_ = null;
/**
* @type {boolean}
*/
this.hasOESElementIndexUint = includes(WEBGL_EXTENSIONS, 'OES_element_index_uint');
// use the OES_element_index_uint extension if available
if (this.hasOESElementIndexUint) {
gl.getExtension('OES_element_index_uint');
}
assert(includes(WEBGL_EXTENSIONS, 'OES_element_index_uint'), 63);
gl.getExtension('OES_element_index_uint');
listen(this.canvas_, ContextEventType.LOST,
this.handleWebGLContextLost, this);
@@ -347,11 +340,10 @@ class WebGLHelper extends Disposable {
* Just bind the buffer if it's in the cache. Otherwise create
* the WebGL buffer, bind it, populate it, and add an entry to
* the cache.
* @param {number} target Target, either ARRAY_BUFFER or ELEMENT_ARRAY_BUFFER.
* @param {import("./Buffer").default} buffer Buffer.
* @api
*/
bindBuffer(target, buffer) {
bindBuffer(buffer) {
const gl = this.getGL();
const bufferKey = getUid(buffer);
let bufferCache = this.bufferCache_[bufferKey];
@@ -362,28 +354,19 @@ class WebGLHelper extends Disposable {
webGlBuffer: webGlBuffer
};
}
gl.bindBuffer(target, bufferCache.webGlBuffer);
gl.bindBuffer(buffer.getType(), bufferCache.webGlBuffer);
}
/**
* Update the data contained in the buffer array; this is required for the
* new data to be rendered
* @param {number} target Target, either ARRAY_BUFFER or ELEMENT_ARRAY_BUFFER.
* @param {import("./Buffer").default} buffer Buffer.
* @api
*/
flushBufferData(target, buffer) {
flushBufferData(buffer) {
const gl = this.getGL();
const arr = buffer.getArray();
this.bindBuffer(target, buffer);
let /** @type {ArrayBufferView} */ arrayBuffer;
if (target == ARRAY_BUFFER) {
arrayBuffer = new Float32Array(arr);
} else if (target == ELEMENT_ARRAY_BUFFER) {
arrayBuffer = this.hasOESElementIndexUint ?
new Uint32Array(arr) : new Uint16Array(arr);
}
gl.bufferData(target, arrayBuffer, buffer.getUsage());
this.bindBuffer(buffer);
gl.bufferData(buffer.getType(), buffer.getArray(), buffer.getUsage());
}
/**
@@ -462,9 +445,8 @@ class WebGLHelper extends Disposable {
*/
drawElements(start, end) {
const gl = this.getGL();
const elementType = this.hasOESElementIndexUint ?
gl.UNSIGNED_INT : gl.UNSIGNED_SHORT;
const elementSize = this.hasOESElementIndexUint ? 4 : 2;
const elementType = gl.UNSIGNED_INT;
const elementSize = 4;
const numItems = end - start;
const offsetInBytes = start * elementSize;