mirror of
https://github.com/visgl/luma.gl.git
synced 2026-02-01 14:33:49 +00:00
Improve perf of uniform setters (#370)
This commit is contained in:
parent
be430a33a7
commit
7f654b8c22
@ -81,24 +81,24 @@ const UNIFORM_SETTERS = {
|
||||
|
||||
/* eslint-disable max-len */
|
||||
[GL_FLOAT]: (gl, location, value) => gl.uniform1f(location, value),
|
||||
[GL_FLOAT_VEC2]: (gl, location, value) => gl.uniform2fv(location, new Float32Array(value)),
|
||||
[GL_FLOAT_VEC3]: (gl, location, value) => gl.uniform3fv(location, new Float32Array(value)),
|
||||
[GL_FLOAT_VEC4]: (gl, location, value) => gl.uniform4fv(location, new Float32Array(value)),
|
||||
[GL_FLOAT_VEC2]: (gl, location, value) => gl.uniform2fv(location, toFloatArray(value, 2)),
|
||||
[GL_FLOAT_VEC3]: (gl, location, value) => gl.uniform3fv(location, toFloatArray(value, 3)),
|
||||
[GL_FLOAT_VEC4]: (gl, location, value) => gl.uniform4fv(location, toFloatArray(value, 4)),
|
||||
|
||||
[GL_INT]: (gl, location, value) => gl.uniform1i(location, value),
|
||||
[GL_INT_VEC2]: (gl, location, value) => gl.uniform2iv(location, new Int32Array(value)),
|
||||
[GL_INT_VEC3]: (gl, location, value) => gl.uniform3iv(location, new Int32Array(value)),
|
||||
[GL_INT_VEC4]: (gl, location, value) => gl.uniform4iv(location, new Int32Array(value)),
|
||||
[GL_INT_VEC2]: (gl, location, value) => gl.uniform2iv(location, toIntArray(value, 2)),
|
||||
[GL_INT_VEC3]: (gl, location, value) => gl.uniform3iv(location, toIntArray(value, 3)),
|
||||
[GL_INT_VEC4]: (gl, location, value) => gl.uniform4iv(location, toIntArray(value, 4)),
|
||||
|
||||
[GL_BOOL]: (gl, location, value) => gl.uniform1i(location, value),
|
||||
[GL_BOOL_VEC2]: (gl, location, value) => gl.uniform2iv(location, new Int32Array(value)),
|
||||
[GL_BOOL_VEC3]: (gl, location, value) => gl.uniform3fv(location, new Int32Array(value)),
|
||||
[GL_BOOL_VEC4]: (gl, location, value) => gl.uniform4iv(location, new Int32Array(value)),
|
||||
[GL_BOOL_VEC2]: (gl, location, value) => gl.uniform2iv(location, toIntArray(value, 2)),
|
||||
[GL_BOOL_VEC3]: (gl, location, value) => gl.uniform3iv(location, toIntArray(value, 3)),
|
||||
[GL_BOOL_VEC4]: (gl, location, value) => gl.uniform4iv(location, toIntArray(value, 4)),
|
||||
|
||||
// uniformMatrix(false): don't transpose the matrix
|
||||
[GL_FLOAT_MAT2]: (gl, location, value) => gl.uniformMatrix2fv(location, false, new Float32Array(value)),
|
||||
[GL_FLOAT_MAT3]: (gl, location, value) => gl.uniformMatrix3fv(location, false, new Float32Array(value)),
|
||||
[GL_FLOAT_MAT4]: (gl, location, value) => gl.uniformMatrix4fv(location, false, new Float32Array(value)),
|
||||
[GL_FLOAT_MAT2]: (gl, location, value) => gl.uniformMatrix2fv(location, false, toFloatArray(value, 4)),
|
||||
[GL_FLOAT_MAT3]: (gl, location, value) => gl.uniformMatrix3fv(location, false, toFloatArray(value, 9)),
|
||||
[GL_FLOAT_MAT4]: (gl, location, value) => gl.uniformMatrix4fv(location, false, toFloatArray(value, 16)),
|
||||
|
||||
[GL_SAMPLER_2D]: (gl, location, value) => gl.uniform1i(location, value),
|
||||
[GL_SAMPLER_CUBE]: (gl, location, value) => gl.uniform1i(location, value),
|
||||
@ -106,17 +106,17 @@ const UNIFORM_SETTERS = {
|
||||
// WEBGL2 - unsigned integers, irregular matrices, additional texture samplers
|
||||
|
||||
[GL_UNSIGNED_INT]: (gl, location, value) => gl.uniform1ui(location, value),
|
||||
[GL_UNSIGNED_INT_VEC2]: (gl, location, value) => gl.uniform2uiv(location, new Uint32Array(value)),
|
||||
[GL_UNSIGNED_INT_VEC3]: (gl, location, value) => gl.uniform3uiv(location, new Uint32Array(value)),
|
||||
[GL_UNSIGNED_INT_VEC4]: (gl, location, value) => gl.uniform4uiv(location, new Uint32Array(value)),
|
||||
[GL_UNSIGNED_INT_VEC2]: (gl, location, value) => gl.uniform2uiv(location, toUIntArray(value, 2)),
|
||||
[GL_UNSIGNED_INT_VEC3]: (gl, location, value) => gl.uniform3uiv(location, toUIntArray(value, 3)),
|
||||
[GL_UNSIGNED_INT_VEC4]: (gl, location, value) => gl.uniform4uiv(location, toUIntArray(value, 4)),
|
||||
|
||||
// uniformMatrix(false): don't transpose the matrix
|
||||
[GL_FLOAT_MAT2x3]: (gl, location, value) => gl.uniformMatrix2x3fv(location, false, new Float32Array(value)),
|
||||
[GL_FLOAT_MAT2x4]: (gl, location, value) => gl.uniformMatrix2x4fv(location, false, new Float32Array(value)),
|
||||
[GL_FLOAT_MAT3x2]: (gl, location, value) => gl.uniformMatrix3x2fv(location, false, new Float32Array(value)),
|
||||
[GL_FLOAT_MAT3x4]: (gl, location, value) => gl.uniformMatrix3x4fv(location, false, new Float32Array(value)),
|
||||
[GL_FLOAT_MAT4x2]: (gl, location, value) => gl.uniformMatrix4x2fv(location, false, new Float32Array(value)),
|
||||
[GL_FLOAT_MAT4x3]: (gl, location, value) => gl.uniformMatrix4x3fv(location, false, new Float32Array(value)),
|
||||
[GL_FLOAT_MAT2x3]: (gl, location, value) => gl.uniformMatrix2x3fv(location, false, toFloatArray(value, 6)),
|
||||
[GL_FLOAT_MAT2x4]: (gl, location, value) => gl.uniformMatrix2x4fv(location, false, toFloatArray(value, 8)),
|
||||
[GL_FLOAT_MAT3x2]: (gl, location, value) => gl.uniformMatrix3x2fv(location, false, toFloatArray(value, 6)),
|
||||
[GL_FLOAT_MAT3x4]: (gl, location, value) => gl.uniformMatrix3x4fv(location, false, toFloatArray(value, 12)),
|
||||
[GL_FLOAT_MAT4x2]: (gl, location, value) => gl.uniformMatrix4x2fv(location, false, toFloatArray(value, 8)),
|
||||
[GL_FLOAT_MAT4x3]: (gl, location, value) => gl.uniformMatrix4x3fv(location, false, toFloatArray(value, 12)),
|
||||
|
||||
[GL_SAMPLER_3D]: (gl, location, value) => gl.uniform1i(location, value),
|
||||
[GL_SAMPLER_2D_SHADOW]: (gl, location, value) => gl.uniform1i(location, value),
|
||||
@ -134,6 +134,56 @@ const UNIFORM_SETTERS = {
|
||||
/* eslint-enable max-len */
|
||||
};
|
||||
|
||||
// Pre-allocated typed arrays for temporary conversion
|
||||
const FLOAT_ARRAY = [2, 3, 4, 6, 8, 9, 12, 16].reduce((arrays, length) => {
|
||||
arrays[length] = new Float32Array(length);
|
||||
return arrays;
|
||||
}, {});
|
||||
const INT_ARRAY = {
|
||||
2: new Int32Array(2),
|
||||
3: new Int32Array(3),
|
||||
4: new Int32Array(4)
|
||||
};
|
||||
const UINT_ARRAY = {
|
||||
2: new Uint32Array(2),
|
||||
3: new Uint32Array(3),
|
||||
4: new Uint32Array(4)
|
||||
};
|
||||
|
||||
/* Functions to ensure the type of uniform values */
|
||||
function toFloatArray(value, length) {
|
||||
if (value instanceof Float32Array) {
|
||||
return value;
|
||||
}
|
||||
const result = FLOAT_ARRAY[length];
|
||||
for (let i = 0; i < length; i++) {
|
||||
result[i] = value[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function toIntArray(value, length) {
|
||||
if (value instanceof Int32Array) {
|
||||
return value;
|
||||
}
|
||||
const result = INT_ARRAY[length];
|
||||
for (let i = 0; i < length; i++) {
|
||||
result[i] = value[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function toUIntArray(value, length) {
|
||||
if (value instanceof Uint32Array) {
|
||||
return value;
|
||||
}
|
||||
const result = UINT_ARRAY[length];
|
||||
for (let i = 0; i < length; i++) {
|
||||
result[i] = value[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function parseUniformName(name) {
|
||||
// name = name[name.length - 1] === ']' ?
|
||||
// name.substr(0, name.length - 3) : name;
|
||||
|
||||
@ -22,10 +22,12 @@
|
||||
import {Bench} from 'probe.gl';
|
||||
|
||||
import shadersBench from './shaders.bench';
|
||||
import uniformsBench from './uniforms.bench';
|
||||
|
||||
const suite = new Bench();
|
||||
|
||||
// add tests
|
||||
uniformsBench(suite);
|
||||
shadersBench(suite);
|
||||
|
||||
// Run the suite
|
||||
|
||||
74
test/bench/uniforms.bench.js
Normal file
74
test/bench/uniforms.bench.js
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright (c) 2015 - 2017 Uber Technologies, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
import {createGLContext, Program} from 'luma.gl';
|
||||
const gl = createGLContext();
|
||||
|
||||
const VS = `
|
||||
uniform vec3 positions;
|
||||
uniform mat4 uMVMatrix;
|
||||
uniform mat4 uPMatrix;
|
||||
void main(void) {
|
||||
gl_Position = uPMatrix * uMVMatrix * vec4(positions, 1.0);
|
||||
}
|
||||
`;
|
||||
|
||||
const FS = `
|
||||
void main(void) {
|
||||
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
}
|
||||
`;
|
||||
|
||||
const program = new Program(gl, {vs: VS, fs: FS});
|
||||
program.use();
|
||||
|
||||
const projectionMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
|
||||
const projectionMatrixTyped = new Float32Array(projectionMatrix);
|
||||
const projectionMatrixIntTyped = new Int32Array(projectionMatrix);
|
||||
const positions = [0, 0, 1];
|
||||
const positionsTyped = new Float32Array(positions);
|
||||
const positionsIntTyped = new Int32Array(positions);
|
||||
|
||||
export default function uniformsBench(suite) {
|
||||
return suite
|
||||
|
||||
.group('SET UNIFORMS')
|
||||
|
||||
.add('Set vec3 uniform from Float32Array', () => {
|
||||
program.setUniforms({positions: positionsTyped});
|
||||
})
|
||||
.add('Set vec3 uniform from plain array', () => {
|
||||
program.setUniforms({positions});
|
||||
})
|
||||
.add('Set vec3 uniform from Int32Array', () => {
|
||||
program.setUniforms({positions: positionsIntTyped});
|
||||
})
|
||||
|
||||
.add('Set mat4 uniform from Float32Array', () => {
|
||||
program.setUniforms({uPMatrix: projectionMatrixTyped});
|
||||
})
|
||||
.add('Set mat4 uniform from plain array', () => {
|
||||
program.setUniforms({uPMatrix: projectionMatrix});
|
||||
})
|
||||
.add('Set mat4 uniform from Int32Array', () => {
|
||||
program.setUniforms({uPMatrix: projectionMatrixIntTyped});
|
||||
})
|
||||
;
|
||||
}
|
||||
@ -39,13 +39,20 @@ precision highp float;
|
||||
#endif
|
||||
|
||||
uniform float f;
|
||||
uniform int i;
|
||||
uniform bool b;
|
||||
uniform vec2 v2;
|
||||
uniform vec3 v3;
|
||||
uniform vec4 v4;
|
||||
// int vectors
|
||||
// bool vectors
|
||||
|
||||
uniform int i;
|
||||
uniform ivec2 iv2;
|
||||
uniform ivec3 iv3;
|
||||
uniform ivec4 iv4;
|
||||
|
||||
uniform bool b;
|
||||
uniform bvec2 bv2;
|
||||
uniform bvec3 bv3;
|
||||
uniform bvec4 bv4;
|
||||
|
||||
uniform mat2 m2;
|
||||
uniform mat3 m3;
|
||||
uniform mat4 m4;
|
||||
@ -54,24 +61,40 @@ uniform sampler2D s2d;
|
||||
// uniform samplerCube sCube;
|
||||
|
||||
void main(void) {
|
||||
vec4 v = vec4(f) + vec4(v2, 0., 0.) + vec4(v3, 0.) + v4;
|
||||
ivec4 iv = ivec4(i) + ivec4(iv2, 0., 0.) + ivec4(iv3, 0.) + iv4;
|
||||
|
||||
bvec4 bv = bv4;
|
||||
bv = bvec4(bv3, 0.);
|
||||
bv = bvec4(bv2, 0., 0.);
|
||||
bv = bvec4(b);
|
||||
|
||||
vec2 transform_v2 = m2 * v2;
|
||||
vec3 transform_v3 = m3 * v3;
|
||||
vec4 transform_v4 = m4 * v4;
|
||||
|
||||
v = texture2D(s2d, v2);
|
||||
|
||||
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
}
|
||||
`;
|
||||
|
||||
const WEBGL1_GOOD_UNIFORMS = {
|
||||
f: 1.0,
|
||||
i: 1,
|
||||
b: true,
|
||||
v2: new Float32Array([1, 2]), // FLOAT_VEC2 0x8B50
|
||||
v3: new Float32Array([1, 2, 3]), // FLOAT_VEC3 0x8B51
|
||||
v4: new Float32Array([1, 2, 3, 4]), // FLOAT_VEC4 0x8B52
|
||||
// INT_VEC2 0x8B53
|
||||
// INT_VEC3 0x8B54
|
||||
// INT_VEC4 0x8B55
|
||||
// BOOL 0x8B56
|
||||
// BOOL_VEC2 0x8B57
|
||||
// BOOL_VEC3 0x8B58
|
||||
// BOOL_VEC4 0x8B59
|
||||
|
||||
i: -1,
|
||||
iv2: new Int32Array([1, 2]), // INT_VEC2 0x8B53
|
||||
iv3: new Int32Array([1, 2, 3]), // INT_VEC3 0x8B54
|
||||
iv4: new Int32Array([1, 2, 3, 4]), // INT_VEC4 0x8B55
|
||||
|
||||
b: true, // BOOL 0x8B56
|
||||
bv2: new Int32Array([false, true]), // BOOL_VEC2 0x8B57
|
||||
bv3: new Int32Array([false, true, false]), // BOOL_VEC3 0x8B58
|
||||
bv4: new Int32Array([false, true, false, true]), // BOOL_VEC4 0x8B59
|
||||
|
||||
m2: new Float32Array(MATRIX_2), // FLOAT_MAT2 0x8B5A
|
||||
m3: new Float32Array(MATRIX_3), // FLOAT_MAT3 0x8B5B
|
||||
m4: new Float32Array(MATRIX_4), // FLOAT_MAT4 0x8B5C
|
||||
@ -155,14 +178,77 @@ test('WebGL#Uniforms pre verify uniforms', t => {
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('WebGL#Uniforms Program construct/delete', t => {
|
||||
test('WebGL#Uniforms Program uniform locations', t => {
|
||||
const {gl} = fixture;
|
||||
|
||||
const program = new Program(gl, {
|
||||
vs: VERTEX_SHADER,
|
||||
fs: WEBGL1_FRAGMENT_SHADER
|
||||
});
|
||||
t.ok(program instanceof Program, 'Program construction successful');
|
||||
|
||||
for (const uniformName in WEBGL1_GOOD_UNIFORMS) {
|
||||
t.ok(program._uniformSetters[uniformName], `Program found uniform setter ${uniformName}`);
|
||||
}
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
const testSetUniform = (gl, t) => {
|
||||
const program = new Program(gl, {
|
||||
vs: VERTEX_SHADER,
|
||||
fs: WEBGL1_FRAGMENT_SHADER
|
||||
});
|
||||
program.use();
|
||||
|
||||
let uniforms = Object.assign({}, WEBGL1_GOOD_UNIFORMS);
|
||||
|
||||
t.comment('Test setting typed arrays');
|
||||
program.setUniforms(uniforms);
|
||||
t.pass('Set typed array uniforms successful');
|
||||
|
||||
uniforms = {};
|
||||
for (const uniformName in WEBGL1_GOOD_UNIFORMS) {
|
||||
const value = WEBGL1_GOOD_UNIFORMS[uniformName];
|
||||
if (value.length) {
|
||||
// Convert to plain array
|
||||
uniforms[uniformName] = Array.from(value);
|
||||
}
|
||||
}
|
||||
|
||||
t.comment('Test setting plain arrays');
|
||||
program.setUniforms(uniforms);
|
||||
t.pass('Set plain array uniforms successful');
|
||||
|
||||
uniforms = {};
|
||||
for (const uniformName in WEBGL1_GOOD_UNIFORMS) {
|
||||
const value = WEBGL1_GOOD_UNIFORMS[uniformName];
|
||||
if (value.length) {
|
||||
// Convert to wrong typed array
|
||||
uniforms[uniformName] = (value instanceof Float32Array) ?
|
||||
new Int32Array(value) : new Float32Array(value);
|
||||
}
|
||||
}
|
||||
|
||||
t.comment('Test setting malformed typed arrays');
|
||||
program.setUniforms(uniforms);
|
||||
t.pass('Set malformed typed array uniforms successful');
|
||||
|
||||
t.end();
|
||||
};
|
||||
|
||||
test('WebGL#Uniforms Program setUniforms', t => {
|
||||
const {gl} = fixture;
|
||||
|
||||
testSetUniform(gl, t);
|
||||
});
|
||||
|
||||
test('WebGL2#Uniforms Program setUniforms', t => {
|
||||
const {gl2} = fixture;
|
||||
|
||||
if (gl2) {
|
||||
testSetUniform(gl2, t);
|
||||
} else {
|
||||
t.end();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user