Skip to content

Commit

Permalink
Merge bc261e4 into 21f0436
Browse files Browse the repository at this point in the history
  • Loading branch information
tsherif committed Oct 16, 2019
2 parents 21f0436 + bc261e4 commit 441d563
Show file tree
Hide file tree
Showing 9 changed files with 254 additions and 221 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Expand Up @@ -9,6 +9,7 @@ module.exports = {
'no-inline-comments': 0,
camelcase: 0,
'max-statements': 0,
'max-depth': 0,
'luma-gl-custom-rules/check-log-call': 1,
'import/no-unresolved': ['error'],
'import/no-extraneous-dependencies': [
Expand Down
1 change: 1 addition & 0 deletions docs/api-reference/webgl/program.md
Expand Up @@ -159,6 +159,7 @@ Notes:
* Indexed rendering uses the element buffer (`GL.ELEMENT_ARRAY_BUFFER`), make sure your attributes or `VertexArray` contains one.
* If a `TransformFeedback` object is supplied, `transformFeedback.begin()` and `transformFeedback.end()` will be called before and after the draw call.
* A `Sampler` will only be bound if there is a matching Texture with the same key in the supplied `uniforms` object.
* Once a uniform is set, it's size should not be changed. This is only a concern for array uniforms.

The following WebGL APIs are called in this function:

Expand Down
1 change: 1 addition & 0 deletions docs/upgrade-guide.md
Expand Up @@ -6,6 +6,7 @@
- `BaseModel` and `Model` have been consolidated in `Model`. `Model` be used as a substitute for `BaseModel` where necessary.
- `AmbientLight`, `DirectionalLight`, `PointLight`, `PhongMaterial`, `PBRMaterial`, `CameraNode` have been removed from @luma.gl/core. These were either empty classes or simple data objects and so can be replaced by plain JavaScript objects in most cases.
- `ShaderCache` has been removed and superseded by `ProgramManager`.
- `VertexArray.getDrawParams` no longer takes overrides as an argument. The calling function can manually override values as needed.
- @luma.gl/glfx has been renamed to @luma.gl/effects.
- @luma.gl/main has been removed. Use individual modules instead.
- `Multipass` classes have been removed.
Expand Down
7 changes: 6 additions & 1 deletion examples/performance/stress-test/app.js
Expand Up @@ -165,11 +165,16 @@ export default class AppAnimationLoop extends AnimationLoop {
opaqueCubes,
transparentCubes,
angle,
statsWidget
statsWidget,
tick
} = props;

statsWidget.update();

if (tick % 600 === 0) {
this.stats.reset();
}

const camX = Math.cos(angle);
const camZ = Math.sin(angle);
const camRadius = 800;
Expand Down
31 changes: 23 additions & 8 deletions modules/core/src/lib/model.js
Expand Up @@ -17,6 +17,9 @@ const LOG_DRAW_TIMEOUT = 10000;

const ERR_MODEL_PARAMS = 'Model needs drawMode and vertexCount';

const NOOP = () => {};
const DRAW_PARAMS = {};

export default class Model {
constructor(gl, props = {}) {
// Deduce a helpful id
Expand All @@ -25,6 +28,7 @@ export default class Model {
this.id = id;
this.gl = gl;
this.id = props.id || uid('Model');
this.debug = props.debug || false;
this.lastLogTime = 0; // TODO - move to probe.gl
this.initialize(props);
}
Expand Down Expand Up @@ -236,25 +240,34 @@ export default class Model {
this.updateModuleSettings(moduleSettings);
this.setUniforms(uniforms);

const logPriority = this._logDrawCallStart(2);
let logPriority;

if (this.debug) {
logPriority = this._logDrawCallStart(2);
}

const drawParams = this.vertexArray.getDrawParams();
const {
isIndexed = drawParams.isIndexed,
indexType = drawParams.indexType,
indexOffset = drawParams.indexOffset,
vertexArrayInstanced = drawParams.isInstanced
} = this.props;

const drawParams = this.vertexArray.getDrawParams(this.props);
if (drawParams.isInstanced && !this.isInstanced) {
if (vertexArrayInstanced && !this.isInstanced) {
log.warn('Found instanced attributes on non-instanced model', this.id)();
}

const {isIndexed, indexType, indexOffset} = drawParams;
const {isInstanced, instanceCount} = this;

const noop = () => {};
const {onBeforeRender = noop, onAfterRender = noop} = this.props;
const {onBeforeRender = NOOP, onAfterRender = NOOP} = this.props;

onBeforeRender();

this.program.setUniforms(this.uniforms);

const didDraw = this.program.draw(
Object.assign({}, opts, {
Object.assign(DRAW_PARAMS, opts, {
logPriority,
uniforms: null, // Already set (may contain "function values" not understood by Program)
framebuffer,
Expand All @@ -273,7 +286,9 @@ export default class Model {

onAfterRender();

this._logDrawCallEnd(logPriority, vertexArray, framebuffer);
if (this.debug) {
this._logDrawCallEnd(logPriority, vertexArray, framebuffer);
}

return didDraw;
}
Expand Down
116 changes: 56 additions & 60 deletions modules/webgl/src/classes/program.js
Expand Up @@ -6,7 +6,7 @@ import Framebuffer from './framebuffer';
import {parseUniformName, getUniformSetter} from './uniforms';
import {VertexShader, FragmentShader} from './shader';
import ProgramConfiguration from './program-configuration';
import {checkUniformValues, areUniformsEqual, getUniformCopy} from './uniforms';
import {copyUniform, checkUniformValues} from './uniforms';

import {withParameters} from '../context';
import {assertWebGL2Context, isWebGL2, getKey} from '../webgl-utils';
Expand Down Expand Up @@ -54,9 +54,10 @@ export default class Program extends Resource {
}

initialize(props = {}) {
const {hash, vs, fs, varyings, bufferMode = GL_SEPARATE_ATTRIBS} = props;
const {hash, vs, fs, varyings, bufferMode = GL_SEPARATE_ATTRIBS, debug = false} = props;

this.hash = hash || ''; // Used by ProgramManager
this.debug = debug;

// Create shaders if needed
this.vs =
Expand All @@ -69,6 +70,8 @@ export default class Program extends Resource {
// uniforms
this.uniforms = {};

this._texturesRenderable = true;

// Setup varyings if supplied
if (varyings && varyings.length > 0) {
assertWebGL2Context(this.gl);
Expand Down Expand Up @@ -128,7 +131,7 @@ export default class Program extends Resource {
this.setUniforms(uniforms || {});
}

if (logPriority !== undefined) {
if (this.debug && logPriority !== undefined) {
const fb = framebuffer ? framebuffer.id : 'default';
const message =
`mode=${getKey(this.gl, drawMode)} verts=${vertexCount} ` +
Expand Down Expand Up @@ -185,36 +188,66 @@ export default class Program extends Resource {
return true;
}

setUniforms(uniforms = {}, _onChangeCallback = () => {}) {
// Simple change detection - if all uniforms are unchanged, do nothing
let somethingChanged = false;
const changedUniforms = {};
for (const key in uniforms) {
if (!areUniformsEqual(this.uniforms[key], uniforms[key])) {
somethingChanged = true;
changedUniforms[key] = uniforms[key];
this.uniforms[key] = getUniformCopy(uniforms[key]);
}
setUniforms(uniforms = {}) {
if (this.debug) {
checkUniformValues(uniforms, this.id, this._uniformSetters);
}

if (somethingChanged) {
_onChangeCallback();
checkUniformValues(changedUniforms, this.id, this._uniformSetters);
this._setUniforms(changedUniforms);
this.gl.useProgram(this.handle);

for (const uniformName in uniforms) {
const uniform = uniforms[uniformName];
const uniformSetter = this._uniformSetters[uniformName];

if (uniformSetter) {
let value = uniform;
let textureUpdate = false;
if (value instanceof Framebuffer) {
value = value.texture;
}
if (value instanceof Texture) {
textureUpdate = this.uniforms[uniformName] !== uniform;

if (textureUpdate) {
// eslint-disable-next-line max-depth
if (uniformSetter.textureIndex === undefined) {
uniformSetter.textureIndex = this._textureIndexCounter++;
}

// Bind texture to index
const texture = value;
const {textureIndex} = uniformSetter;

texture.bind(textureIndex);
value = textureIndex;

if (!texture.loaded) {
this._texturesRenderable = false;
}
}
}

// NOTE(Tarek): uniformSetter returns whether
// value had to be updated or not.
if (uniformSetter(value) || textureUpdate) {
copyUniform(this.uniforms, uniformName, uniform);
}
}
}

return this;
}

// PRIVATE METHODS

// stub for shader chache, should reset uniforms to default valiues
reset() {}

// Checks if all texture-values uniforms are renderable (i.e. loaded)
// Note: This is currently done before every draw call
_areTexturesRenderable() {
let texturesRenderable = true;
if (this._texturesRenderable) {
return true;
}

this._texturesRenderable = true;

for (const uniformName in this.uniforms) {
const uniformSetter = this._uniformSetters[uniformName];
Expand All @@ -230,12 +263,12 @@ export default class Program extends Resource {
if (uniform instanceof Texture) {
const texture = uniform;
// Check that texture is loaded
texturesRenderable = texturesRenderable && texture.loaded;
this._texturesRenderable = this._texturesRenderable && texture.loaded;
}
}
}

return texturesRenderable;
return this._texturesRenderable;
}

// Binds textures
Expand All @@ -259,43 +292,6 @@ export default class Program extends Resource {
}
}

// Apply a set of uniform values to a program
// Only uniforms actually present in the linked program will be updated.
_setUniforms(uniforms) {
this.gl.useProgram(this.handle);

for (const uniformName in uniforms) {
let uniform = uniforms[uniformName];
const uniformSetter = this._uniformSetters[uniformName];

if (uniformSetter) {
if (uniform instanceof Framebuffer) {
uniform = uniform.texture;
}
if (uniform instanceof Texture) {
// eslint-disable-next-line max-depth
if (uniformSetter.textureIndex === undefined) {
uniformSetter.textureIndex = this._textureIndexCounter++;
}

// Bind texture to index
const texture = uniform;
const {textureIndex} = uniformSetter;

texture.bind(textureIndex);

// Set the uniform sampler to the texture index
uniformSetter(textureIndex);
} else {
// Just set the value
uniformSetter(uniform);
}
}
}

return this;
}

// RESOURCE METHODS

_createHandle() {
Expand Down

0 comments on commit 441d563

Please sign in to comment.