Skip to content

Commit

Permalink
trackState
Browse files Browse the repository at this point in the history
  • Loading branch information
ibgreen committed Apr 29, 2024
1 parent 7859594 commit 0c668b8
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 76 deletions.
9 changes: 3 additions & 6 deletions modules/webgl/src/adapter/webgl-device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {DeviceProps, DeviceInfo, CanvasContextProps, TextureFormat} from '@
import type {Buffer, Texture, Framebuffer, VertexArray, VertexArrayProps} from '@luma.gl/core';
import {Device, CanvasContext, log} from '@luma.gl/core';
import type {GLExtensions} from '@luma.gl/constants';
import {WebGLStateTracker, trackContextState} from '../context/state-tracker/webgl-state-tracker';
import {WebGLStateTracker} from '../context/state-tracker/webgl-state-tracker';
import {createBrowserContext} from '../context/helpers/create-browser-context';
import {getDeviceInfo} from './device-helpers/webgl-device-info';
import {WebGLDeviceFeatures} from './device-helpers/webgl-device-features';
Expand Down Expand Up @@ -227,13 +227,10 @@ ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContex
this.canvasContext.resize();

// Install context state tracking
// @ts-expect-error - hidden parameters
const {enable = true, copyState = false} = props;
trackContextState(this.gl, {
enable,
copyState,
const glState = new WebGLStateTracker(this.gl, {
log: (...args: any[]) => log.log(1, ...args)()
});
glState.trackState(this.gl, {copyState: false});

// DEBUG contexts: Add debug instrumentation to the context, force log level to at least 1
if (props.debug) {
Expand Down
97 changes: 39 additions & 58 deletions modules/webgl/src/context/state-tracker/webgl-state-tracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,19 @@ export class WebGLStateTracker {
program: unknown = null;
stateStack: object[] = [];
enable = true;
cache: Record<string, any>;
cache: Record<string, any> = null!;
log;

protected initialized = false;

constructor(
gl: WebGL2RenderingContext,
{
copyState = false, // Copy cache from params (slow) or initialize from WebGL defaults (fast)
log = () => {} // Logging function, called when gl parameter change calls are actually issued
} = {}
props?: {
log; // Logging function, called when gl parameter change calls are actually issued
}
) {
this.gl = gl;
this.cache = copyState ? getGLParameters(gl) : Object.assign({}, GL_PARAMETER_DEFAULTS);
this.log = log;
this.log = props?.log || (() => {});

this._updateCache = this._updateCache.bind(this);
Object.seal(this);
Expand All @@ -57,6 +57,38 @@ export class WebGLStateTracker {
this.stateStack.pop();
}

/**
* Initialize WebGL state caching on a context
* can be called multiple times to enable/disable
*
* @note After calling this function, context state will be cached
* .push() and .pop() will be available for saving,
* temporarily modifying, and then restoring state.
*/
trackState(gl: WebGL2RenderingContext, options?: {copyState?: boolean}): void {
this.cache = options.copyState ? getGLParameters(gl) : Object.assign({}, GL_PARAMETER_DEFAULTS);

if (this.initialized) {
throw new Error('WebGLStateTracker');
}
this.initialized = true;

// @ts-expect-error
this.gl.state = this;

installProgramSpy(gl);

// intercept all setter functions in the table
for (const key in GL_HOOKED_SETTERS) {
const setter = GL_HOOKED_SETTERS[key];
installSetterSpy(gl, key, setter);
}

// intercept all getter functions in the table
installGetterOverride(gl, 'getParameter');
installGetterOverride(gl, 'isEnabled');
}

/**
// interceptor for context set functions - update our cache and our stack
// values (Object) - the key values for this setter
Expand Down Expand Up @@ -95,57 +127,6 @@ export class WebGLStateTracker {
}
}

// PUBLIC API

/**
* Initialize WebGL state caching on a context
* can be called multiple times to enable/disable
*
* @note After calling this function, context state will be cached
* gl.state.push() and gl.state.pop() will be available for saving,
* temporarily modifying, and then restoring state.
*/
export function trackContextState(
gl: WebGL2RenderingContext,
options?: {
enable?: boolean;
copyState?: boolean;
log?: any;
}
): WebGL2RenderingContext {
const {enable = true, copyState} = options || {};
// assert(copyState !== undefined);
// @ts-expect-error
if (!gl.state) {
// @ts-ignore
// const {polyfillContext} = global_;
// if (polyfillContext) {
// polyfillContext(gl);
// }

// Create a state cache
// @ts-expect-error
gl.state = new WebGLStateTracker(gl, {copyState});

installProgramSpy(gl);

// intercept all setter functions in the table
for (const key in GL_HOOKED_SETTERS) {
const setter = GL_HOOKED_SETTERS[key];
installSetterSpy(gl, key, setter);
}

// intercept all getter functions in the table
installGetterOverride(gl, 'getParameter');
installGetterOverride(gl, 'isEnabled');
}

const glState = WebGLStateTracker.get(gl);
glState.enable = enable;

return gl;
}

// HELPER FUNCTIONS - INSTALL GET/SET INTERCEPTORS (SPYS) ON THE CONTEXT

/**
Expand Down
3 changes: 1 addition & 2 deletions modules/webgl/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,12 @@ export {setDeviceParameters, withDeviceParameters} from './adapter/converters/de

// HELPERS - EXPERIMENTAL
export {getShaderLayout} from './adapter/helpers/get-shader-layout';
export {WebGLStateTracker} from './context/state-tracker/webgl-state-tracker';

// TEST EXPORTS
export {TEXTURE_FORMATS as _TEXTURE_FORMATS} from './adapter/converters/texture-formats';

// DEPRECATED TEST EXPORTS
// State tracking
export {WebGLStateTracker, trackContextState} from './context/state-tracker/webgl-state-tracker';

export {
resetGLParameters,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import type {WebGLDevice} from '@luma.gl/webgl';

import {
WebGLStateTracker,
trackContextState,
getGLParameters,
setGLParameters,
resetGLParameters,
Expand All @@ -31,18 +30,17 @@ const device = createTestDevice({debug: true}) as WebGLDevice;

test('WebGLStateTracker#imports', t => {
t.ok(typeof WebGLStateTracker === 'function', 'WebGLStateTracker imported OK');
t.ok(typeof trackContextState === 'function', 'trackContextState imported OK');
t.end();
});

test('WebGLStateTracker#trackContextState', t => {
const {gl} = device;
t.doesNotThrow(
() => trackContextState(gl, {copyState: false}),
'trackContextState call succeeded'
);
t.end();
});
// test.skip('WebGLStateTracker#trackContextState', t => {
// const {gl} = device;
// t.doesNotThrow(
// () => trackContextState(gl, {copyState: false}),
// 'trackContextState call succeeded'
// );
// t.end();
// });

test('WebGLStateTracker#push & pop', t => {
const {gl} = device;
Expand Down

0 comments on commit 0c668b8

Please sign in to comment.