Skip to content

Commit

Permalink
Merge b0c22c1 into 94e45c2
Browse files Browse the repository at this point in the history
  • Loading branch information
ibgreen committed Apr 29, 2024
2 parents 94e45c2 + b0c22c1 commit 7c1c1f2
Show file tree
Hide file tree
Showing 8 changed files with 1,261 additions and 78 deletions.
10 changes: 8 additions & 2 deletions modules/core/src/adapter/device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,11 @@ export type DeviceProps = {
debug?: boolean;
/** Break on WebGL functions matching these strings */
break?: string[];

/** WebGL: Initialize the SpectorJS WebGL debugger */
spector?: boolean;
debugWithSpectorJS?: boolean;
/** SpectorJS URL. Override if CDN is down or different SpectorJS version is desired */
spectorUrl?: string;

// EXPERIMENTAL SETTINGS
/** Set to false to disable WebGL state management instrumentation: TODO- Unclear if still supported / useful */
Expand Down Expand Up @@ -279,9 +282,12 @@ export abstract class Device {
// failIfMajorPerformanceCaveat: undefined

debug: Boolean(log.get('debug')), // Instrument context (at the expense of performance)
spector: Boolean(log.get('spector')), // Initialize the SpectorJS WebGL debugger
break: (log.get('break') as string[]) || [],

// WebGL specific debugging
debugWithSpectorJS: undefined!,
spectorUrl: undefined!,

// TODO - Change these after confirming things work as expected
initalizeFeatures: true,
disabledFeatures: {
Expand Down
2 changes: 1 addition & 1 deletion modules/engine/src/animation-loop/make-animation-loop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function makeAnimationLoop(
): AnimationLoop {
let renderLoop: AnimationLoopTemplate | null = null;

const device = props?.device || luma.createDevice();
const device = props?.device || luma.createDevice({id: 'animation-loop'});

// Create an animation loop;
const animationLoop = new AnimationLoop({
Expand Down
74 changes: 41 additions & 33 deletions modules/webgl/src/adapter/webgl-device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,26 @@ 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 {createBrowserContext} from '../context/helpers/create-browser-context';
import {
popContextState,
trackContextState,
pushContextState,
trackContextState
popContextState
} from '../context/state-tracker/track-context-state';
import {createBrowserContext} from '../context/helpers/create-browser-context';
import {getDeviceInfo} from './device-helpers/webgl-device-info';
import {WebGLDeviceFeatures} from './device-helpers/webgl-device-features';
import {WebGLDeviceLimits} from './device-helpers/webgl-device-limits';
import {WebGLCanvasContext} from './webgl-canvas-context';
import {loadSpectorJS, initializeSpectorJS} from '../context/debug/spector';

import type {Spector} from '../context/debug/spector-types';
import {loadSpectorJS, initializeSpectorJS, DEFAULT_SPECTOR_PROPS} from '../context/debug/spector';
import {loadWebGLDeveloperTools, makeDebugContext} from '../context/debug/webgl-developer-tools';
import {
isTextureFormatSupported,
isTextureFormatRenderable,
isTextureFormatFilterable
} from './converters/texture-formats';
import {uid} from '../utils/uid';

// WebGL classes
import type {
Expand Down Expand Up @@ -97,6 +100,20 @@ export class WebGLDevice extends Device {

private _resolveContextLost?: (value: {reason: 'destroyed'; message: string}) => void;

/** WebGL2 context. */
readonly gl: WebGL2RenderingContext;
readonly debug: boolean = false;

/** State used by luma.gl classes: TODO - move to canvasContext*/
readonly _canvasSizeInfo = {clientWidth: 0, clientHeight: 0, devicePixelRatio: 1};

/** State used by luma.gl classes - TODO - not used? */
readonly _extensions: GLExtensions = {};
_polyfilled: boolean = false;

/** Instance of Spector.js (if initialized) */
spectorJS: Spector;

//
// Static methods, expected to be present by `luma.createDevice()`
//
Expand Down Expand Up @@ -128,6 +145,11 @@ export class WebGLDevice extends Device {
}

static async create(props: DeviceProps = {}): Promise<WebGLDevice> {
for (const [key, value] of Object.entries(DEFAULT_SPECTOR_PROPS)) {
if (props[key] === undefined) {
props[key] = value;
}
}
log.groupCollapsed(LOG_LEVEL, 'WebGLDevice created')();

const promises: Promise<unknown>[] = [];
Expand All @@ -137,9 +159,7 @@ export class WebGLDevice extends Device {
promises.push(loadWebGLDeveloperTools());
}

if (props.spector) {
promises.push(loadSpectorJS());
}
promises.push(loadSpectorJS(props));

// Wait for page to load: if canvas is a string we need to query the DOM for the canvas element.
// We only wait when props.canvas is string to avoids setting the global page onload callback unless necessary.
Expand Down Expand Up @@ -183,7 +203,10 @@ ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContex
//

constructor(props: DeviceProps) {
super({...props, id: props.id || 'webgl-device'});
// Add spector default props to device default props
Device.defaultProps = {...Device.defaultProps, ...DEFAULT_SPECTOR_PROPS};

super({...props, id: props.id || uid('webgl-device')});

// If attaching to an already attached context, return the attached device
// @ts-expect-error device is attached to context
Expand All @@ -200,27 +223,30 @@ ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContex
this._resolveContextLost = resolve;
});

let gl: WebGL2RenderingContext | null = props.gl || null;
gl ||= createBrowserContext(this.canvasContext.canvas, {
this.handle = createBrowserContext(this.canvasContext.canvas, {
...props,
onContextLost: (event: Event) =>
this._resolveContextLost?.({
reason: 'destroyed',
message: 'Entered sleep mode, or too many apps or browser tabs are using the GPU.'
})
});
this.gl = this.handle;

if (!gl) {
if (!this.handle) {
throw new Error('WebGL context creation failed');
}

this.handle = gl;
this.gl = gl;
// Add spector debug instrumentation to context
// We need to trust spector integration to decide if spector should be initialized
// We also run spector instrumentation first, otherwise spector can clobber luma instrumentation.
this.spectorJS = initializeSpectorJS({...this.props, gl: this.handle});

// Instrument context
(this.gl as any).device = this; // Update GL context: Link webgl context back to device
(this.gl as any)._version = 2; // Update GL context: Store WebGL version field on gl context (HACK to identify debug contexts)

// luma Device fields
// initialize luma Device fields
this.info = getDeviceInfo(this.gl, this._extensions);
this.limits = new WebGLDeviceLimits(this.gl);
this.features = new WebGLDeviceFeatures(this.gl, this._extensions, this.props.disabledFeatures);
Expand All @@ -239,17 +265,13 @@ ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContex
log: (...args: any[]) => log.log(1, ...args)()
});

// DEBUG contexts: Add debug instrumentation to the context, force log level to at least 1
// DEBUG contexts: Add luma debug instrumentation to the context, force log level to at least 1
if (props.debug) {
this.gl = makeDebugContext(this.gl, {...props, throwOnError: true});
this.debug = true;
log.level = Math.max(log.level, 1);
log.warn('WebGL debug mode activated. Performance reduced.')();
}

if (props.spector) {
this.spectorJS = initializeSpectorJS({...this.props, canvas: this.handle.canvas});
}
}

/**
Expand Down Expand Up @@ -425,20 +447,6 @@ ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContex
// WebGL-only API (not part of `Device` API)
//

/** WebGL2 context. */
readonly gl: WebGL2RenderingContext;
readonly debug: boolean = false;

/** State used by luma.gl classes: TODO - move to canvasContext*/
readonly _canvasSizeInfo = {clientWidth: 0, clientHeight: 0, devicePixelRatio: 1};

/** State used by luma.gl classes - TODO - not used? */
readonly _extensions: GLExtensions = {};
_polyfilled: boolean = false;

/** Instance of Spector.js (if initialized) */
spectorJS: unknown;

/**
* Triggers device (or WebGL context) loss.
* @note primarily intended for testing how application reacts to device loss
Expand Down
Loading

0 comments on commit 7c1c1f2

Please sign in to comment.